プログラミング超初心者のゲーム製作 by Pyxel(14日目)

今日は「車を動かす」を学びます。

今日書いたコード

結果:スペースキーで車が動くようになった

import pyxel

GAME_TITLE = "TAXI PICUP" #ゲームタイトル。定数を定義する

CAR_ACCEL_X = 0.06 #車の左右移動の加速度
CAR_ACCEL_UP = 0.04 #車の前移動の加速度
CAR_ACCEL_DOWN = 0.02 #車の後ろ移動の加速度
MAX_CAR_SPEED = 0.8 #車の最大速度

OBJECT_SPAWN_INTERVAL = 150 #オブジェクトの出現間隔

class OneKeyGame:
    def __init__(self):
        #pyxelを初期化する
        pyxel.init(160, 120, title=GAME_TITLE)

        #リソースファイルを読み込む
        pyxel.load("taxi_picup.pyxres") #pyxel.load関数の呼び出し

        #ゲームをリセットする
        self.is_title = True
        self.reset_game()

        #アプリの実行を開始する
        pyxel.run(self.update, self.draw)

    #ゲームをリセットする
    def reset_game(self): #ゲームで使う変数を一括で初期化
        #得点を初期化する
        self.score = 0

        #出現タイマーを初期化する
        self.timer = 0

        #車を初期化する
        self.car_x = (pyxel.width - 8) / 2 #X座標
        self.car_y = pyxel.height / 4 #Y座標
        self.car_vx = 0 #X移動の速度
        self.car_vy = 0 #Y移動の速度
        self.car_dir = 1 #車の左右の向き(-1:左, +1:右)
        self.is_turbo = False #ターボ中かどうか
        self.is_exploding = False #爆発中かどうか

        #マップの配置を初期化する
        self.survivors = [] #客の配置
        self.rock = [] #岩の配置

    #車を更新する
    def update_car(self):
        #車の速度を更新する
        if pyxel.btn(pyxel.KEY_SPACE): #スペースキーが押されている時
            self.is_turbo = True
            self.car_vy = max(self.car_vy - CAR_ACCEL_UP, -MAX_CAR_SPEED)
            self.car_vx = max(
                min(self.car_vx + self.car_dir * CAR_ACCEL_X, 1), -MAX_CAR_SPEED
            )
            pyxel.play(0, 0) #チャンネル0で効果音0を再生する
        else: #スペースキーが押されてない時
            self.is_turbo = False
            self.car_vy = min(self.car_vy + CAR_ACCEL_DOWN, MAX_CAR_SPEED)

        #スペースキーが離された時に次に進方向を逆にする
        if pyxel.btnr(pyxel.KEY_SPACE):
            self.car_dir = -self.car_dir

        #宇宙船の位置を更新する
        self.car_x += self.car_vx
        self.car_y += self.car_vy

        if self.car_x < 0: #画面左端を越えた時
            self.car_x = 0
            self.car_vx = abs(self.car_vx)
            pyxel.play(0, 1)

        max_car_x = pyxel.width - 8
        if self.car_x > max_car_x: #画面右端を越えた時
            self.car_x = max_car_x
            self.car_vx = -abs(car_vx)
            pyxel.play(0, 1)

        if self.car_y < 0: #画面上端を越えた時
            self.car_y = 0
            self.car_vy = abs(self.car_vy)
            pyxel.play(0, 1)

        max_car_y = pyxel.height -8
        if self.car_y > max_car_y: #画面下端を越えた時
            self.car_y = max_car_y
            self.car_vy = -abs(self.car_vy)
            pyxel.play(0, 1)

    #アプリを更新する
    def update(self):
        #タイトル画面の時はRETURNキーの入力を待つ
        if self.is_title: #タイトル画面かの判定を追加
            if pyxel.btnp(pyxel.KEY_RETURN): #キー入力の判定を追加
                self.is_title = False #Falseに変え、ゲームプレイ中とする
                self.reset_game() #reset_game関数の呼び出しを追加
            return #return文を追加

        #ゲームを更新する
        self.update_car() #update_car関数の呼び出しを追加

    #地面を描画する
    def draw_ground(self): #draw_ground関数を追加
        num_grads = 10 #グラデーションの数
        grad_width = 4 #グラデーションの幅
        grad_height = 160
        grad_start_x = pyxel.width - grad_width * num_grads #描画開始位置

        pyxel.cls(9)
        for i in range(num_grads):
            pyxel.dither((i + 1) / num_grads) #ディザリングを有効にする
            pyxel.rect(
                grad_start_x + i * grad_width,
                0,
                pyxel.width,
                grad_height,
                11,
            )
        pyxel.dither(1) #ディザリングを無効にする

    #タイトルを描画する
    def draw_title(self):
        for i in range(1, -1, -1):
            color = 10 if i == 0 else 8
            pyxel.text(57, 50 +i, GAME_TITLE, color)
            pyxel.text(42, 70, "- Press Enter Key -", 3)

    #タクシーを描画する
    def draw_car(self): #draw_car関数を追加
        #ターボの噴射の表示位置をずらす量を計算する
        offset_y = (pyxel.frame_count % 3 +2) if self.is_turbo else 0
        offset_x = offset_y * -self.car_dir

        #左右のターボ噴射を描画する
        pyxel.blt(
            self.car_x -self.car_dir * 3 + offset_x, #描画位置のX座標
            self.car_y, #描画位置のY座標
            0, #参照するイメージバンクの番号
            0, #参照イメージの左上のX座標
            0, #参照イメージの左上のY座標
            8 * self.car_dir, #参照イメージの幅(負の値だと左右反転する)
            8, #参照イメージの高さ
            0, #色番号0を透明として扱う
        )

        # 左右のターボ噴射を描画する
        pyxel.blt(
            self.car_x,
            self.car_y + 3 + offset_y,
            0, #参照するイメージバンクの番号
            8, #参照イメージの左上のX座標
            8, #参照イメージの左上のY座標
            8 * self.car_dir,  # 参照イメージの幅(負の値だと左右反転する)
            8, #参照イメージの高さ
            0, #色番号0を透明として扱う
        )

        pyxel.blt( #pyxel.blt関数で画像を描画する
            self.car_x,
            self.car_y,
            0,
            8,
            0,
            8,
            8,
            0,
        )
    #スコアを描画する
    def draw_score(self): #draw_score関数を追加
        score = f"SCORE:{self.score:05}"
        for i in range(1, -1, -1):
            color = 7 if i == 0 else 0
            pyxel.text(3 + i, 3, score, color)

    #アプリを描画する
    def draw(self):
        #画面を描画する
        self.draw_ground()
        self.draw_car()
        self.draw_score()

        #タイトル画面の時はタイトルを描画する
        if self.is_title: #タイトル画面かの判定を追加
            self.draw_title() #draw_title関数の呼び出しを追加

OneKeyGame()

コードの要点

pyxel.btnp関数:キーが押された瞬間を判定
pyxel.btn関数:キーが押下しつづけられているか判定
pyxel.btnr関数:キーが離された瞬間を判定
max関数:複数の引数のうち、もっとも大きい値を返す
min関数:複数の引数のうち、もっとも小さい値を返す
pyxel.play関数:サウンドを再生する