北尾崇氏の講演中に完成!Pyxelで30分シューティングゲーム開発チャレンジ(pythonコード付き)

北尾崇氏の講演中に完成!Pyxelで30分シューティングゲーム開発チャレンジ(pythonコード付き)

先日、AICUで開催された「AICU Creators Talk 5 Pythonをゲーム開発で楽しく学ぶ 書籍出版記念ワークショップ」に参加してきました。このイベントでは、Pyxelの開発者である北尾崇さん(@kitao)が「ゲーム開発少年からの30年を30分で!」というタイトルで講演されていました。

https://note.com/aicu/n/ne9cdfd210a33

実は私、その講演を聴きながら「じゃあ私も30分でゲーム作れるんじゃね?」と思い立ち、その場でシューティングゲームを開発してみることにしました。今回はその開発過程と成果を紹介します!

Pyxelとは?

Pyxelは北尾さんが開発したPython向けのレトロゲームエンジンです。16色のカラーパレットや同時再生音数の制限など、あえてレトロな制約を設けることで、初心者でも取り組みやすく、また創造性を引き出すことを目的としています。

https://github.com/kitao/pyxel/blob/main/docs/README.ja.md

Pyxelは、開発者の北尾氏により、Pyxelを使ったゲーム開発方法をまとめた書籍として販売されています。

https://amzn.to/4i6AJQA

私自身、Pythonは使ったことがあるものの、Pyxelは今回が初めての挑戦。「30分でゲームが作れるのか?」という疑問を抱きながらも、思い切って挑戦することにしました。

開発環境の準備

今回は以下のような環境で開発を行いました:

  • エディタ:Windsurf

  • 開発支援:Claude 3.5 Sonnet(AI)

  • 参考資料:PyxelのREADMEとサンプルコード

プロジェクトのファイル構成はこんな感じです。

pyxel-test/  
├── docs/ - プロジェクトのドキュメントが含まれるディレクトリ
│ ├── pyxel-manual.md - Pyxel のREADMEとサンプルコードをまとめたファイル
│ ├── ゲーム仕様書.md - ゲームの仕様書(日本語)
├── assets.pyxres - Pyxelのリソースファイル(画像、タイルマップ、サウンドなど)
├── main.py - プロジェクトのメインのPythonスクリプトファイル
└── README.md - プロジェクトの概要や使用方法を記載したドキュメント
 

Pyxel Editorでリソース作成

画像

ゲーム開発の最初のステップとして、Pyxel Editorを使ってゲームで使用する画像リソースを作成しました。コマンドラインで以下のコマンドを実行すると、Pyxel Editorが起動します。

pyxel edit assets.pyxres
 

Pyxel Editorには以下の4つの編集モードがあります。

  1. Image Editor: 各イメージバンクの画像を編集するモード

  2. Tilemap Editor: イメージバンクの画像をタイルパターンで配置するモード

  3. Sound Editor: メロディやサウンドエフェクトに使用するサウンドを編集するモード

  4. Music Editor: サウンドを再生順に配置した音楽を編集するモード

今回は主にImage Editorを使用して、プレイヤー、敵、ボス、弾などのスプライトを作成しました。ドット絵を描くのは初めてでしたが、Pyxel Editorのシンプルなインターフェースのおかげで直感的に操作できました。

作成したスプライトは以下の通りです。

  • プレイヤーの宇宙船 (8x8ピクセル)

画像
  • 敵の小型機 (8x8ピクセル)

画像
  • 中ボス (16x16ピクセル)

画像
  • ラスボス (16x16ピクセル)

画像
  • 弾 (8x2ピクセル)

画像

リソースファイルが完成したら、「pyxel.load("assets.pyxres")」でゲーム内に読み込むことができます。

AIの力を借りた開発プロセス

実は今回、開発をスピードアップするためにClaude 3.5 Sonnetの力を借りました。具体的には、PyxelのREADMEとサンプルコードをAIに読み込ませ、シューティングゲームの基本構造を提案してもらいました。

AIとの対話例

私:「Pyxelを使って簡単なシューティングゲームを作りたいです。プレイヤーが移動して弾を撃ち、敵を倒すゲームの基本構造を教えてください。」

Claude:「Pyxelでシューティングゲームを作るなら、まずはゲームのメインループを作成し、そこにプレイヤーの移動、弾の発射、敵の生成と移動、当たり判定などの機能を実装していきます。以下に基本構造を示します...」

