見出し画像

ChatGPT4に作ってもらったRPGゲームの素その2。~イベント~

前回


Block版

マップのオブジェクトを増やし、プレイヤーに反応してイベントを発動するようにした。否、してもらった。してって言ったらChatGPTがしてくれた。

増えたマップオブジェクトは、敷き詰めるためだけの何もしないCellBase。
プレイヤーが進入できないBlock。

ソース全部

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Game</title>
    <style>
        canvas {
            display: block;
            margin: 0 auto;
            background-color: #f0f0f0;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas" width="320" height="320"></canvas>
    <script>
    
    
	let objectIdCounter = 0;

	class MapObject {
	    constructor(x, y) {
	        this.x = x;
	        this.y = y;
	        this.onObjectEnter = null;
	    }

	    draw(context2d) {
	        // 基本の描画処理は何もしない
	    }

	    triggerEvent(object) {
	        if (this.onObjectEnter) {
	            return this.onObjectEnter(object);
	        }
	        return true; // Default behavior is to allow the object to enter
	    }
	}

	class CellBase extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	    }
	    draw(context2d) {
	        context2d.fillStyle = 'gray';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	}

	class Block extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	        this.onObjectEnter = (object) => {
	            // Block the object from entering the block
	            return false;
	        };
	    }

	    draw(context2d) {
	        context2d.fillStyle = 'black';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	}

	class Player extends MapObject {
	    constructor(x, y) {
	        super(x, y);
		    }

	    move(direction) {
	        let newX = this.x;
	        let newY = this.y;

	        switch (direction) {
	            case 1:
	                newX -= 1;
	                newY += 1;
	                break;
	            case 2:
	                newY += 1;
	                break;
	            case 3:
	                newX += 1;
	                newY += 1;
	                break;
	            case 4:
	                newX -= 1;
	                break;
	            case 6:
	                newX += 1;
	                break;
	            case 7:
	                newX -= 1;
	                newY -= 1;
	                break;
	            case 8:
	                newY -= 1;
	                break;
	            case 9:
	                newX += 1;
	                newY -= 1;
	                break;
	            default:
	                console.log("Invalid direction. Please enter a valid number (1-9, excluding 5).");
	                break;
	        }//switch

	        if (gameMap.triggerEvent(newX, newY, this)) {
	            this.x = newX;
	            this.y = newY;
	        }
	    }//move

	    draw(context2d) {
	        context2d.fillStyle = 'blue';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	    

        	    
	}//player

	class Map {
	    constructor(w, h) {
	        this.Width = w;
	        this.Height = h;
	        this.GameBoard = Array.from({ length: this.Height }, () => Array(this.Width).fill(null));
	        this.MapObjects = [];
	        
	        // Fill the map with CellBase objects
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                const cell = new CellBase(x, y);
	                this.addObject(cell);
	            }
	        }

	        // Surround the map with Block objects
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                if (y === 0 || y === this.Height - 1 || x === 0 || x === this.Width - 1) {
	                    const block = new Block(x, y);
	                    this.addObject(block);
	                }
	            }
	        }

	        // Add some Block objects randomly on the map
	        const randomBlockPositions = [
	            { x: 3, y: 3 },
	            { x: 6, y: 2 },
	            { x: 2, y: 5 }
	        ];
	        for (const position of randomBlockPositions) {
	            const block = new Block(position.x, position.y);
	            this.addObject(block);
	        }	        
		}
	    
	    addObject(mapObject) {
	        if (mapObject instanceof MapObject) {
	            this.MapObjects.push(mapObject);
	            this.GameBoard[mapObject.y][mapObject.x] = mapObject;
	        }
	    }
	    
	    removeObject(mapObject) {
	        if (mapObject instanceof MapObject) {
	            const index = this.MapObjects.indexOf(mapObject);
	            if (index > -1) {
	                this.MapObjects.splice(index, 1);
	                this.GameBoard[mapObject.y][mapObject.x] = null;
	            }
	        }
	    }
	    
	    draw(context2d) {
	        // Draw background
	        context2d.fillStyle = 'white';
	        context2d.fillRect(0, 0, this.Width * 32, this.Height * 32);
	        // Draw grid
	        context2d.strokeStyle = 'black';
	        context2d.lineWidth = 1;
	        for (let y = 0; y <= this.Height; y++) {
	            context2d.beginPath();
	            context2d.moveTo(0, y * 32);
	            context2d.lineTo(this.Width * 32, y * 32);
	            context2d.stroke();
	        }
	        for (let x = 0; x <= this.Width; x++) {
	            context2d.beginPath();
	            context2d.moveTo(x * 32, 0);
	            context2d.lineTo(x * 32, this.Height * 32);
	            context2d.stroke();
	        }
	        // Draw objects
	        for (const obj of this.MapObjects) {
	            obj.draw(context2d);
	        }
	    }//draw
	    
	    triggerEvent(x, y, object) {
	        const mapObject = this.GameBoard[y][x];
	        if (mapObject) {
	            return mapObject.triggerEvent(object);
	        }
	        return true; // Default behavior is to allow the object to enter
	    }	    
	    
	}//Map


        const canvas = document.getElementById('gameCanvas');
        const context2d = canvas.getContext('2d');
        const gameMap = new Map(10, 10);
        const player = new Player(4, 4);
        gameMap.addObject(player);

        let lastFrameTime = performance.now();
        const targetFrameDuration = 1000 / 60; // 60FPSの場合のフレーム間隔(ミリ秒)

		const keyStates = {};

		function gameLoop(currentTime) {
		    const deltaTime = currentTime - lastFrameTime;
		    if (deltaTime >= targetFrameDuration) {
		        update(deltaTime);
		        draw();
		        lastFrameTime = currentTime;
		    }
		    requestAnimationFrame(gameLoop);
		}

		function update(deltaTime) {
		    for (const key in keyStates) {
		        const state = keyStates[key];
		        if (state === 'pressed') {
		            const direction = directionKeyMap[key];
		            if (direction) {
		                player.move(direction);
		            }
		            keyStates[key] = 'holding';
		        }
		    }
		}

		function keydownHandler(event) {
		    if (!keyStates[event.code]) {
		        keyStates[event.code] = 'pressed';
		    }
		}

		function keyupHandler(event) {
		    delete keyStates[event.code];
		}  

        function draw() {
            gameMap.draw(context2d);
        }


        const directionKeyMap = {
            'Numpad1': 1,
            'Numpad2': 2,
            'Numpad3': 3,
            'Numpad4': 4,
            'Numpad6': 6,
            'Numpad7': 7,
            'Numpad8': 8,
            'Numpad9': 9,
            
		    'ArrowDown': 2,
		    'ArrowUp': 8,
		    'ArrowLeft': 4,
		    'ArrowRight': 6,     
            
        };

        document.addEventListener("keydown", keydownHandler);
        document.addEventListener("keyup", keyupHandler);
        requestAnimationFrame(gameLoop);
    </script>
