コンテンツにスキップ

2 ボールゲーム

ボールをパドルで跳ね返すゲームを作成します。 ball,pyに作成します。

2.1 パドル

800×600の黒い背景を作成します。

import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "100,100"
import pgzrun
from pgzero.builtins import *

WIDTH = 800
HEIGHT = 600

def draw():
    screen.clear()

pgzrun.go()

まず、パドルを作成します。

paddle = Actor('paddle', pos=(400,500))

そしてdraw関数でpaddleのdrawを呼ぶようにします。

def draw():
    screen.clear()
    paddle.draw()

2.2 マウスで移動

マウスによりパドルが移動するようにします。 on_mouse_move関数でマウスのx座標をそのままpaddleのx座標に入れます。 これによりマウスを動かすとその位置に連動してパドルが移動します。

def on_mouse_move(pos):
    paddle.x = pos[0]

Xとleftについて

Actorのleftは画像左端の位置、xは画像中央のx座標を表します。 同様にtopが画像上端、yは画像中央のy座標です。

2.3 ボールの描画

次にボールを作成します。

ball = Actor('ball', pos=(50,50))

ballに移動方向を表すvx、vy属性を作り、初期値として5を入れておきます。

ball.vx = 5
ball.vy = 5

draw関数でBallを描画します。

def draw():
    screen.clear()
    paddle.draw()
    ball.draw()

2.4 ボールの移動

ボールの移動はupdate関数を定義し、その中でvx、vy分だけ移動させます。

def update():
    # ボール移動
    ball.x += ball.vx
    ball.y += ball.vy

パドルに当たったときには、縦方向を逆に移動するようにします。update関数内に以下を追加します。

# パドルに当たったとき
if(paddle.colliderect(ball)):
    ball.vy *= -1

壁に当たったときのバウンドを行います。 左右の壁に当たったときには 横方向の移動方向を変えます。

# 左右の壁に当たったとき
if (ball.right > WIDTH) or (ball.left < 0):
    ball.vx *= -1

上の壁に当たったときには縦方向の移動を変えます。

# 上の壁に当たったとき
if ball.top < 0:
    ball.vy *= -1

2.5 ゲームオーバー

ゲーム終了の判定を行います。まずゲームオーバーなどゲームの情報を管理するクラスGameを作成します。このクラスは、属性にゲームオーバーしたかどうかのフラグ game_overと得点 scoreを入れることにします。

このようなデータを管理するクラスを作成する場合、pythonではdataclassを使うことが出来ます。まず、ファイル先頭でdataclassをインポートします。

from dataclasses import dataclass

次に、クラスを作成します。属性とデータ型を作成します。

@dataclass
class Game:
    game_over :bool
    score :int

そしてこのクラスのインスタンスを作成しておきます。game_overはFalse、scoreは0に初期化します。

game = Game(False, 0)

メインではupdate関数内でボールの位置がパドルを超えた場合、ゲームオーバーとします。

# ゲームオーバー判定
if ball.bottom > paddle.bottom:
    game.game_over = True

ゲームオーバー時にはゲームオーバーの表示を行います。

def draw():
    screen.clear()
    paddle.draw()
    ball.draw()

    if game.game_over:
        screen.draw.text("GAME OVER", (650, 10), fontsize=30, color='white')

update関数で更新を行わないようにします。

def update():
    if game.game_over:
           return

2.6 再実行

ゲームオーバーした後、マウスをクリックしたら再度実行するようにします。

def on_mouse_down(pos):
    if game.game_over:
        ball.x = 50
        ball.y = 50
        ball.vx = 5
        ball.vy = 5
        game.game_over = False

2.7 得点

ゲームの得点を記録するために、Gameクラスにscore属性がありますので、これに得点を記録します。パドルに当たったときに得点を1加えます。

# パドルに当たったとき
if(paddle.colliderect(ball)):
    ball.vy *= -1
    game.score += 1

draw関数で得点を表示します。

def draw():
    screen.clear()
    paddle.draw()
    ball.draw()

    screen.draw.text(str(game.score), (50, 10), fontsize=30, color='white')

    if game.game_over:
        screen.draw.text("GAME OVER", (650, 10), fontsize=30, color='white')

ゲーム再開時に得点をリセットします。

def on_mouse_down(pos):
    if game.game_over:
        ball.x = 100
        ball.y = 50
        game.game_over = False
        game.score = 0