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

在游戏中,一般使用二维矢量保存玩家的位置,使用矢量计算可以计算出玩家移动的位置,下面的 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. Spring & Java

    Spring & Java https://spring.io/ Spring Boot https://www.shiyanlou.com/courses/1152 Spring Boot入 ...

  2. 【springmvc】传值的几种方式&&postman接口测试

    最近在用postman测试postman接口,对于springmvc传值这一块,测试了几种常用方式,总结一下.对于postman这个工具的使用也增加了了解.postman测试很棒,有了工具,测试接口, ...

  3. Codeforces Round #374 (Div. 2) C DAG上dp

    C. Journey time limit per test 3 seconds memory limit per test 256 megabytes input standard input ou ...

  4. php把时间计算成几分钟前,几小时前,几天前的函数

    function time_tran($the_time){ $now_time = date("Y-m-d H:i:s",time()+8*60*60); $now_time = ...

  5. paramiko_su_root

    #coding=utf8 import paramiko import time import logging ''' if user root,can not login,must use user ...

  6. png图片解码

    PNG.可移植网络图形格式(Portable Network Graphic Format,PNG)名称来源于非官方的"PNG's Not GIF",是一种位图文件(bitmap ...

  7. web 页面传值乱码问题

    今天碰到一个问题,将A页面中文值传到B页面,session保存,然后在C页面显示,页面显示乱码 百度了一下什么原因,以为是session保存中乱码,于是将B页面的通过Server.UrlDecode( ...

  8. [计算机故障]为什么我的手机SD卡一打开就是说“你的磁盘未格式化,现在需要格式化吗”?

    现在随着智能手机的普及,越来越多的人使用到了手机SD卡.也有的是micro SD(更小一些). 最近一个朋友说,为什么我的手机SD卡插到手机里一打开就是说“你的磁盘未格式化,现在需要格式化吗?” 但是 ...

  9. Apache2.2安装

    貌似Apache官网从2.2.X之后不再发布Windows安装版本,需要的话得自己编译 从官网下载2.2.25(我下了一个no-ssl的),安装提示 因为本机已经安装IIS,占用80端口,修改Apac ...

  10. document.body.className = document.body.className.replace("siteorigin-panels-before-js","");

    document.body.className = document.body.className.replace("siteorigin-panels-before-js",&q ...