【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();
}
}
この記事が気に入ったらサポートをしてみませんか?