次はコンピューター(CPU)側のバーの動きを作っていくけど、まずはプレイヤー側とは反対側にバーを設置しようか!
おっけー!今回はちょっと自分で考えてみる!!
まず、y座標はプレイヤーのバーと同じ位置で良いよね
そうだね!
x座標は、プレイヤーのバーの座標が「10」だったから、CPUは「ウィンドウの幅 - 10」か!
...だけど、バーの座標の基準は左上だから、バーの幅の分も考えないといけないね!
お!よく気付いたね!!
...ということはー?
「ウィンドウの幅 - 10 - バーの幅」だね!
プログラムにすると「pyxel.width - 10 - self.bar_width」だ!
おー!正解!!
そしたら、今の内容をCPUのx座標を「self.cpu_x」、y座標を「self.cpu_y」として関数「__init__」に追加しよう!
# 関数「__init__」の「pyxel.run()」の上の行に追加
self.cpu_x = pyxel.width - 10 - self.bar_width
self.cpu_y = (pyxel.height - self.bar_height) // 2
あとは、関数「draw」の方にCPU用の「pyxel.rect()」を追加だね!
# 関数「draw」の最後に追加
pyxel.rect(self.cpu_x, self.cpu_y, self.bar_width, self.bar_height, 14)
もうここまでの流れはバッチリだね!早速、どうなったか確認してみよう!
うん、良い感じ!!
そしたら次は、ホッケーとCPUのバーとの衝突判定を作ろうか!
...とは言っても、条件式は前回の方法と同じで、「self.bar_x」と「self.bar_y」が「self.cpu_x」と「self.cpu_y」に変わったバージョンを追加して、衝突したときに左に行くように変えれば良いだけだよ
# 関数「update」の最後に追加
if (
self.x - self.r <= self.cpu_x + self.bar_width and
self.x + self.r >= self.cpu_x and
self.y + self.r >= self.cpu_y and
self.y - self.r <= self.cpu_y + self.bar_height
):
self.vx = -abs(self.vx) # 絶対値にマイナスをつける
前回と一緒だから簡単だね!
さて、ここからが本番!CPUの動きを作るけど、葵はどうやって作るのが良いと思う?
そうだねー
まずはホッケーのy座標に合わせて動いてみるとか??
オッケー!そしたら、単純にその仕組みで動かしてみようか!
# 関数「update」のプレイヤーバーの操作の下に追加
# プレイヤーバーの操作(上下キー)
if pyxel.btn(pyxel.KEY_UP):
self.bar_y -= 2
if pyxel.btn(pyxel.KEY_DOWN):
self.bar_y += 2
self.bar_y = max(0, min(pyxel.height - self.bar_height, self.bar_y))
# CPUバーの自動追尾(この2行を追加)
self.cpu_y = self.y - self.bar_height // 2
self.cpu_y = max(0, min(pyxel.height - self.bar_height, self.cpu_y))
絶対にバーの真ん中でホッケーを捉えてるの強すぎる(笑)
常にホッケーと上下の方向は同じだしね
そしたら、もう少しだけ動きを変えてみようか
例えば、ランダムを使ってたまに動かない場合を作るならこんな感じだよ
さっきのCPUの動き部分のプログラムを下のプログラムに変えてみよう!
import random # 追加を忘れずに!!
# 途中省略
# CPUバーの自動追尾
if random.random() > 0.2: # 80%の確率で追尾
if self.y > self.cpu_y + self.bar_height // 2:
self.cpu_y += 1.2
elif self.y < self.cpu_y + self.bar_height // 2:
self.cpu_y -= 1.2
self.cpu_y = max(0, min(pyxel.height - self.bar_height, self.cpu_y))
あ!ちょっとぎこちない動きになって、ホッケーに追いつかない時が出てくるようになった!
他にも、「反応するのはホッケーが一定距離まで近づいてきてから」や「5フレームに1回しか動かない」って感じで動きを作ってあげると面白いかもね!
自分でもちょっと考えてみる!
この時点での全体のプログラム
import pyxel
import random
class App:
def __init__(self):
pyxel.init(160, 120, title="ホッケーゲーム")
# ホッケーの座標、速度、半径
self.x = pyxel.width // 2
self.y = pyxel.height // 2
self.vx = 1
self.vy = 1
self.r = 4
# プレイヤー(左側)のバー
self.bar_height = 20 # バーの高さ
self.bar_width = 5 # バーの幅
self.bar_x = 10 # プレイヤーのx座標
self.bar_y = (pyxel.height - self.bar_height) // 2 # プレイヤーのy座標
# CPU(右側)のバー
self.cpu_x = pyxel.width - 10 - self.bar_width # CPUのx座標
self.cpu_y = (pyxel.height - self.bar_height) // 2 # CPUのy座標
pyxel.run(self.update, self.draw)
def update(self):
self.x += self.vx
self.y += self.vy
# プレイヤーバーの操作(上下キー)
if pyxel.btn(pyxel.KEY_UP):
self.bar_y -= 2
if pyxel.btn(pyxel.KEY_DOWN):
self.bar_y += 2
self.bar_y = max(0, min(pyxel.height - self.bar_height, self.bar_y))
# CPUバーの自動追尾
if random.random() > 0.2: # 80%の確率で追尾
if self.y > self.cpu_y + self.bar_height // 2:
self.cpu_y += 1.2
elif self.y < self.cpu_y + self.bar_height // 2:
self.cpu_y -= 1.2
self.cpu_y = max(0, min(pyxel.height - self.bar_height, self.cpu_y))
# ウィンドウの端に当たったら反射(跳ね返る)
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
# プレイヤーバーの衝突判定
if (
self.x + self.r >= self.bar_x and
self.x - self.r <= self.bar_x + self.bar_width and
self.y + self.r >= self.bar_y and
self.y - self.r <= self.bar_y + self.bar_height
):
self.vx = abs(self.vx)
# CPUの衝突判定
if (
self.x - self.r <= self.cpu_x + self.bar_width and
self.x + self.r >= self.cpu_x and
self.y + self.r >= self.cpu_y and
self.y - self.r <= self.cpu_y + self.bar_height
):
self.vx = -abs(self.vx)
def draw(self):
pyxel.cls(0)
pyxel.circ(self.x, self.y, self.r, 8)
pyxel.rect(self.bar_x, self.bar_y, self.bar_width, self.bar_height, 11)
pyxel.rect(self.cpu_x, self.cpu_y, self.bar_width, self.bar_height, 14)
App()