</body>
</html>

レイヤー多層化

グリッドの各セルが、MapObjectを複数格納する。
描画は下から順に、イベントは上から順に反応するものとする。

class MapObject {
    // ... (MapObject, CellBase, Block, Playerクラスに変更はありません)
}

class Blank extends MapObject {
    constructor(x, y) {
        super(x, y);
    }
}

class Map {
    constructor(w, h) {
        this.Width = w;
        this.Height = h;
        this.GameBoard = Array.from({ length: this.Height }, () => Array(this.Width).fill([]));
        this.MapObjects = [];

        // ... (マップの初期化処理に変更はありません)
    }

    addObject(mapObject) {
        if (mapObject instanceof MapObject) {
            this.MapObjects.push(mapObject);
            this.GameBoard[mapObject.y][mapObject.x] = [...this.GameBoard[mapObject.y][mapObject.x], mapObject];
        }
    }

    removeObject(mapObject) {
        if (mapObject instanceof MapObject) {
            const index = this.MapObjects.indexOf(mapObject);
            if (index > -1) {
                this.MapObjects.splice(index, 1);
                this.GameBoard[mapObject.y][mapObject.x] = this.GameBoard[mapObject.y][mapObject.x].filter(obj => obj !== mapObject);
            }
        }
    }

    draw(context2d) {
        // ... (背景とグリッドの描画処理に変更はありません)

        // Draw objects from bottom to top
        for (let y = 0; y < this.Height; y++) {
            for (let x = 0; x < this.Width; x++) {
                const objectsInCell = this.GameBoard[y][x];
                for (const obj of objectsInCell) {
                    obj.draw(context2d);
                }
            }
        }
    }

    triggerEvent(x, y, object) {
        const objectsInCell = this.GameBoard[y][x];
        for (let i = objectsInCell.length - 1; i >= 0; i--) {
            const mapObject = objectsInCell[i];
            if (mapObject) {
                const result = mapObject.triggerEvent(object);
                if (!result) {
                    return false;
                }
            }
        }
        return true; // Default behavior is to allow the object to enter
    }
}