こうしたやり取りを通じて、徐々にゲームの骨格を作り上げていきました。最終的に出力されたゲームの仕様は以下の通りです。

# シューティングゲーム仕様書

## 1. ゲーム概要
横スクロールシューティングゲームで、プレイヤーは宇宙船を操作して敵を倒しながら、中ボスとラスボスに挑戦します。

### 1.1 ゲームの目的
- 敵を倒してスコアを獲得
- 中ボス(スコア10)とラスボス(スコア30)を倒す
- ラスボスを倒すとゲームクリア

## 2. ゲームシステム

### 2.1 基本操作
- 矢印キー: 上下左右移動
- スペースキー: 弾を発射

### 2.2 プレイヤーキャラクター
- スプライト: assets.pyxres (0, 0)から8x8の領域
- 3機のライフ
- 敵や弾に当たるとライフが減少
- 被弾後は一時的な無敵時間あり(点滅で表示)

### 2.3 弾システム
- スプライト: assets.pyxres (8, 0)から8x2の領域
- スペースキー長押しで連射可能(10フレームごとに発射)
- 直線的に右方向へ移動
- 画面外に出ると消滅

### 2.4 通常の敵
- スプライト: assets.pyxres (16, 0)から8x8の領域
- 画面右から左へ移動
- ランダムな速度(1.0-2.0の範囲)
- 30フレームごとにランダムな高さから出現
- 弾に当たると消滅し、スコア+1

## 3. ボスキャラクター

### 3.1 中ボス(スコア10で出現)
- スプライト: assets.pyxres (40, 0)から16x16の領域
- HP: 20
- 倒すとスコア+10
- 移動パターン:
- 画面右側で上下に揺れる
- 左右にも小さく移動
- 攻撃パターン:
- 3方向に弾を発射
- 30フレームごとに攻撃

