Pythonistaでゲームを作ろう!iPhoneでできるゲームプログラミング入門


1. 導入:スマホでPythonゲーム開発は可能?

「Pythonでゲームを作りたい。でもパソコンがない…」
そんな風に思ったことはありませんか?

実は、iPhoneやiPadでもPythonでゲームを作る方法があるんです。
その秘密が Pythonista というアプリ。

Pythonistaを使えば、スマホ1台でプログラムを書いて、本格的なミニゲームを開発できます。
この記事では、初心者でもできる「Pythonistaを使ったゲームプログラミング入門」を、サンプルコード付きで解説します。


2. Pythonistaとは?【スマホで使えるPython開発環境】

PythonistaはApp Storeで販売されている有料アプリで、**iOS専用のPython統合開発環境(IDE)**です。

  • Pythonのコードを直接書いて実行できる
  • コード補完機能・専用キーボード付きでスマホ操作でも快適
  • 画像表示やタップ操作ができる scene モジュールを標準搭載

つまり、Pythonistaを入れるだけで 「iPhoneがポケットサイズのPython開発PCになる」 のです。


3. ゲーム作りの基本:scene モジュールを理解しよう

Pythonistaのゲーム開発は、scene モジュールを使います。
これはスマホ向けに作られた簡易ゲームエンジンのようなもの。

基本構造は以下の3つを覚えればOKです。

  • setup() → 初期化処理(キャラ配置など)
  • update() → 毎フレーム処理(動きや当たり判定)
  • touch_xxx() → タップやスワイプの入力処理

サンプルコード:

from scene import *

class MyGame(Scene):
    def setup(self):
        print("ゲーム開始!")

    def update(self):
        pass

    def touch_began(self, touch):
        print("画面タップ!")

run(MyGame(), PORTRAIT)

👉 このコードを動かすと、タップするたびに「画面タップ!」と表示され、ゲームループの仕組みが理解できます。


4. Pythonistaで作る簡単ゲーム【サンプル付き】

4-1. タップで猫を動かすミニゲーム

from scene import *
import sound

class CatGame(Scene):
    def setup(self):
        self.cat = SpriteNode('emj:cat', position=self.size/2, parent=self)

    def touch_began(self, touch):
        sound.play_effect('arcade:Jump_1')
        self.cat.run_action(Action.move_to(touch.location.x, touch.location.y, 0.5))

run(CatGame(), PORTRAIT)

👉 タップした場所に猫がジャンプ!Pythonistaなら数行で作れます。


4-2. ボールをキャッチするゲーム

from scene import *
import random

class CatchBall(Scene):
    def setup(self):
        self.player = SpriteNode('typb:Alien_Monster', position=(self.size.w/2, 50), parent=self)
        self.ball = None
        self.score = 0
        self.label = LabelNode(f"Score: {self.score}", position=(80, self.size.h-40), parent=self)

    def update(self):
        if not self.ball:
            self.spawn_ball()
        else:
            self.ball.position = (self.ball.position.x, self.ball.position.y - 5)
            if self.ball.position.y < 0:
                self.ball.remove_from_parent()
                self.ball = None
            elif self.player.frame.intersects(self.ball.frame):
                self.score += 1
                self.label.text = f"Score: {self.score}"
                self.ball.remove_from_parent()
                self.ball = None

    def spawn_ball(self):
        x = random.randint(20, int(self.size.w-20))
        self.ball = SpriteNode('shp:Circle', position=(x, self.size.h-20), parent=self)

    def touch_moved(self, touch):
        self.player.position = (touch.location.x, self.player.position.y)

run(CatchBall(), PORTRAIT)

👉 「落ちものをキャッチする」仕組みを学べます。


4-3. 簡易シューティングゲーム

from scene import *
import sound
import random

