インベーダー2

【python】Pyxelでシューティングゲームを作る(続々)

前回の続きです。draw関数から書いていきます。

   def draw(self):
       pyxel.cls(0)
       
       #ゲームオーバー
       if self.game_over:
           pyxel.text(60, 40, "Game Over!", pyxel.frame_count % 16)
       
       #ゲームクリア
       if self.game_end:
           pyxel.text(60, 40, "Completed!", pyxel.frame_count % 16)
       
       #得点描写
       pyxel.text(1, 2, "score:" + str(self.score), pyxel.frame_count % 16)
       pyxel.text(120, 2, "boss:" + str(self.boss_hp), pyxel.frame_count % 16)

画面描写の部分に入っていきます。ゲームオーバー・ゲームクリア・得点とボスの体力のテキストをpyxel.textを使って表示させます。

       #宇宙船の描画
       pyxel.blt(self.p_ship.ship_x, self.p_ship.ship_y, 0, 0, 0, 
                 -SHIP_W, SHIP_H, 15)
       #SPACEが押された際に発射する
       if self.game_over == False:
           if pyxel.btn(pyxel.KEY_SPACE):
               if len(self.shots) < 11:
           #make shot instance
                   new_shot = Shot()
                   new_shot.update(self.p_ship.ship_x, self.p_ship.ship_y, 8)
                   self.shots.append(new_shot)
       
       #弾の描画
       for i in self.shots:
           pyxel.rect(i.pos_x+7, i.pos_y-3,
                      i.pos_x+7, i.pos_y+0.5, 8)

自機と弾を描画します。今回はSPACEキーで弾を発射し連射ができるようにしています。ただ、無限に弾が出てしまうのもゲームが簡単になりすぎるので、画面上に存在できるのは10発までとしています。ここはキーが戻ったかを判定することで、連射できなくすることができそうです。自機はbltでドット絵を描画し、弾はrectで長方形を表示しています。まだよく分かっていないんですけど、自機弾のオブジェクトを作成する部分はupdate関数に入れたほうがいいのかも…? 動き的には問題なさそうですが。

        #敵の描画
       for i in self.enemys:
           if self.boss_flug == False:
               enemy_flug = randint(0, 7)
               if enemy_flug % 2 == 0:
                   pyxel.blt(i.ene_x, i.ene_y, 1, 0, 0, 
                             -SHIP_W, SHIP_H, 15)
               else:
                   pyxel.blt(i.ene_x, i.ene_y, 1, 16, 0, 
                             -SHIP_W, SHIP_H, 15)
           else:
               enemy_flug = randint(0, 7)
               if enemy_flug % 2 == 0:
                   pyxel.blt(i.ene_x, i.ene_y, 1, 0, 32, 
                             -SHIP_W, SHIP_H, 15)
               else:
                   pyxel.blt(i.ene_x, i.ene_y, 1, 16, 32, 
                             -SHIP_W, SHIP_H, 15)

敵の描画です。ランダム関数を使うことで、敵が動く様子を表現してみたかったのですが、変化が速すぎてよくわかりませんでした…。理想としてはスペースインベーダーみたいに足(触覚?)をぴょこぴょこさせたかったのですが…。

        #ボスの描画            
       if self.boss_flug == True:
           pyxel.blt(50, 10, 1, 0, 16, 63, 16, 15)
           pyxel.blt(95, 25, 1, 32, 32, -SHIP_W, SHIP_H, 15)
           pyxel.blt(85, 25, 1, 32, 32, SHIP_W, SHIP_H, 15)
           pyxel.blt(72, 25, 1, 32, 32, SHIP_W, SHIP_H, 15)
           pyxel.blt(64, 25, 1, 32, 32, -SHIP_W, SHIP_H, 15)
           pyxel.blt(51, 25, 1, 32, 32, SHIP_W, SHIP_H, 15)
           
       #爆発の描写
       for i in self.bombs:
           pyxel.blt(i.bomb_x, i.bomb_y, 2, 0, 0, 
                     -SHIP_W, SHIP_H, 15)       

ボスの描画は座標を決め打ちでドット絵を乗せただけ。爆発も座標に爆発画像を乗せただけです。

#オブジェクトのクラス
         
class Ship:   
   def __init__(self):
       self.ship_x = 0
       self.ship_y = 0
   
   def update(self, x, y):
       self.ship_x = x
       self.ship_y = y

class Shot:
   def __init__(self):
       self.pos_x = 0
       self.pos_y = 0
       self.color = 8 # 0~15
   def update(self, x, y, color):
       self.pos_x = x
       self.pos_y = y
       self.color = color
       
class Enemy:
   def __init__(self):
       self.ene_x = randint(30, 125)
       self.ene_y = 5
   
   def update(self, x, y):
       self.ene_x = x
       self.ene_y = y

class Bomb:
   def __init__(self, x, y):
       self.bomb_x = x
       self.bomb_y = y       

オブジェクトのクラスになります。__init__が作成時の初期化、updateはそのまま更新ですね。各オブジェクトの座標を更新しています。

APP()

ゲームの起動部分です。

これで全部になります。一応は形になった気がします。今回はシンプルなシューティングゲームを作ってみました。今後はpythonを勉強しながらいろいろなジャンルのゲームを作っていきたいと思います。

ここまで読んでいただきありがとうございます!