以下は、PyCATIAを使用してCATIAでテトリスをプレイできるように書き換えたPythonコードです。この実装では、CATIAの3D空間でテトリミノを表現し、キーボード操作でゲームをプレイできます。
```python
import pycatia
from pycatia import catia
import random
import time
import pythoncom
import win32api
import win32con
# CATIA初期化
caa = catia()
documents = caa.documents
documents.add("Part")
part = caa.active_document.part
factory = part.shape_factory
bodies = part.bodies
body = bodies.add()
# ゲーム定数
BLOCK_SIZE = 10 # ブロックサイズ(mm)
GRID_WIDTH = 10
GRID_HEIGHT = 20
FALL_SPEED = 0.5 # 落下間隔(秒)
# テトリミノの形状と色
SHAPES = [
1, 1, 1, 1, # I
[[1, 1], [1, 1]], # O
[[1, 1, 1], [0, 1, 0]], # T
[[1, 1, 1], [1, 0, 0]], # L
[[1, 1, 1], [0, 0, 1]], # J
[[0, 1, 1], [1, 1, 0]], # S
[[1, 1, 0], [0, 1, 1]] # Z
]
COLORS = [
(0, 255, 255), # CYAN
(255, 255, 0), # YELLOW
(128, 0, 128), # PURPLE
(255, 165, 0), # ORANGE
(0, 0, 255), # BLUE
(0, 255, 0), # GREEN
(255, 0, 0) # RED
]
class Tetrimino:
def __init__(self):
self.shape_idx = random.randint(0, len(SHAPES) - 1)
self.shape = SHAPES[self.shape_idx]
self.color = COLORS[self.shape_idx]
self.x = GRID_WIDTH // 2 - len(self.shape[0]) // 2
self.y = 0
self.blocks =
def rotate(self):
rows = len(self.shape)
cols = len(self.shape[0])
rotated = [[0 for _ in range(rows)] for _ in range(cols)]
for r in range(rows):
for c in range(cols):
rotated[c][rows - 1 - r] = self.shape[r][c]
return rotated
def create_block(x, y, color):
"""3Dブロックを作成"""
box = factory.add_new_box_along_axes(
[x * BLOCK_SIZE, y * BLOCK_SIZE, 0],
[BLOCK_SIZE, 0, 0],
[0, BLOCK_SIZE, 0],
[0, 0, BLOCK_SIZE]
)
box.color = color
body.append_hybrid_shape(box)
return box
def clear_blocks(blocks):
"""ブロックを削除"""
for block in blocks:
try:
block.delete()
except:
pass
part.update()
def draw_tetrimino(tetrimino):
"""テトリミノを描画"""
clear_blocks(tetrimino.blocks)
tetrimino.blocks =
for y, row in enumerate(tetrimino.shape):
for x, cell in enumerate(row):
if cell:
block = create_block(
tetrimino.x + x,
tetrimino.y + y,
tetrimino.color
)
tetrimino.blocks.append(block)
part.update()
def draw_grid(grid):
"""グリッドを描画"""
for y in range(GRID_HEIGHT):
for x in range(GRID_WIDTH):
if grid[y][x] != 0:
create_block(x, y, COLORS[grid[y][x] - 1])
part.update()
def is_valid_position(tetrimino, grid):
"""有効な位置かチェック"""
for y, row in enumerate(tetrimino.shape):
for x, cell in enumerate(row):
if cell:
if (tetrimino.x + x < 0 or
tetrimino.x + x >= GRID_WIDTH or
tetrimino.y + y >= GRID_HEIGHT or
(tetrimino.y + y >= 0 and grid[tetrimino.y + y][tetrimino.x + x] != 0)):
return False
return True
def clear_lines(grid):
"""行を消去"""
lines_cleared = 0
for y in range(GRID_HEIGHT - 1, -1, -1):
if all(grid[y]):
lines_cleared += 1
for y2 in range(y, 0, -1):
grid[y2] = grid[y2 - 1][:]
grid[0] = [0] * GRID_WIDTH
# スコア計算
score = 0
if lines_cleared == 1:
score = 100
elif lines_cleared == 2:
score = 300
elif lines_cleared == 3:
score = 500
elif lines_cleared == 4:
score = 800
return score
def check_game_over(grid):
"""ゲームオーバーチェック"""
return any(cell != 0 for cell in grid[0])
def main():
# グリッド初期化
grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
current_tetrimino = Tetrimino()
next_tetrimino = Tetrimino()
game_over = False
score = 0
last_fall_time = time.time()
# メインゲームループ
while not game_over:
pythoncom.PumpWaitingMessages()
# キー入力処理
if win32api.GetAsyncKeyState(win32con.VK_LEFT):
current_tetrimino.x -= 1
if not is_valid_position(current_tetrimino, grid):
current_tetrimino.x += 1
draw_tetrimino(current_tetrimino)
time.sleep(0.1)
elif win32api.GetAsyncKeyState(win32con.VK_RIGHT):
current_tetrimino.x += 1
if not is_valid_position(current_tetrimino, grid):
current_tetrimino.x -= 1
draw_tetrimino(current_tetrimino)
time.sleep(0.1)
elif win32api.GetAsyncKeyState(win32con.VK_UP):
rotated = current_tetrimino.rotate()
old_shape = current_tetrimino.shape
current_tetrimino.shape = rotated
if not is_valid_position(current_tetrimino, grid):
current_tetrimino.shape = old_shape
draw_tetrimino(current_tetrimino)
time.sleep(0.1)
elif win32api.GetAsyncKeyState(win32con.VK_DOWN):
current_tetrimino.y += 1
if not is_valid_position(current_tetrimino, grid):
current_tetrimino.y -= 1
draw_tetrimino(current_tetrimino)
time.sleep(0.05)
# 自動落下
if time.time() - last_fall_time > FALL_SPEED:
last_fall_time = time.time()
current_tetrimino.y += 1
if not is_valid_position(current_tetrimino, grid):
current_tetrimino.y -= 1
# グリッドに固定
for y, row in enumerate(current_tetrimino.shape):
for x, cell in enumerate(row):
if cell and current_tetrimino.y + y >= 0:
grid[current_tetrimino.y + y][current_tetrimino.x + x] = current_tetrimino.shape_idx + 1
# 行消去
score += clear_lines(grid)
# 新しいテトリミノ
clear_blocks(current_tetrimino.blocks)
current_tetrimino = next_tetrimino
next_tetrimino = Tetrimino()
# ゲームオーバーチェック
if check_game_over(grid):
game_over = True
draw_tetrimino(current_tetrimino)
# ゲームオーバー処理
print(f"Game Over! Final Score: {score}")
clear_blocks(current_tetrimino.blocks)
draw_grid(grid)
if __name__ == "__main__":
main()
```
### この実装の特徴
1. **3Dテトリスの実現**:
- CATIAの3D空間で立方体ブロックを使用してテトリミノを表現
- 各ブロックはCATIAのハイブリッド形状として作成
2. **キーボード操作**:
- 左/右キーで移動、上キーで回転、下キーで加速落下
3. **ゲームロジック**:
- 衝突判定、回転、行消去などの基本機能を保持
4. **パフォーマンス対策**:
- テトリミノ移動時に前のブロックを削除
- 必要時のみ画面更新
### 実行手順
1. CATIA V5を起動
2. このスクリプトをPyCATIA環境で実行
3. 矢印キーでテトリミノを操作
### 注意点
- PyCATIAのインストールが必要 (`pip install pycatia`)
- CATIAのCOMインターフェースを使用するため、CATIAはあらかじめ起動しておく
- 3D表示のため、2D版より若干動作が重くなる可能性あり
- ゲームオーバー時のリスタート機能は未実装(再度スクリプトを実行する必要あり)
この実装では、CADソフトならではの3D表示を活かしつつ、テトリス本来のゲームプレイが可能です。必要に応じて落下速度やグリッドサイズを調整できます。