pygame里实现导弹追踪效果,同时对python的指针机制有一点点思考

       最近,儿子一直缠着让我把之前给他编写的游戏重做一下,要加一些功能.但是因为之前写代码的时候刚学会python,当时的想法就是能跑就行,现在回头看来,代码的可维护性几乎为零.所以没办法只能冲头再来,重构了几乎所有代码.在编写的时候遇到了一个有意思的问题,儿子让我给游戏添加一种带追踪能力的导弹.导弹不仅要能追踪目标不断修正轨迹向着目标前进,同时导弹的弹头要一直朝向目标,我一听,这不就是弹道导弹嘛,有意思,整!

        当时我想,这还不简单,在追踪的时候顺手把本体和目标之间连线的斜率计算出来不久完了吗?于是说干就干,但是当我到了真正编写的时候还是发现了一些问题.今天就来和大家分享一下.

        首先呢,路径追踪很简单,我之前写过一篇相关的文章可以参考这个http://t.csdnimg.cn/soVGy,所以路径这里咱们就跳过.

        这篇文章主要就聊聊如何实现导弹通过旋转始终指向目标.

先来看一张示意图

如图,当A点向B移动时是沿着AB移动,所以只要计算出AB的斜率时就会得到第一个旋转角度,当A移动到A`点时追踪目标变为了C,这时算出A`C的斜率就能得到第二个旋转角度,如此循环往复,无论被追踪的目标如何变化,我们只要算出当前目标和本身的斜率就能得出要旋转的角度了.明白了实现旋转的方法以后,我们就开始写代码.这里多说一句,其实一开始我在这里思考了很长时间,主要的问题是我的一个闪念,既然正切函数能够得到斜率,那么正弦余弦甚至正割余割,也应该能到倾斜角度(其实是废话,利用推导公式本来就可以推导出的,但我也不知道为什么非要跟自己较劲,花了一整天时间去复习初中数学),但是,正弦余弦有一个问题,就是要判断象限.我甚至写了一大段"if"函数去判断象限.知道我发现math模块里的atan2()这个方法,我才明白,我之前想多了.这个方法不用考虑象限,只需要输入对边临边的值就会自动判断象限,从而得出当前的弧度.

代码如下:

import mathimport pygame,sys
from math import *
pygame.init()
screen=pygame.display.set_mode((800,700),0,32)
pygame.display.set_caption("弹道导弹")
clock = pygame.time.Clock()class Sprite1(pygame.sprite.Sprite):def __init__(self):super().__init__()self.image = pygame.image.load('2.png')self.rect = self.image.get_rect()def update(self, *args, **kwargs):self.rect.center = pygame.mouse.get_pos()class Sprite2(pygame.sprite.Sprite):def __init__(self):super().__init__()self.mumimage = pygame.image.load('1.png')self.image = self.mumimage# print(id(self.mumimage), id(self.image))self.rect = self.image.get_rect()self.speed = 3def update(self, target):deltax = target.rect.centerx - self.rect.midtop[0]deltay = target.rect.centery - self.rect.midtop[1]distance = math.sqrt(deltax ** 2 + deltay ** 2)if distance != 0:angle = math.degrees(math.atan2(-deltay, deltax))self.image = pygame.transform.rotate(self.mumimage, angle - 90)# print(id(self.mumimage), id(self.image))stepx = self.speed * deltax / distancestepy = self.speed * deltay / distanceself.rect.centerx += stepxself.rect.centery += stepysprite1 = Sprite1()
sprite2 = Sprite2()
sprites = pygame.sprite.Group()
sprites.add(sprite1,sprite2)
while True:for event in pygame.event.get():if event.type==pygame.QUIT:sys.exit()screen.fill((0,0,0))sprites.update(sprite1)sprites.draw(screen)pygame.draw.rect(screen, (0,255,0), sprite2.rect, 2)pygame.display.update()clock.tick(60)

运行效果如下

其实写到这里,我要的目的目的其实已经达到了.但是,在写代码的时候我发现一个问题.

可以看到,我在编写sprite2的时候,定义了一个self.mumimage对象,然后又创建了一个self.image对象指向self.mumimage.这样做,主要是因为python的变量赋值其实是将变量指向了对象的内存地址,也就是说python里的变量都是指针变量.

pygame.transform.rotate()这个方法会生成一个新的对象,同时在内存中开辟一个新的地址.

如果我们直接使用self.image = pygame.transform.rotate(self.mumimage, angle - 90),那么就会产生递归,self.image 会不停的迭代self.image会不停的指向新地址而pygame.transform.rotate()方法会使用self.image迭代的新对象.这就产生了无限递归,直至内存泄漏,程序崩溃.下面举个例子.当我们删掉self.mumimage这个变量,直接定义self.image = pygame.image.load('1.png'),那么运行会得到以下结果.