Player.Moveの変更

class Player extends MapObject {
    // ...

    move(direction) {
        let newX = this.x;
        let newY = this.y;
        // ... (座標の更新処理に変更はありません)

        if (gameMap.triggerEvent(newX, newY, this)) {
            gameMap.removeObject(this);  // 追加: 古いセルからプレイヤーを削除
            this.x = newX;
            this.y = newY;
            gameMap.addObject(this);     // 追加: 新しいセルにプレイヤーを追加
        }
    }

    // ...
}

ソース全部

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Game</title>
    <style>
        canvas {
            display: block;
            margin: 0 auto;
            background-color: #f0f0f0;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas" width="320" height="320"></canvas>
    <script>
    
    
	let objectIdCounter = 0;

	class MapObject {
	    constructor(x, y) {
	        this.x = x;
	        this.y = y;
	        this.onObjectEnter = null;
	    }

	    draw(context2d) {
	        // 基本の描画処理は何もしない
	    }

	    triggerEvent(object) {
	        if (this.onObjectEnter) {
	            return this.onObjectEnter(object);
	        }
	        return true; // Default behavior is to allow the object to enter
	    }
	}

	class CellBase extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	    }
	    draw(context2d) {
	        context2d.fillStyle = 'gray';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	}

	class Block extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	        this.onObjectEnter = (object) => {
	            // Block the object from entering the block
	            return false;
	        };
	    }

	    draw(context2d) {
	        context2d.fillStyle = 'black';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	}
	
	class Blank extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	    }
	}	

	class Player extends MapObject {
	    constructor(x, y) {
	        super(x, y);
		    }

	    move(direction) {
	        let newX = this.x;
	        let newY = this.y;

	        switch (direction) {
	            case 1:
	                newX -= 1;
	                newY += 1;
	                break;
	            case 2:
	                newY += 1;
	                break;
	            case 3:
	                newX += 1;
	                newY += 1;
	                break;
	            case 4:
	                newX -= 1;
	                break;
	            case 6:
	                newX += 1;
	                break;
	            case 7:
	                newX -= 1;
	                newY -= 1;
	                break;
	            case 8:
	                newY -= 1;
	                break;
	            case 9:
	                newX += 1;
	                newY -= 1;
	                break;
	            default:
	                console.log("Invalid direction. Please enter a valid number (1-9, excluding 5).");
	                break;
	        }//switch

	        if (gameMap.triggerEvent(newX, newY, this)) {
	            gameMap.removeObject(this);  // 追加: 古いセルからプレイヤーを削除
	            this.x = newX;
	            this.y = newY;
	            gameMap.addObject(this);     // 追加: 新しいセルにプレイヤーを追加
	        }
	    }//move

	    draw(context2d) {
	        context2d.fillStyle = 'blue';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	    

        	    
	}//player

	class Map {
	    constructor(w, h) {
	        this.Width = w;
	        this.Height = h;
	        this.GameBoard = Array.from({ length: this.Height }, () => Array(this.Width).fill([]));
	        this.MapObjects = [];
	        
	        // Fill the map with CellBase objects
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                const cell = new CellBase(x, y);
	                this.addObject(cell);
	            }
	        }

	        // Surround the map with Block objects
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                if (y === 0 || y === this.Height - 1 || x === 0 || x === this.Width - 1) {
	                    const block = new Block(x, y);
	                    this.addObject(block);
	                }
	            }
	        }

	        // Add some Block objects randomly on the map
	        const randomBlockPositions = [
	            { x: 3, y: 3 },
	            { x: 6, y: 2 },
	            { x: 2, y: 5 }
	        ];
	        for (const position of randomBlockPositions) {
	            const block = new Block(position.x, position.y);
	            this.addObject(block);
	        }	        
		}//constructor
	    
	    addObject(mapObject) {
	        if (mapObject instanceof MapObject) {
	            this.MapObjects.push(mapObject);
	            this.GameBoard[mapObject.y][mapObject.x] = [...this.GameBoard[mapObject.y][mapObject.x], mapObject];
	        }
	    }

	    removeObject(mapObject) {
	        if (mapObject instanceof MapObject) {
	            const index = this.MapObjects.indexOf(mapObject);
	            if (index > -1) {
	                this.MapObjects.splice(index, 1);
	                this.GameBoard[mapObject.y][mapObject.x] = this.GameBoard[mapObject.y][mapObject.x].filter(obj => obj !== mapObject);
	            }
	        }
	    }
	    
	    draw(context2d) {
	        // Draw background
	        context2d.fillStyle = 'white';
	        context2d.fillRect(0, 0, this.Width * 32, this.Height * 32);
	        // Draw grid
	        context2d.strokeStyle = 'black';
	        context2d.lineWidth = 1;
	        for (let y = 0; y <= this.Height; y++) {
	            context2d.beginPath();
	            context2d.moveTo(0, y * 32);
	            context2d.lineTo(this.Width * 32, y * 32);
	            context2d.stroke();
	        }
	        for (let x = 0; x <= this.Width; x++) {
	            context2d.beginPath();
	            context2d.moveTo(x * 32, 0);
	            context2d.lineTo(x * 32, this.Height * 32);
	            context2d.stroke();
	        }
	        // Draw objects from bottom to top
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                const objectsInCell = this.GameBoard[y][x];
	                for (const obj of objectsInCell) {
	                    obj.draw(context2d);
	                }
	            }
	        }
	    }//draw
	    
	    triggerEvent(x, y, object) {
	        const objectsInCell = this.GameBoard[y][x];
	        for (let i = objectsInCell.length - 1; i >= 0; i--) {
	            const mapObject = objectsInCell[i];
	            if (mapObject) {
	                const result = mapObject.triggerEvent(object);
	                if (!result) {
	                    return false;
	                }
	            }
	        }
	        return true; // Default behavior is to allow the object to enter
	    }    
	    
	}//Map


        const canvas = document.getElementById('gameCanvas');
        const context2d = canvas.getContext('2d');
        const gameMap = new Map(10, 10);
        const player = new Player(4, 4);
        gameMap.addObject(player);

        let lastFrameTime = performance.now();
        const targetFrameDuration = 1000 / 60; // 60FPSの場合のフレーム間隔(ミリ秒)

		const keyStates = {};

		function gameLoop(currentTime) {
		    const deltaTime = currentTime - lastFrameTime;
		    if (deltaTime >= targetFrameDuration) {
		        update(deltaTime);
		        draw();
		        lastFrameTime = currentTime;
		    }
		    requestAnimationFrame(gameLoop);
		}

		function update(deltaTime) {
		    for (const key in keyStates) {
		        const state = keyStates[key];
		        if (state === 'pressed') {
		            const direction = directionKeyMap[key];
		            if (direction) {
		                player.move(direction);
		            }
		            keyStates[key] = 'holding';
		        }
		    }
		}

		function keydownHandler(event) {
		    if (!keyStates[event.code]) {
		        keyStates[event.code] = 'pressed';
		    }
		}

		function keyupHandler(event) {
		    delete keyStates[event.code];
		}  

        function draw() {
            gameMap.draw(context2d);
        }


        const directionKeyMap = {
            'Numpad1': 1,
            'Numpad2': 2,
            'Numpad3': 3,
            'Numpad4': 4,
            'Numpad6': 6,
            'Numpad7': 7,
            'Numpad8': 8,
            'Numpad9': 9,
            
		    'ArrowDown': 2,
		    'ArrowUp': 8,
		    'ArrowLeft': 4,
		    'ArrowRight': 6,     
            
        };

        document.addEventListener("keydown", keydownHandler);
        document.addEventListener("keyup", keyupHandler);
        requestAnimationFrame(gameLoop);
    </script>
