今までプライベートや仕事でもゲームは作ったことがなかったのですが
今回、ブラウザでできる簡単なゲームを3つ作ってみました!
良かったら遊んでみてください。

また皆さんにも試して貰えるようにコードも掲載します。
良かったら改良して、コメントで改良したコードを共有貰えると励みになります!
一緒にプログラミングを盛り上げていきましょう!

クリックゲーム

1つ目はクリックで1~100のポイントがランダムで付与されるゲームです。
こちらで試すことができます。良かったら遊んでみてください。

【index.html】

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>クリックしてポイントをゲットするゲーム</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>クリックしてポイントをゲットするゲーム</h1>
    <div id="game">
        <button id="clickButton">クリック!</button>
        <p>合計ポイント: <span id="score">0</span></p>
        <p>前回のポイント: <span id="lastPoints">0</span></p>
        <p>今回のポイント: <span id="currentPoints">0</span></p>
    </div>
    <script src="game.js"></script>
</body>
</html>

【style.css】

body {
    font-family: Arial, sans-serif;
    text-align: center;
    margin-top: 50px;
}

#game {
    display: inline-block;
    padding: 20px;
    border: 1px solid #ccc;
    border-radius: 10px;
}

#clickButton {
    padding: 10px 20px;
    font-size: 16px;
}

【game.js】

let score = 0;
let lastPoints = 0;

document.getElementById('clickButton').addEventListener('click', function() {
    let randomPoints = Math.floor(Math.random() * 101); // 0から100までのランダムな値を生成
    score += randomPoints;
    document.getElementById('score').textContent = score;
    document.getElementById('lastPoints').textContent = lastPoints;
    document.getElementById('currentPoints').textContent = randomPoints;
    lastPoints = randomPoints; // 現在のポイントを前回のポイントとして保存
});

ミニマル迷路ゲーム

2つ目は迷路です。
こちらで試すことができます。良かったら遊んでみてください。

【index.html】

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ミニマル迷路ゲーム</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>ミニマル迷路ゲーム</h1>
    <div id="gameBoard">
        <div id="player"></div>
        <div id="goal"></div>
    </div>
    <div id="controls">
        <button class="control-button" id="up">↑</button><br>
        <button class="control-button" id="left">←</button>
        <button class="control-button" id="down">↓</button>
        <button class="control-button" id="right">→</button>
    </div>
    <script src="game.js"></script>
</body>
</html>

【style.css】

body {
    font-family: Arial, sans-serif;
    text-align: center;
    margin-top: 50px;
}

#gameBoard {
    position: relative;
    width: 400px;
    height: 400px;
    margin: 0 auto;
    border: 2px solid #000;
    background-color: #f0f0f0;
}

#player, #goal {
    position: absolute;
    width: 20px;
    height: 20px;
}

#player {
    background-color: blue;
    top: 0;
    left: 0;
}

#goal {
    background-color: green;
    bottom: 0;
    right: 0;
}

.wall {
    position: absolute;
    background-color: black;
}

#controls {
    margin-top: 20px;
}

.control-button {
    width: 70px; /* ボタンのサイズを大きく */
    height: 70px; /* ボタンのサイズを大きく */
    background-color: #4CAF50;
    color: white;
    border: none;
    margin: 5px;
    font-size: 20px;
    cursor: pointer;
}

【game.js】

const player = document.getElementById('player');
const goal = document.getElementById('goal');
const gameBoard = document.getElementById('gameBoard');
const boardSize = 400;
const cellSize = 20;
let walls = [];

let playerPosition = { top: 0, left: 0 };
let goalPosition = { top: boardSize - cellSize, left: boardSize - cellSize };

function drawWalls() {
    generateRandomWalls();
    
    const existingWalls = document.querySelectorAll('.wall');
    existingWalls.forEach(wall => wall.parentNode.removeChild(wall));
    
    walls.forEach(wall => {
        const wallElement = document.createElement('div');
        wallElement.classList.add('wall');
        wallElement.style.top = wall.top + 'px';
        wallElement.style.left = wall.left + 'px';
        wallElement.style.width = wall.width + 'px';
        wallElement.style.height = wall.height + 'px';
        gameBoard.appendChild(wallElement);
    });
}

