Pygameで作る指ゲーム
こんにちは、今回の三回目の記事では、クリスマスカレンダーイベントを参加したくて、今週余ってる時間を利用して作りました。
PythonのPygameライブラリを使用して簡単な指ゲームを作成する方法を紹介します。
このゲームは2人で遊ぶことができ、プレイヤーは相手の手の指の数を増やしながら戦います。
目標は相手の両手の指をすべて消滅させることです。多分皆さん昔よく学校で遊んでたと思います。
台湾も同じ文化でした。僕の場合は学校で友たちと遊ぶというより家族と遊んだ回数の方が多いですね。
ここから説明に入ります。よろしくお願いします
ゲームのルール by Wikipedia (gpt4で省略)
ゲームは2人のプレイヤーで行います。
各プレイヤーは、自分の番で相手のどちらかの手を選んで、指の数を増やします。
指の合計が5を超えると、その手は「消滅」します。
先に相手の両手を消滅させたプレイヤーが勝利します。
必要なセットアップ
Pythonがインストールされていること。
Pygameライブラリがインストールされていること。
ゲームの具体的な動作
手の動き
ゲーム中、プレイヤーはマウスを使って自分の手をドラッグし、相手の手に重ねることができます。
手をドラッグしている間、その手はマウスカーソルに追従します。
ドラッグ操作を終了すると(マウスボタンを離すと)、手は自動的に元の位置(原点座標)に戻ります。
ターンの変更
プレイヤーが相手の手に自分の手を重ねた場合、相手のその手の指の数が増加し、ターンが次のプレイヤーに移ります。
画面の左上には、現在どちらのプレイヤーのターンかが表示されます。
指の数の計算
プレイヤーが相手の手を選んだ時、選んだ手の指の数に、選んだプレイヤーの手の指の数が加算されます。
指の合計が5になると、その手はゲームから消滅します。
勝利条件
いずれかのプレイヤーの両手が消滅すると、もう一方のプレイヤーが勝利します。
勝利したプレイヤーの情報が画面に表示され、ゲームが終了します。
ゲームの実装
以下のコードは、この指ゲームの基本的な実装を示しています。
コードには、ゲームの初期設定、メインループ、イベント処理、画面更新などの主要な部分が含まれています。
動作動画です
* font は自分のfontを使ってください。import pygame
import os
# 初期設定
pygame.init()
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Finger Game with Interaction")
sysfont = pygame.font.Font("C:/Windows/Fonts/HGRPP1.TTC", 33)
# 画像の読み込み
hand_images = [
pygame.image.load(os.path.join("./hand_game/image/", f"hand_{i}.png"))
for i in range(1, 6)
]
# プレイヤーとCPUの手の初期化
player_hands = [1, 1]
player2_hands = [1, 1]
# ドラッグ状態とオリジナルの位置
dragging_hand_index = None
offset_x = offset_y = 0
original_pos_player = [
(screen_width // 4, screen_height - hand_images[0].get_height()),
(3 * screen_width // 4, screen_height - hand_images[0].get_height()),
]
original_pos_player2 = [(screen_width // 4, 0), (3 * screen_width // 4, 0)]
# 現在のターンを示す変数(1: プレイヤー1、2: プレイヤー2)
current_turn = 1
# ハンドル関数
def update_hand(hand, added_fingers):
hand += added_fingers
if hand >= 5:
hand = 0
return hand
# プレイヤーの手が相手の手に触れているかをチェックする関数
def check_overlap(player_hand_pos, player2_hand_positions, player2_hands):
for i, pos in enumerate(player2_hand_positions):
hand_rect = hand_images[player2_hands[i] - 1].get_rect(topleft=pos)
if hand_rect.collidepoint(player_hand_pos):
return i # 触れている手のインデックスを返す
return None # 触れていない場合はNoneを返す
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# 現在のターンに応じて対応するプレイヤーの手を選択
if current_turn == 1:
for i, pos in enumerate(original_pos_player):
hand_rect = hand_images[player_hands[i] - 1].get_rect(topleft=pos)
if hand_rect.collidepoint(event.pos):
dragging_hand_index = i
break
elif current_turn == 2:
for i, pos in enumerate(original_pos_player2):
hand_rect = hand_images[player2_hands[i] - 1].get_rect(topleft=pos)
if hand_rect.collidepoint(event.pos):
dragging_hand_index = i
break
elif event.type == pygame.MOUSEBUTTONUP:
if dragging_hand_index is not None:
if current_turn == 1:
player_hand_pos = original_pos_player[dragging_hand_index]
overlap_index = check_overlap(
player_hand_pos, original_pos_player2, player2_hands
)
if overlap_index is not None:
player2_hands[overlap_index] = update_hand(
player2_hands[overlap_index],
player_hands[dragging_hand_index],
)
print(
f"Player 2 hand {overlap_index + 1}: {player2_hands[overlap_index]} fingers"
)
current_turn = 2 # ターンをプレイヤー2に切り替える
# プレイヤー1の手を原点に戻す
original_pos_player[dragging_hand_index] = (
(screen_width // 4, screen_height - hand_images[0].get_height())
if dragging_hand_index == 0
else (
3 * screen_width // 4,
screen_height - hand_images[0].get_height(),
)
)
elif current_turn == 2:
player2_hand_pos = original_pos_player2[dragging_hand_index]
overlap_index = check_overlap(
player2_hand_pos, original_pos_player, player_hands
)
if overlap_index is not None:
player_hands[overlap_index] = update_hand(
player_hands[overlap_index],
player2_hands[dragging_hand_index],
)
print(
f"Player 1 hand {overlap_index + 1}: {player_hands[overlap_index]} fingers"
)
current_turn = 1 # ターンをプレイヤー1に切り替える
# プレイヤー2の手を原点に戻す
original_pos_player2[dragging_hand_index] = (
(screen_width // 4, 0)
if dragging_hand_index == 0
else (3 * screen_width // 4, 0)
)
dragging_hand_index = None
elif event.type == pygame.MOUSEMOTION:
if dragging_hand_index is not None:
# ドラッグ中の手の位置を更新
mouse_x, mouse_y = event.pos
if current_turn == 1:
original_pos_player[dragging_hand_index] = (mouse_x, mouse_y)
elif current_turn == 2:
original_pos_player2[dragging_hand_index] = (mouse_x, mouse_y)
# 画面のクリア
screen.fill((255, 255, 255))
# ターン表示用のテキストを画面に描画
turn_text = f"P{current_turn}'s Turn"
text_surface = sysfont.render(turn_text, True, (0, 0, 0)) # 黒色でテキストをレンダリング
screen.blit(text_surface, (10, 10)) # 位置は(10, 10)
for i in range(2):
if player_hands[i] > 0:
player_hand_img = hand_images[player_hands[i] - 1]
pos = original_pos_player[i]
screen.blit(player_hand_img, pos)
if player2_hands[i] > 0:
player2_hand_img = pygame.transform.rotate(
hand_images[player2_hands[i] - 1], 180
)
pos = original_pos_player2[i]
screen.blit(player2_hand_img, pos)
pygame.display.flip()
# 勝敗の確認
if all(hand == 0 for hand in player2_hands):
print("Player 1 wins!")
running = False
elif all(hand == 0 for hand in player_hands):
print("Player 2 wins!")
running = False
pygame.quit()
最後
これから、AI搭載しようと思います。
今回も最後まで見てくれてありがとうございます。
bugは今回あまりないと思いますがなにか見つかったら、ご指摘よろしくお願いします。
参考資料、手のフリー素材リンク