我正在尝试通过将fillRect替换为图像来修改this画布游戏。
在第529行更改 spaceinvaders.js 中的船舶代码时没有问题:
ship = new Image();
ship.src = "images/ship.svg";
ctx.drawImage(ship, this.ship.x - (this.ship.width / 2), this.ship.y - (this.ship.height / 2), this.ship.width, this.ship.height);
但遇到入侵者循环问题:
for(var i=0; i<this.invaders.length; i++) {
var invader = this.invaders[i] = new Image();
this.invaders[i].src = "images/space_invader.png";
//ctx.fillRect(invader.x - invader.width/2, invader.y - invader.height/2, invader.width, invader.height);
this.invaders[i].onload = function(){
var thisX = invader.x * 18;
var thisY = invader.y * 14;
return function() {
ctx.drawImage(invader,invader.x - invader.width/2, invader.y - invader.height/2, invader.width, invader.height);
//ctx.drawImage(this, thisX, thisY, invader.width, invader.height);
};
};
}
当我最终显示入侵者图像时,它将它们全部叠加在一起。 - 即使使用thisX和thisY变量。
编辑:
img = new Image();
img.onload = function(){
for(var i=0; i<this.invaders.length; i++) {
for(var j=0; j<this.invaders.length; j++) {
var invader = this.invaders[i];
ctx.drawImage(img,j*18, i*14, invader.width, invader.height);
}
}
}
img.src = "images/space_invader.png";
给出:无法读取未定义的属性“长度”。
编辑2:
img = new Image();
img.onload = function(){
for(var i=0; i<5; i++) {
for(var j=0; j<10; j++) {
ctx.drawImage(img,j*22, i*16, 18, 14);
}
}
}
img.src = "images/space_invader.png";
编辑3:
var invaders=[{x:0,y:0},{x:20,y:0},{x:40,y:0},{x:60,y:0},{x:80,y:0},{x:100,y:0},{x:120,y:0},{x:140,y:0},{x:160,y:0},{x:180,y:0},{x:0,y:16},{x:20,y:16},{x:40,y:16},{x:60,y:16},{x:80,y:16},{x:100,y:16},{x:120,y:16},{x:140,y:16},{x:160,y:16},{x:180,y:16},{x:200,y:16},{x:0,y:32},{x:20,y:32},{x:40,y:32},{x:60,y:32},{x:80,y:32},{x:100,y:32},{x:120,y:32},{x:140,y:32},{x:160,y:32},{x:180,y:32},{x:200,y:32},{x:0,y:48},{x:20,y:48},{x:40,y:48},{x:60,y:48},{x:80,y:48},{x:100,y:48},{x:120,y:48},{x:140,y:48},{x:160,y:48},{x:180,y:48},{x:200,y:48},{x:0,y:64},{x:20,y:64},{x:40,y:64},{x:60,y:64},{x:80,y:64},{x:100,y:64},{x:120,y:64},{x:140,y:64},{x:160,y:64},{x:180,y:64},{x:200,y:64}];
for (var i=0; i<this.invaders.length; i++) {
invaders[i] = new Image();
invaders[i].onload = function() {
ctx.drawImage(this, x, y);
};
invaders[i].src = "images/space_invader.png";
}
未定义x。
编辑4:
function createImage(i){
var image = new Image();
image.src = "images/space_invader.png";
image.onload = function(){
ctx.drawImage(image,imagePos[i][0],imagePos[i][1], 20, 16);
}
}
var imagePos=[[0,0],[20,0],[40,0],[60,0],[80,0],[100,0],[120,0],[140,0],[160,0],[180,0],[0,16],[20,16],[40,16],[60,16],[80,16],[100,16],[120,16],[140,16],[160,16],[180,16],[0,32],[20,32],[40,32],[60,32],[80,32],[100,32],[120,32],[140,32],[160,32],[180,32],[0,48],[20,48],[40,48],[60,48],[80,48],[100,48],[120,48],[140,48],[160,48],[180,48],[0,64],[20,64],[40,64],[60,64],[80,64],[100,64],[120,64],[140,64],[160,64],[180,64]];
for(var i = 0; i <this.invaders.length; i += 1){
createImage(i);
}
return
显示入侵者,但他们一直闪烁。 (主要游戏循环?)
答案 0 :(得分:3)
有一条简单的规则可以帮助您避免这样的问题。永远不要在循环中声明函数。
<强>为什么?强>
让我们看一个循环
[Wed Jan 04 21:23:09 2017] [error] [client ::1] Traceback (most recent call last):
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/home/blakeh/test.py", line 7, in <module>
[Wed Jan 04 21:23:09 2017] [error] [client ::1] client.foo()
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/xmlrpc/client.py", line 1092, in __call__
[Wed Jan 04 21:23:09 2017] [error] [client ::1] return self.__send(self.__name, args)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/xmlrpc/client.py", line 1432, in __request
[Wed Jan 04 21:23:09 2017] [error] [client ::1] verbose=self.__verbose
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/xmlrpc/client.py", line 1134, in request
[Wed Jan 04 21:23:09 2017] [error] [client ::1] return self.single_request(host, handler, request_body, verbose)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/xmlrpc/client.py", line 1146, in single_request
[Wed Jan 04 21:23:09 2017] [error] [client ::1] http_conn = self.send_request(host, handler, request_body, verbose)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/xmlrpc/client.py", line 1259, in send_request
[Wed Jan 04 21:23:09 2017] [error] [client ::1] self.send_content(connection, request_body)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/xmlrpc/client.py", line 1289, in send_content
[Wed Jan 04 21:23:09 2017] [error] [client ::1] connection.endheaders(request_body)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/http/client.py", line 1102, in endheaders
[Wed Jan 04 21:23:09 2017] [error] [client ::1] self._send_output(message_body)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/http/client.py", line 934, in _send_output
[Wed Jan 04 21:23:09 2017] [error] [client ::1] self.send(msg)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/http/client.py", line 877, in send
[Wed Jan 04 21:23:09 2017] [error] [client ::1] self.connect()
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/http/client.py", line 849, in connect
[Wed Jan 04 21:23:09 2017] [error] [client ::1] (self.host,self.port), self.timeout, self.source_address)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/socket.py", line 711, in create_connection
[Wed Jan 04 21:23:09 2017] [error] [client ::1] raise err
[Wed Jan 04 21:23:09 2017] [error] [client ::1] File "/usr/local/lib/python3.5/socket.py", line 702, in create_connection
[Wed Jan 04 21:23:09 2017] [error] [client ::1] sock.connect(sa)
[Wed Jan 04 21:23:09 2017] [error] [client ::1] PermissionError: [Errno 13] Permission denied
您希望开始加载10张图片,当每张图片都已加载时,您希望它们在正确的位置绘制。但这永远不会发生。
在for循环完成并返回执行之前,var imagePos = [[10,10],[10,20],[10,30],[10,40],[10,50],[20,10],[20,20],[20,30],[20,40],[20,50]];
for(var i = 0; i < 10; i += 1){
var image = new Image();
image.src = "imagename";
image.onload = function(){
ctx.drawImage(image,imagePos[i][0],imagePos[i][1]);
}
}
// end
return
函数不会触发。在第一个onload事件触发onload
时,您有2个变量i
和image
,并且每个onload都会保持这种变量。您在onload函数中提供的图像也只是一个变量,不能容纳多个图像。即使每个i = 10
都正确绑定到图像,onload
变量也将指向循环中创建的最后一个图像。
您希望image
和i
分别拥有10个单独的值,并知道什么时候需要什么值。
正确的方法如下
image
您也可以使用循环内的函数完成它,但您需要使用函数绑定对象来存储您想要的值。
function createImage(i){ // load an image function
// creates a new i each time it is called
var image = new Image(); // create a new image variable
image.src = "imagename";
image.onload = function(){ // now the onload will have the correct variables
ctx.drawImage(image,imagePos[i][0],imagePos[i][1]);
}
}
var imagePos = [[10,10],[10,20],[10,30],[10,40],[10,50],[20,10],[20,20],[20,30],[20,40],[20,50]];
for(var i = 0; i < 10; i += 1){
createImage(i); // call the function so it can create unique variables for each image
}
// end
return
除了你发现的陷阱之外,这样做是没有错的。这就是为什么一般规则是,如果你不熟悉javascript,不要在循环中声明函数。
答案 1 :(得分:1)
您可能不应该使用Image对象的x和y属性。首先它是只读的,第二个可能没有设置,因为你正在创建一个新的Image实例,所以总是为0。
请参阅https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image以及https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement
答案 2 :(得分:0)
大!现在你所需要的只是某种游戏循环来让它们移动。我会将x和y位置(从你当前的for循环)移动到单个对象中,这样你就可以修改每个(更新)循环的每个入侵者。
var invaders = [
{x: 100, y: 100, speed: 10},
{x: 140, y: 100, speed: 10},
{x: 180, y: 100, speed: 10},
// and so on
];
尝试阅读有关游戏循环及其工作方式的更多信息:https://www.isaacsukin.com/news/2015/01/detailed-explanation-javascript-game-loops-and-timing
编辑:像这样......
for(var i = 0; i < invaders.length; i++) {
var invader = new Image();
invader.onload = function() {
ctx.drawImage(this, invaders[i].x, invaders[i].y);
};
invaders[i].src = "images/space_invader.png";
}