如何将我的代码重构为游戏循环?
How to refactor my code to a game loop?
现在我有了一个没有主游戏循环的简单代码。我正在使用 Loader 构造函数及其 image.onload 函数在 canvas 上渲染精灵(因为没有 image.onload 我将看不到任何精灵)现在我想为我的精灵制作动画为此,我需要创建一个绘制循环。不幸的是,这是我的知识结束的地方。我尝试创建渲染函数并只是复制粘贴我的 ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
方法,但它不起作用,因为我需要 Loader
中的 image.onload 函数。而且我不能将 Loader 构造函数放入我的 render()
函数,因为那样 var background = new Loader("ground.png");
var boat = new Loader("ship.png");
就无法访问构造函数变量来初始化新对象。
所以在这一点上我很迷茫我应该如何更好地重构我的代码?
完整代码如下:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]
]
var StyleSheet = function(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight,x, y, width, height);
}
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
}
}
/* Initial Sprite Position */
var boatPosX = 230;
var boatPosY = 200;
var Loader = function(src) {
this.image = new Image();
this.image.src = src;
this.image.onload = function() {
var sprite = new StyleSheet(background, 36, 36);
var ship = new StyleSheet(boat, 90, 100);
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
sprite.draw(background, 190, 230, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 1) {
sprite.draw(background, 30, 30, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 2) {
sprite.draw(background, 200, 20, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
}
}
ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
}
return this.image;
}
function render() {
}
setInterval(render, 10);
/* Sprite controls */
function move(e) {
if (e.keyCode == 39) {
boatPosX += 2;
console.log("works");
}
if (e.keyCode == 37) {
boatPosX -= 2;
}
}
document.onkeydown = move;
var background = new Loader("ground.png");
var boat = new Loader("ship.png");
console.log(background);
更新:
所以根据我的老问题,我决定对我的代码做一些更改,这样我就可以为我的 onload
函数调用 requestAnimationFrame
并在 [=40 上绘制精灵=]不断。为此,我通过将 onload
放入一个新函数并将该函数分配给 Loader
原型来分离 Loader 构造函数和我的方法 onload
。然后我执行 var background = new Loader("ground.png");
和 background.render();
但我得到 Uncaught TypeError: background.render is not a function
错误。不确定我做错了什么?
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]
]
var StyleSheet = function(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight,x, y, width, height);
}
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
}
}
/* Initial Sprite Position */
var boatPosX = 230;
var boatPosY = 200;
var Loader = function(src) {
this.image = new Image();
this.image.src = src;
return this.image;
}
Loader.prototype.render = function() {
this.image.onload = function() {
var sprite = new StyleSheet(background, 36, 36);
var ship = new StyleSheet(boat, 90, 100);
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
sprite.draw(background, 190, 230, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 1) {
sprite.draw(background, 30, 30, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 2) {
sprite.draw(background, 200, 20, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
}
}
ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
}
}
/* Sprite controls */
function move(e) {
if (e.keyCode == 39) {
boatPosX += 2;
console.log("works");
}
if (e.keyCode == 37) {
boatPosX -= 2;
}
}
document.onkeydown = move;
var background = new Loader("ground.png");
var boat = new Loader("ship.png");
background.render();
console.log(background);
Codepen 示例:https://codepen.io/Limpuls/pen/dejVpR
我对你的 Pen 进行了分叉并重构了你的代码。现在你有一个使用 requestAnimationFrame 的游戏循环:https://codepen.io/DonKarlssonSan/pen/rvrGvL/
编辑,添加我更改的内容:
我删除了 Loader,而是只使用纯图像和 img.src = url,然后我将其作为参数传递给 StyleSheet 的构造函数。
我将 mapArray 上的循环提取到渲染方法中,该方法也用作主 ("game") 循环。
代码:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]
];
var StyleSheet = function(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
};
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
};
};
/* Initial Sprite Position */
var boatPosX = 230;
var boatPosY = 200;
function render() {
requestAnimationFrame(render);
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
this.sprite.draw(
background,
190,
230,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
if (mapArray[i][j] == 1) {
this.sprite.draw(
background,
30,
30,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
if (mapArray[i][j] == 2) {
this.sprite.draw(
background,
200,
20,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
}
}
this.ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
};
function move(e) {
if (e.keyCode == 39) {
boatPosX += 2;
console.log("right");
}
if (e.keyCode == 37) {
boatPosX -= 2;
console.log("left");
}
}
document.onkeydown = move;
var background = new Image();
background.src = "http://i67.tinypic.com/35lx8y0.png";
var sprite = new StyleSheet(background, 36, 36);
var boat = new Image();
boat.src = "http://i66.tinypic.com/b7b9tc.png";
var ship = new StyleSheet(boat, 90, 100);
render();
现在我有了一个没有主游戏循环的简单代码。我正在使用 Loader 构造函数及其 image.onload 函数在 canvas 上渲染精灵(因为没有 image.onload 我将看不到任何精灵)现在我想为我的精灵制作动画为此,我需要创建一个绘制循环。不幸的是,这是我的知识结束的地方。我尝试创建渲染函数并只是复制粘贴我的 ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
方法,但它不起作用,因为我需要 Loader
中的 image.onload 函数。而且我不能将 Loader 构造函数放入我的 render()
函数,因为那样 var background = new Loader("ground.png");
var boat = new Loader("ship.png");
就无法访问构造函数变量来初始化新对象。
所以在这一点上我很迷茫我应该如何更好地重构我的代码?
完整代码如下:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]
]
var StyleSheet = function(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight,x, y, width, height);
}
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
}
}
/* Initial Sprite Position */
var boatPosX = 230;
var boatPosY = 200;
var Loader = function(src) {
this.image = new Image();
this.image.src = src;
this.image.onload = function() {
var sprite = new StyleSheet(background, 36, 36);
var ship = new StyleSheet(boat, 90, 100);
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
sprite.draw(background, 190, 230, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 1) {
sprite.draw(background, 30, 30, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 2) {
sprite.draw(background, 200, 20, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
}
}
ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
}
return this.image;
}
function render() {
}
setInterval(render, 10);
/* Sprite controls */
function move(e) {
if (e.keyCode == 39) {
boatPosX += 2;
console.log("works");
}
if (e.keyCode == 37) {
boatPosX -= 2;
}
}
document.onkeydown = move;
var background = new Loader("ground.png");
var boat = new Loader("ship.png");
console.log(background);
更新:
所以根据我的老问题,我决定对我的代码做一些更改,这样我就可以为我的 onload
函数调用 requestAnimationFrame
并在 [=40 上绘制精灵=]不断。为此,我通过将 onload
放入一个新函数并将该函数分配给 Loader
原型来分离 Loader 构造函数和我的方法 onload
。然后我执行 var background = new Loader("ground.png");
和 background.render();
但我得到 Uncaught TypeError: background.render is not a function
错误。不确定我做错了什么?
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]
]
var StyleSheet = function(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight,x, y, width, height);
}
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
}
}
/* Initial Sprite Position */
var boatPosX = 230;
var boatPosY = 200;
var Loader = function(src) {
this.image = new Image();
this.image.src = src;
return this.image;
}
Loader.prototype.render = function() {
this.image.onload = function() {
var sprite = new StyleSheet(background, 36, 36);
var ship = new StyleSheet(boat, 90, 100);
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
sprite.draw(background, 190, 230, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 1) {
sprite.draw(background, 30, 30, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
if (mapArray[i][j] == 2) {
sprite.draw(background, 200, 20, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
}
}
}
ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
}
}
/* Sprite controls */
function move(e) {
if (e.keyCode == 39) {
boatPosX += 2;
console.log("works");
}
if (e.keyCode == 37) {
boatPosX -= 2;
}
}
document.onkeydown = move;
var background = new Loader("ground.png");
var boat = new Loader("ship.png");
background.render();
console.log(background);
Codepen 示例:https://codepen.io/Limpuls/pen/dejVpR
我对你的 Pen 进行了分叉并重构了你的代码。现在你有一个使用 requestAnimationFrame 的游戏循环:https://codepen.io/DonKarlssonSan/pen/rvrGvL/
编辑,添加我更改的内容:
我删除了 Loader,而是只使用纯图像和 img.src = url,然后我将其作为参数传递给 StyleSheet 的构造函数。
我将 mapArray 上的循环提取到渲染方法中,该方法也用作主 ("game") 循环。
代码:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var mapArray = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0]
];
var StyleSheet = function(image, width, height) {
this.image = image;
this.width = width;
this.height = height;
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
};
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
};
};
/* Initial Sprite Position */
var boatPosX = 230;
var boatPosY = 200;
function render() {
requestAnimationFrame(render);
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
this.sprite.draw(
background,
190,
230,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
if (mapArray[i][j] == 1) {
this.sprite.draw(
background,
30,
30,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
if (mapArray[i][j] == 2) {
this.sprite.draw(
background,
200,
20,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
}
}
this.ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
};
function move(e) {
if (e.keyCode == 39) {
boatPosX += 2;
console.log("right");
}
if (e.keyCode == 37) {
boatPosX -= 2;
console.log("left");
}
}
document.onkeydown = move;
var background = new Image();
background.src = "http://i67.tinypic.com/35lx8y0.png";
var sprite = new StyleSheet(background, 36, 36);
var boat = new Image();
boat.src = "http://i66.tinypic.com/b7b9tc.png";
var ship = new StyleSheet(boat, 90, 100);
render();