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

在游戏中,一般使用二维矢量保存玩家的位置,使用矢量计算可以计算出玩家移动的位置,下面的 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. jmeter接口测试实战简例

    1.接口需求文档说明 2.打开jmeter,新建线程组,线程组里面默认配置就可以 3.建立http请求,我这里是http请求,所以我选择这个,跟进实际情况 4.post请求说明,post直接加参数和参 ...

  2. 使用IDEA部署Myeclipse项目----亲测有效

    使用IDEA部署Myeclipse项目-----https://blog.csdn.net/u010570551/article/details/51510447

  3. HDU 4803 贪心

    尽可能的让当前的平均值接近最后的平均值才能最快达到终点的情况 #include <cstdio> #include <cstring> #include <iostrea ...

  4. 从零开始写STL-容器-list

    从零开始写STL-容器-list List 是STL 中的链表容器,今天我们将通过阅读和实现list源码来解决一下问题: List内部的内存结构是如何实现的? 为什么List的插入复杂度为O(1)? ...

  5. Inversion 归并求逆元

    bobo has a sequence a 1,a 2,…,a n. He is allowed to swap twoadjacent numbers for no more than k time ...

  6. 输入一个URL之后。。。

    1.输入URL2.浏览器去浏览器缓存.系统缓存.路由器缓存查找缓存记录,有则直接访问URL对应的IP,无则下一步3.DNS解析URL,获得对应的IP4.浏览器通过TCP/IP三次握手连接服务器5.客户 ...

  7. Memcached集群之通过Repcached实现主从复制(待实践)

    暂时了解有这东西,不搭建了. Mamcached可以通过Repcached实现主从复制.有以下优缺点: 优点: 1.能够实现Cache的冗余功能 2.主从之间可以互相读写(亮点) 参考: http:/ ...

  8. 基于xml配置springmvc

    controller关键代码 public class MenuController extends MultiActionController 方法: public ModelAndView lis ...

  9. Ionic3错误记录:navigation stack needs at least one root page

    BUG场景:在 ActionSheetController 使用modalCtrl.create 创建模态框时报如下错误 原代码片段 解决方式: 重新设置root page

  10. linux shell学习一点点

    问题,从shell command 交互式地由用户输入密码,但是输入的过程中不会显示用户输入的密码,起到类似于于html中input type=password的作用. #!/bin/bash rea ...