Pyxelを触ってみよう2

こんにちは。元TENTO生で現在スタッフをしているSです。

少し時間は経ってしまいましたが、前回の続きに取り組みたいと思います。今日は、ミニゲームを完成させるところまで取り組みたいと思います。

前回のブログについてはこちらから↓
https://www.tento-net.com/blog/pyxel1

水色のキャラクターを動かそう

前回、白いキャラクターは動かせるようにしました。
水色のキャラクターも同じように矢印キーで動かすと、白いキャラクターとくっついて動いてしまうため、別の方法で動かしていきたいと思います。

今回は水色のキャラクターは、上から下に自動的に落ちていくようにします。水色のキャラクターのための変数を作成し、コードが走っている間に1ずつ値が増えるようにしました。

今回変更したコード部分↓
blueY = 0 # 水色キャラクターのY座標のための変数
blueY += 1
blt(20,blueY, 1, 0, 0, 8, 8, 0) # 水色のキャラクター

しかし、このままだと水色キャラクターが枠外に出てしまうと、もう一度再実行をしないと水色のキャラクターが戻ってきません。そこで次は、水色のキャラクターが枠外に行ってしまったら、上に戻してもう一度落ちていくようにします。ついでに、水色キャラクターのx座標についてもランダムに出現させるようにします。

今回変更したコード部分↓
blueX = 4 # 水色キャラクターのX座標のための変数を作成

if blueY > 92: # 水色キャラクターのyが92を超えたら0にしてもう一度上に戻らせる
blueX = random.randint(8, 89)
blueY = 0

水色のキャラクターを捕まえたらコスチュームを変える

では次に、水色のキャラクターを敵に見立てて、白いキャラクターが捕まえたら、敵が死ぬ仕組みを作ります。

まず、死んだキャラクターのコスチュームを作ります。今回はピンクのキャラクターを作ってみました。

キャラクターが作れたら、次に当たり判定に取り掛かります。

当たり判定では、
1,敵キャラクターに白いキャラクターが触れたかどうかを確かめる
2,もし触れていたら、敵のコスチュームを先ほど新しく作ったコスチュームに変更させる
ということを行います。

今回変更したコード部分↓
blueImg = 1 # 水色キャラクターのコスチュームのための変数(1が通常、2が死んだ状態)

# 敵を動かしている部分
blueY += 1
if blueY > 92: # 水色キャラクターのyが92を超えたら0にしてもう一度上に戻らせる
blueX = random.randint(8, 89)
blueY = 0
blueImg = 1 # 上に戻ってきたら通常の見た目に戻す
# 敵の当たり判定部分
if (whiteX < blueX + 8 and
whiteX + 8 > blueX and
whiteY < blueY + 8 and
whiteY + 8 > blueY):
blueImg = 2 # 当たったら2番の見た目に変える

blt(blueX,blueY, blueImg, 0, 0, 8, 8, 0) # 水色のキャラクターに見た目のための変数を追加

ひとまず、基本のミニゲームは完成しました。こんな感じで、敵を捕らえたら敵が赤くなります。

完成版コード

基本のコードはこちら↓
from pyxel import *
import random

init(100, 100) # 画面の大きさ
load("my_resource.pyxres") # キャラクターのインポート

whiteX = 10 # 白キャラクターのX座標のための変数
whiteY = 50 # 白キャラクターのY座標のための変数
blueX = 4 # 水色キャラクターのX座標のための変数
blueY = 0 # 水色キャラクターのY座標のための変数
blueImg = 1 # 水色キャラクターのコスチュームのための変数(1が通常、2が死んだ状態)

while True:
if btn(KEY_RIGHT) and whiteX < 88: # 右矢印が押されたら whiteX += 2 if btn(KEY_LEFT) and whiteX > 4: # 左矢印が押されたら
whiteX -= 2
if btn(KEY_UP) and whiteY > 4: # 上矢印が押されたら
whiteY -= 2
if btn(KEY_DOWN) and whiteY < 88: # 下矢印が押されたら
whiteY += 2

# 敵を動かしている部分
blueY += 1
if blueY > 92: # 水色キャラクターのyが92を超えたら0にしてもう一度上に戻らせる
blueX = random.randint(8, 89)
blueY = 0
blueImg = 1 # 上に戻ってきたら通常の見た目に戻す

# 敵の当たり判定部分
if (whiteX < blueX + 8 and
whiteX + 8 > blueX and
whiteY < blueY + 8 and
whiteY + 8 > blueY):
blueImg = 2 # 当たったら2番の見た目に変える

cls(3) # 背景
rect(2, 2, 96, 96, 13) # 枠のための灰色の四角
rect(3, 3, 94, 94, 3) # 枠のための緑色の四角

blt(whiteX,whiteY, 0, 0, 0, 8, 8, 0) # 白いキャラクター
blt(blueX,blueY, blueImg, 0, 0, 8, 8, 0) # 水色のキャラクター

flip()

番外編

ここからは、色々と遊び心を加えていきます。

1,敵を再利用せず、敵が下まで行ったらもう一体表示させる
2,敵を消さず、ずっと表示させる
3,効果音を付け加える
4,10体敵が出現したところで終わりにする
5,ゲームが終了した時に、倒した敵の数によって異なるメッセージを表示させる

これらの機能を追加したコードはこちら↓

from pyxel import *
import random

init(100, 100)
load("my_resource.pyxres")

whiteX = 10
whiteY = 50
finish = False

#敵の状態をまとめた配列(x座標, y座標, スプライト番号, 停止フラグ)
enemyX = [random.randint(8, 89)]
enemyY = [0]
enemyImg = [1]
enemyStopped = [False]

while True:
# --- 白キャラ操作 ---
if btn(KEY_RIGHT) and whiteX < 88: whiteX += 2 if btn(KEY_LEFT) and whiteX > 4:
whiteX -= 2
if btn(KEY_UP) and whiteY > 4:
whiteY -= 2
if btn(KEY_DOWN) and whiteY < 88:
whiteY += 2

new_enemy_needed = False

# --- 敵の更新 ---
for i in range(len(enemyX)):
if not enemyStopped[i]:
enemyY[i] += 2

# 衝突判定
if abs(enemyX[i] - whiteX) < 8 and abs(enemyY[i] - whiteY) < 8:
enemyImg[i] = 2
enemyStopped[i] = True
new_enemy_needed = True
play(0, 0)

# 底まで落ちたら停止
elif enemyY[i] >= 89:
enemyY[i] = 89
enemyStopped[i] = True
new_enemy_needed = True
play(0, 1)

# 新しい敵を追加
if new_enemy_needed:
if len(enemyX) < 10:
enemyX.append(random.randint(8, 89))
enemyY.append(0)
enemyImg.append(1)
enemyStopped.append(False)
else:
finish = True

# --- 描画 ---
cls(3)
rect(2, 2, 96, 96, 13)
rect(3, 3, 94, 94, 3)

# 白キャラ
blt(whiteX, whiteY, 0, 0, 0, 8, 8, 0)

# 敵
for i in range(len(enemyX)):
blt(enemyX[i], int(enemyY[i]), enemyImg[i], 0, 0, 8, 8, 0)

# ゲーム終了メッセージ
if finish:
caught_count = sum(1 for img in enemyImg if img == 2)
if caught_count > 5:
rect(30, 43, 47, 10, 8)
text(34, 46, "FANTASTIC!", 7)
else:
rect(30, 43, 47, 10, 13)
text(34, 46, "TRY AGAIN!", 3)

flip()

ちなみに操作画面はこんな感じです。