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

在游戏中,一般使用二维矢量保存玩家的位置,使用矢量计算可以计算出玩家移动的位置,下面的 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. [luoguP1074] 靶形数独(搜索)

    传送门 75分,太菜,不会优化了,吐了. 几点优化. 1.先搜索容易确定的位置 2.从中心往周围搜 3.枚举数字的时候倒序枚举 4.如果没有枚举到的数字都是最优情况的话也不能比当前ans大就剪枝 5. ...

  2. 【NOIP2017练习】怎样更有力气(二分答案,线性扫描)

    题意:OI大师抖儿在夺得银牌之后,顺利保送pku.这一天,抖儿问长者:“我虽然已经保送了,但我的志向是为国家健康工作五十年.请问我应该怎样变得更有力气?”   长者回答:“你啊,Too Young T ...

  3. web文件管理系统和日志实时监控工具

    https://blog.csdn.net/xuesong123/article/details/52752384

  4. java.lang.RuntimeException: JPedal Trial has now expired

    具体提示: java.lang.RuntimeException: JPedal Trial has now expired jpedal-server-trial.jar jar包过期了,jpeda ...

  5. iframe显示滚动条

    子页面通过iframe加载,出现了竖向滚动条 最后查出原因:文档申明 iframe有滚动条的页面的文档申明 <!DOCTYPE html> 改成如下就行了 <!DOCTYPE HTM ...

  6. Django学习系列之重写User模型和登录验证

    重写User模型 Django内置的User模型可能不适合某些项目,我们可能要基于内置的添加一些字段 创建users app startapp users 修改settings.py配置文件,覆盖默认 ...

  7. Django学习系列之中间件

    中间件的定义 中间件是一个.一个的管道,如果相对任何所有的通过Django的请求进行管理都需要自定义中间件 中间件可以对进来的请求和出去的请求进行控制 中间件是一类 django请求生命周期 自定义中 ...

  8. start-all.sh 启动时报错解决方案

    文件拥有者不是当前用户,或者文件权限没有修改权限 解决方法: sudo chmod 777  "文件名" 或者用 su root 登录,然后删除  再 exit Datanote服 ...

  9. Jmeter技巧

    Jmeter参数化的4种方法 用Jmeter测试时包含两种情况的参数,一种是在url中,一种是请求中需要发送的参数. URL中的参数,如:http://blog.da-fang.com/index.p ...

  10. Spring MVC 数据验证——validate编码方式

    1.导入jar包 validation-api-1.0.0.GA.jar这是比較关键的一个jar包,主要用于解析注解@Valid. hibernate-validator-4.3.2.Final.ja ...