見出し画像

ゲーム開発、1分で終了!プログラミング未経験者でもChatGPTを使えばわずか3ステップでゲームを作れた方法がヤバすぎた

こんにちは、レジェンドです。

プログラムがまったくわからない人でも、1分でゲームを作れる?

そんな嘘みたいな話が、実際に起こりました。

Xでo3-mini-highを使ってゲームを作られてる方を拝見したので、「僕も作ってみたいな~」と簡単なゲームを作ってみようとチャレンジしてみました。

でも、プログラミング経験ゼロの僕にできるのか…?

こたえはYES

作ったゲームは↓↓↓

※ゲームが動くのは10秒当たりから

動物の落ち物パズルゲームで、動物の顔のアイコンが上から落ちてきて、縦か横に4つ並ぶと消えるというシンプルなゲームです。

このゲームを、プログラミングを1秒も勉強したことがない人間が作っちゃいました。凄くないですか????笑

しかも、

ゲーム開発はわずか3ステップ、しかも時間は1分(笑)


作り方は以下です。

ステップ1.ChatGPTを開いて「o3-mini-high」を選択する

まずは、ChatGPTを開いて「o3-mini-high」を選択します。

※4oでも作れます

ステップ2 作りたいゲームの内容を指示する

ブロック崩しとかシューティングゲームとか適当に伝えればいOKです。

僕の場合、

ブラウザで遊ぶための落ち物パズルゲームのコードを生成してください。
縦、横4つ並ぶと消えるルールです。
動物はパンダ、犬、トラ、ウサギでお願いします。
ポーズ機能を付けてください。

と、指示しました。

そうすると、以下のコードを生成してくれました。


<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>動物の落ち物パズルゲーム(ルール変更・ポーズ機能付き)</title>
<style>
body {
background: #222;
color: #fff;
font-family: sans-serif;
text-align: center;
margin: 0;
padding: 0;
}
#gameCanvas {
background: #f0f0f0;
display: block;
margin: 20px auto;
border: 2px solid #333;
}
#gameOver {
font-size: 2em;
color: #ff4444;
}
</style>
</head>
<body>
<h1>動物の落ち物パズルゲーム</h1>
<canvas id="gameCanvas" width="300" height="600"></canvas>
<div id="gameOver"></div>

<script>
// --- 定数とグローバル変数 ---
const COLS = 6; // 横マス数
const ROWS = 12; // 縦マス数
const CELL_SIZE = 50; // セルのピクセルサイズ
const DROP_INTERVAL = 500; // 落下間隔(ミリ秒)
// 使用する動物(Unicodeエスケープ)
const animalTypes = [
"\uD83D\uDC36", // 🐶
"\uD83D\uDC31", // 🐱
"\uD83D\uDC3C", // 🐼
"\uD83D\uDC30" // 🐰
];

// ゲーム盤(ROWS x COLS の2次元配列、空セルは null)
let grid = [];
for (let y = 0; y < ROWS; y++) {
  grid[y] = [];
  for (let x = 0; x < COLS; x++) {
    grid[y][x] = null;
  }
}

// 現在操作中の落下ブロック(2体のブロック:メインブロックと付随ブロック)
let fallingPiece = null;

// ゲームオーバーフラグ
let gameOver = false;
// ポーズ状態フラグ
let paused = false;

// Canvas の準備
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
ctx.font = "40px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";

// --- 落下ブロックの生成 ---
function spawnPiece() {
  // 落下開始位置(中央上部)
  let startX = Math.floor(COLS / 2);
  let startY = 0;
  // 落下する2体の動物をランダムに選択
  fallingPiece = {
    x: startX,       // メインブロックの x 座標
    y: startY,       // メインブロックの y 座標
    block1: Math.floor(Math.random() * animalTypes.length), // メインブロックの種類
    block2: Math.floor(Math.random() * animalTypes.length), // 付随ブロックの種類
    // 付随ブロックの位置は、初期状態ではメインブロックの下(相対位置)
    offsetX: 0,
    offsetY: 1
  };
  // 新規ブロックを配置する位置が既に埋まっている場合はゲームオーバー
  if (!isValidPosition(fallingPiece, fallingPiece.x, fallingPiece.y, fallingPiece.offsetX, fallingPiece.offsetY)) {
    gameOver = true;
    document.getElementById('gameOver').textContent = "GAME OVER";
  }
}

// --- 衝突判定 ---
// 指定の座標と相対位置にブロックが配置できるかチェック
function isValidPosition(piece, x, y, offX, offY) {
  // メインブロックのチェック
  if (!isCellEmpty(x, y)) return false;
  // 付随ブロックのチェック
  let x2 = x + offX, y2 = y + offY;
  if (!isCellEmpty(x2, y2)) return false;
  return true;
}