</body>
</html>

イベント発動、メッセージウィンドウ追加

メッセージウィンドウ

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Game</title>
    <style>
        canvas {
            display: block;
            margin: 0 auto;
            background-color: #f0f0f0;
        }
        #messageWindow {
            width: 320px;
            height: 50px;
            margin: 10px auto 0;
            border: 1px solid black;
            text-align: center;
            line-height: 50px;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas" width="320" height="320"></canvas>
    <div id="messageWindow"></div>
    <!-- 以下の JavaScript コードは以前と同様です。 -->

踏んだらイベント発動Blankセル

class Blank extends MapObject {
    constructor(x, y) {
        super(x, y);
        this.onObjectEnter = (object) => {
            showMessage('test');
            return true; // Allow the object to enter
        };
    }
}

showMessageおよびMapコンストラクタ内でのBlank作成

// Add a message window
const messageWindow = document.getElementById('messageWindow');

function showMessage(message) {
    messageWindow.textContent = message;
}

class Map {
    constructor(w, h) {
        // ... (以前のコード)

        // Add a Blank object with a "test" message at a random accessible position
        let randomX, randomY;
        do {
            randomX = Math.floor(Math.random() * (this.Width - 2)) + 1;
            randomY = Math.floor(Math.random() * (this.Height - 2)) + 1;
        } while (this.GameBoard[randomY][randomX] instanceof Block);
        const blank = new Blank(randomX, randomY);
        this.addObject(blank);
    }

