0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Python模拟导弹自动追踪的代码实例

马哥Linux运维 来源:博客园 作者:半壶砂 2021-06-13 16:35 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

自动追踪算法,在我们制作射击类游戏时经常会用到。这个听起来很高大上的东西,其实并不是军事学的专利,从数学上来说就是解微分方程,这个没有点数学基础是很难算出来的。但是我们有了计算机就不一样了,依靠计算机极快速的运算速度,我们利用微分的思想,加上一点简单的三角学知识,就可以实现它。

由于待会要用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),正弦对比斜,余弦邻比斜,斜边可以利用两点距离公式计算出,即。

8152f754-c668-11eb-9e57-12bb97331649.png

于是

815a5800-c668-11eb-9e57-12bb97331649.png

AC的长度就是导弹的速度乘以时间即 |AC|=vt,然后即可计算出AD和CD的长度,于是这一个时间片过去后,导弹应该出现在新的位置C点,他的坐标就是老的点A的x增加AD和y减去CD。于是,新的C点坐标就是。

8163a220-c668-11eb-9e57-12bb97331649.png

只要一直反复循环执行这个操作即可,好吧,为了更形象,把第一个时间片和第二个时间片放在一起看看。第一个是时间片构造出的三角形是ABE,经过一个时间片后,目标从B点走到了D点,导弹此时在C点,于是构造新的三角形CDF,重复刚才的计算过程即可,图中的角∠b就是导弹需要旋转的角度,现实中只需要每个时间片修正导弹的方向就可以了,具体怎么让导弹改变方向,这就不是我们需要研究的问题了好,由于最近在用Python的pygame库制作小游戏玩,接下来我们就用pygame来演示一下这个效果,效果如下图。

很简单的代码如下。

import pygame,sysfrom 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=0while 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)/distance cosa=(x-x1)/distance angle=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,sysfrom 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)/distance cosa=(x-x1)/distance angle=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模拟导弹自动追踪的代码实例。

原文标题。通过Python实现导弹自动追踪

文章出处。【微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4947

    浏览量

    73220
  • python
    +关注

    关注

    57

    文章

    4860

    浏览量

    89650

原文标题:通过Python实现导弹自动追踪

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Termux中调试圣诞树Python代码

    在Termux中调试Python代码(以圣诞树立例)非常简单,核心分为环境准备、代码编写、运行调试三个步骤,下面一步步教你操作: 一、环境准备(首次使用需做) Termux默认可能没有Pyth
    发表于 12-09 09:02

    语法纠错和testbench的自动生成

    ,回到写好的Verilog代码,按住ctrl+shift+p,在弹出的搜索框里输入testbench。 点击后会自动将当前模块的testbench生成在终端框内。 当然,本质上该插件还是通过python来实现的,因此
    发表于 10-27 07:07

    Python 给 Amazon 做“全身 CT”——可量产、可扩展的商品详情爬虫实战

      目标字段 & CSS 选择器   四、MVP:120 行代码即可跑通 单文件脚本,支持异步并发 10 个 ASIN,自动
    的头像 发表于 10-21 16:59 393次阅读
    用 <b class='flag-5'>Python</b> 给 Amazon 做“全身 CT”——可量产、可扩展的商品详情爬虫实战

    termux如何搭建python游戏

    模拟器,支持通过APT包管理器安装软件。搭建Python游戏开发环境前需完成以下基础配置: 1. 更换国内源 为提升下载速度,需替换Termux默认源为清华源,执行以下命令: ```bash
    发表于 08-29 07:06

    Python脚本实现运维工作自动化案例

    还在为重复性运维工作而烦恼?每天被各种告警、监控、部署搞得焦头烂额?作为一名有10年经验的运维老司机,今天分享5个超实用的Python自动化脚本,让你的运维工作效率提升300%!这些都是我在生产环境中实际使用的案例,代码简洁高效
    的头像 发表于 08-27 14:46 848次阅读

    模拟导弹热电池指示信号的电路设计与实现

    在某型导弹的设计中,热电池激活后,产生电池电压经DC-DC模块转换最终发送给发射装置作为热电池工作正常的指示信号,这是导弹接口中一个关键信号,本文提出的电路设计正是用于模拟此信号。
    的头像 发表于 06-20 09:45 2w次阅读
    <b class='flag-5'>模拟</b><b class='flag-5'>导弹</b>热电池指示信号的电路设计与实现

    实例解读模拟电子技术

    资料介绍:本文通过丰富多彩的应用实例,由浅入深地剖析模拟电子电路各方面的知识。例如,通过电子地动仪的介绍带领读者进入电子学的殿堂,通过USB充电器和电池保护器介绍有关直流电源的知识,通过电子听诊器
    发表于 05-16 13:29

    零基础入门:如何在树莓派上编写和运行Python程序?

    是一种非常有用的编程语言,其语法易于阅读,允许程序员使用比汇编、C或Java等语言更少的代码行。Python编程语言最初实际上是作为Linux的脚本语言而开发的。Py
    的头像 发表于 03-25 09:27 1578次阅读
    零基础入门:如何在树莓派上编写和运行<b class='flag-5'>Python</b>程序?

    27个FPGA实例代码

    本资料收集汇总了27个FPGA实例代码,有需要的可以下载学习! 获取完整文档资料可下载附件哦!!!!如果内容有帮助可以关注、点赞、评论支持一下哦~
    发表于 03-14 17:31

    如何提高多摄像头多目标Python演示的性能选项?

    Multi-Camera Multi-Target Python 演示中的_compute_mct_distance_matrixfunction可通过多个摄像头检查彼此之间对每条轨道的正弦距离。 大量的追踪工作需要花费数小时到几天才能检查踪迹。
    发表于 03-06 06:48

    创建了用于OpenVINO™推理的自定义C++和Python代码,从C++代码中获得的结果与Python代码不同是为什么?

    创建了用于OpenVINO™推理的自定义 C++ 和 Python* 代码。 在两个推理过程中使用相同的图像和模型。 从 C++ 代码中获得的结果与 Python*
    发表于 03-06 06:22

    运行OVModelForCausalLM Python模块时出错了,怎么解决?

    创建了一个自定义 Python* 代码,类似于遵循 240-dolly-2-instruction 的 Jupyter 笔记本。 OVModelForCausalLM Python* 模块运行时出错。
    发表于 03-05 06:44

    如何将python文件导入到ROS系统中

    本文通过使用myCobot机械臂进行QR码视觉追踪的实践案例分析,介绍如何将 python 文件导入到 ROS 系统中。
    的头像 发表于 02-11 11:08 1242次阅读
    如何将<b class='flag-5'>python</b>文件导入到ROS系统中

    使用Python实现xgboost教程

    装: bash复制代码conda install -c conda-forge xgboost 2. 导入必要的库 在你的Python脚本或Jupyter Notebook中,导入必要的库: python复制
    的头像 发表于 01-19 11:21 2256次阅读

    华为云 Flexus X 实例下的场景体验——小企业使用 Python 语言——超迅速搭建简单公网 API 接口服务

      前言 小企业为了快速搞定一些接口功能如果不使用 Python 的话相对来说复杂度还是很高的,这里我来通过【华为云 Flexus X 实例】来迅速的搭建一个 Python 的 WebApi 示例
    的头像 发表于 12-27 13:46 878次阅读
    华为云 Flexus X <b class='flag-5'>实例</b>下的场景体验——小企业使用 <b class='flag-5'>Python</b> 语言——超迅速搭建简单公网 API 接口服务