私はプログラミングは全くやろうとしたことがなく、中学時代にBASICという言語をPC-8001mk IIで勉強しようとして挫折した記憶があります。ベーシックマガジンに載っているプログラムのリストを手打ちで打ってゲームを楽しむ程度でした。”こんにちはマイコン”を読んで懐かしく思います。
あれから40年近く経ってしまい今では私が自分でテトリスを作れるようになってしまいました。作ってもらうと言ったほうがいいと思います。Macを使ってゲームを作るにはから始まって、、、テトリスのゲームを作ってと打ち込めばどうしたら良いのか?
PythonとPygameのインストールのやり方から始まり、至れり尽くせりです。ただ初めから思ったようなテトリスができないので何度か修正を繰り返すことが必要です。毎回違うテトリスができるのも事実です。
元々Python何?から始まっているので、ここまでできただけでも感動です。
chatGPTが教えてくれたこと↓
その後最終的にできたのがこちらのコード。
import pygame
import random
pygame.init()
# 定数
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600
GRID_SIZE = 30
GRID_WIDTH, GRID_HEIGHT = SCREEN_WIDTH // GRID_SIZE, SCREEN_HEIGHT // GRID_SIZE
# 色の定義
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
COLORS = [RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, ORANGE]
# テトリミノの形
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[1, 1, 0], [0, 1, 1]], # S
[[0, 1, 1], [1, 1, 0]], # Z
[[1, 0, 0], [1, 1, 1]], # J
[[0, 0, 1], [1, 1, 1]] # L
]
# ゲームスクリーンの設定
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Tetris")
# テトリミノクラス
class Tetromino:
def __init__(self):
self.shape = random.choice(SHAPES)
self.color = random.choice(COLORS)
self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2
self.y = 0
def rotate(self):
self.shape = [list(row) for row in zip(*self.shape[::-1])]
# グリッドの初期化
grid = [[BLACK for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
def draw_grid():
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
pygame.draw.rect(screen, grid[y][x], (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE), 0)
pygame.draw.rect(screen, WHITE, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE), 1)
def check_collision(shape, offset):
off_x, off_y = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
if x + off_x < 0 or x + off_x >= GRID_WIDTH or y + off_y >= GRID_HEIGHT or grid[y + off_y][x + off_x] != BLACK:
return True
return False
def merge(shape, offset, color):
off_x, off_y = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
grid[y + off_y][x + off_x] = color
def remove_line():
global grid
lines_removed = 0
new_grid = [row for row in grid if any(cell == BLACK for cell in row)]
lines_removed = len(grid) - len(new_grid)
grid = [[BLACK for _ in range(GRID_WIDTH)] for _ in range(lines_removed)] + new_grid
return lines_removed
def game_over():
for cell in grid[0]:
if cell != BLACK:
return True
return False
def draw_text(text, size, color, x, y):
font = pygame.font.Font(pygame.font.get_default_font(), size)
surface = font.render(text, True, color)
rect = surface.get_rect()
rect.topleft = (x, y)
screen.blit(surface, rect)
# スコア
score = 0
# 経過時間
elapsed_time = 0
# メインゲームループ
def game_loop():
global grid, score, elapsed_time
clock = pygame.time.Clock()
fall_time = 0
speed_increase_time = 0 # 速度を増加させる時間を計測
speed_reset_interval = 60000 # 60秒ごとに速度をリセット
current_piece = Tetromino()
running = True
while running:
screen.fill(BLACK)
fall_speed = max(100, 500 - (speed_increase_time // 1000) * 10) # 時間経過で落下速度が速くなる
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
if not check_collision(current_piece.shape, (current_piece.x - 1, current_piece.y)):
current_piece.x -= 1
elif event.key == pygame.K_RIGHT:
if not check_collision(current_piece.shape, (current_piece.x + 1, current_piece.y)):
current_piece.x += 1
elif event.key == pygame.K_DOWN:
if not check_collision(current_piece.shape, (current_piece.x, current_piece.y + 1)):
current_piece.y += 1
elif event.key == pygame.K_UP:
rotated_shape = [list(row) for row in zip(*current_piece.shape[::-1])]
if not check_collision(rotated_shape, (current_piece.x, current_piece.y)):
current_piece.shape = rotated_shape
fall_time += clock.get_rawtime()
elapsed_time += clock.get_rawtime()
speed_increase_time += clock.get_rawtime()
clock.tick()
if speed_increase_time > speed_reset_interval:
speed_increase_time = 0 # 速度増加時間をリセット
if fall_time > fall_speed:
if not check_collision(current_piece.shape, (current_piece.x, current_piece.y + 1)):
current_piece.y += 1
else:
merge(current_piece.shape, (current_piece.x, current_piece.y), current_piece.color)
lines_removed = remove_line()
score += lines_removed * 100
if game_over():
running = False
current_piece = Tetromino()
fall_time = 0
draw_grid()
for y, row in enumerate(current_piece.shape):
for x, cell in enumerate(row):
if cell:
pygame.draw.rect(screen, current_piece.color, ((current_piece.x + x) * GRID_SIZE, (current_piece.y + y) * GRID_SIZE, GRID_SIZE, GRID_SIZE), 0)
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if grid[y][x] != BLACK:
pygame.draw.rect(screen, grid[y][x], (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE), 0)
draw_text(f"Score: {score}", 20, WHITE, 10, 10)
pygame.display.flip()
pygame.quit()
game_loop()
デスクトップに置いてターミナルに打ち込めばpython3 tetris.pyでプレイできます。
いちばんやさしい Python入門教室 改訂第2版
ただ根本的なことは何一つわかっていないので、何度修正をお願いしても、いつまで経っても変わらないことはわかります。ブロックが消えてしまったり、スコアーが表示されなかったり、、そういうところは本を読んでchatGPTと二人三脚で勉強していくのがベストかと思います。
あれから40年近く経ってしまい今では私が自分でテトリスを作れるようになってしまいました。作ってもらうと言ったほうがいいと思います。Macを使ってゲームを作るにはから始まって、、、テトリスのゲームを作ってと打ち込めばどうしたら良いのか?
PythonとPygameのインストールのやり方から始まり、至れり尽くせりです。ただ初めから思ったようなテトリスができないので何度か修正を繰り返すことが必要です。毎回違うテトリスができるのも事実です。
元々Python何?から始まっているので、ここまでできただけでも感動です。
chatGPTが教えてくれたこと↓
その後最終的にできたのがこちらのコード。
import pygame
import random
pygame.init()
# 定数
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600
GRID_SIZE = 30
GRID_WIDTH, GRID_HEIGHT = SCREEN_WIDTH // GRID_SIZE, SCREEN_HEIGHT // GRID_SIZE
# 色の定義
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
COLORS = [RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, ORANGE]
# テトリミノの形
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[1, 1, 0], [0, 1, 1]], # S
[[0, 1, 1], [1, 1, 0]], # Z
[[1, 0, 0], [1, 1, 1]], # J
[[0, 0, 1], [1, 1, 1]] # L
]
# ゲームスクリーンの設定
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Tetris")
# テトリミノクラス
class Tetromino:
def __init__(self):
self.shape = random.choice(SHAPES)
self.color = random.choice(COLORS)
self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2
self.y = 0
def rotate(self):
self.shape = [list(row) for row in zip(*self.shape[::-1])]
# グリッドの初期化
grid = [[BLACK for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
def draw_grid():
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
pygame.draw.rect(screen, grid[y][x], (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE), 0)
pygame.draw.rect(screen, WHITE, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE), 1)
def check_collision(shape, offset):
off_x, off_y = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
if x + off_x < 0 or x + off_x >= GRID_WIDTH or y + off_y >= GRID_HEIGHT or grid[y + off_y][x + off_x] != BLACK:
return True
return False
def merge(shape, offset, color):
off_x, off_y = offset
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
grid[y + off_y][x + off_x] = color
def remove_line():
global grid
lines_removed = 0
new_grid = [row for row in grid if any(cell == BLACK for cell in row)]
lines_removed = len(grid) - len(new_grid)
grid = [[BLACK for _ in range(GRID_WIDTH)] for _ in range(lines_removed)] + new_grid
return lines_removed
def game_over():
for cell in grid[0]:
if cell != BLACK:
return True
return False
def draw_text(text, size, color, x, y):
font = pygame.font.Font(pygame.font.get_default_font(), size)
surface = font.render(text, True, color)
rect = surface.get_rect()
rect.topleft = (x, y)
screen.blit(surface, rect)
# スコア
score = 0
# 経過時間
elapsed_time = 0
# メインゲームループ
def game_loop():
global grid, score, elapsed_time
clock = pygame.time.Clock()
fall_time = 0
speed_increase_time = 0 # 速度を増加させる時間を計測
speed_reset_interval = 60000 # 60秒ごとに速度をリセット
current_piece = Tetromino()
running = True
while running:
screen.fill(BLACK)
fall_speed = max(100, 500 - (speed_increase_time // 1000) * 10) # 時間経過で落下速度が速くなる
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
if not check_collision(current_piece.shape, (current_piece.x - 1, current_piece.y)):
current_piece.x -= 1
elif event.key == pygame.K_RIGHT:
if not check_collision(current_piece.shape, (current_piece.x + 1, current_piece.y)):
current_piece.x += 1
elif event.key == pygame.K_DOWN:
if not check_collision(current_piece.shape, (current_piece.x, current_piece.y + 1)):
current_piece.y += 1
elif event.key == pygame.K_UP:
rotated_shape = [list(row) for row in zip(*current_piece.shape[::-1])]
if not check_collision(rotated_shape, (current_piece.x, current_piece.y)):
current_piece.shape = rotated_shape
fall_time += clock.get_rawtime()
elapsed_time += clock.get_rawtime()
speed_increase_time += clock.get_rawtime()
clock.tick()
if speed_increase_time > speed_reset_interval:
speed_increase_time = 0 # 速度増加時間をリセット
if fall_time > fall_speed:
if not check_collision(current_piece.shape, (current_piece.x, current_piece.y + 1)):
current_piece.y += 1
else:
merge(current_piece.shape, (current_piece.x, current_piece.y), current_piece.color)
lines_removed = remove_line()
score += lines_removed * 100
if game_over():
running = False
current_piece = Tetromino()
fall_time = 0
draw_grid()
for y, row in enumerate(current_piece.shape):
for x, cell in enumerate(row):
if cell:
pygame.draw.rect(screen, current_piece.color, ((current_piece.x + x) * GRID_SIZE, (current_piece.y + y) * GRID_SIZE, GRID_SIZE, GRID_SIZE), 0)
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if grid[y][x] != BLACK:
pygame.draw.rect(screen, grid[y][x], (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE, GRID_SIZE), 0)
draw_text(f"Score: {score}", 20, WHITE, 10, 10)
pygame.display.flip()
pygame.quit()
game_loop()
デスクトップに置いてターミナルに打ち込めばpython3 tetris.pyでプレイできます。
いちばんやさしい Python入門教室 改訂第2版
ただ根本的なことは何一つわかっていないので、何度修正をお願いしても、いつまで経っても変わらないことはわかります。ブロックが消えてしまったり、スコアーが表示されなかったり、、そういうところは本を読んでchatGPTと二人三脚で勉強していくのがベストかと思います。