pygame 飞机大战子弹的编写(六)自动导航系统,子弹的AI实现

目标:子弹自动导航,根据目标的位置,随时调整方向,自动导航

已经能够定向发射了,离自动导航也不远了。

经过前面的积累,计算公式已经完整,只要稍微调整下,就能自动导航了。

原理很好理解,发射时,计算各自坐标,定向发射,过一点时间间隔,再各种计算坐标,再定向发射。直到打中为止。

吃饭了,待续

继续。

附上演示代码。

main.py

import pygame
from bullet import *
from sys import exit
import random
from pygame import Vector2
vect = pygame.math.Vector2
pygame.init()
#定义屏幕类
class MainScene(object):
    #初始化
    def __init__(self):
        self.size = (480,860)
        self.scene = pygame.display.set_mode(self.size)
        pygame.display.set_caption("自学飞机大战--V0.98")
        self.image = pygame.image.load('images/bg.png')
       
        self.bullet_sprite = pygame.sprite.Group()
        bullet_tract = Bullet()
        self.bullet_sprite.add(bullet_tract)
 

    #绘制各个元素
    def drawElements(self):
        self.scene.blit(self.image,(0,0))
        self.bullet_sprite.draw(self.scene)

    #处理键盘和鼠标相应
    #只是编写了子弹模块,那么跟踪弹在这里处理算了,
    def handleEvent(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            if event.type == pygame.MOUSEMOTION:
                 # 获得鼠标点击三个按钮的点击情况(1,0,0)
                # 如果第一个参数为1,表示左键被按下
                # 如果第二个参数为1,表示滚轮被按下
                # 如果第三个参数为1,表示右键被按下
                buttons = pygame.mouse.get_pressed()
                # 我们只处理左键被按下的情况
                if buttons[0]:
                    # 获得拖动鼠标的拖动位置
                    pos_mouse = pygame.mouse.get_pos()
                    pos1 = vect(pos_mouse[0], pos_mouse[1])
                    for bullet in self.bullet_sprite.sprites():
                        pos_bullet = bullet.get_pos()
                        pos2 = vect(pos_bullet[0],pos_bullet[1])
                        pos0 = vect(0,0)
                        pos = pos1 - pos2
                        angle = pos0.angle_to(pos)
                        bullet.set_speed(5,angle)

   #运行主程序
    def runScene(self):
        while True:
            self.drawElements()
            self.handleEvent()
            self.bullet_sprite.update()
            pygame.display.update()
            # pygame.time.delay(100)



if __name__ == '__main__':
    mainScene = MainScene()
    mainScene.runScene()

因为需要知道子弹的位置,在子弹类中添加了get_pos函数。

bullet.py代码

import pygame
import math
import random 

class Bullet(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('images/enemybullet5.png')
        self.rect = self.image.get_rect()
        # self.speed = 2
        self.x_speed = 0.00
        self.y_speed = 2.00
        self.angle = 0

    def update(self):
        self.rect.x += self.x_speed
        self.rect.y += self.y_speed

    def set_pos(self,x, y):
        self.rect.x = x
        self.rect.y = y 

    def get_pos(self):
        return (self.rect.x,self.rect.y)
        
    def set_speed(self,speed, angle = 0):
        # self.speed = speed
        self.angle = math.pi * angle/180
        self.x_speed = speed * math.cos(self.angle)
        self.y_speed = speed * math.sin(self.angle)

到此结束了吗?没,圆形的子弹没问题,不是圆形的,哼哼哼,呵呵呵。

谁解决了不是圆形子弹的旋转问题了吗?麻烦贴个代码看看。

尝试了几天,还是没有结果,图形旋转后,直接给子弹的image赋值,没几下就跑到屏幕外面了。

看来很多pygame.transform.rotate()例子,能实现图像的绕着图像中心点转动角度,但是这些例子都是用Surface.blit()函数来绘制。我用了sprite想直接用图像替换的方式,图像没转几次就跑到天边去了,也变形的厉害。

用了临时变量,也一样的结果,哪怕在bullet的类里,用旋转后的图像替换原图像,也跑的没变。

最终还是妥协了,用了古老的办法,自己编写draw()函数,在函数里blit绘制。在主函数里,用了 列表来记录跟踪导弹的数据,不用sprite了。其他的不需要旋转的类,还是用sprite来管理。

猜你喜欢

转载自blog.csdn.net/hailler1119/article/details/88594578