背景
pygameでスペースインベーダー作りたい。
PCスペック
項目 | 情報 |
---|---|
OS | macOS Sonoma 14.4.1 |
ハードウェア | MacBook Pro 16inc 2023 |
プロセッサ | Apple M2 pro |
メモリ | 32GB |
ソースコード
py main.py
import pygame
import random
import sys
# Pygameの初期化
pygame.init()
# 定数の設定
WIDTH = 800
HEIGHT = 600
GRID_SIZE = 20
TILE_SIZE = 30
MINE_COUNT = 50
# 色の定義
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREY = (192, 192, 192)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# フォントの設定
FONT = pygame.font.SysFont('comicsans', 20)
# スクリーンの設定
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Minesweeper')
# タイルクラスの定義
class Tile:
def __init__(self, x, y):
self.x = x
self.y = y
self.is_mine = False
self.is_revealed = False
self.is_flagged = False
self.adjacent_mines = 0
def draw(self):
if self.is_revealed:
pygame.draw.rect(screen, GREY, (self.x * TILE_SIZE, self.y * TILE_SIZE, TILE_SIZE, TILE_SIZE))
if self.is_mine:
pygame.draw.circle(screen, BLACK, (self.x * TILE_SIZE + TILE_SIZE // 2, self.y * TILE_SIZE + TILE_SIZE // 2), TILE_SIZE // 4)
elif self.adjacent_mines > 0:
text = FONT.render(str(self.adjacent_mines), True, BLACK)
screen.blit(text, (self.x * TILE_SIZE + TILE_SIZE // 2 - text.get_width() // 2, self.y * TILE_SIZE + TILE_SIZE // 2 - text.get_height() // 2))
else:
pygame.draw.rect(screen, WHITE, (self.x * TILE_SIZE, self.y * TILE_SIZE, TILE_SIZE, TILE_SIZE))
if self.is_flagged:
pygame.draw.circle(screen, RED, (self.x * TILE_SIZE + TILE_SIZE // 2, self.y * TILE_SIZE + TILE_SIZE // 2), TILE_SIZE // 4)
pygame.draw.rect(screen, BLACK, (self.x * TILE_SIZE, self.y * TILE_SIZE, TILE_SIZE, TILE_SIZE), 1)
# ゲームボードの初期化
def init_board():
board = [[Tile(x, y) for y in range(HEIGHT // TILE_SIZE)] for x in range(WIDTH // TILE_SIZE)]
mines = random.sample([tile for row in board for tile in row], MINE_COUNT)
for mine in mines:
mine.is_mine = True
for row in board:
for tile in row:
if not tile.is_mine:
tile.adjacent_mines = sum(1 for nx in range(tile.x - 1, tile.x + 2) for ny in range(tile.y - 1, tile.y + 2) if 0 <= nx < WIDTH // TILE_SIZE and 0 <= ny < HEIGHT // TILE_SIZE and board[nx][ny].is_mine)
return board
# ゲームオーバーの処理
def game_over(board):
for row in board:
for tile in row:
tile.is_revealed = True
draw_board(board)
pygame.display.update()
pygame.time.wait(2000)
pygame.quit()
sys.exit()
# ゲームクリアの確認
def check_win(board):
for row in board:
for tile in row:
if not tile.is_mine and not tile.is_revealed:
return False
return True
# タイルを開く処理
def reveal_tile(board, x, y):
tile = board[x][y]
if tile.is_revealed or tile.is_flagged:
return
tile.is_revealed = True
if tile.is_mine:
game_over(board)
elif tile.adjacent_mines == 0:
for nx in range(x - 1, x + 2):
for ny in range(y - 1, y + 2):
if 0 <= nx < WIDTH // TILE_SIZE and 0 <= ny < HEIGHT // TILE_SIZE:
reveal_tile(board, nx, ny)
# ゲームボードの描画
def draw_board(board):
for row in board:
for tile in row:
tile.draw()
# メイン関数
def main():
board = init_board()
run = True
while run:
screen.fill(GREEN)
draw_board(board)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.MOUSEBUTTONDOWN:
x, y = pygame.mouse.get_pos()
x //= TILE_SIZE
y //= TILE_SIZE
if event.button == 1:
reveal_tile(board, x, y)
if check_win(board):
print("You win!")
run = False
elif event.button == 3:
tile = board[x][y]
tile.is_flagged = not tile.is_flagged
pygame.quit()
if __name__ == "__main__":
main()
画面
まとめ
できた。