// 指定セルが盤内で空かどうかをチェック(盤外の場合は false)
function isCellEmpty(x, y) {
  if (x < 0 || x >= COLS || y < 0 || y >= ROWS) return false;
  if (grid[y][x] !== null) return false;
  return true;
}

// --- 操作処理 ---
// キーハンドリング(左右移動・回転・加速落下・ポーズ)
document.addEventListener('keydown', function(e) {
  // ポーズ切替(Pキー)
  if (e.key === 'p' || e.key === 'P') {
    paused = !paused;
    if (paused) {
      document.getElementById('gameOver').textContent = "PAUSED";
      draw();  // ポーズ中のオーバーレイを描画
    } else {
      document.getElementById('gameOver').textContent = "";
    }
    return;
  }
  
  // ゲームオーバーまたはポーズ中なら操作無効
  if (gameOver || paused) return;
  if (!fallingPiece) return;
  
  // 現在の位置と回転情報
  let newX = fallingPiece.x;
  let newY = fallingPiece.y;
  let newOffX = fallingPiece.offsetX;
  let newOffY = fallingPiece.offsetY;
  
  switch(e.key) {
    case "ArrowLeft":
      newX = fallingPiece.x - 1;
      break;
    case "ArrowRight":
      newX = fallingPiece.x + 1;
      break;
    case "ArrowDown":
      // 下キーで一段早く落とす
      newY = fallingPiece.y + 1;
      break;
    case "ArrowUp":
      // 回転(時計回り): (offX, offY) → (offY, -offX)
      newOffX = fallingPiece.offsetY;
      newOffY = -fallingPiece.offsetX;
      break;
    case " ":
      // スペースキーで即落下
      while (canMove(fallingPiece, 0, 1, fallingPiece.offsetX, fallingPiece.offsetY)) {
        fallingPiece.y++;
      }
      lockPiece();
      spawnPiece();
      draw();
      return;
    default:
      return; // その他のキーは無視
  }
  
  // 衝突チェック
  if (isValidPosition(fallingPiece, newX, newY, newOffX, newOffY)) {
    fallingPiece.x = newX;
    fallingPiece.y = newY;
    fallingPiece.offsetX = newOffX;
    fallingPiece.offsetY = newOffY;
    draw();
  }
  e.preventDefault(); // ページスクロール防止
});

// 落下移動可能かをチェック
function canMove(piece, dx, dy, offX, offY) {
  let newX = piece.x + dx;
  let newY = piece.y + dy;
  return isValidPosition(piece, newX, newY, offX, offY);
}

// --- ゲーム更新 ---
// 定期的に呼び出し、ブロックを下に落とす
function update() {
  if (gameOver) return;
  if (paused) return;
  
  if (fallingPiece && canMove(fallingPiece, 0, 1, fallingPiece.offsetX, fallingPiece.offsetY)) {
    fallingPiece.y++;
  } else {
    // これ以上下に落とせなければ盤に固定
    lockPiece();
    // 縦または横に4つ以上並んだ動物を除去
    clearMatches();
    // 重力処理で上のブロックが落ちる
    applyGravity();
    // 新たなブロックを生成
    spawnPiece();
  }
  draw();
}

// 落下ブロックを盤に固定
function lockPiece() {
  if (!fallingPiece) return;
  let x1 = fallingPiece.x;
  let y1 = fallingPiece.y;
  let x2 = fallingPiece.x + fallingPiece.offsetX;
  let y2 = fallingPiece.y + fallingPiece.offsetY;
  if (y1 >= 0 && y1 < ROWS && x1 >= 0 && x1 < COLS)
    grid[y1][x1] = fallingPiece.block1;
  if (y2 >= 0 && y2 < ROWS && x2 >= 0 && x2 < COLS)
    grid[y2][x2] = fallingPiece.block2;
  fallingPiece = null;
}

