用 Python 实现导弹自动追踪,超燃!
作者丨半壶砂
https://www.cnblogs.com/halfsand/p/7976636.html
大家好,我是J哥。
自动追踪算法,在我们制作射击类游戏时经常会用到。这个听起来很高大上的东西,其实并不是军事学的专利,从数学上来说就是解微分方程。
这个没有点数学基础是很难算出来的。但是我们有了计算机就不一样了,依靠计算机极快速的运算速度,我们利用微分的思想,加上一点简单的三角学知识,就可以实现它。
好,话不多说,我们来看看它的算法原理,看图:
由于待会要用pygame演示,它的坐标系是y轴向下,所以这里我们也用y向下的坐标系。
算法总的思想就是根据上图,把时间t分割成足够小的片段(比如1/1000,这个时间片越小越精确),每一个片段分别构造如上三角形,计算出导弹下一个时间片走的方向(即∠a)和走的路程(即vt=|AC|),这时候目标再在第二个时间片移动了位置,这时刚才计算的C点又变成了第二个时间片的初始点,这时再在第二个时间片上在C点和新的目标点构造三角形计算新的vt,然后进入第三个时间片,如此反复即可。
假定导弹和目标的初始状态下坐标分别是(x1,y1),(x,y),构造出直角三角形ABE,这个三角形用来求∠a的正弦和余弦值,因为vt是自己设置的,我们需要计算A到C点x和y坐标分别移动了多少,移动的值就是AD和CD的长度,这两个分别用vt乘cos(a)和sin(a)即可。
计算sin(a)和cos(a),正弦对比斜,余弦邻比斜,斜边可以利用两点距离公式计算出,即:
于是
AC的长度就是导弹的速度乘以时间即 |AC|=vt,然后即可计算出AD和CD的长度,于是这一个时间片过去后,导弹应该出现在新的位置C点,他的坐标就是老的点A的x增加AD和y减去CD。
于是,新的C点坐标就是:
只要一直反复循环执行这个操作即可,好吧,为了更形象,把第一个时间片和第二个时间片放在一起看看:
第一个是时间片构造出的三角形是ABE,经过一个时间片后,目标从B点走到了D点,导弹此时在C点,于是构造新的三角形CDF,重复刚才的计算过程即可,图中的角∠b就是导弹需要旋转的角度,现实中只需要每个时间片修正导弹的方向就可以了,具体怎么让导弹改变方向,这就不是我们需要研究的问题了
好,由于最近在用Python的pygame库制作小游戏玩,接下来我们就用pygame来演示一下这个效果,效果如下图:
很简单的代码如下:
import pygame,sys
from math import *
pygame.init()
screen=pygame.display.set_mode((800,700),0,32)
missile=pygame.image.load('element/red_pointer.png').convert_alpha()
x1,y1=100,600 #导弹的初始发射位置
velocity=800 #导弹速度
time=1/1000 #每个时间片的长度
clock=pygame.time.Clock()
old_angle=0
while True:for event in pygame.event.get():if event.type==pygame.QUIT:sys.exit()clock.tick(300)x,y=pygame.mouse.get_pos() #获取鼠标位置,鼠标就是需要打击的目标distance=sqrt(pow(x1-x,2)+pow(y1-y,2)) #两点距离公式section=velocity*time #每个时间片需要移动的距离sina=(y1-y)/distancecosa=(x-x1)/distanceangle=atan2(y-y1,x-x1) #两点线段的弧度值x1,y1=(x1+section*cosa,y1-section*sina)d_angle = degrees(angle) #弧度转角度screen.blit(missile, (x1-missile.get_width(), y1-missile.get_height()/2))dis_angle=d_angle-old_angle #dis_angle就是到下一个位置需要改变的角度old_angle=d_angle #更新初始角度pygame.display.update()
如果仅把导弹考虑为一个质点的话,那么以上算法就已经足矣,我没有做导弹的旋转,因为一个质点也不分头尾不需要旋转,当然这前提得是你加载的导弹图片很小的时候不旋转看起来也没什么问题。但是在pygame里面做旋转并不是一件容易的事情,我们先把图片替换成一张矩形的,再加入旋转函数看看效果如何
missiled = pygame.transform.rotate(missile, -(d_angle))
screen.blit(missiled, (x1-missile.get_width(), y1-
missile.get_height()/2))
因为图片的坐标点是它的左上角的点,所以如果我们想让图片的坐标固定在箭头尖点,那么把图片实际打印位置x减少图片长度,y减少一半宽度就行。但是实际运行效果并不好:
大致方向相同,但是图片箭头的尖点并没有一直跟随鼠标,这是为什么呢。经过一番研究,我发现原来是这个图旋转的机制问题,我们看看旋转后的图片变成什么样了:
旋转后的图片变成了蓝色的那个范围,根据旋转角度的不同,所变成的图片大小也不一样,我们看旋转90的情况
我们发现,旋转后的图片不仅面积变大了,导弹头的位置也变了。那应该怎么解决这个问题呢?思路是,每一次旋转图片以后,求出旋转图的头位置(图中的绿色箭头点),然后把绿图的打印位置移动一下,下,x,y分别移动两个头的距离,就可以让旋转后的导弹头对准实际我们参与运算的那个导弹头的位置,移动后应该是这样的:
这样,两个导弹头的点就一致了。接下来我们分析求旋转后的导弹头的算法。根据旋转角度的不同,旋转角在不同象限参数不一样,所以我们分为这四种情况
1,2象限
3,4象限,它的旋转只有正负0—180,所以3,4象限就是负角
显示图片的时候我们将他移动
screen.blit(missiled, (x1-width+(x1-C[0]),y1-height/2+(y1-C[1])))
这里的 (x1-width, y1-height/2) 其实才是上图中的 (x1, y1)
所以最后我们加入相关算法代码,效果就比较完美了
大功告成,最后附上全部的算法代码
import pygame,sys
from math import *
pygame.init()
font1=pygame.font.SysFont('microsoftyaheimicrosoftyaheiui',23)
textc=font1.render('*',True,(250,0,0))
screen=pygame.display.set_mode((800,700),0,32)
missile=pygame.image.load('element/rect1.png').convert_alpha()
height=missile.get_height()
width=missile.get_width()
pygame.mouse.set_visible(0)
x1,y1=100,600 #导弹的初始发射位置
velocity=800 #导弹速度
time=1/1000 #每个时间片的长度
clock=pygame.time.Clock()
A=()
B=()
C=()
while True:for event in pygame.event.get():if event.type==pygame.QUIT:sys.exit()clock.tick(300)x,y=pygame.mouse.get_pos() #获取鼠标位置,鼠标就是需要打击的目标distance=sqrt(pow(x1-x,2)+pow(y1-y,2)) #两点距离公式section=velocity*time #每个时间片需要移动的距离sina=(y1-y)/distancecosa=(x-x1)/distanceangle=atan2(y-y1,x-x1) #两点间线段的弧度值fangle=degrees(angle) #弧度转角度x1,y1=(x1+section*cosa,y1-section*sina)missiled=pygame.transform.rotate(missile,-(fangle))if 0<=-fangle<=90:A=(width*cosa+x1-width,y1-height/2)B=(A[0]+height*sina,A[1]+height*cosa)if 90<-fangle<=180:A = (x1 - width, y1 - height/2+height*(-cosa))B = (x1 - width+height*sina, y1 - height/2)if -90<=-fangle<0:A = (x1 - width+missiled.get_width(), y1 - height/2+missiled.get_height()-height*cosa)B = (A[0]+height*sina, y1 - height/2+missiled.get_height())if -180<-fangle<-90:A = (x1-width-height*sina, y1 - height/2+missiled.get_height())B = (x1 - width,A[1]+height*cosa )C = ((A[0] + B[0]) / 2, (A[1] + B[1]) / 2)screen.fill((0,0,0))screen.blit(missiled, (x1-width+(x1-C[0]),y1-height/2+(y1-C[1])))screen.blit(textc, (x,y)) #鼠标用一个红色*代替pygame.display.update()
以上便是用Python模拟导弹自动追踪的代码实例。
2022GTC峰会,面基吴恩达老师
注册就有礼品,报名之后还有2份礼品
推荐阅读:
入门: 最全的零基础学Python的问题 | 零基础学了8个月的Python | 实战项目 |学Python就是这条捷径
干货:爬取豆瓣短评,电影《后来的我们》 | 38年NBA最佳球员分析 | 从万众期待到口碑扑街!唐探3令人失望 | 笑看新倚天屠龙记 | 灯谜答题王 |用Python做个海量小姐姐素描图 |碟中谍这么火,我用机器学习做个迷你推荐系统电影
趣味:弹球游戏 | 九宫格 | 漂亮的花 | 两百行Python《天天酷跑》游戏!
AI: 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影
小工具: Pdf转Word,轻松搞定表格和水印! | 一键把html网页保存为pdf!| 再见PDF提取收费! | 用90行代码打造最强PDF转换器,word、PPT、excel、markdown、html一键转换 | 制作一款钉钉低价机票提示器! |60行代码做了一个语音壁纸切换器天天看小姐姐!|
年度爆款文案
1).卧槽!Pdf转Word用Python轻松搞定!
2).学Python真香!我用100行代码做了个网站,帮人PS旅行图片,赚个鸡腿吃
3).首播过亿,火爆全网,我分析了《乘风破浪的姐姐》,发现了这些秘密
4).80行代码!用Python做一个哆来A梦分身
5).你必须掌握的20个python代码,短小精悍,用处无穷
6).30个Python奇淫技巧集
7).我总结的80页《菜鸟学Python精选干货.pdf》,都是干货
8).再见Python!我要学Go了!2500字深度分析!
9).发现一个舔狗福利!这个Python爬虫神器太爽了,自动下载妹子图片
点阅读原文,看200个Python案例!
用 Python 实现导弹自动追踪,超燃!相关推荐
- Python大数据演示|超燃动态排序图(亲测)
lualu.txt里面存放文件: Vijayanagar,India,1537,485.2,India,Vijayanagar - India,485.6,15.335,76.462 Vijayana ...
- Python实现吃鸡游戏子弹and导弹自动追踪!原来是这样的一个原理啊!
一,前言 自动追踪算法,在我们制作射击类游戏时经常会用到.这个听起来很高大上的东西,其实并不是军事学的专利,从数学上来说就是解微分方程, 这个没有点数学基础是很难算出来的.但是我们有了计算机就不一样了 ...
- 会玩,有人用 Python 模拟导弹防御!
作者:半壶砂 https://www.cnblogs.com/halfsand/p/7976636.html 最近中|东闹得凶,除了对某色列强烈谴责,最吸引眼球的要是他们的铁穹防御系统. 那如何用Py ...
- python怎么设置文字云_超燃的文字云效果,用Python就能轻松get!
原标题:超燃的文字云效果,用Python就能轻松get! 本文转载自公众号:数据森麟(ID:shujusenlin) 作者:叶庭云 链接:https://blog.csdn.net/fyfugoyfa ...
- 使用Python和OpenCV实现超快速,简单的伽玛校正功能
使用Python和OpenCV实现超快速,简单的伽玛校正功能 1. 效果图 2. 什么是伽玛校正? 3. 源码 参考 这篇博客将介绍伽马校正(也称为幂律变换)是什么,并将演示如何使用Python和Op ...
- Python的零基础超详细讲解(第十三天)-Python的类与对象
基础篇往期文章如下: Python的零基础超详细讲解(第一天)-Python简介以及下载 Python的零基础超详细讲解(第二天)-Python的基础语法1 Python的零基础超详细讲解(第三天)- ...
- Python的零基础超详细讲解(第十二天)-Python函数及使用
基础篇往期文章: Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博 ...
- Python的零基础超详细讲解(第七天)-Python的数据的应用
往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...
- Python的零基础超详细讲解(第五天)-Python的运算符
往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...
最新文章
- 安装上传下载插件,jdk及redis
- hdu 4907(并查集)
- [数据结构]顺序单链表插入
- AOJ 0118: Property Distribution (简单DFS)
- 自媒体时代的贤内助——AI 视频云
- Go tcp客户端、服务端编程
- 链表之单链表的反转总结
- [Spark]Could not locate executable null\bin\winutils.exe in the Hadoop binaries
- mysql之家_MySQL
- NAS和私有云盘的区别?1篇文章说清楚
- 三菱plc控制电动推杆
- 5.3 使用数据结构对真实世界建模
- Vim简单介绍和使用方法
- H2O中添加算法-模型训练篇
- Peer-to-Peer Sockets 工程入门
- android 面试题(史上最全)
- Unity 2D 混合树小例子
- 扫描版pdf重排 linux,【Kindle Pdf Viewer中文安装教程】支持扫描版PDF重排及其他主流文件格式...
- 微服务之RPC(远程过程调用)的四种方式
- 【云栖大会】马云口中创造未来的年轻人,把数据+环保玩出了新花样