🌸 「なでしこ」
>
🍯 「貯蔵庫」
🐍スネークゲーム
🌟新規
📒一覧
🔌
🔍検索
🚪ログイン
🐍スネークゲーム 📖
自分を食べてはいけない。りんごを食べてスコアを伸ばそう
プログラム:
(→大)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>🐍 スネークゲーム - PyScript</title> <link rel="stylesheet" href="https://pyscript.net/releases/2023.11.2/core.css"> <script type="module" src="https://pyscript.net/releases/2023.11.2/core.js"></script> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { min-height: 100vh; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); display: flex; flex-direction: column; align-items: center; justify-content: center; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #fff; padding: 20px; } h1 { font-size: 2.5rem; margin-bottom: 10px; text-shadow: 0 0 20px rgba(0, 255, 136, 0.5); letter-spacing: 2px; } .game-container { background: rgba(255, 255, 255, 0.05); border-radius: 20px; padding: 30px; backdrop-filter: blur(10px); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); } #game-canvas { border: 3px solid #00ff88; border-radius: 10px; box-shadow: 0 0 30px rgba(0, 255, 136, 0.3); display: block; } .info-panel { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; padding: 15px 20px; background: rgba(0, 0, 0, 0.3); border-radius: 10px; } .score-display { font-size: 1.5rem; font-weight: bold; } .score-display span { color: #00ff88; } #start-btn { padding: 12px 30px; font-size: 1.1rem; font-weight: bold; background: linear-gradient(45deg, #00ff88, #00d4ff); border: none; border-radius: 25px; color: #1a1a2e; cursor: pointer; transition: all 0.3s ease; } #start-btn:hover { transform: scale(1.05); box-shadow: 0 0 20px rgba(0, 255, 136, 0.5); } .instructions { margin-top: 20px; text-align: center; opacity: 0.7; font-size: 0.9rem; } .mobile-controls { display: none; margin-top: 20px; gap: 10px; } .control-row { display: flex; justify-content: center; gap: 10px; } .control-btn { width: 60px; height: 60px; font-size: 1.5rem; background: rgba(0, 255, 136, 0.2); border: 2px solid #00ff88; border-radius: 10px; color: #fff; cursor: pointer; transition: all 0.2s; } .control-btn:active { background: rgba(0, 255, 136, 0.5); transform: scale(0.95); } @media (max-width: 600px) { .mobile-controls { display: flex; flex-direction: column; } } </style> </head> <body> <h1>🐍 スネークゲーム</h1> <div class="game-container"> <canvas id="game-canvas" width="400" height="400"></canvas> <div class="info-panel"> <div class="score-display">スコア: <span id="score">0</span></div> <button id="start-btn" py-click="start_game">ゲーム開始</button> </div> <div class="mobile-controls"> <div class="control-row"> <button class="control-btn" py-click="move_up">↑</button> </div> <div class="control-row"> <button class="control-btn" py-click="move_left">←</button> <button class="control-btn" py-click="move_down">↓</button> <button class="control-btn" py-click="move_right">→</button> </div> </div> </div> <div class="instructions"> <p>⌨️ 矢印キーまたはWASDで操作 | 🍎 りんごを食べてスコアアップ!</p> </div> <script type="py"> from pyscript import document, window from pyodide.ffi import create_proxy import random # ゲーム設定 GRID_SIZE = 20 CANVAS_SIZE = 400 CELL_COUNT = CANVAS_SIZE // GRID_SIZE # ゲーム状態 snake = [(5, 5), (4, 5), (3, 5)] direction = [1, 0] next_direction = [1, 0] food = [10, 10] score = 0 game_over = False running = False interval_id = None # キャンバス取得 canvas = document.getElementById("game-canvas") ctx = canvas.getContext("2d") def spawn_food(): global food while True: x = random.randint(0, CELL_COUNT - 1) y = random.randint(0, CELL_COUNT - 1) if (x, y) not in snake: food = [x, y] break def draw(): global ctx # 背景 ctx.fillStyle = "#1a1a2e" ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE) # グリッド線 ctx.strokeStyle = "rgba(255, 255, 255, 0.05)" ctx.lineWidth = 1 for i in range(CELL_COUNT + 1): ctx.beginPath() ctx.moveTo(i * GRID_SIZE, 0) ctx.lineTo(i * GRID_SIZE, CANVAS_SIZE) ctx.stroke() ctx.beginPath() ctx.moveTo(0, i * GRID_SIZE) ctx.lineTo(CANVAS_SIZE, i * GRID_SIZE) ctx.stroke() # 食べ物 fx, fy = food[0], food[1] ctx.fillStyle = "#ff4757" ctx.beginPath() ctx.arc(fx * GRID_SIZE + GRID_SIZE // 2, fy * GRID_SIZE + GRID_SIZE // 2, GRID_SIZE // 2 - 2, 0, 3.14159 * 2) ctx.fill() # 蛇 for i, pos in enumerate(snake): x, y = pos[0], pos[1] if i == 0: ctx.fillStyle = "#00ff88" else: green_value = max(100, 255 - i * 10) ctx.fillStyle = "rgb(0, " + str(green_value) + ", 100)" ctx.fillRect(x * GRID_SIZE + 2, y * GRID_SIZE + 2, GRID_SIZE - 4, GRID_SIZE - 4) # ゲームオーバー表示 if game_over: ctx.fillStyle = "rgba(0, 0, 0, 0.7)" ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE) ctx.fillStyle = "#ff4757" ctx.font = "bold 36px sans-serif" ctx.textAlign = "center" ctx.fillText("GAME OVER", CANVAS_SIZE // 2, CANVAS_SIZE // 2 - 20) ctx.fillStyle = "#fff" ctx.font = "20px sans-serif" ctx.fillText("スコア: " + str(score), CANVAS_SIZE // 2, CANVAS_SIZE // 2 + 20) def update(): global snake, direction, next_direction, score, game_over, running, interval_id if game_over or not running: return direction[0] = next_direction[0] direction[1] = next_direction[1] # 新しい頭の位置 head_x, head_y = snake[0][0], snake[0][1] new_head = ((head_x + direction[0]) % CELL_COUNT, (head_y + direction[1]) % CELL_COUNT) # 自分自身との衝突判定 if new_head in snake: game_over = True running = False if interval_id is not None: window.clearInterval(interval_id) document.getElementById("start-btn").textContent = "リトライ" draw() return # 蛇を移動 snake.insert(0, new_head) # 食べ物を食べたか if new_head[0] == food[0] and new_head[1] == food[1]: score += 10 document.getElementById("score").textContent = str(score) spawn_food() else: snake.pop() draw() def start_game(event=None): global snake, direction, next_direction, score, game_over, running, interval_id # リセット snake = [(5, 5), (4, 5), (3, 5)] direction = [1, 0] next_direction = [1, 0] score = 0 game_over = False running = True document.getElementById("score").textContent = "0" document.getElementById("start-btn").textContent = "リスタート" spawn_food() # 既存のインターバルをクリア if interval_id is not None: window.clearInterval(interval_id) # ゲームループ開始 update_proxy = create_proxy(update) interval_id = window.setInterval(update_proxy, 120) draw() def handle_key(event): global next_direction, direction key = event.key.lower() if key == "arrowup" or key == "w": if direction[1] != 1: next_direction = [0, -1] elif key == "arrowdown" or key == "s": if direction[1] != -1: next_direction = [0, 1] elif key == "arrowleft" or key == "a": if direction[0] != 1: next_direction = [-1, 0] elif key == "arrowright" or key == "d": if direction[0] != -1: next_direction = [1, 0] if key in ["arrowup", "arrowdown", "arrowleft", "arrowright"]: event.preventDefault() def move_up(event=None): global next_direction, direction if direction[1] != 1: next_direction = [0, -1] def move_down(event=None): global next_direction, direction if direction[1] != -1: next_direction = [0, 1] def move_left(event=None): global next_direction, direction if direction[0] != 1: next_direction = [-1, 0] def move_right(event=None): global next_direction, direction if direction[0] != -1: next_direction = [1, 0] # キーボードイベント設定 key_proxy = create_proxy(handle_key) document.addEventListener("keydown", key_proxy) # 初期描画 draw() </script> </body> </html>
プログラムを実行
⭐ TkoTko 作
タイトル:
🐍スネークゲーム
ライセンス:
未指定 (未指定/貯蔵庫のみ)
タイプ:
html
タグ:
-
利用バージョン:
3.7.14
作成日時:
2026/01/29 11:06
公開の投稿
ログイン
して★を付けよう!
📝作品を編集
作品公開情報
📍この作品のURL:
📍アプリ(即時実行)のURL:
📍アプリ(実行ボタンあり)のURL:
📍ブログパーツ:
上記HTML↑をブログに貼り付けることでアプリを埋め込めます。
📍ライブラリ直リンク - 『!「***」を取込』で使うとき:
通報数:
0
通報って何?