第4回 UFOが攻撃
 UFOからの攻撃がないとゲームとして簡単すぎて面白くありません。ゼロ戦の武器はかめはめ波ですが、UFOの武器はレーザービームです。 ちょっと陳腐ですが、面白い武器が思いつきませんでした。動画です。


UFOの攻撃は案外面倒になることは予測していたので、グチャグチャなソースにならないように気を付けました。


攻撃するUFOは乱数を使って不定にします。また、赤の四角で囲んだUFOも攻撃できるようにします。また、ゼロ戦にレーザービームが命中するとゲームオーバーになります。



レーザービームの生成

            #レーザービーム
            if int(1000 / FRAMES * timeCnt)  % 200 == 0:
                makeLaserbeam(groupUfo, groupLaserbeam)
200msecごとにmakeLaserbeam()を起動します。

 #UFOのレーザービーム発射
def makeLaserbeam(ufoGrp, laserGrp):
    ufoY = []
    for index, uf in enumerate(ufoGrp):
        ufoY.append([uf.rect.bottom, uf, uf.col])    
    size = len(ufoY)
    if size == 0:
        return False
    ufoY = sorted(ufoY, reverse=True, key=lambda y: y[0]) 
    #レーザービームの発射数
    beams = random.randint(0, 4)
    for i in range(0, beams):
        sel = random.randint(0, size - 1)
        for j in range(0,size):
            if sel != j:
                col1 = ufoY[sel][2]
                col2 = ufoY[j][2]
                if col1 ==  col2:
                    #同じ列にある
                    y1 = ufoY[sel][0]
                    y2 = ufoY[j][0]
                    if y1 < y2:#自分より下にUFOがいる
                        break 
        if j == size - 1:
            #自分より下にUFOがいなかった
            uf = ufoY[sel][1]
            x = uf.rect.left + (uf.rect.right - uf.rect.left) / 2
            y =  uf.rect.bottom
            fireLaserbeam( x, y, uf.image, laserGrp)
    return True
ちょっと長いですね。
sel = random.randint(0, size - 1)
グループに属しているUFOをランダムに選びます。

グループに属しているUFOと選ばれたUFOについて、
選ばれたUFOよりグループに属しているUFOが下にあれば無効です。

自分より下にUFOがいなかったらLaserBeamグループに追加します。

レーザービームの移動とゼロ戦命中の判定

#レーザービームを下に移動する
def moveLaser(grp, x, y, w):
    for laser  in grp:
        if laser.rect.top >= SCREEN.height:
            laser.remove(grp)
            continue
        a = laser.rect.bottom
        if laser.rect.bottom >= y:
            centerX = laser.rect.left + (laser.rect.right - laser.rect.left) / 2
            if centerX > x  and centerX < x + w:
                #レーザービームが命中
                return True
    return False
レーザービームがゼロ戦に命中しないでスクリーンの下を通過するとレーザービームグループから削除します。
レーザービームの下端がゼロ戦の先端以上になったとき、レーザービームのX座標がゼロ戦の範囲内の位置にあれば命中と判定します。

pygame.sprite.Sprite

pygame.sprite.RenderUpdates()
を使うことにより、移動ものゲームを楽に作れます。

ソースのダウンロード
ソースが200行を超えて長いのでダウンロードしてください。
invader_4.py

画像のダウンロード