import pygame
import random
import sys
# 初期化
pygame.init()
# 画面サイズ
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("インベーダーゲーム")
# 色の定義
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# フォント設定
font = pygame.font.SysFont(None, 36)
# FPS設定
clock = pygame.time.Clock()
FPS = 60
# プレイヤー設定
player_width, player_height = 60, 20
player_x = (WIDTH - player_width) // 2
player_y = HEIGHT - 50
player_speed = 5
# 弾設定
bullet_width, bullet_height = 5, 10
bullet_speed = 7
bullets = []
# 敵設定
enemy_width, enemy_height = 40, 30
enemy_speed = 1
enemy_direction = 1 # 1:右, -1:左
enemies = []
enemy_rows = 3
enemy_cols = 7
enemy_padding = 20
enemy_offset_x = 100
enemy_offset_y = 50
# UFO設定
ufo_width, ufo_height = 60, 30
ufo_speed = 3
ufo = None
ufo_timer = 0
UFO_INTERVAL = 10 * FPS # 10秒ごとにUFO出現
# スコアとステージ
score = 0
stage = 1
# ゲームオーバーフラグ
game_over = False
def create_enemies():
new_enemies = []
# グローバル変数のenemy_speedをここで参照しないように注意(create_enemiesが呼ばれる前に設定されている)
for row in range(enemy_rows):
for col in range(enemy_cols):
x = enemy_offset_x + col * (enemy_width + enemy_padding)
y = enemy_offset_y + row * (enemy_height + enemy_padding)
new_enemies.append(pygame.Rect(x, y, enemy_width, enemy_height))
return new_enemies
# ゲーム開始時に一度敵を作成
enemies = create_enemies()
def draw_player(x, y):
pygame.draw.rect(screen, WHITE, (x, y, player_width, player_height))
def draw_bullets(bullets):
for bullet in bullets:
pygame.draw.rect(screen, RED, bullet)
def draw_enemies(enemies):
for enemy in enemies:
pygame.draw.rect(screen, WHITE, enemy)
def draw_ufo(ufo):
if ufo:
pygame.draw.rect(screen, GREEN, ufo)
def draw_score(score, stage):
text = font.render(f"Score: {score} Stage: {stage}", True, WHITE)
screen.blit(text, (10, 10))
def draw_game_over():
text = font.render("GAME OVER", True, RED)
text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 2))
screen.blit(text, text_rect)
# メインループ
running = True
while running:
clock.tick(FPS)
screen.fill(BLACK)
# イベント処理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if not game_over:
# キー入力処理
keys = pygame.key.get_pressed()
# プレイヤーの移動制限を考慮
if keys[pygame.K_LEFT]:
player_x -= player_speed
if player_x < 0: # 画面左端に制限
player_x = 0
if keys[pygame.K_RIGHT]:
player_x += player_speed
if player_x > WIDTH - player_width: # 画面右端に制限
player_x = WIDTH - player_width
# スペースキーは押しっぱなしではなく、押された瞬間に弾を発射するように変更(連続発射防止)
# ただし、現在のコードでは長押しで連続発射されているので、その挙動を維持
# もし1発ずつにしたい場合は event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE で判定する
if keys[pygame.K_SPACE]:
# 画面上に弾が5発未満の場合に発射
if len(bullets) < 5:
bullet = pygame.Rect(player_x + player_width // 2 - bullet_width // 2,
player_y, bullet_width, bullet_height)
bullets.append(bullet)
# 弾の移動
for bullet in bullets[:]: # リストをコピーして要素削除中のエラーを防ぐ
bullet.y -= bullet_speed
if bullet.y < 0:
bullets.remove(bullet)
# 敵の移動ロジック (修正箇所)
move_down = False
for enemy in enemies:
enemy.x += enemy_speed * enemy_direction
# 画面端での位置調整
if enemy.right >= WIDTH:
enemy.right = WIDTH # 画面右端に強制的に固定
move_down = True
elif enemy.left <= 0:
enemy.left = 0 # 画面左端に強制的に固定
move_down = True
if move_down:
enemy_direction *= -1 # 方向転換
for enemy in enemies:
enemy.y += enemy_height # Y座標を下げる
# 弾と敵の衝突判定
for bullet in bullets[:]:
for enemy in enemies[:]:
if bullet.colliderect(enemy):
bullets.remove(bullet)
enemies.remove(enemy) # 敵をリストから削除
score += 100
break # 1つの弾は1つの敵にしか当たらないため、内側のループを抜ける
# 敵が画面下部に到達したかチェック
for enemy in enemies:
if enemy.bottom >= player_y: # プレイヤーのY座標まで到達したらゲームオーバー
game_over = True
break
# 敵を全滅させた場合
if not enemies:
stage += 1
enemy_speed += 0.5 # 敵の速度を上げる
# 次のステージのために新しい敵を生成
enemies = create_enemies()
# 敵のY座標がリセットされるが、念のため敵の方向も初期化
enemy_direction = 1 # 新しいステージは常に右からスタート
# UFOの出現管理
ufo_timer += 1
if ufo_timer >= UFO_INTERVAL:
ufo_timer = 0
ufo_y = 50
ufo_direction_choice = random.choice([-1, 1]) # UFOの進行方向を決定
if ufo_direction_choice == 1: # 右から左へ
ufo_x = -ufo_width
ufo_speed = 3 # 正の方向
else: # 左から右へ
ufo_x = WIDTH
ufo_speed = -3 # 負の方向
ufo = pygame.Rect(ufo_x, ufo_y, ufo_width, ufo_height)
# ufo_speedは上で設定済みなので、ここでは設定しない
# UFOの移動
if ufo:
ufo.x += ufo_speed
# UFOが画面外に出たら消滅させる
if (ufo_speed > 0 and ufo.left > WIDTH) or \
(ufo_speed < 0 and ufo.right < 0):
ufo = None
# 弾とUFOの衝突判定
if ufo: # UFOが存在する場合のみ判定
for bullet in bullets[:]:
if bullet.colliderect(ufo):
bullets.remove(bullet)
ufo = None # UFOを消滅させる
score += 500
break # 弾がUFOに当たったら、その弾は消えるのでループを抜ける
# 描画
draw_player(player_x, player_y)
draw_bullets(bullets)
draw_enemies(enemies)
draw_ufo(ufo)
draw_score(score, stage)
else:
# ゲームオーバー画面の描画
draw_game_over()
# ゲームオーバー時のキー入力で再スタートなどを実装するならここに追記
# 今回は特に再スタートロジックは追加していません
pygame.display.flip() # 画面を更新
# Pygameの終了処理
pygame.quit()
sys.exit()