タイトル画像
琴葉茜

前回土台となるウィンドウが出せるようになったから、次はウィンドウ内の真ん中にホッケーを配置してみよう!
今回はシンプルに「円」をホッケーとして扱うよ

琴葉葵

円を表示するから、関数「draw」の中に作るんだね!

琴葉茜

そうだね!
「円」を配置する場合は「pyxel.circ(円の中心のx座標, 円の中心のy座標, 円の半径, 円の色)」ってするよ

def draw(self):
    pyxel.cls(0)  # 背景色(黒)
    pyxel.circ(pyxel.width // 2, pyxel.height // 2, 4, 8)  # 赤い円(色番号8)
琴葉葵

円の中心の座標で考えられるのは分かりやすいね!

琴葉茜

ちなみに、xy座標(0, 0)はウィンドウ内の一番左上だから覚えておいてね

解説画像1
琴葉葵

おお!ちゃんと真ん中に円が現れた!

琴葉茜

ちゃんと表示されたね!あとは更新する度に、円の中心の「x座標」と「y座標」が変化すれば動くようになるよ

琴葉葵

ということは、それぞれの座標用の変数を用意すれば良いんだね!

琴葉茜

そういうこと!
じゃあ円を動かす準備として、インスタンス変数「self.x」「self.y」を用意して、さっきの「pyxel.circ()」の引数を書き換えよう

class App:
    def __init__(self):
        pyxel.init(160, 120, title="ホッケーゲーム")

        self.x = pyxel.width // 2 # 円のx座標の変数
        self.y = pyxel.height // 2 # 円のy座標の変数

        pyxel.run(self.update, self.draw)

    def update(self):
        pass

    def draw(self):
        pyxel.cls(0)  
        pyxel.circ(self.x, self.y, 4, 8) # 引数を変更
琴葉葵

変更完了!起動してみたけど問題なさそう

琴葉茜

おっけー!
じゃあ次は、円の座標に変化をつけるために関数「update」の中で、それぞれのインスタンス変数が「+1」されるようにしよう

def update(self):
    self.x += 1
    self.y += 1
琴葉葵

おお!右下に向かって円が動いt...って画面の外に消えていっちゃったよ!?

琴葉茜

これは、別にウィンドウの端に壁があるわけじゃないから、「ウィンドウの端に来た時」の処理を作る必要があるんだ

琴葉葵

なんかややこしそうな予感が...汗

琴葉茜

そしたら、図で説明してみよう

解説画像2
琴葉葵

なるほど
ということは、ウィンドウの範囲を指定したif文を作る必要があるんだね!

琴葉茜

ここで気を付けないといけない点は、「円には半径分の大きさがある」ことだね

琴葉葵

そうか、普通に円の中心座標がウィンドウからはみ出してるかをチェックしても、実際は半分はみ出しちゃうのか

琴葉茜

そういうことだね
だから、「ウィンドウの端より内側に円の半径分小さくなった見えない壁がある」って考え方で判定を作るよ

解説画像3
琴葉葵

なんとなくイメージしやすくなった!

琴葉茜

じゃあ次はこのイメージを基準に「ホッケーがウィンドウの端に来たら跳ね返す」プログラムにしていくよ

琴葉葵

「跳ね返す」っていうのは具体的にどうしたら良いの??

琴葉茜

ウィンドウの左右の端に来た場合は「self.x」、上下の端に来た時は「self.y」の値が変化する処理のプラスマイナスが逆になれば良いんだ

琴葉葵

なるほど
でも、それってどうやるの?

琴葉茜

関数「update」内で変化している量は「+1」になってるけど、これをフレームごとに変化する速度「self.vx」「self.vy」にして、端に来た時に「-1の掛け算をする」ことでいけるようになるよ!

琴葉葵

そうか!-1を掛ければプラスマイナスが逆になるもんね!

琴葉茜

なんとなくやり方が分かったところで、実際にプログラムに反映してみようか

import pyxel

class App:
    def __init__(self):
        pyxel.init(160, 120, title="ホッケーゲーム")
        self.x = pyxel.width // 2
        self.y = pyxel.height // 2
        self.vx = 1  # 速度(x方向)
        self.vy = 1  # 速度(y方向)
        self.r = 4   # 半径
        pyxel.run(self.update, self.draw)

    def update(self):
        self.x += self.vx
        self.y += self.vy

        # ウィンドウの端に当たったら反射(跳ね返る)
        if self.x <= self.r or self.x >= pyxel.width - self.r:
            self.vx *= -1
        if self.y <= self.r or self.y >= pyxel.height - self.r:
            self.vy *= -1

    def draw(self):
        pyxel.cls(0)
        pyxel.circ(self.x, self.y, self.r, 8)  # 半径もインスタンス変数に変更

App()
琴葉葵

おおーーちゃんと跳ね返るようになった!なんか、動きが付くと一気にゲームっぽくなったね

琴葉茜

そうでしょー