見出し画像

【JavaScript】滑るタイルゲームをプログラミングで作成

今回はJavaScriptで滑るタイルゲームを作成しました!

皆さんもどこかでやったことがるのではないでしょうか?

私はポケモンで初めて出会いました。なかなかクリアできずに、苦労した経験があります。

皆さんもぜひ、作成してみてください。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>ナミさん〜!!</title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" media="screen" href="style.css">
  </head>
  <body>
    <canvas id="canvas"></canvas>
    <p><button id="reset">リセット</button></p>
    <p id="message"></p>
    <script src="index.js"></script>
  </body>
</html>
body {
    text-align: center;
    background-color: aliceblue;
}

#message {
    margin-top: 0;
    font-size: 30px;
    color: red;
}
//変数の定義
let reset = document.getElementById('reset');
let message = document.getElementById('message');
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
//ブロック情報
const blockSize = 60;
const blockCount = 10;
//キャンバス情報
canvas.width = blockSize * blockCount;
canvas.height = blockSize * blockCount;
//サンジ関連
let sanji = new Object();
sanji.img = new Image();
sanji.img.src = 'img/sanji.png';
sanji.cx = 0;           // キャラクタベース(ブロック)の座標
sanji.cy = 0;
sanji.x = 0;            // ピクセルベースの座標
sanji.y = 0;
sanji.move = 0;
//ゴール情報
let goal = new Object();
goal.cx = 0;
goal.cy = 0;
goal.point = 0;         // ゴールしたかどうかのフラグ 1:ゴール
const GOAL_X = 5;
const GOAL_Y = 5;
// キー関連
let key = new Object();
key.up = false;
key.down = false;
key.right = false;
key.left = false;
key.push = '';
//イベント関連
window.addEventListener("keydown", keydown);
function keydown(e) {
  let key_code = e.keyCode;
  if (key_code === 37) key.left = true;
  if (key_code === 38) key.up = true;
  if (key_code === 39) key.right = true;
  if (key_code === 40) key.down = true;
  goal.point = 0;      // 指定場所まで滑り続ける
  e.preventDefault();
}
window.addEventListener("keyup", keyup);
function keyup(e) {
  let key_code = e.keyCode;
  if (key_code === 37) key.left = false;
  if (key_code === 38) key.up = false;
  if (key_code === 39) key.right = false;
  if (key_code === 40) key.down = false;
}
// マップ配列を初期化  0: 何もない 1:壁 2:ゴール
let map = [];
for (let i = 0; i < blockCount; i++) {
  map.push("0".repeat(blockCount));
}
// 新しいマップを作成
makeMap();
//リロードで関数実行
window.addEventListener('load', main);
function main() {
  ctx.fillStyle = "powderblue";
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  for (let y = 0; y < blockCount; y++) {
    for (let x = 0; x < blockCount; x++) {
      if (map[y][x] == 1) { //ブロックの設定
        ctx.fillStyle = 'black';
        ctx.fillRect(x * blockSize, y * blockSize, blockSize, blockSize);
      }
      if (map[y][x] == 2) {	//ゴールの設定
        image = new Image();
        image.src = "img/nami.png";
        ctx.drawImage(image, x * blockSize, y * blockSize, blockSize, blockSize);
      }
    }
  }
  if (sanji.move === 0) { //サンジが動いていないとき
    let dx = 0, dy = 0;  //ブロックベースで移動するための情報
    if (key.left === true) {
      dx = -1;
      key.push = 'left';
      key.left = false;
    } else if (key.up === true) {
      dy = -1;
      key.push = 'up';
      key.up = false;
    } else if (key.right === true) {
      dx = 1;
      key.push = 'right';
      key.right = false;
    } else if (key.down === true) {
      dy = 1;
      key.push = 'down';
      key.down = false;
    }
    if (dx != 0 || dy != 0) {
      sanji.cx += dx;
      sanji.cy += dy;
      sanji.move = blockSize; //動く指示(下のif文を実行させる)

      let n = map[sanji.cy][sanji.cx];    // 進む先の情報
      if (n == 2) {                       // ゴール位置
        message.innerHTML = 'ナミさん!!助けに来たよ';
        goal.point = 1;
      } else if (n != 0) {                //ブロックであれば動かさない
        sanji.cx -= dx;
        sanji.cy -= dy;
        sanji.move = 0;
        key.push = "";
      }
    }
  }
  if (sanji.move > 0) {
    let nowMove = 4;   //	最大4ピクセル移動します。
    if (sanji.move < 4) {
      nowMove = sanji.move;
    }
    sanji.move -= nowMove; //最後は0になる
    //ピクセルベースで移動し続ける
    if (key.push === 'left') sanji.x -= nowMove;
    if (key.push === 'up') sanji.y -= nowMove;
    if (key.push === 'right') sanji.x += nowMove;
    if (key.push === 'down') sanji.y += nowMove;
    //ブロックベースで移動し続ける
    if (sanji.move == 0 && goal.point == 0) {
      let px = sanji.cx;
      let py = sanji.cy;
      if (key.push === 'left') {
        px--;
      } else if (key.push === 'up') {
        py--;
      } else if (key.push === 'right') {
        px++;
      } else if (key.push === 'down') {
        py++;
      }
      if (px != sanji.cx || py != sanji.cy) {
        if (map[py][px] == 0) {    // 進む先が 0
          sanji.cx = px;
          sanji.cy = py;
          sanji.move = blockSize;
        }
      }
    }
  }
  ctx.drawImage(sanji.img, sanji.x, sanji.y, blockSize, blockSize);
  requestAnimationFrame(main);
}

function makeMap() {
  for (let i = 0; i < blockCount; i++) {
    if (i == 0 || i == blockCount - 1) {
      map[i] = "1".repeat(blockCount);	// すべて壁
    } else {
      map[i] = "1" + "0".repeat(blockCount - 2) + "1";	// クリア
    }
  }
  //サンジの初期位置
  sanji.cx = 1;                        //ブロックベース
  sanji.x = sanji.cx * blockSize;      //ピクセルベース
  sanji.cy = 1;
  sanji.y = sanji.cy * blockSize;
  //ブロックを作成
  map[1] = replaceValue(map[1], 4, 1);
  map[4] = replaceValue(map[4], 4, 1);
  map[3] = replaceValue(map[3], 6, 1);
  map[7] = replaceValue(map[8], 7, 1);
  map[8] = replaceValue(map[8], 3, 1);
  //	ゴールの座標
  goal.cx = GOAL_X;
  goal.cy = GOAL_Y;
  map[goal.cy] = replaceValue(map[goal.cy], goal.cx, 2);
}
//ブロックを作成する関数
function replaceValue(mapstr, pos, value) {
  let m = mapstr.substr(0, pos) + value + mapstr.substr(pos + 1);
  return m;
}
//リセットボタン
reset.addEventListener("click", restart);
function restart() {
  if (sanji.move === 0) {
    sanji.cx = 1;
    sanji.cy = 1;
    sanji.x = blockSize;
    sanji.y = blockSize;
    message.innerHTML = "";
    makeMap();
  }
}

この記事が気に入ったらサポートをしてみませんか?