function generateRandomWalls() {
    walls = [];
    const numWalls = Math.floor(Math.random() * 6) + 5;
    
    for (let i = 0; i < numWalls; i++) {
        let wallWidth = Math.floor(Math.random() * (boardSize / 2)) + cellSize;
        let wallHeight = Math.floor(Math.random() * (boardSize / 2)) + cellSize;
        let wallTop = Math.floor(Math.random() * (boardSize - wallHeight));
        let wallLeft = Math.floor(Math.random() * (boardSize - wallWidth));

        if (wallTop + wallHeight > boardSize) {
            wallTop = boardSize - wallHeight;
        }
        if (wallLeft + wallWidth > boardSize) {
            wallLeft = boardSize - wallWidth;
        }
        
        let wall = { top: wallTop, left: wallLeft, width: wallWidth, height: wallHeight };
        walls.push(wall);
    }
    
    addPathToGoal();
}

function addPathToGoal() {
    const pathWidth = 40;
    walls = walls.filter(wall => !isWallAroundGoal(wall));
}

function isWallAroundGoal(wall) {
    return wall.top >= goalPosition.top - cellSize &&
           wall.top <= goalPosition.top + cellSize &&
           wall.left >= goalPosition.left - cellSize &&
           wall.left <= goalPosition.left + cellSize;
}

function movePlayer(direction) {
    let newPosition = { ...playerPosition };

    switch (direction) {
        case 'up':
            newPosition.top -= cellSize;
            break;
        case 'down':
            newPosition.top += cellSize;
            break;
        case 'left':
            newPosition.left -= cellSize;
            break;
        case 'right':
            newPosition.left += cellSize;
            break;
    }

    if (canMoveTo(newPosition)) {
        playerPosition = newPosition;
        player.style.top = playerPosition.top + 'px';
        player.style.left = playerPosition.left + 'px';

        if (playerPosition.top === goalPosition.top && playerPosition.left === goalPosition.left) {
            alert('ゴールしました!');
            resetGame();
        }
    }
}

function canMoveTo(position) {
    if (position.top < 0 || position.left < 0 || position.top >= boardSize || position.left >= boardSize) {
        return false;
    }

    return !walls.some(wall => {
        return position.top < wall.top + wall.height &&
               position.top + cellSize > wall.top &&
               position.left < wall.left + wall.width &&
               position.left + cellSize > wall.left;
    });
}

function resetGame() {
    playerPosition = { top: 0, left: 0 };
    player.style.top = playerPosition.top + 'px';
    player.style.left = playerPosition.left + 'px';
    generateRandomWalls();
    drawWalls();
}

document.addEventListener('keydown', (event) => {
    switch (event.key) {
        case 'ArrowUp':
            movePlayer('up');
            break;
        case 'ArrowDown':
            movePlayer('down');
            break;
        case 'ArrowLeft':
            movePlayer('left');
            break;
        case 'ArrowRight':
            movePlayer('right');
            break;
    }
});

function handleTouch(event, direction) {
    event.preventDefault();
    console.log(`Touch event: ${direction}`);
    movePlayer(direction);
}

document.getElementById('up').addEventListener('touchend', (event) => handleTouch(event, 'up'));
document.getElementById('up').addEventListener('click', () => movePlayer('up'));

document.getElementById('down').addEventListener('touchend', (event) => handleTouch(event, 'down'));
document.getElementById('down').addEventListener('click', () => movePlayer('down'));

document.getElementById('left').addEventListener('touchend', (event) => handleTouch(event, 'left'));
document.getElementById('left').addEventListener('click', () => movePlayer('left'));

document.getElementById('right').addEventListener('touchend', (event) => handleTouch(event, 'right'));
document.getElementById('right').addEventListener('click', () => movePlayer('right'));

drawWalls();

シューティングゲーム

3つ目は敵を打って倒すシューティングゲームです。
こちらから試すことができます。良かったら遊んでみてください。

【index.html】

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>シューティングゲーム</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="game">
        <div id="player" class="fighter-jet"></div>
    </div>
    <div id="score">スコア: 0</div>
    <button id="start-btn">ゲームスタート</button>
    <script src="script.js"></script>