// --- マッチ(縦または横に4つ以上並んだ動物の除去) ---
function clearMatches() {
  let toClear = [];
  
  // 横方向のチェック
  for (let y = 0; y < ROWS; y++) {
    let x = 0;
    while (x < COLS) {
      if (grid[y][x] !== null) {
        let type = grid[y][x];
        let start = x;
        while (x < COLS && grid[y][x] === type) {
          x++;
        }
        let count = x - start;
        if (count >= 4) {
          for (let i = start; i < x; i++) {
            toClear.push({ x: i, y: y });
          }
        }
      } else {
        x++;
      }
    }
  }
  
  // 縦方向のチェック
  for (let x = 0; x < COLS; x++) {
    let y = 0;
    while (y < ROWS) {
      if (grid[y][x] !== null) {
        let type = grid[y][x];
        let start = y;
        while (y < ROWS && grid[y][x] === type) {
          y++;
        }
        let count = y - start;
        if (count >= 4) {
          for (let i = start; i < y; i++) {
            toClear.push({ x: x, y: i });
          }
        }
      } else {
        y++;
      }
    }
  }
  
  // 対象セルを消去
  toClear.forEach(cell => {
    grid[cell.y][cell.x] = null;
  });
}

// --- 重力処理 ---
// 空いたセルに対して上のブロックを下へ落とす
function applyGravity() {
  for (let x = 0; x < COLS; x++) {
    for (let y = ROWS - 1; y >= 0; y--) {
      if (grid[y][x] === null) {
        for (let k = y - 1; k >= 0; k--) {
          if (grid[k][x] !== null) {
            grid[y][x] = grid[k][x];
            grid[k][x] = null;
            break;
          }
        }
      }
    }
  }
}

// --- 描画 ---
function draw() {
  // キャンバス全体をクリア
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "#f0f0f0";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  
  // 盤面のグリッド線を描画
  ctx.strokeStyle = "#ccc";
  for (let x = 0; x <= COLS; x++) {
    ctx.beginPath();
    ctx.moveTo(x * CELL_SIZE, 0);
    ctx.lineTo(x * CELL_SIZE, ROWS * CELL_SIZE);
    ctx.stroke();
  }
  for (let y = 0; y <= ROWS; y++) {
    ctx.beginPath();
    ctx.moveTo(0, y * CELL_SIZE);
    ctx.lineTo(COLS * CELL_SIZE, y * CELL_SIZE);
    ctx.stroke();
  }
  
  // 盤に固定されたブロックを描画
  for (let y = 0; y < ROWS; y++) {
    for (let x = 0; x < COLS; x++) {
      if (grid[y][x] !== null) {
        drawBlock(x, y, animalTypes[grid[y][x]]);
      }
    }
  }
  
  // 落下中のブロックを描画
  if (fallingPiece) {
    drawBlock(fallingPiece.x, fallingPiece.y, animalTypes[fallingPiece.block1]);
    drawBlock(fallingPiece.x + fallingPiece.offsetX, fallingPiece.y + fallingPiece.offsetY, animalTypes[fallingPiece.block2]);
  }
  
  // ポーズ中の場合、半透明のオーバーレイと「PAUSED」を描画
  if (paused) {
    ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#fff";
    ctx.font = "50px sans-serif";
    ctx.fillText("PAUSED", canvas.width / 2, canvas.height / 2);
  }
}

// 各ブロックを描画する関数(セルの中心に文字を表示)
function drawBlock(x, y, text) {
  if (x < 0 || x >= COLS || y < 0 || y >= ROWS) return;
  let centerX = x * CELL_SIZE + CELL_SIZE / 2;
  let centerY = y * CELL_SIZE + CELL_SIZE / 2;
  ctx.fillText(text, centerX, centerY);
}

// --- メインループ ---
spawnPiece();
draw();
let gameInterval = setInterval(update, DROP_INTERVAL);

</script>
</body>
</html>


このコードがなんと1分でできちゃうんです(笑)

ステップ3.テキストをHTMLとして保存&実行

このコードをコピペして、テキストエディタに貼り付けます。

テキストエディタは、
・秀丸
・Notepad++
・Visual Studio Code

・Atom
・Su
blime Text

などあるので、お好みのテキストエディタを使ってください。

僕は、秀丸を使いました。

貼り付けたら、ファイル形式を「HTML」を指定して保存。

そして、保存したhtmlファイルをクリックするとブラウザゲームが動きます!!!

このようにたった3ステップでプログラムを1秒も勉強したことがない人間でも動物落ち物パズルゲームを1分で作れてしまいました

もし良かったら、みなさんもオリジナルゲーム制作にチャレンジされてみてください♪

「作ったゲームのスクリーンショット」をシェアしてもらえたら嬉しいです✨

追記
節分にちなんで、鬼を豆で倒すシューティングゲームを制作してみました。

今回はオリジナル鬼イラストを作ってみました。

このイラストが実装されたシューティングゲームが↓↓↓
(ゲームが動くのは10秒あたりから)

自分で作ったイラストもゲームに反映できるなら、色々と幅が広がりますね♪

いいなと思ったら応援しよう!

この記事が参加している募集