实例:二维矢量模拟玩家移动

在游戏中,一般使用二维矢量保存玩家的位置,使用矢量计算可以计算出玩家移动的位置,下面的 demo 中,首先实现二维矢量对象,接着构造玩家对象,最后使用矢量对象和玩家对象共同模拟玩家移动的过程

1)实现二维矢量结构

矢量是数据中的概念,二维矢量拥有两个方向的信息,同时可以进行加、减、乘(缩放)、距离、单位化等计算

在计算机中,使用拥有 x 和 y 两个分量的 Vecor2 结构体实现数学中二维向量的概念,如下:

# coding=utf-8
import math
import time # 坐标类
class Vector(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y # 相加
def add(self, vector):
self.x += vector.x
self.y += vector.y # 相减
def sub(self, vector):
x = self.x - vector.x
y = self.y - vector.y
return Vector(x, y) # 相乘
def multi(self, speed):
self.x *= speed
self.y *= speed
return self # 计算距离
def distance(self, vector):
dx = self.x - vector.x
dy = self.y - vector.y
return math.sqrt(dx ** 2 + dy ** 2) # 矢量单位化
def normalize(self):
mag = self.x ** 2 + self.y ** 2
if mag > 0:
one_over_mag = 1 / math.sqrt(mag)
vector = Vector(x=self.x * one_over_mag, y=self.y * one_over_mag)
else:
vector = Vector()
return vector

2)实现玩家对象

玩家对象负责存储玩家的当前位置、目标位置和移动速度,使用 moveTo() 为玩家设定目的地坐标,使用 update() 更新玩家坐标

# 玩家类
class Player(object):
def __init__(self, current_vector=None, target_vector=None, speed=0):
self.current_vector = current_vector
self.target_vector = target_vector
self.speed = speed # 获取玩家坐标
def get_current_vector(self):
return self.current_vector # 判断是否到达终点
def is_arrived(self):
return self.current_vector.distance(self.target_vector) < self.speed # 更新玩家位置
def update_vector(self):
# 获取方向矢量(固定值)
direction_vector = self.target_vector.sub(self.current_vector)
# 矢量单位化(固定值)
normalize_vector = direction_vector.normalize()
# 根据速度计算 x, y 方向上前进的长度
ongoing_vector = normalize_vector.multi(self.speed)
# 更新位置
self.current_vector.add(ongoing_vector)

更新坐标稍微复杂一些,需要通过矢量计算获得玩家移动后的新位置,步骤如下:

  1. 使用矢量减法,将目标位置(targetPos)减去当前位置(currPos)即可计算出位于两个位置之间的新矢量
  2. 使用 normalize() 方法将方向矢量变为模为 1 的单位化矢量,
  3. 然后用单位化矢量乘以玩家的速度,就能得到玩家每次分别在 x, y 方向上移动的长度
  4. 将目标当前位置的坐标与移动的坐标相加,得到新位置的坐标,并做修改

3)主程序

玩家移动是一个不断更新位置的循环过程,每次检测玩家是否靠近目标点附近,如果还没有到达,则不断地更新位置,并打印出玩家的当前位置,直到玩家到达终点

if __name__ == '__main__':
p = Player()
p.current_vector = Vector(0, 0)
p.target_vector = Vector(2, 2)
p.speed = 0.2 while not p.is_arrived():
p.update_vector()
print(f"({p.current_vector.x}, {p.current_vector.y})")
time.sleep(1) print("arrive at the destination")
  1. 将 Player 实例化,设定玩家终点坐标,当前坐标
  2. 更新玩家位置
  3. 每次移动后,打印玩家的位置坐标
  4. 延时 1 秒(便于观察效果)

 

ending~

