天天看點

pygame 飛機大戰子彈的編寫(四)向着夕陽奔跑吧,子彈的AI實作

目标:實作子彈向目标發射

子彈的發射是為了射中目标,傻乎乎的直上直下,還以為是在滾鍵盤呢。

向目标發射,實作的原理很簡單,得到敵機的坐标pos1,得到子彈的坐标pos2,讓pos2朝着po1飛行。

坐标可以直接讀取 目标的rect.x rect.y來計算擷取。飛行的方向,稍微複雜一點,用到高中的一些知識,已知兩個坐标的坐标點,求他們的角度。有了角度,設定速度和起始點,就能朝着目标發射了。

假如 pos1 = (pos1_x, pos1_y) ,pos2 = (pos2_x,pox2_y),子彈pos1朝着 pos2的方向的角度,計算公式如下:

atan((pos2_y - pos1_y) / (pos2_x-pos1)) 得到兩者的斜率,用atan得到角度,這個角度的機關是弧度。

測試代碼如下:

import math
pos1_x ,pos1_y = 1, 1
pos2_x, pos2_y = 2, 2
angle = math.atan((pos2_y - pos1_y) / (pos2_x - pos1_x))
print(angle)
           

輸出的結果是0.785398163397448 。他們的角度是45度,孤弧度是pi/4=0.785398163397448。沒錯了。

但是當兩個坐标點的X坐标可能相等,這樣無法用在分母上。做個判斷在計算??

pos1_x ,pos1_y = 1, 11
pos2_x, pos2_y = 1, 2
if pos2_x == pos1_x:
    if pos1_y <= pos2_y:
        angle = math.pi / 2
    else:
        angle = - math.pi / 2
else:
    angle = math.atan((pos2_y - pos1_y) / (pos2_x - pos1_x))
print(angle)
           

能得到結果了,符合要求。

算法沒問題了,回到遊戲裡來測試。因為目前沒有飛機在螢幕,就測試下飛到螢幕正中下方把。為了測試簡單,直接定義為點(240,860),由于數學的直角坐标系和遊戲的坐标系,Y方向是反的,可以換算。這裡直接用了fabs函數,未考慮轉換。

#子彈3,随機水準線出來,夕陽方向(240,680)
        bullet3 = Bullet()
        
        pos1_x ,pos1_y = random.randint(0,400), 200
        bullet3.set_pos(pos1_x,pos1_y)
        pos2_x, pos2_y = 240, 680
        if pos2_x == pos1_x:
            if pos1_y <= pos2_y:
                bullet3_angle = math.pi / 2
            else:
                bullet3_angle =  -math.pi / 2
        else:
            bullet3_angle = math.atan(fabs((pos2_y - pos1_y) / (pos2_x - pos1_x)))
        print(bullet3_angle)
        #傳回的是弧度,要進行角度轉換
        bullet3_angle  = bullet3_angle *180 / math.pi
        bullet3.set_speed(20,bullet3_angle)
        # print(angle)

        self.bullet_sprite.add(bullet3)
           

奇怪的現象發生了,大部分子彈能朝着目标發射(請忽略子彈的圖像大小引起的偏差),小部分亂飛了。

要對  方向的象限做判斷:angle為弧度

第一象限: angle = angle

第二象限:angle = pi - angle

第三象限:angle = pi + angle

第四象限: angle = 2*pi - angle

測試了一下,子彈朝着夕陽奔跑了。

裡面還是存在錯誤,圖像的每次運動方向上的距離是個int ,計算出來的是float,取整數後有偏差。

繼續閱讀