所以,在这里我们必须要先声明一个变量self.mumimage,然后用self.image捕获self.mumimage迭代后的对象.这样才能保证pygame.transformer.rotate()这个方法一直作用与self.mumimage而不会产生无限的递归导致程序崩溃.

最后是文章中用到的素材

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【.NET Core】 多线程之(Thread)详解

【.NET Core】 多线程之(Thread)详解 文章目录 【.NET Core】 多线程之(Thread)详解一、概述二、线程的创建和使用2.1 ThreadStart用于无返回值,无参数的方法2.2 ParameterizedThreadStart:用于带参数的方法 三、线程的…

美摄视频SDK的HDR格式编辑方案

在当今的视觉媒体时代,高动态范围(HDR)技术已成为高质量视频内容的标配。为了满足企业对高效、高质量视频处理的需求,美摄科技推出了业界领先的视频SDK,全面支持多种HDR标准的图像视频进行处理。 一、核心优势 HDR全…

设计一个网页爬虫

定义 User Case 和 约束 注意:没有一个面试官会阐述清楚问题,我们需要定义Use case和约束 Use cases 我们的作用域只是处理以下Use Case: Service 爬取一批 url 生成包含搜索词的单词到页面的反向索引给页面生成标题和片段– 标题和片段是…

Docker 安装 MongoDb4

Docker 安装mongoDb 获取mongodb安装参考 获取mongodb 注意: WARNING: MongoDB 5.0 requires a CPU with AVX support, and your current system does not appear to have that! **hub官网(需要梯子):**https://hub.docker.com/_…

sc.pl.umap 画feature plot

今天有时间尝试测试了这个scanpy的feature plot,其实很简单,就是使用 sc.pl.umap(adata,color"gene name"), 但是这个地方就有一个问题,这个画出来的值是原始的基因值还是scale之后的,这个我得搞清楚 首先看使用例子,参…

【高并发内存池】定长内存池实现

目录 一、项目介绍 二、内存池介绍 2.1、池化技术 2.2、内存池 2.3、内存池主要解决的问题 三、malloc了解 四、设计定长内存池 五、和new(实际malloc)对比性能测试 一、项目介绍 当前项目实现的高并发内存池原型是goole的开源项目tcmalloc,tcmalloc全称为T…

Docker-02-镜像项目部署

Docker-02-镜像&项目部署 文章目录 Docker-02-镜像&项目部署一、镜像①:镜像结构②:Dockerfile③:构建镜像01:构建02:查看镜像列表03:运行镜像 二、网络①:容器的网络IP地址②&#xff…

SQL性能分析

SQL性能分析 1、SQL执行频率 ​ MySQL 客户端连接成功后,通过 show [session|global] status 命令可以提供服务器状态信 息。通过如下指令,可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次: -- session 是查看当前会话 ; …

oracle11g的闪回技术-闪回表-时间戳

--数据库闪回表 --1创建表(登录模式system) CREATE table dept2 as select * from dept;--此语句如果加上where条件可用于工作中数据的临时备份 select * from dept2;--查询新建表信息 --进入sql>set time on 通过时间点闪回 记录弹出的时间点&#…

flutter 五点一:MaterialApp Theme

ThemeData factory ThemeData({bool? applyElevationOverlayColor, //material2的darkTheme下 增加一个半透明遮罩 来凸显阴影效果 material3下无效 貌似没啥用NoDefaultCupertinoThemeData? cupertinoOverrideTheme, //ios组件样式 Iterable<ThemeExtension<dyn…

zabbix客户端配置及自定义监控

部署zabbix客户机 1.服务端和客户端都配置时间同步 yum install -y ntpdate ntpdate -u ntp.aliyun.com 2.服务端和客户端都设置 hosts 解析 cat > /etc/hosts << EOF 172.16.23.16 localhost 172.16.23.17 zbx-server EOF 3.被监控端 //设置 zabbix 的下载源&…

MySQL深度分页优化问题

☆* o(≧▽≦)o *☆嗨~我是小奥&#x1f379; &#x1f4c4;&#x1f4c4;&#x1f4c4;个人博客&#xff1a;小奥的博客 &#x1f4c4;&#x1f4c4;&#x1f4c4;CSDN&#xff1a;个人CSDN &#x1f4d9;&#x1f4d9;&#x1f4d9;Github&#xff1a;传送门 &#x1f4c5;&a…