一応何とかそれらしきものを表示させることはできたが、一瞬だけであり、すぐに表示がおかしくなってしまった。
まだまだ手直ししなければならない。
"""
CATIA Tetris Game - 動的更新版
1つのスケッチ内でリアルタイムに更新されるバージョン
必要なライブラリ:
pip install pywin32
使用方法:
1. CATIA V5R21を起動
2. このスクリプトを実行
3. 1つのスケッチ内でゲームが動きます
"""
import time
import random
import sys
import win32com.client
# テトリミノの形状定義
TETROMINOS = {
'I': [[1, 1, 1, 1]],
'O': [[1, 1], [1, 1]],
'T': [[0, 1, 0], [1, 1, 1]],
'S': [[0, 1, 1], [1, 1, 0]],
'Z': [[1, 1, 0], [0, 1, 1]],
'J': [[1, 0, 0], [1, 1, 1]],
'L': [[0, 0, 1], [1, 1, 1]]
}
def check_catia():
"""CATIA接続確認"""
try:
catia = win32com.client.Dispatch("CATIA.Application")
version = catia.SystemConfiguration.Version
print("✓ CATIAへの接続に成功")
print(f" バージョン: {version}")
return True
except Exception as e:
print(f"✗ CATIA接続失敗: {e}")
return False
class CATIATetrisDynamic:
def __init__(self):
print("\n" + "=" * 60)
print("CATIA Tetris - 動的更新版 初期化中...")
print("=" * 60)
# CATIA接続
self.catia = win32com.client.Dispatch("CATIA.Application")
self.catia.Visible = True
self.catia.DisplayFileAlerts = False
self.documents = self.catia.Documents
# 新規Partドキュメント作成
print("\n新しいPartドキュメントを作成...")
self.part_document = self.documents.Add("Part")
self.part = self.part_document.Part
# ゲームボード設定
self.board_width = 10
self.board_height = 20
self.block_size = 10.0 # mm
# ゲーム状態
self.board = [[0 for _ in range(self.board_width)] for _ in range(self.board_height)]
self.current_piece = None
self.current_shape = None
self.current_x = 0
self.current_y = 0
self.score = 0
self.game_over = False
self.lines_cleared_total = 0
# Body取得
self.bodies = self.part.Bodies
self.body = self.bodies.Item(1)
self.sketches = self.body.Sketches
# XY平面取得
self.origin_elements = self.part.OriginElements
self.xy_plane = self.origin_elements.PlaneXY
# ゲーム用スケッチを1つだけ作成
print("\nゲーム用スケッチを作成...")
self.game_sketch = self.sketches.Add(self.xy_plane)
self.game_sketch.Name = "TetrisGame"
print("✓ 初期化完了")
print(f" ボードサイズ: {self.board_width} x {self.board_height}")
print(f" ブロックサイズ: {self.block_size} mm")
print("\n【重要】")
print(" 1つのスケッチ 'TetrisGame' 内でゲームが動きます")
print(" スケッチは常に編集モードのままです")
def clear_sketch(self, factory):
"""スケッチ内のすべての要素を削除"""
try:
# V5R21では、HybridShapeFactory経由で要素にアクセス
# しかし、2D Sketchの場合は直接要素を削除できないため
# 新しい要素を描画することで上書きする方式を取る
# 実際には、すべての線を削除する方法がないため、
# 代わりに白色(背景色)で上書きするか、
# スケッチを閉じて再度開く方式を使用
pass
except Exception as e:
print(f"クリアエラー: {e}")
def draw_board(self):
"""ボードを描画(既存のスケッチを更新)"""
try:
# スケッチを閉じてから再度開く(これによりクリアされる)
try:
self.game_sketch.CloseEdition()
except:
pass
# スケッチを再度開く
factory = self.game_sketch.OpenEdition()
border_width = self.board_width * self.block_size
border_height = self.board_height * self.block_size
# 外枠
factory.CreateLine(0, 0, border_width, 0)
factory.CreateLine(border_width, 0, border_width, border_height)
factory.CreateLine(border_width, border_height, 0, border_height)
factory.CreateLine(0, border_height, 0, 0)
# グリッド
for i in range(1, self.board_width):
x = i * self.block_size
factory.CreateLine(x, 0, x, border_height)
for i in range(1, self.board_height):
y = i * self.block_size
factory.CreateLine(0, y, border_width, y)
# 固定ブロック
for y in range(self.board_height):
for x in range(self.board_width):
if self.board[y][x] != 0:
self.draw_filled_block(factory, x, y)
# 現在のピース
if self.current_piece:
for y, row in enumerate(self.current_piece):
for x, cell in enumerate(row):
if cell and self.current_y + y >= 0:
self.draw_current_block(factory, self.current_x + x, self.current_y + y)
# スケッチは開いたまま(次の更新のため)
# 画面を強制更新
self.part.Update()
# ビューアを更新
try:
windows = self.catia.Windows
if windows.Count > 0:
active_window = windows.Item(1)
active_window.ActiveViewer.Reframe()
except:
pass
except Exception as e:
print(f"描画エラー: {e}")
def draw_filled_block(self, factory, x, y):
"""固定ブロック描画"""
x_pos = x * self.block_size
y_pos = y * self.block_size
# 四角形
factory.CreateLine(x_pos, y_pos, x_pos + self.block_size, y_pos)
factory.CreateLine(x_pos + self.block_size, y_pos, x_pos + self.block_size, y_pos + self.block_size)
factory.CreateLine(x_pos + self.block_size, y_pos + self.block_size, x_pos, y_pos + self.block_size)
factory.CreateLine(x_pos, y_pos + self.block_size, x_pos, y_pos)
# X印
factory.CreateLine(x_pos, y_pos, x_pos + self.block_size, y_pos + self.block_size)
factory.CreateLine(x_pos + self.block_size, y_pos, x_pos, y_pos + self.block_size)
def draw_current_block(self, factory, x, y):
"""現在のピース描画"""
x_pos = x * self.block_size
y_pos = y * self.block_size
offset = 1.0
# 外側
factory.CreateLine(x_pos, y_pos, x_pos + self.block_size, y_pos)
factory.CreateLine(x_pos + self.block_size, y_pos, x_pos + self.block_size, y_pos + self.block_size)
factory.CreateLine(x_pos + self.block_size, y_pos + self.block_size, x_pos, y_pos + self.block_size)
factory.CreateLine(x_pos, y_pos + self.block_size, x_pos, y_pos)
# 内側
factory.CreateLine(x_pos + offset, y_pos + offset, x_pos + self.block_size - offset, y_pos + offset)
factory.CreateLine(x_pos + self.block_size - offset, y_pos + offset, x_pos + self.block_size - offset, y_pos + self.block_size - offset)
factory.CreateLine(x_pos + self.block_size - offset, y_pos + self.block_size - offset, x_pos + offset, y_pos + self.block_size - offset)
factory.CreateLine(x_pos + offset, y_pos + self.block_size - offset, x_pos + offset, y_pos + offset)
def spawn_piece(self):
"""新ピース生成"""
self.current_shape = random.choice(list(TETROMINOS.keys()))
self.current_piece = [row[:] for row in TETROMINOS[self.current_shape]]
self.current_x = self.board_width // 2 - len(self.current_piece[0]) // 2
self.current_y = 0
if self.check_collision():
self.game_over = True
return False
print(f"新ピース: {self.current_shape}")
return True
def check_collision(self, offset_x=0, offset_y=0, piece=None):
"""衝突判定"""
if piece is None:
piece = self.current_piece
for y, row in enumerate(piece):
for x, cell in enumerate(row):
if cell:
new_x = self.current_x + x + offset_x
new_y = self.current_y + y + offset_y
if new_x < 0 or new_x >= self.board_width:
return True
if new_y >= self.board_height:
return True
if new_y >= 0 and self.board[new_y][new_x]:
return True
return False
def lock_piece(self):
"""ピース固定"""
for y, row in enumerate(self.current_piece):
for x, cell in enumerate(row):
if cell and self.current_y + y >= 0:
self.board[self.current_y + y][self.current_x + x] = 1
self.clear_lines()
return self.spawn_piece()
def clear_lines(self):
"""ライン消去"""
lines_cleared = 0
y = self.board_height - 1
while y >= 0:
if all(self.board[y]):
del self.board[y]
self.board.insert(0, [0 for _ in range(self.board_width)])
lines_cleared += 1
else:
y -= 1
if lines_cleared > 0:
self.lines_cleared_total += lines_cleared
points = lines_cleared * 100 * lines_cleared
self.score += points
print(f"★ {lines_cleared}ライン! +{points}点 (計{self.score}点)")
def move_down(self):
if not self.check_collision(offset_y=1):
self.current_y += 1
return True
else:
return self.lock_piece()
def move_left(self):
if not self.check_collision(offset_x=-1):
self.current_x -= 1
return True
return False
def move_right(self):
if not self.check_collision(offset_x=1):
self.current_x += 1
return True
return False
def rotate(self):
if len(self.current_piece) == 0:
return False
rotated = [[self.current_piece[y][x]
for y in range(len(self.current_piece) - 1, -1, -1)]
for x in range(len(self.current_piece[0]))]
if not self.check_collision(piece=rotated):
self.current_piece = rotated
return True
return False
def play_auto(self, moves=50, delay=0.3):
"""自動プレイ"""
print("\n" + "=" * 60)
print("自動プレイ開始")
print("CATIAの 'TetrisGame' スケッチが更新されます")
print("=" * 60)
self.spawn_piece()
self.draw_board()
print("\n最初のフレームを描画しました")
print("CATIAウィンドウで 'TetrisGame' スケッチが見えますか?")
input("確認したらEnterでゲーム開始...")
move_count = 0
while move_count < moves and not self.game_over:
actions = ['left', 'right', 'rotate', 'down']
weights = [1, 1, 1, 6]
action = random.choices(actions, weights=weights)[0]
action_name = ""
if action == 'left':
if self.move_left():
action_name = "←"
elif action == 'right':
if self.move_right():
action_name = "→"
elif action == 'rotate':
if self.rotate():
action_name = "↻"
else:
if not self.move_down():
action_name = "着地"
else:
action_name = "↓"
# 画面を更新
self.draw_board()
move_count += 1
print(f"[{move_count:2d}/{moves}] {action_name:4s} | スコア:{self.score:4d} | ライン:{self.lines_cleared_total:2d}")
time.sleep(delay)
# 最後にスケッチを閉じる
try:
self.game_sketch.CloseEdition()
except:
pass
print("\n" + "=" * 60)
if self.game_over:
print("ゲームオーバー!")
else:
print("デモ終了")
print(f"スコア: {self.score}点 | ライン: {self.lines_cleared_total}")
print("=" * 60)
def main():
print("\n")
print("╔" + "═" * 58 + "╗")
print("║" + " " * 58 + "║")
print("║" + " CATIA Tetris - 動的更新版".center(58) + "║")
print("║" + " (1つのスケッチ内で動きます)".center(58) + "║")
print("║" + " " * 58 + "║")
print("╚" + "═" * 58 + "╝")
print("\n")
if not check_catia():
print("\nCATIAを起動してから再実行してください")
input("\nEnterキーで終了...")
return
try:
game = CATIATetrisDynamic()
moves = input("\n何手プレイ? (デフォルト:50): ").strip()
moves = int(moves) if moves.isdigit() else 50
delay = input("速度(秒)? (デフォルト:0.3): ").strip()
delay = float(delay) if delay else 0.3
game.play_auto(moves=moves, delay=delay)
except KeyboardInterrupt:
print("\n\n中断しました")
except Exception as e:
print(f"\n❌ エラー: {e}")
import traceback
traceback.print_exc()
input("\nEnterキーで終了...")
if __name__ == "__main__":
main()
コメント
コメントを投稿