我一直在想一种方法来设置与玩家的瓷砖地图碰撞,方法与到目前为止开发游戏的方法相同(或者,如果可能的话,也可以采用类似的方法,因此我不必重做所有的事情:))。
我从教程和视频中获得了一些想法,并决定将其实现到我的代码中,并且播放器肯定会与某些内容发生冲突,尽管它看起来并不是应该的正确图块。
例如,我希望它在索引为1的图块上行走,但要与索引为0和3的图块相撞,以停止玩家的移动。
这是到目前为止我得到的:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Canvas Tile Map</title>
<style>
#canvas{
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" height="650px" width="1000px"></canvas>
<script>
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var go = 0;
var canvasBegX = -64;
var canvasEndX = 999;
var canvasBegY = -64;
var canvasEndY = 649;
var heroX = 0;
var heroY = 0;
var heroIndexX = 0;
var heroIndexY = 0;
var heroIndexXnew = 0;
var heroIndexYnew = 0;
//--------------------------------------------------------------
//ADD CHECKER IF KEY IS PRESSED OR RELEASED
window.addEventListener('keydown', function (e) {
canvas.key = e.keyCode;
})
window.addEventListener('keyup', function (e) {
canvas.key = false;
})
//--------------------------------------------------------------
//THE MAP
var mapArray=[
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
[3,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,3],
[3,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,3],
[3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,3],
[3,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,3],
[3,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,3],
[3,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,3],
[3,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3],
[3,0,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,3],
[3,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3],
[3,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,3],
[3,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,1,3],
[3,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,1,1,0,0,3],
[3,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,3],
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
];
// x= 22
// y= 15
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
// DRAW PLAYER
player_image = new Image();
var player = new Object();
player.y = canvas.height/2-220; //player position y
player.x = canvas.width/2-340; //player position x
player.Width = 60;
player.Height = 60;
function drawPlayer() { // drawing the player
context.beginPath();
context.fillStyle = "red";
context.fillRect(player.x,player.y,player.Width,player.Height);
context.closePath();
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
// These I need for the map co-ordinates and when it moves the map upon key-press
var updateX=(player.x-210); // Starting point of canvas X
var updateY=(player.y-160); // Starting point of canvas Y
var posX=updateX;
var posY=updateY;
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//DRAW THE MAP AND THE PLAYER
var grass = new Image();
var stone = new Image();
var black = new Image();
function drawMap() {
var posY = updateY; // new Y coordinates for the map after movement
grass.src= 'https://sarahkerrigan.biz/wpmtest/hosting/images/tile/grass.jpeg';
stone.src = 'https://sarahkerrigan.biz/wpmtest/hosting/images/tile/sand.jpeg';
black.src = 'https://sarahkerrigan.biz/wpmtest/hosting/images/tile/black.png';
//---------------------------------------------------------
// Draw the map loop
grass.onload = function (){
stone.onload = function (){
black.onload = function (){
for(var i=0; i < mapArray.length; i++){
for(var j=0; j < mapArray[i].length; j++){
if(mapArray[i][j]==0){
if (posY > canvasBegY && posY < canvasEndY && posX > canvasBegX && posX < canvasEndX){
context.drawImage(grass,posX, posY, 64, 64); // Load image for grass "0"
}
}
if(mapArray[i][j]==1){
if (posY > canvasBegY && posY < canvasEndY && posX > canvasBegX && posX < canvasEndX){
context.drawImage(stone,posX,posY,64,64); // Load image for stone "1"
}
}
if(mapArray[i][j]==3){
if (posY > canvasBegY && posY < canvasEndY && posX > canvasBegX && posX < canvasEndX){
context.drawImage(black,posX,posY,64,64); // Load image for black "3"
}
}
posX+=64;
}
posY+=64;
posX=updateX; // new X coordinates for the map after movement
//---------------------------------------------------------
drawPlayer(); // Draw the player
}
}
}
}
}
//-----------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// PLAYER MOVEMENT BUTTONS
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
var endX=1408;
var endY=960;
document.addEventListener("keydown", keyDownHandler);
function keyDownHandler(e) {
if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 37) {
leftPressed = true;
}
if(e.keyCode == 40) {
downPressed = true;
}
else if(e.keyCode == 38) {
upPressed = true;
}
}
document.addEventListener("keyup", keyUpHandler);
function keyUpHandler(e) {
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
if(e.keyCode == 40) {
downPressed = false;
}
else if(e.keyCode == 38) {
upPressed = false;
}
}
//----------------------------------------------
//THE ACTUAL MOVEMENT + BOUNDARIES
function playerMovement(){
//------------------------------
//CHECK PLAYER X AND Y IN TILE INDEXES
heroX = Math.abs(updateX - player.x); //current hero X position starting from beginning of tilemap(outside of visible part)
heroY = Math.abs(updateY - player.y); //current hero Y position starting from beginning of tilemap(outside of visible part)
heroIndexX = heroX/64; // X index of hero to chech in which tile is currently located
heroIndexY = heroY/64; // Y index of hero to chech in which tile is currently located
heroIndexXnew = Math.ceil(heroIndexX); //index positioned on the right of the heroes index
heroIndexYnew = Math.ceil(heroIndexY) -2; //index positioned on the left of the heroes index
if(rightPressed) {
if (isPathTile(mapArray, heroIndexXnew, heroIndexYnew)){ // Nothing happens because you hit a tile
}else {
moveRight(); // if you are not at the wall, you go right
}
}
//------------------------------
else if(leftPressed) {
if (isPathTile(mapArray, heroIndexXnew - 2, heroIndexYnew)){ // Nothing happens because you hit a tile
}else {
moveLeft(); // if you are not at the wall, you go left
}
}
//------------------------------
if(downPressed) {
if(player.y>updateY+834){} // Nothing happens because you hit the bottom wall
else {
moveDown(); // if you are not at the wall, you go down
}
}
//------------------------------
else if(upPressed) {
if(player.y<updateY+64){} // Nothing happens because you hit the top wall
else {
moveUp(); // if you are not at the wall, you go up
}
}
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//CAMERA BOUNDARIES
function moveRight(){
if(player.x<820){
player.x=player.x+4.1; //If you are at this position, move the player
}
else if(player.x>820){
updateX=updateX-4.1; //If you go over this position, move the background
}
}
function moveLeft(){
if(player.x>100){
player.x=player.x-4.1; //If you are at this position, move the player
}
else if(player.x<100){
updateX=updateX+4.1; //If you go over this position, move the background
}
}
function moveUp(){
if(player.y>80){
player.y=player.y-4.1; //If you are at this position, move the player
}
else if(player.y<80){
updateY=updateY+4.1; //If you go over this position, move the background
}
}
function moveDown(){
if(player.y<500){
player.y=player.y+4.1; //If you are at this position, move the player
}
else if(player.y>500){
updateY=updateY-4.1; //If you go over this position, move the background
}
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// MOVEMENT BOUNDARIES WITH TILES
function isPathTile(mapArray, x, y) {
return (mapArray[x][y] === 0); // Because 0 is the path tile
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// THE GAME LOOP
function gameLoop(){
console.log("index X =" + heroIndexXnew);
console.log("index Y =" + heroIndexYnew);
playerMovement(); //Check for movements
drawMap(); //Draw the map and the player
requestAnimationFrame(gameLoop);
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
gameLoop(); // start the gameLoop
</script>
</body>
</html>
这是测试它的代码-
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var go = 0;
var canvasBegX = -64;
var canvasEndX = 999;
var canvasBegY = -64;
var canvasEndY = 649;
var heroX = 0;
var heroY = 0;
var heroIndexX = 0;
var heroIndexY = 0;
var heroIndexXnew = 0;
var heroIndexYnew = 0;
//--------------------------------------------------------------
//ADD CHECKER IF KEY IS PRESSED OR RELEASED
window.addEventListener('keydown', function (e) {
canvas.key = e.keyCode;
})
window.addEventListener('keyup', function (e) {
canvas.key = false;
})
//--------------------------------------------------------------
//THE MAP
var mapArray=[
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3],
[3,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,3],
[3,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,3],
[3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,3],
[3,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,3],
[3,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,3],
[3,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,3],
[3,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3],
[3,0,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,3],
[3,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3],
[3,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,3],
[3,0,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,1,3],
[3,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,1,1,0,0,3],
[3,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,3],
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
];
// x= 22
// y= 15
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
// DRAW PLAYER
player_image = new Image();
var player = new Object();
player.y = canvas.height/2-220; //player position y
player.x = canvas.width/2-340; //player position x
player.Width = 60;
player.Height = 60;
function drawPlayer() { // drawing the player
context.beginPath();
context.fillStyle = "red";
context.fillRect(player.x,player.y,player.Width,player.Height);
context.closePath();
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
// These I need for the map co-ordinates and when it moves the map upon key-press
var updateX=(player.x-210); // Starting point of canvas X
var updateY=(player.y-160); // Starting point of canvas Y
var posX=updateX;
var posY=updateY;
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//DRAW THE MAP AND THE PLAYER
var grass = new Image();
var stone = new Image();
var black = new Image();
function drawMap() {
var posY = updateY; // new Y coordinates for the map after movement
grass.src= 'https://sarahkerrigan.biz/wpmtest/hosting/images/tile/grass.jpeg';
stone.src = 'https://sarahkerrigan.biz/wpmtest/hosting/images/tile/sand.jpeg';
black.src = 'https://sarahkerrigan.biz/wpmtest/hosting/images/tile/black.png';
//---------------------------------------------------------
// Draw the map loop
grass.onload = function (){
stone.onload = function (){
black.onload = function (){
for(var i=0; i < mapArray.length; i++){
for(var j=0; j < mapArray[i].length; j++){
if(mapArray[i][j]==0){
if (posY > canvasBegY && posY < canvasEndY && posX > canvasBegX && posX < canvasEndX){
context.drawImage(grass,posX, posY, 64, 64); // Load image for grass "0"
}
}
if(mapArray[i][j]==1){
if (posY > canvasBegY && posY < canvasEndY && posX > canvasBegX && posX < canvasEndX){
context.drawImage(stone,posX,posY,64,64); // Load image for stone "1"
}
}
if(mapArray[i][j]==3){
if (posY > canvasBegY && posY < canvasEndY && posX > canvasBegX && posX < canvasEndX){
context.drawImage(black,posX,posY,64,64); // Load image for black "3"
}
}
posX+=64;
}
posY+=64;
posX=updateX; // new X coordinates for the map after movement
//---------------------------------------------------------
drawPlayer(); // Draw the player
}
}
}
}
}
//-----------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// PLAYER MOVEMENT BUTTONS
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
var endX=1408;
var endY=960;
document.addEventListener("keydown", keyDownHandler);
function keyDownHandler(e) {
if(e.keyCode == 39) {
rightPressed = true;
}
else if(e.keyCode == 37) {
leftPressed = true;
}
if(e.keyCode == 40) {
downPressed = true;
}
else if(e.keyCode == 38) {
upPressed = true;
}
}
document.addEventListener("keyup", keyUpHandler);
function keyUpHandler(e) {
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
if(e.keyCode == 40) {
downPressed = false;
}
else if(e.keyCode == 38) {
upPressed = false;
}
}
//----------------------------------------------
//THE ACTUAL MOVEMENT + BOUNDARIES
function playerMovement(){
//------------------------------
//CHECK PLAYER X AND Y IN TILE INDEXES
heroX = Math.abs(updateX - player.x); //current hero X position starting from beginning of tilemap(outside of visible part)
heroY = Math.abs(updateY - player.y); //current hero Y position starting from beginning of tilemap(outside of visible part)
heroIndexX = heroX/64; // X index of hero to chech in which tile is currently located
heroIndexY = heroY/64; // Y index of hero to chech in which tile is currently located
heroIndexXnew = Math.ceil(heroIndexX); //index positioned on the right of the heroes index
heroIndexYnew = Math.ceil(heroIndexY) -2; //index positioned on the left of the heroes index
if(rightPressed) {
if (isPathTile(mapArray, heroIndexXnew, heroIndexYnew)){ // Nothing happens because you hit a tile
}else {
moveRight(); // if you are not at the wall, you go right
}
}
//------------------------------
else if(leftPressed) {
if (isPathTile(mapArray, heroIndexXnew - 2, heroIndexYnew)){ // Nothing happens because you hit a tile
}else {
moveLeft(); // if you are not at the wall, you go left
}
}
//------------------------------
if(downPressed) {
if(player.y>updateY+834){} // Nothing happens because you hit the bottom wall
else {
moveDown(); // if you are not at the wall, you go down
}
}
//------------------------------
else if(upPressed) {
if(player.y<updateY+64){} // Nothing happens because you hit the top wall
else {
moveUp(); // if you are not at the wall, you go up
}
}
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//CAMERA BOUNDARIES
function moveRight(){
if(player.x<820){
player.x=player.x+4.1; //If you are at this position, move the player
}
else if(player.x>820){
updateX=updateX-4.1; //If you go over this position, move the background
}
}
function moveLeft(){
if(player.x>100){
player.x=player.x-4.1; //If you are at this position, move the player
}
else if(player.x<100){
updateX=updateX+4.1; //If you go over this position, move the background
}
}
function moveUp(){
if(player.y>80){
player.y=player.y-4.1; //If you are at this position, move the player
}
else if(player.y<80){
updateY=updateY+4.1; //If you go over this position, move the background
}
}
function moveDown(){
if(player.y<500){
player.y=player.y+4.1; //If you are at this position, move the player
}
else if(player.y>500){
updateY=updateY-4.1; //If you go over this position, move the background
}
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// MOVEMENT BOUNDARIES WITH TILES
function isPathTile(mapArray, x, y) {
return (mapArray[x][y] === 0); // Because 0 is the path tile
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
// THE GAME LOOP
function gameLoop(){
console.log("index X =" + heroIndexXnew);
console.log("index Y =" + heroIndexYnew);
playerMovement(); //Check for movements
drawMap(); //Draw the map and the player
requestAnimationFrame(gameLoop);
}
//-----------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
gameLoop(); // start the gameLoop
#canvas{
border: 1px solid black;
}
<canvas id="canvas" height="650px" width="1000px"></canvas>
所有代码都有一些变量,即tilemap数组,仅在画布的可见部分绘制tilemap,当然,每次绘制时,播放器都将其绘制在画布上,然后我们进行了移动,并且我认为某些地方设置不正确。有一个isPathTile函数可以查看当前播放器位置旁边的索引是否为0,如果为0,则不执行任何操作(右键单击时播放器不会移动)。我认为这是我弄错的地方。非常感谢任何人都可以看一下。
最佳答案
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin: auto;
left: 0;
right: 0;
border: solid 1px white;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
// IIFE
// https://developer.mozilla.org/en-US/docs/Glossary/IIFE
void function() {
// Enforce strict mode inside the IIFE
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
"use strict";
// Var declaration
var canvasWidth = 320;
var canvasHeight = 320;
var canvas = null;
var ctx = null;
var player = {
// Position
x: 35.0,
y: 35.0,
// Velocity
dx: 0.0,
dy: 0.0,
// Size
width: 20,
height: 20,
// Input
up: false,
down: false,
left: false,
right: false
};
// Defined this way the map will need to be indexed as
// map[y][x]
// 0 = not solid
// 1 = solid
var mapTileSize = 32; // size for each tile in pixels
var map = [
[1,1,1,1,1,1,1,1,1,1],
[1,0,1,0,0,0,0,0,1,1],
[1,0,0,1,1,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,0,1,1,1,1,0,1,0,1],
[1,0,0,0,0,0,0,1,0,1],
[1,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1]
];
// Runs after the page has finished loading
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
loop();
}
// Key Input
window.onkeydown = function(e) {
switch(e.key) {
case "w": player.up = true; break;
case "s": player.down = true; break;
case "a": player.left = true; break;
case "d": player.right = true; break;
}
}
window.onkeyup = function(e) {
switch(e.key) {
case "w": player.up = false; break;
case "s": player.down = false; break;
case "a": player.left = false; break;
case "d": player.right = false; break;
}
}
function loop() {
// Tick
// Player movement
if (player.up) {
player.dy = -2;
}
if (player.down) {
player.dy = +2;
}
if (!player.up && !player.down) {
player.dy = 0;
}
if (player.left) {
player.dx = -2;
}
if (player.right) {
player.dx = +2;
}
if (!player.left && !player.right) {
player.dx = 0;
}
// Collision detection & resolution
// Only perform collision detection in either axis
// if the player is actually moving on that axis
// Map grid coordinates at the corners of the player's bounding box
/*
-> *-----* <-
| |
| |
| |
-> *-----* <-
*/
var invMapTileSize = 1.0 / mapTileSize;
var nextX = player.x + player.dx;
var nextY = player.y + player.dy;
// Current position
var currentMinX = (player.x * invMapTileSize) | 0;
var currentMaxX = ((player.x + player.width) * invMapTileSize) | 0;
var currentMinY = (player.y * invMapTileSize) | 0;
var currentMaxY = ((player.y + player.height) * invMapTileSize) | 0;
// Next position
var nextMinX = (nextX * invMapTileSize) | 0;
var nextMaxX = ((nextX + player.width) * invMapTileSize) | 0;
var nextMinY = (nextY * invMapTileSize) | 0;
var nextMaxY = ((nextY + player.height) * invMapTileSize) | 0;
/*
Collision checks are performed down along each axis of the player's
collision box, this way it won't matter if the player is larger
or smaller then the map tiles.
*/
// X axis collision
if (player.dx !== 0.0) {
for (var x = nextMinX; x <= nextMaxX; ++x) {
for (var y = currentMinY; y <= currentMaxY; ++y) {
if (map[y][x]) {
player.dx = 0.0;
break;
}
}
}
}
// Y axis collision
if (player.dy !== 0.0) {
for (var y = nextMinY; y <= nextMaxY; ++y) {
for (var x = currentMinX; x <= currentMaxX; ++x) {
if (map[y][x]) {
player.dy = 0.0;
break;
}
}
}
}
// Update player position
player.x = player.x + player.dx;
player.y = player.y + player.dy;
// render
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
// draw map
ctx.fillStyle = "darkred";
ctx.beginPath();
for (var y = 0; y < map.length; ++y) {
for (var x = 0; x < map[0].length; ++x) {
if (map[y][x]) {
ctx.rect(
x * mapTileSize,
y * mapTileSize,
mapTileSize,
mapTileSize
);
}
}
}
ctx.fill();
// draw player
ctx.fillStyle = "darkblue";
ctx.fillRect(
player.x,
player.y,
player.width,
player.height
);
//
requestAnimationFrame(loop);
}
}();
</script>
</body>
</html>