</body>
</html>

【style.css】

body, html {
    height: 100%;
    margin: 0;
    overflow: hidden;
}

#game {
    width: 80%;
    height: 100%;
    background-color: #333;
    position: relative;
    margin: 0 auto;
}

.fighter-jet {
    width: 60px;
    height: 45px;
    background-color: red;
    position: absolute;
    bottom: 20px;
    left: calc(50% - 30px);
}

.enemy {
    width: 40px;
    height: 30px;
    background-color: blue;
    position: absolute;
    top: 0;
    left: 0;
}

.bullet {
    width: 5px;
    height: 10px;
    background-color: yellow;
    position: absolute;
}

#score {
    position: absolute;
    top: 10px;
    right: 10px;
    color: white;
    font-size: 20px;
}

#start-btn {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    padding: 15px 30px;
    font-size: 24px;
    background-color: #4CAF50;
    color: white;
    border: none;
    cursor: pointer;
    border-radius: 5px;
}

【game.js】

const gameContainer = document.getElementById('game');
const player = document.getElementById('player');
const scoreDisplay = document.getElementById('score');
const startBtn = document.getElementById('start-btn');

let score = 0;
let enemies = [];
let bullets = [];
let enemySpeed = 1;
const bulletSpeed = 5;
const enemySpawnInterval = 2000;
let enemySpawnTimer;
let bulletTimer;

function createEnemy() {
    const enemy = document.createElement('div');
    enemy.className = 'enemy';
    enemy.style.left = Math.random() * (gameContainer.offsetWidth - 60) + 'px';
    gameContainer.appendChild(enemy);
    enemies.push(enemy);
}

function moveEnemies() {
    enemies.forEach(enemy => {
        let top = enemy.offsetTop + enemySpeed;
        enemy.style.top = top + 'px';
        if (top > gameContainer.offsetHeight) {
            gameOver();
        } else {
            checkCollision(enemy);
        }
    });
}

function checkCollision(enemy) {
    const playerRect = player.getBoundingClientRect();
    const enemyRect = enemy.getBoundingClientRect();

    if (
        playerRect.left < enemyRect.right &&
        playerRect.right > enemyRect.left &&
        playerRect.top < enemyRect.bottom &&
        playerRect.bottom > enemyRect.top
    ) {
        gameOver();
    }
}

function shootBullet() {
    const bullet = document.createElement('div');
    bullet.className = 'bullet';
    bullet.style.left = player.offsetLeft + player.offsetWidth / 2 - 2.5 + 'px';
    bullet.style.top = player.offsetTop + 'px';
    gameContainer.appendChild(bullet);
    bullets.push(bullet);
}

function moveBullets() {
    bullets.forEach(bullet => {
        bullet.style.top = bullet.offsetTop - bulletSpeed + 'px';
        if (bullet.offsetTop < 0) {
            bullet.parentNode.removeChild(bullet);
            bullets.splice(bullets.indexOf(bullet), 1);
        } else {
            checkBulletCollision(bullet);
        }
    });
}

function checkBulletCollision(bullet) {
    const bulletRect = bullet.getBoundingClientRect();
    enemies.forEach(enemy => {
        const enemyRect = enemy.getBoundingClientRect();
        if (
            bulletRect.left < enemyRect.right &&
            bulletRect.right > enemyRect.left &&
            bulletRect.top < enemyRect.bottom &&
            bulletRect.bottom > enemyRect.top
        ) {
            enemy.parentNode.removeChild(enemy);
            const index = enemies.indexOf(enemy);
            if (index !== -1) enemies.splice(index, 1);
            bullet.parentNode.removeChild(bullet);
            bullets.splice(bullets.indexOf(bullet), 1);
            score++;
            scoreDisplay.innerText = 'スコア: ' + score;
        }
    });
}