    // ...
}

ソース全部

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Game</title>
    <style>
        canvas {
            display: block;
            margin: 0 auto;
            background-color: #f0f0f0;
        }
        #messageWindow {
            width: 320px;
            height: 50px;
            margin: 10px auto 0;
            border: 1px solid black;
            text-align: center;
            line-height: 50px;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas" width="320" height="320"></canvas>
    <div id="messageWindow"></div>
    <script>
    
    
	let objectIdCounter = 0;

	class MapObject {
	    constructor(x, y) {
	        this.x = x;
	        this.y = y;
	        this.onObjectEnter = null;
	    }

	    draw(context2d) {
	        // 基本の描画処理は何もしない
	    }

	    triggerEvent(object) {
	        if (this.onObjectEnter) {
	            return this.onObjectEnter(object);
	        }
	        return true; // Default behavior is to allow the object to enter
	    }
	}

	class CellBase extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	    }
	    draw(context2d) {
	        context2d.fillStyle = 'gray';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	}

	class Block extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	        this.onObjectEnter = (object) => {
	            // Block the object from entering the block
	            return false;
	        };
	    }

	    draw(context2d) {
	        context2d.fillStyle = 'black';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	}
	
	class Blank extends MapObject {
	    constructor(x, y) {
	        super(x, y);
	        this.onObjectEnter = (object) => {
	            showMessage('test');
	            return true; // Allow the object to enter
	        };
	    }
	}	
	
	

	class Player extends MapObject {
	    constructor(x, y) {
	        super(x, y);
		    }

	    move(direction) {
	        let newX = this.x;
	        let newY = this.y;

	        switch (direction) {
	            case 1:
	                newX -= 1;
	                newY += 1;
	                break;
	            case 2:
	                newY += 1;
	                break;
	            case 3:
	                newX += 1;
	                newY += 1;
	                break;
	            case 4:
	                newX -= 1;
	                break;
	            case 6:
	                newX += 1;
	                break;
	            case 7:
	                newX -= 1;
	                newY -= 1;
	                break;
	            case 8:
	                newY -= 1;
	                break;
	            case 9:
	                newX += 1;
	                newY -= 1;
	                break;
	            default:
	                console.log("Invalid direction. Please enter a valid number (1-9, excluding 5).");
	                break;
	        }//switch

	        if (gameMap.triggerEvent(newX, newY, this)) {
	            gameMap.removeObject(this);  // 追加: 古いセルからプレイヤーを削除
	            this.x = newX;
	            this.y = newY;
	            gameMap.addObject(this);     // 追加: 新しいセルにプレイヤーを追加
	        }
	    }//move

	    draw(context2d) {
	        context2d.fillStyle = 'blue';
	        context2d.fillRect(this.x * 32, this.y * 32, 32, 32);
	    }
	    

        	    
	}//player
	
	


	// Add a message window
	const messageWindow = document.getElementById('messageWindow');

	function showMessage(message) {
	    messageWindow.textContent = message;
	}	

	class Map {
	    constructor(w, h) {
	        this.Width = w;
	        this.Height = h;
	        this.GameBoard = Array.from({ length: this.Height }, () => Array(this.Width).fill([]));
	        this.MapObjects = [];
	        
	        // Fill the map with CellBase objects
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                const cell = new CellBase(x, y);
	                this.addObject(cell);
	            }
	        }

	        // Surround the map with Block objects
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                if (y === 0 || y === this.Height - 1 || x === 0 || x === this.Width - 1) {
	                    const block = new Block(x, y);
	                    this.addObject(block);
	                }
	            }
	        }

	        // Add some Block objects randomly on the map
	        const randomBlockPositions = [
	            { x: 3, y: 3 },
	            { x: 6, y: 2 },
	            { x: 2, y: 5 }
	        ];
	        for (const position of randomBlockPositions) {
	            const block = new Block(position.x, position.y);
	            this.addObject(block);
	        }	 
	        
	        
	               
	        // Add a Blank object with a "test" message at a random accessible position
	        let randomX, randomY;
	        do {
	            randomX = Math.floor(Math.random() * (this.Width - 2)) + 1;
	            randomY = Math.floor(Math.random() * (this.Height - 2)) + 1;
	        } while (this.GameBoard[randomY][randomX] instanceof Block);
	        const blank = new Blank(randomX, randomY);
	        this.addObject(blank);
	        
	    }
	    
	    addObject(mapObject) {
	        if (mapObject instanceof MapObject) {
	            this.MapObjects.push(mapObject);
	            this.GameBoard[mapObject.y][mapObject.x] = [...this.GameBoard[mapObject.y][mapObject.x], mapObject];
	        }
	    }

	    removeObject(mapObject) {
	        if (mapObject instanceof MapObject) {
	            const index = this.MapObjects.indexOf(mapObject);
	            if (index > -1) {
	                this.MapObjects.splice(index, 1);
	                this.GameBoard[mapObject.y][mapObject.x] = this.GameBoard[mapObject.y][mapObject.x].filter(obj => obj !== mapObject);
	            }
	        }
	    }
	    
	    draw(context2d) {
	        // Draw background
	        context2d.fillStyle = 'white';
	        context2d.fillRect(0, 0, this.Width * 32, this.Height * 32);
	        // Draw grid
	        context2d.strokeStyle = 'black';
	        context2d.lineWidth = 1;
	        for (let y = 0; y <= this.Height; y++) {
	            context2d.beginPath();
	            context2d.moveTo(0, y * 32);
	            context2d.lineTo(this.Width * 32, y * 32);
	            context2d.stroke();
	        }
	        for (let x = 0; x <= this.Width; x++) {
	            context2d.beginPath();
	            context2d.moveTo(x * 32, 0);
	            context2d.lineTo(x * 32, this.Height * 32);
	            context2d.stroke();
	        }
	        // Draw objects from bottom to top
	        for (let y = 0; y < this.Height; y++) {
	            for (let x = 0; x < this.Width; x++) {
	                const objectsInCell = this.GameBoard[y][x];
	                for (const obj of objectsInCell) {
	                    obj.draw(context2d);
	                }
	            }
	        }
	    }//draw
	    
	    triggerEvent(x, y, object) {
	        const objectsInCell = this.GameBoard[y][x];
	        for (let i = objectsInCell.length - 1; i >= 0; i--) {
	            const mapObject = objectsInCell[i];
	            if (mapObject) {
	                const result = mapObject.triggerEvent(object);
	                if (!result) {
	                    return false;
	                }
	            }
	        }
	        return true; // Default behavior is to allow the object to enter
	    }    
	    
	}//Map


        const canvas = document.getElementById('gameCanvas');
        const context2d = canvas.getContext('2d');
        const gameMap = new Map(10, 10);
        const player = new Player(4, 4);
        gameMap.addObject(player);

        let lastFrameTime = performance.now();
        const targetFrameDuration = 1000 / 60; // 60FPSの場合のフレーム間隔(ミリ秒)

		const keyStates = {};

		function gameLoop(currentTime) {
		    const deltaTime = currentTime - lastFrameTime;
		    if (deltaTime >= targetFrameDuration) {
		        update(deltaTime);
		        draw();
		        lastFrameTime = currentTime;
		    }
		    requestAnimationFrame(gameLoop);
		}

		function update(deltaTime) {
		    for (const key in keyStates) {
		        const state = keyStates[key];
		        if (state === 'pressed') {
		            const direction = directionKeyMap[key];
		            if (direction) {
		                player.move(direction);
		            }
		            keyStates[key] = 'holding';
		        }
		    }
		}

		function keydownHandler(event) {
		    if (!keyStates[event.code]) {
		        keyStates[event.code] = 'pressed';
		    }
		}

		function keyupHandler(event) {
		    delete keyStates[event.code];
		}  

        function draw() {
            gameMap.draw(context2d);
        }


        const directionKeyMap = {
            'Numpad1': 1,
            'Numpad2': 2,
            'Numpad3': 3,
            'Numpad4': 4,
            'Numpad6': 6,
            'Numpad7': 7,
            'Numpad8': 8,
            'Numpad9': 9,
            
		    'ArrowDown': 2,
		    'ArrowUp': 8,
		    'ArrowLeft': 4,
		    'ArrowRight': 6,     
            
        };

        document.addEventListener("keydown", keydownHandler);
        document.addEventListener("keyup", keyupHandler);
        requestAnimationFrame(gameLoop);
    </script>
</body>
</html>

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