class Shooting(Scene):
    def setup(self):
        self.player = SpriteNode('spc:PlayerShip3Green', position=(self.size.w/2, 50), parent=self)
        self.bullets = []
        self.enemies = []
        self.spawn_enemy()
        self.score = 0
        self.label = LabelNode(f"Score: {self.score}", position=(80, self.size.h-40), parent=self)

    def touch_began(self, touch):
        bullet = SpriteNode('spc:LaserBlue6', position=self.player.position, parent=self)
        self.bullets.append(bullet)
        sound.play_effect('arcade:Laser_1')

    def update(self):
        for bullet in list(self.bullets):
            bullet.position = (bullet.position.x, bullet.position.y + 10)
            if bullet.position.y > self.size.h:
                self.bullets.remove(bullet)
                bullet.remove_from_parent()
            else:
                for enemy in list(self.enemies):
                    if bullet.frame.intersects(enemy.frame):
                        enemy.remove_from_parent()
                        self.enemies.remove(enemy)
                        bullet.remove_from_parent()
                        self.bullets.remove(bullet)
                        sound.play_effect('arcade:Explosion_2')
                        self.score += 1
                        self.label.text = f"Score: {self.score}"

        if not self.enemies:
            self.spawn_enemy()

    def spawn_enemy(self):
        for _ in range(3):
            x = random.randint(50, int(self.size.w-50))
            y = random.randint(int(self.size.h/2), int(self.size.h-50))
            enemy = SpriteNode('spc:EnemyBlue1', position=(x, y), parent=self)
            self.enemies.append(enemy)

    def touch_moved(self, touch):
        self.player.position = (touch.location.x, self.player.position.y)

run(Shooting(), PORTRAIT)

👉 弾・敵・当たり判定を組み合わせて、遊べるシューティングに。


4-4. おまけ:テトリスもどき

from scene import *
import random, ui

GRID_W, GRID_H = 10, 20
CELL_SIZE = 20

class Tetris(Scene):
    def setup(self):
        self.grid = [[0]*GRID_W for _ in range(GRID_H)]
        self.active = [[1,1],[1,1]]
        self.x, self.y = 4, 0
        self.drop_timer = 0
        self.speed = 0.5
    
    def update(self):
        self.drop_timer += self.dt
        if self.drop_timer > self.speed:
            self.drop_timer = 0
            self.y += 1
            if self.collide():
                self.y -= 1
                self.lock_piece()
                self.spawn_piece()
        self.draw_grid()
        self.draw_piece()
    
    def collide(self):
        for r in range(len(self.active)):
            for c in range(len(self.active[0])):
                if self.active[r][c]:
                    gx, gy = self.x+c, self.y+r
                    if gy >= GRID_H or gx < 0 or gx >= GRID_W or self.grid[gy][gx]:
                        return True
        return False
    
    def lock_piece(self):
        for r in range(len(self.active)):
            for c in range(len(self.active[0])):
                if self.active[r][c]:
                    gx, gy = self.x+c, self.y+r
                    if 0 <= gy < GRID_H:
                        self.grid[gy][gx] = 1
        self.grid = [row for row in self.grid if any(cell == 0 for cell in row)]
        while len(self.grid) < GRID_H:
            self.grid.insert(0, [0]*GRID_W)
    
    def spawn_piece(self):
        self.active = [[1,1],[1,1]]
        self.x, self.y = 4, 0
    
    def draw_grid(self):
        self.background_color = 'black'
        for r in range(GRID_H):
            for c in range(GRID_W):
                if self.grid[r][c]:
                    path = ui.Path.rect(c*CELL_SIZE, (GRID_H-r-1)*CELL_SIZE, CELL_SIZE, CELL_SIZE)
                    ui.set_color('blue')
                    path.fill()
    
    def draw_piece(self):
        for r in range(len(self.active)):
            for c in range(len(self.active[0])):
                if self.active[r][c]:
                    path = ui.Path.rect((self.x+c)*CELL_SIZE, (GRID_H-(self.y+r)-1)*CELL_SIZE, CELL_SIZE, CELL_SIZE)
                    ui.set_color('red')
                    path.fill()
    
    def touch_began(self, touch):
        if touch.location.x < self.size.w/2:
            self.x -= 1
            if self.collide(): self.x += 1
        else:
            self.x += 1
            if self.collide(): self.x -= 1

run(Tetris(), PORTRAIT)

👉 「落ちる・積む・揃ったら消える」という基本だけ実装した簡易版テトリスです。


5. Pythonistaでゲームを作るメリット

  • パソコン不要 → スマホ1台で完結
  • 通勤・通学のスキマ時間に練習可能
  • Pythonの基礎を遊びながら学べる
  • ゲーム開発の仕組みを理解できる

6. まとめ

Pythonistaを使えば、iPhoneひとつでPythonゲーム開発が楽しめます。

  • タップで猫を動かす
  • ボールキャッチゲーム
  • シューティングゲーム
  • テトリスもどき

ステップアップ式に学べば、初心者でもゲーム作りの感覚がつかめるはずです。
ぜひ「Pythonista ゲームプログラミング入門」として挑戦してみてください!

コメント

タイトルとURLをコピーしました