function startGame() {
    player.style.left = gameContainer.offsetWidth / 2 - 30 + 'px';
    player.style.top = gameContainer.offsetHeight - 100 + 'px';

    enemies = [];
    bullets = [];

    enemySpawnTimer = setInterval(createEnemy, enemySpawnInterval);
    bulletTimer = setInterval(moveBullets, 20);
    setInterval(moveEnemies, 20);

    document.addEventListener('keydown', handleKeyPress);
    gameContainer.addEventListener('touchstart', handleTouchStart);
    gameContainer.addEventListener('touchmove', handleTouchMove);
    gameContainer.addEventListener('touchend', handleTouchEnd); // 追加: タッチが終了したときの処理を追加
}

function handleKeyPress(event) {
    switch (event.key) {
        case 'ArrowUp':
            movePlayer('up');
            break;
        case 'ArrowDown':
            movePlayer('down');
            break;
        case 'ArrowLeft':
            movePlayer('left');
            break;
        case 'ArrowRight':
            movePlayer('right');
            break;
        case ' ':
            shootBullet();
            break;
    }
}

let touchStartX = 0;
let touchStartY = 0;

function handleTouchStart(event) {
    event.preventDefault();
    touchStartX = event.touches[0].clientX;
    touchStartY = event.touches[0].clientY;
}

function handleTouchMove(event) {
    event.preventDefault();
    const touchMoveX = event.touches[0].clientX;
    const touchMoveY = event.touches[0].clientY;

    const deltaX = touchMoveX - touchStartX;
    const deltaY = touchMoveY - touchStartY;

    touchStartX = touchMoveX;
    touchStartY = touchMoveY;

    movePlayerWithTouch(deltaX, deltaY);
}

function handleTouchEnd(event) {
    event.preventDefault();
    console.log('Touch end');
    // 弾を発射する処理を追加
    shootBullet();
}

function movePlayer(direction) {
    const playerRect = player.getBoundingClientRect();
    const gameRect = gameContainer.getBoundingClientRect();

    switch (direction) {
        case 'up':
            if (playerRect.top > gameRect.top) {
                player.style.top = player.offsetTop - 10 + 'px';
            }
            break;
        case 'down':
            if (playerRect.bottom < gameRect.bottom) {
                player.style.top = player.offsetTop + 10 + 'px';
            }
            break;
        case 'left':
            if (playerRect.left > gameRect.left) {
                player.style.left = player.offsetLeft - 10 + 'px';
            }
            break;
        case 'right':
            if (playerRect.right < gameRect.right) {
                player.style.left = player.offsetLeft + 10 + 'px';
            }
            break;
    }
}

function movePlayerWithTouch(deltaX, deltaY) {
    const playerRect = player.getBoundingClientRect();
    const gameRect = gameContainer.getBoundingClientRect();

    let newLeft = player.offsetLeft + deltaX;
    let newTop = player.offsetTop + deltaY;

    if (newLeft < 0) newLeft = 0;
    if (newLeft + playerRect.width > gameRect.width) newLeft = gameRect.width - playerRect.width;
    if (newTop < 0) newTop = 0;
    if (newTop + playerRect.height > gameRect.height) newTop = gameRect.height - playerRect.height;

    player.style.left = newLeft + 'px';
    player.style.top = newTop + 'px';
}

function gameOver() {
    clearInterval(enemySpawnTimer);
    clearInterval(bulletTimer);
    alert('ゲームオーバー! あなたのスコア: ' + score);
    resetGame();
}

function resetGame() {
    score = 0;
    scoreDisplay.innerText = 'スコア: ' + score;
    enemies.forEach(enemy => enemy.parentNode.removeChild(enemy));
    bullets.forEach(bullet => bullet.parentNode.removeChild(bullet));
    startGame();
}

startBtn.addEventListener('click', () => {
    startBtn.style.display = 'none';
    startGame();
});

まとめ

今回は、シンプルにHTML/CSS/Javascriptで作成しました。
こちらにBGM、迷路やシューティングゲームのキャラを画像にするなどで本格的なゲームが作成できます。

ゲームを作りたいけどイメージが湧かない人など、このコードを参考にまずはシンプルなものを作成して
そこからカスタマイズしながら本格的なゲームを作成してみませんか?

今回、初めて作成しましたが面白かったです!
またRPGなど複雑なゲームも作成してみたいと思います。

Follow me!