![見出し画像](https://assets.st-note.com/production/uploads/images/10353992/rectangle_large_type_2_3326763cad431188534157663175dc9e.png?width=1200)
【python】Pyxelでシューティングゲームを作る
なんとなくpythonを勉強してみたいなー、と思っていた時に、pythonでレトロ風ゲームを作れるpyxelというエンジンに出会いました。やっぱり何かを作って動かしてみることがプログラミングの勉強には大事だと思うので、これを使ってゲームを作ってみたいと思います。
環境としてはAnaconda+python3.7.2を使っています
シューティングゲームを作る
というわけで、シューティングゲームを作ってみます。内容は単純明快、画面の上から降ってくるインベーダーを撃ち落とすのみ。インベーダーの攻撃は体当たりのみ。インベーダーは1種類のみ。「のみ」だらけになってしまいましたが、きっと最初はこんなもんでしょう。ポジティブに行きましょう。可能であればボスも出してみます。
といった感じで作ってみました
つけたしつけたししているうちにごちゃごちゃになってしまいました…。
次のnoteからわかる範囲で(?)注釈をつけていきたいと思います。
from random import randint
import pyxel
WINDOW_H = 120
WINDOW_W = 160
SHIP_H = 16
SHIP_W = 16
class APP:
def __init__(self):
self.IMG_ID0 = 0
self.IMG_ID1 = 1
self.IMG_ID0_X = 60
self.IMG_ID0_Y = 65
self.game_over = False
self.game_end = False
self.boss_flug = False
self.boss_count = 1
self.score = 0
self.shots = []
self.enemys = []
self.boss_hp = 500
self.bombs = []
self.p_ship = Ship()
pyxel.init(WINDOW_W, WINDOW_H, caption="Hello Pyxel")
# ドット絵を読み込む
pyxel.load("/Users/xxxxxxxx/pyxel/image/sample.pyxel")
pyxel.mouse(False)
pyxel.run(self.update, self.draw)
def update(self):
if pyxel.btnp(pyxel.KEY_Q):
pyxel.quit()
#自機の更新
if self.game_over == False:
self.p_ship.update(pyxel.mouse_x, pyxel.mouse_y)
shot_count = len(self.shots)
for j in range (shot_count):
if self.shots[j].pos_y > 10:
self.shots[j].pos_y = self.shots[j].pos_y - 3
else:
del self.shots[j]
break
#当たり判定
#敵と弾
shot_hit = len(self.shots)
for h in range (shot_hit):
enemy_hit = len(self.enemys)
for e in range (enemy_hit):
if ((self.enemys[e].ene_x <= self.shots[h].pos_x
<= self.enemys[e].ene_x + 20)and(self.enemys[e].ene_y
<= self.shots[h].pos_y <= self.enemys[e].ene_y + 20)):
#敵に当たったらその座標に爆発を乗せる
new_bomb = Bomb(self.enemys[e].ene_x,
self.enemys[e].ene_y)
self.bombs.append(new_bomb)
del self.enemys[e]
if self.boss_flug == False:
self.score = self.score + 100
break#敵に当たったらbreak
else:
continue
break#敵に当たったらbreak
#敵と自機
enemy_atk = len(self.enemys)
for e in range (enemy_atk):
if (((self.enemys[e].ene_x >= self.p_ship.ship_x) and
(self.enemys[e].ene_x <= self.p_ship.ship_x + 15) and
(self.enemys[e].ene_y >= self.p_ship.ship_y) and
(self.enemys[e].ene_y <= self.p_ship.ship_y + 15))or
((self.enemys[e].ene_x + 15 >= self.p_ship.ship_x) and
(self.enemys[e].ene_x + 15 <= self.p_ship.ship_x + 15) and
(self.enemys[e].ene_y + 15 >= self.p_ship.ship_y) and
(self.enemys[e].ene_y + 15 <= self.p_ship.ship_y + 15))):
self.game_over = True
new_bomb = Bomb(self.p_ship.ship_x, self.p_ship.ship_y)
self.bombs.append(new_bomb)
#enemy update
if self.game_end == False:
if self.boss_flug == False:
if pyxel.frame_count % 20 == 0:
new_enemy = Enemy()
self.enemys.append(new_enemy)
else:
if pyxel.frame_count % 8 == 0:
new_enemy = Enemy()
self.enemys.append(new_enemy)
enemy_count = len(self.enemys)
for e in range (enemy_count):
enemy_vec1 = randint(0, 7)
enemy_vec2 = enemy_vec1 % 2
if self.enemys[e].ene_y < 115:
if enemy_vec2 > 0:
self.enemys[e].ene_x = self.enemys[e].ene_x + 4
self.enemys[e].ene_y = self.enemys[e].ene_y + 1.5
else:
self.enemys[e].ene_x = self.enemys[e].ene_x - 4
self.enemys[e].ene_y = self.enemys[e].ene_y + 1.5
else:
del self.enemys[e]
break
#画面の爆発が3以上になったら古いものから消していく
if len(self.bombs) > 3:
del self.bombs[0]
#ボス出現フラグ
if self.boss_flug == False: #ボス未出現の状態で
if self.score != 0: #ゲーム開始直後ではなく
if self.score % 2000 == 0: #スコアxxxx点に達したら
if self.game_end == False: #ゲームクリアフラグがない場合にボス発生
self.boss_flug = True
self.boss_hp = 200 * self.boss_count
#ボスの当たり判定
if self.boss_flug == True:
shot_hit = len(self.shots)
for h in range (shot_hit):
if ((70 <= self.shots[h].pos_x <= 85)and
(10 <= self.shots[h].pos_y <= 20)):
self.boss_hp = self.boss_hp - 1
new_bomb = Bomb(self.shots[h].pos_x, self.shots[h].pos_y)
self.bombs.append(new_bomb)
#ボス消滅
if self.boss_hp <= 0:
if self.boss_flug == True:
self.score = self.score + 5000
pyxel.cls(0)
self.boss_flug = False
#self.game_end = True
self.boss_count = self.boss_count + 1
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.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)
#敵の描画
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
APP()
このpyxelというゲームエンジン、使い方もわかりやすいし、ドット絵やサウンドのエディターもついてくるしで、いい感じです。エディター機能についてはまた時間があるときにまとめたいと思います。
ここまで読んでいただきありがとうございます!