用 python 写一个模拟玩家移动的示例的更多相关文章

  1. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  2. 十行代码--用python写一个USB病毒 (知乎 DeepWeaver)

    昨天在上厕所的时候突发奇想,当你把usb插进去的时候,能不能自动执行usb上的程序.查了一下,发现只有windows上可以,具体的大家也可以搜索(搜索关键词usb autorun)到.但是,如果我想, ...

  3. [py]python写一个通讯录step by step V3.0

    python写一个通讯录step by step V3.0 参考: http://blog.51cto.com/lovelace/1631831 更新功能: 数据库进行数据存入和读取操作 字典配合函数 ...

  4. 【Python】如何基于Python写一个TCP反向连接后门

    首发安全客 如何基于Python写一个TCP反向连接后门 https://www.anquanke.com/post/id/92401 0x0 介绍 在Linux系统做未授权测试,我们须准备一个安全的 ...

  5. Python写一个自动点餐程序

    Python写一个自动点餐程序 为什么要写这个 公司现在用meican作为点餐渠道,每天规定的时间是早7:00-9:40点餐,有时候我经常容易忘记,或者是在地铁/公交上没办法点餐,所以总是没饭吃,只有 ...

  6. 用python写一个自动化盲注脚本

    前言 当我们进行SQL注入攻击时,当发现无法进行union注入或者报错等注入,那么,就需要考虑盲注了,当我们进行盲注时,需要通过页面的反馈(布尔盲注)或者相应时间(时间盲注),来一个字符一个字符的进行 ...

  7. python写一个能变身电光耗子的贪吃蛇

    python写一个不同的贪吃蛇 写这篇文章是因为最近课太多,没有精力去挖洞,记录一下学习中的收获,python那么好玩就写一个大一没有完成的贪吃蛇(主要还是跟课程有关o(╥﹏╥)o,课太多好烦) 第一 ...

  8. python写一个邮箱伪造脚本

    前言: 原本打算学php MVC的思路然后写一个项目.但是贼恶心, 写不出来.然后就还是用python写了个邮箱伪造. 0x01 第一步先去搜狐注册一个邮箱 然后,点开设置,开启SMTP服务. 当然你 ...

  9. 用python写一个非常简单的QQ轰炸机

    闲的没事,就想写一个QQ轰炸机,按照我最初的想法,这程序要根据我输入的QQ号进行轰炸,网上搜了一下,发现网上的案列略复杂,就想着自己写一个算了.. 思路:所谓轰炸机,就是给某个人发很多信息,一直刷屏, ...

随机推荐

  1. CF-697B Barnicle与691C Exponential notation

    无聊写两个题解吧,上午做比赛拉的,感触很多! B. Barnicle time limit per test 1 second memory limit per test 256 megabytes ...

  2. 7-14 电话聊天狂人(25 分)(Hash表基本操作)

    7-14 电话聊天狂人(25 分) 给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人. 输入格式: 输入首先给出正整数N(≤10​5​​),为通话记录条数.随后N行,每行给出一条通话记录.简单 ...

  3. Amoeba新版本MYSQL读写分离配置

    标签:mysql 数据库 读写分离 休闲 amoeba 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://skyson.blog.5 ...

  4. MyChrome制作Chrome浏览器便携版

    Google Chrome官方离线下载地址: https://api.shuax.com/tools/getchrome MyChrome下载地址: http://code.taobao.org/p/ ...

  5. 国内程序员的十大疑问之一:为什么老外不愿意用MyBatis?

    老外用MyBatis吗 昨天我在我在知乎看到了一张比较Hibernate和MyBatis使用情况的图,顺手发了条朋友圈: Hibernate vs MyBatis ,谁能告诉我什么样的国情导致了这么大 ...

  6. [NOIP2004] 提高组 洛谷P1089 津津的储蓄计划

    题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里 ...

  7. 【BZOJ3925】地震后的幻想乡(期望概率DP,状压DP)

    题意:给定一张点数不超过10的无向连通图,每条边有一个[0,1]之间的随机权值,求最小生成树上最大边的期望值 提示:对于n个[0,1]之间的随机变量x1,x2,...,xn,第k小的那个的期望值是k/ ...

  8. muduo buffer类的设计与使用

    Unix/Linux上的五种IO模型(UNP6.2) IO多路复用一般不能和blocking IO用在一起,因为blocking IO中read() write() accept() connect( ...

  9. Windows Update 的工具

    Windows Update MiniTool 是一款管理 Windows Update 的工具,可以取得微軟 Windows 修補程式更新包,Windows Update 是我們用來升級系統的元件, ...

  10. 静态链表的C++实现

    静态链表是使用数组实现的能够高速插入和删除数据的链表,静态链表和链式单链表比的缺点在于链表的长度仅仅能初始化设置好,而相相应普通的顺序存储的链表,静态链表不能实现高速的读写随意的元素. 当然静态链表给 ...