CATIAでテトリス

一応何とかそれらしきものを表示させることはできたが、一瞬だけであり、すぐに表示がおかしくなってしまった。
まだまだ手直ししなければならない。


""" 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()

コメント

このブログの人気の投稿

ミライアイ内服薬は薬事法違反で、ほとんど効果がない詐欺ですか?

最高裁での上告理由書受理・却下の判断基準について

裁判官の忌避申立書の作成例