作者:半壶砂

https://www.cnblogs.com/halfsand/p/7976636.html

最近中|东闹得凶,除了对某色列强烈谴责,最吸引眼球的要是他们的铁穹防御系统。

那如何用Python简单模拟导弹自动追踪的实例,感兴趣的同学可以试试。

自动追踪算法,在我们制作射击类游戏时经常会用到。这个听起来很高大上的东西,其实并不是军事学的专利,从数学上来说就是解微分方程,

这个没有点数学基础是很难算出来的。但是我们有了计算机就不一样了,依靠计算机极快速的运算速度,我们利用微分的思想,加上一点简单的三角学知识,就可以实现它。

好,话不多说,我们来看看它的算法原理,看图:

由于待会要用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,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))      #两点距离公式    p=velocity*time               #每个时间片需要移动的距离    sina=(y1-y)/distance    cosa=(x-x1)/distance    angle=atan2(y-y1,x-x1)              #两点线段的弧度值    x1,y1=(x1+p*cosa,y1-p*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))      #两点距离公式    p=velocity*time               #每个时间片需要移动的距离    sina=(y1-y)/distance    cosa=(x-x1)/distance    angle=atan2(y-y1,x-x1)              #两点间线段的弧度值    fangle=degrees(angle)               #弧度转角度    x1,y1=(x1+p*cosa,y1-p*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的问题  | 零基础学了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爬虫神器太爽了,自动下载妹子图片
点阅读原文,领AI全套资料!

会玩,有人用 Python 模拟导弹防御!相关推荐

  1. 朝韩危机-Python模拟导弹互射

    萨德系统是麻省理工学院的林肯实验室牵头开发的.林肯实验室可以说是美军方手中的一张王牌.二个反导系统(末段高空区域导弹防御(THAAD)系统,和 国家导弹防御系统(NMD))均由实验室牵头.它既是技术支 ...

  2. 用 Python 实现导弹自动追踪,超燃!

    作者丨半壶砂 https://www.cnblogs.com/halfsand/p/7976636.html 大家好,我是J哥. 自动追踪算法,在我们制作射击类游戏时经常会用到.这个听起来很高大上的东 ...

  3. 【NOIP2013模拟】导弹防御塔

    题目 Freda的城堡-- "Freda,城堡外发现了一些入侵者!" "喵-刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~" "可是入侵者已经 ...

  4. 导弹防御系统,如何跟蜻蜓的大脑学习计算?

    来源:大数据文摘 作者:Frances Chance 多雨的夏季,蜻蜓最为常见,这些美丽的生物的飞行速度极快,狩猎能力也极为出色:蜻蜓狩猎的成功率捕获了高达95% ,它们一天可以吃掉数百只蚊子. 这种 ...

  5. Python模拟赌博实验,赌博为什么能赌到倾家荡产?

    Python模拟赌博实验 作者:dalalaa http://www.jianshu.com/p/2d919a028600 概述 前言 实验思路 实验步骤 统计数据 结论 阿广说 福利一刻 推荐阅读 ...

  6. python 模拟浏览器selenium_从零开始写Python爬虫 --- 3.1 Selenium模拟浏览器

    本来说好要写Mechanize模拟浏览器的,结果一看居然只支持2.x版本的Python,而且已经长久没有更新维护了,本着学新不学旧的原则,我决定跳过他,直接开学Selenium(其实就是我懒,逃 Se ...

  7. python 模拟浏览器selenium 要求快速_Selenium模拟浏览器初识

    Seleniumd介绍 在写Python爬虫的时候,最麻烦的不是那些海量的静态网站,而是那些通过JavaScript获取数据的站点.Python本身对js的支持不好,所以就有良心的开发者来做贡献了,这 ...

  8. Python模拟弹道轨迹

    http://www.itongji.cn/cms/article/articledetails?articleid=5029 最近美国把萨德系统部署到韩国,一时心血来潮就用python模拟最简单的弹 ...

  9. pythoncookie自动模拟登录_用Python模拟技巧带你实现自动抽屉登录自动点赞

    原标题:用Python模拟技巧带你实现自动抽屉登录&自动点赞 /1 前言/ 嘿,各位小伙伴们晚上好呀,今天小编又给大家带来干货内容啦,今天带来的是,如何自动登录抽屉,并且点赞! 原计划是不打算 ...

最新文章

  1. 阿里云发布三大人工智能产品:推动AI产业落地
  2. linux 检查 文件末尾 是否有空行
  3. VS2010建立Windows服务项目时的一些问题
  4. 数据结构与算法之二叉树的先序遍历,中序遍历,后序遍历
  5. Eclipse卸载Groovy Development tool时,为什么要去查询hana.ondemand.com的资源?
  6. css样式全大写,用css样式表实现首字大写
  7. 运行npm install命令后的执行过程
  8. 对任意长度字符串,删除其中的任意的N(N=0)个字符
  9. poj 1966 Cable TV Network 顶点连通度
  10. Java 数据库编程 ResultSet 的 使用方法
  11. Python多进程(process)和多线程(thread)的区别
  12. Computing Platform------系统平台及其系列
  13. Ubuntu下安装Fcitx和美化Fcitx,解决方框错误.
  14. kubernetes视频教程笔记 (26)-集群调度-节点亲和性
  15. (转)对冲基金不信中国经济数据,转用卫星监控6000块工业用地
  16. php学生管理系统整理
  17. 支持8086c语言编程的编译器,8086汇编语言编程软件|8086汇编语言编译器(MKStudio) v1.0免费版 附安装教程_星星软件园...
  18. 企业数据总线(ESB)和注册服务管理(dubbo)的区别{{1033}}
  19. 乐乐音乐4.0简洁版
  20. Logisitc Regression 预测员工离职率

热门文章

  1. SSL/TLS 服务器瞬时 Diffie-Hellman 公共密钥过弱
  2. 计算机应用基础在线试题,计算机应用基础试题.DOC
  3. 手机连上wifi不能上网
  4. 手机拨出等待时间长_手机打不出去电话怎么回事 一分钟轻松排查原因
  5. 2023东莞理工学院计算机考研信息汇总
  6. java table数据转excel,excel将数据转化成表格-如何将java数据转换成Excel表格
  7. 网页版linux客户端,网页版微信将关闭,Linux开发者哭惨
  8. 如何用python赚钱_一篇文章教你使用Python自动赚取支付宝积分,网友:发家致富?...
  9. 获取post请求的几种常见方式
  10. 【Luogu5348】密码解锁(莫比乌斯反演,数论)