### 3.2 ラスボス(スコア30で出現)
- スプライト: assets.pyxres (24, 0)から16x16の領域
- HP: 40
- 倒すとスコア+20とゲームクリア
- 4つのフェーズを180フレームごとに切り替え
- 移動パターン:
1. 8の字移動(振幅20px
2. ジグザグ移動(振幅15px
3. 円運動(半径15px
4. 急速な直線移動(振幅10px
- 攻撃パターン:
1. 扇状の弾幕(8方向)
2. プレイヤー追尾弾(3方向)
3. 螺旋状の弾幕(4方向)
4. 全方向ランダム弾(6発)

## 4. ゲームの状態

### 4.1 ゲームオーバー条件
- プレイヤーのライフが0になる
-GAME OVER」表示
- Rキーでリスタート可能

### 4.2 ゲームクリア条件
- ラスボスを倒す
-GAME CLEAR!」表示
- Rキーでリスタート可能

### 4.3 画面表示
- ゲーム画面サイズ: 160x120ピクセル
- スコア表示: 左上
- 残機表示: スコアの下

## 5. エフェクト

### 5.1 爆発エフェクト
- キャラクターが破壊されると発生
- パーティクルが四方八方に飛び散る
- パーティクルの色: 8-10番の色を使用
- パーティクルの寿命: 30フレーム

### 5.2 その他のエフェクト
- 無敵時間中のプレイヤー点滅
- ボスのHPバー表示
- ボスの弾は通常の弾より大きく表示

## 6. 技術仕様
- 開発言語: Python
- 使用ライブラリ: Pyxel
- アセット管理: assets.pyxres
- フレームレート: 30FPSPyxelのデフォルト)
 

ゲームの実装

シューティングゲームの基本的な要素は以下の通りです:

  1. プレイヤーの移動と弾の発射

  2. 敵の生成と移動

  3. 当たり判定の実装

  4. ボス戦の実装

  5. ゲームオーバー/クリア条件の設定

プレイヤーの実装

プレイヤーは矢印キーで上下左右に移動でき、スペースキーで弾を発射します。連射も可能で、ホールド中は一定間隔で弾が出ます。

# プレイヤーの移動
if pyxel.btn(pyxel.KEY_UP):
self.player_y = max(self.player_y - self.player_speed, 0)
if pyxel.btn(pyxel.KEY_DOWN):
self.player_y = min(self.player_y + self.player_speed, pyxel.height - 8)
if pyxel.btn(pyxel.KEY_LEFT):
self.player_x = max(self.player_x - self.player_speed, 0)
if pyxel.btn(pyxel.KEY_RIGHT):
self.player_x = min(self.player_x + self.player_speed, pyxel.width - 8)

# 弾の発射(連射対応)
if pyxel.btn(pyxel.KEY_SPACE):
self.shoot_timer += 1
if self.shoot_timer == 1 or self.shoot_timer % 5 == 0: # 初回か5フレームごとに発射
self.bullets.append({
"x": self.player_x + 8,
"y": self.player_y + 3,
"speed": 4
})
else:
self.shoot_timer = 0 # スペースキーを離したらタイマーをリセット
 

敵の実装

敵は画面右から一定間隔で出現し、左に向かって移動します。ボスは特定のスコアに達すると出現します。

# 敵の生成
self.enemy_timer += 1
if self.enemy_timer >= 30 and not self.boss:
self.enemies.append({
"x": pyxel.width,
"y": pyxel.rndi(0, pyxel.height - 8),
"speed": pyxel.rndf(1, 2)
})
self.enemy_timer = 0
 

ボス戦の実装

ゲームには中ボスとラスボスの2種類のボスが登場します。それぞれ異なる移動パターンと攻撃パターンを持っています。

def spawn_boss(self, boss_type):
if boss_type == "mid":
self.boss = {
"type": "mid",
"x": pyxel.width - 40,
"y": pyxel.height // 2 - 8,
"width": 16,
"height": 16,
"hp": 20,
"score": 10,
# 他のパラメータ...
}
else: # final boss
self.boss = {
"type": "final",
"x": pyxel.width - 48,
"y": pyxel.height // 2 - 8,
"width": 16,
"height": 16,
"hp": 40,
"score": 20,
# 他のパラメータ...
}
 

開発中に直面した課題

当たり判定の実装

当たり判定は単純な矩形同士の衝突検出で実装しましたが、プレイヤーが死亡した後の処理や無敵時間の実装に少し手間取りました。

# プレイヤーと敵の当たり判定
for enemy in self.enemies[:]:
if (self.player_x < enemy["x"] + 8 and
self.player_x + 8 > enemy["x"] and
self.player_y < enemy["y"] + 8 and
self.player_y + 8 > enemy["y"]):
self.create_explosion(self.player_x + 4, self.player_y + 4)
self.is_alive = False
self.explosion_timer = 30
self.lives -= 1
if self.lives <= 0:
self.game_over = True
break
 

ボスの攻撃パターン設計

特にラスボスの複雑な攻撃パターンの実装には時間がかかりました。4つのフェーズを作り、それぞれ異なる弾幕パターンを実装しています。

# ラスボスの攻撃(フェーズに応じて変化)
if boss["attack_phase"] == 0:
# 扇状の弾幕
for i in range(8):
angle = i * 0.785 + pyxel.sin(boss["move_timer"] * 0.1)
self.boss_bullets.append({
"x": boss["x"] + boss["width"]/2,
"y": boss["y"] + boss["height"]/2,
"dx": -4 * pyxel.cos(angle),
"dy": 4 * pyxel.sin(angle)
})
 

完成したゲームの特徴

完成したゲームは以下になります。プレイ映像の一部になりますが、ボス戦までの様子をご覧いただけます(動画は4倍速になります)。

画像

細かく画面を確認していきます。左に自機がおり、右から左に向かって敵キャラが向かってきます。左上にはスコアと自機数が表示され、3回やられるとゲームオーバーです。敵キャラを倒すと、火花が散るようにしています。

画像

以下は中ボスとの戦闘シーンです。ボスキャラの上部には緑色の体力バーが表示されており、これを0にすると撃破です。

画像

以下は大ボスです。大ボスを撃破するとゲームクリアです。

画像

大ボスを撃破し、無事ゲームクリアになります。

画像

30分という短時間で開発したにも関わらず、以下のような機能を実装することができました。

  1. プレイヤーの移動と連射機能

  2. 敵の自動生成と移動

  3. 2種類のボスバトル(中ボスとラスボス)

  4. 複数の攻撃パターンと移動パターン

  5. 爆発エフェクト

  6. スコア表示とライフシステム

  7. ゲームオーバー/クリア画面

最終的なコードは以下になります。

★本稿はアイキューマガジンVol.10に収録予定です、お楽しみに!

https://j.aicu.ai/kindle

この記事の続きはこちらから https://note.com/aicu/n/n4ed8d9da3f80

Originally published at https://note.com on Mar 5, 2025.

 

AICU Japan

AICU Inc. AIDX Lab - Koto

Comments

Related posts

Search Stability AIとArmが提携: スマホでオンデバイス生成AIオーディオを実現!