Python实现导弹自动追踪

news2025/1/12 5:53:15

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

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

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

由于待会要用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)/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,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)/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模拟导弹自动追踪的代码实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/42535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Scala专栏】走进Scala

官方文档: https://www.scala-lang.org/ 一、What is Scala? Scala是一种针对JVM 将面向函数和面向对象技术组合在一起的编程语言。Scala编程语言近来抓住了很多开发者的眼球。它看起来像是一种纯粹的面向对象编程语言&#xff0c;而又无缝地结合了命令式和函数式的编程风格…

服务访问质量(QoS)——流量整形与拥塞管理

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.流量整形和监管配置 1.流量整形配置两种方式 ①流量整形的命…

从零开始上手 MQTT over QUIC:快速体验下一代物联网标准协议

前言 QUIC(RFC9000) 是下一代互联网协议 HTTP/3 的底层传输协议&#xff0c;与 TCP/TLS 协议相比&#xff0c;它在减少连接开销与消息延迟的同时&#xff0c;为现代移动互联网提供了有效灵活的传输层。 EMQX 5.0 是首个将 QUIC 引入 MQTT 的开创性产品。在长期的客户服务和技…

eunomia-bpf项目重磅开源!eBPF 轻量级开发框架来了

近日&#xff0c;在 2022 云栖大会龙蜥峰会 eBPF & Linux 稳定性专场上&#xff0c;来自 eBPF 技术探索 SIG Maintainer 、浙江大学的郑昱笙分享了《eunomia-bpf&#xff1a;eBPF 轻量级开发框架》技术演讲&#xff0c;以下为本次演讲内容&#xff1a; 大家好&#xff01;…

【新知实验室-TRTC开发】实时音视频之web端云监工系统(Vue3+Element plus+TS+Pinia)

在线上线下一体化、虚拟现实加速融合的趋势下&#xff0c;音视频已经演进成一种基本能力&#xff0c;深刻变革了社会的交互方式。未来&#xff0c;音视频作为全真互联时代的重要基石&#xff0c;将持续推动互联网和实体产业的数字化创新与升级。 今天我们将体验腾讯的实时音视…

vue3 antd table表格的增删改查(一)input输入框根据关键字搜索【后台管理系统纯前端filter过滤】

input输入框——关键字模糊搜索引言铺垫场景复现解决方案筛选的实现重置筛选信息优化处理&#xff08;监听的实现&#xff09;功能实现可能要用到的知识&#xff1a;vue3数据变化侦测&&信息筛选过滤.filter() .map() .forEach(). find()&#x1f525;vue3【watch检测/监…

[附源码]Python计算机毕业设计Django4S店汽车售后服务管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【服务器数据恢复】IBM服务器RAID控制器出错的数据恢复案例

服务器数据恢复环境&#xff1a; 北京某公司IBM X系列某型号服务器&#xff1b; 服务器上共8块硬盘组建raid5磁盘阵列&#xff1b; 服务器上部署有oracle数据库。 服务器故障&分析&#xff1a; 服务器在运行过程中&#xff0c;raid5磁盘阵列中有2块硬盘报警&#xff0c;服务…

CRM(Mapper层)详细代码

Mapper详细代码&#xff1a; DicValueMapper&#xff1a; package com.bjpowernode.crm.settings.mapper;import com.bjpowernode.crm.settings.domain.DicValue;import java.util.List;public interface DicValueMapper {/*** This method was generated by MyBatis Generato…

制作覆盖手绘图的导游地图,非常简单,你也可以

目录 1 前言 2 手绘地图的准备 3 下载软件 4 切图软件基本设置 5 配准设置 6 从平台取得上传切片所需要的3个参数 7 程序切片 8 增加位置点 1 前言 上一篇介绍了制作“简版导游地图”的步骤&#xff0c;真的是特别简单&#xff0c;如果提前准备好了文字材料&#xff0c…

PHP转Go,框架选什么?

文章目录内功心法PHP转Go&#xff0c;优选哪个框架&#xff1f;为什么&#xff1f;为什么不火&#xff1f;GoFrame特点优势&#xff1a;劣势&#xff1a;框架选型谁适合用GoFrame谁不适合用GoFrameGoFrame框架设计思想开发流程从0到1核心步骤总结视频一起学习这是一期会引起广泛…

即时通讯赛道开打信创牌,WorkPlus为何独树一帜?

近期&#xff0c;信创火了。 随着近期国家相关政策文件的推出&#xff0c;未来三年&#xff0c;党政信创、行业信创以及央国企信创的建设&#xff0c;将迎来全面加速。业内人士认为&#xff1a;“大信创”时代或已来临&#xff01; 信创是什么&#xff1f; 信创&#xff0c;…

加载用户数据至用户维度表

目录 1.创建转换 2.配置表输入 3.配置表输入2 4.创建新转换 5.配置映射输入规范 6.配置数据库查询 7.配置数据库查询2 8.配置数据库查询3 9.配置过滤记录 10配置JavaScript代码 11.配置字段选择 12.配置映射输出规范 13.配置映射&#xff08;子转换&#xff09; 1…

JS进阶第一篇:手写call apply bind

文章目录手写call apply bind深入理解 call 方法手写call手写apply手写bind手写call apply bind 深入理解 call 方法 call 理解了&#xff0c;apply和bind就都迎刃而解了&#xff0c;他们都是大同小异。在此对call和apply不做过多的定义性解释&#xff0c;先来看下调用了call…

opencv阈值图像Threshold方法

图像阈值 固定阈值&#xff0c;自适应阈值&#xff0c;Otsu 二值化等 全局阈值和局部阈值 一、图像二值化 定义&#xff1a;图像的二值化&#xff0c;就是将图像上的像素点的灰度值设置为0或255&#xff0c;也就是将整个图像呈现出明显的只有黑和白的视觉效果。 灰度值0&…

热门Java开发工具IDEA入门指南——导出项目到Eclipse

IntelliJ IDEA&#xff0c;是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 上文…

打工人,这里有一份述职技巧,请查收

大家好&#xff0c;马上到年底了&#xff0c;有多少小伙伴正在期待着述职邮件&#xff0c;毕竟收到述职邮件&#xff0c;也就意味着有机会升职加薪。有没有跟糖糖一样&#xff0c;没收到邮件的&#xff1f; 工作要善于总结&#xff0c;也要善于表达&#xff0c;如何在限时内将…

跨平台应用开发进阶(四十)自定义插件及引用

文章目录一、前言二、插件制作三、离线插件集成应用示例四、拓展阅读一、前言 正如将可复用功能封装为自定义组件以供他人使用一样&#xff0c;在uni-app开发框架中提供了另一种形式的自定义插件&#xff0c;并可将该插件提交至uni-app插件市场。 二、插件制作 制作插件前&a…

前端 单元测试介绍 - 以及在项目中使用 (史上最全)

前言 我们前端开发过程中&#xff0c;编写测试代码&#xff0c;有以下这些好处&#xff1a; 更快的发现bug&#xff0c;让绝大多数bug在开发阶段发现解决&#xff0c;提高产品质量 比起写注释&#xff0c;单元测试可能是更好的选择&#xff0c;通过运行测试代码&#xff0c;观…

ARM 异常处理方式简单介绍

一、什么是异常 正常工作之外的流程都叫异常&#xff1b; 也就是说&#xff0c;除了用户模式和系统模式外&#xff0c;其他情况都是异常&#xff0c;见下图&#xff1a; 异常会打断正在执行的工作&#xff0c;并且一般我们希望异常处理完成后继续回来执行原来的工作&#xff…