我有这个名为snitch的精灵,我试图让它在一个圆圈中移动,画布中心/ 2(画布命名为空格)和半径30.我使用以下内容代码,但它似乎没有做任何事情," snitch"只是站在那里坐标(0,0)上什么都不做。我尝试从MySprite2函数中删除这些(0,0)坐标,但是当我这样做时,它甚至不会出现。
var ctx = space.getContext("2d");
var FPS = 40;
var snitch= new MySprite2("http://i.imgur.com/IgNKTbW.png");
function MySprite2 (img_url) {
var x = this.x = 0;
var y = this.y = 0;
this.visible= true;
var img = this.MyImg2 = new Image();
this.MyImg2.src = img_url;
}
MySprite2.prototype.Do_Frame_Things = function() {
if (this.visible) ctx.drawImage(this.MyImg2, this.x, this.y);
};
function Do_a_Frame () {
ctx.clearRect(0, 0, space.width, space.height);
snitch.Do_Frame_Things();
}
function theMoves(snitch){
var theta = 0;
for (theta = 0; theta < 2 * Math.PI; theta+=0.1) {
snitch.x = (space.width/2) + Math.sin(theta)*30;
snitch.y = (space.height/2) + Math.cos(theta)*30;
}
}
setInterval(theMoves, 1000/FPS);
setInterval(Do_a_Frame, 1000/FPS);
知道出了什么问题吗? 确定它正在移动但现在它只是以直线而不是圆形运行。下面的新代码。
function MySprite (img_url) {
var x = this.x = (space_x/2);
var y = this.y = (space_y/2);
var angle = this.angle = 0;
this.visible= true;
var img = this.MyImg = new Image();
this.MyImg.src = img_url;
}
MySprite.prototype.Do_Frame_Things = function() {
if (this.visible) ctx.drawImage(this.MyImg, this.x, this.y);
};
function theMoves(){
snitch.x += Math.cos(snitch.angle)*2;
snitch.y += Math.sin(snitch.angle)*2;
}
setInterval(theMoves, 40);
答案 0 :(得分:1)
很多问题所以我做了重写。已经完成并解释了我做了什么以及为什么要这样做。
第一行所有好但不需要FPS,因为这将由浏览器来决定。对于游戏,除非您拥有专用硬件和确定性操作系统,否则您永远无法保证任何帧速率。只有专用游戏机提供此功能。
var ctx = space.getContext("2d");
使用new
和prototypes
对游戏设计不利,因为它们会产生大量不需要的额外开销。事实上,完全避免使用这种类型的构造函数通常是一个好主意。
使用生成器功能,不要直接触摸原型
首先在生成器BTW之前声明你的方法在变量开头的Javascript大写字母为类类型对象保留,但这不再是个人风格选择
// draw the sprite is visible
var doFrameThings = function() {
if (this.visible) { // though you don't have to put the curly braces here
// you should make it a habit to always use them
ctx.drawImage(this.myImg , this.x, this.y);
}
};
创建一个更新精灵的函数,如果帧速率下降,则使用最后一帧时间来确保速度一致
var updateSprite = function(frameTime){
this.theta += this.deltaTheta * frameTime;
this.x = (space.width/2) + Math.sin(this.theta)*30;
this.y = (space.height/2) + Math.cos(this.theta)*30;
}
创建一个精灵。这种方法几乎与原型方法没有区别,但它提供了更好的性能
function createSprite(imgURL){
var sprite = { // create the sprite
x:0,
y:0,
theta: 0,
deltaTheta: Math.PI/40,
visible:false, // not visible until it has loaded.
draw : doFrameThings, // add the draw function
update : updateSprite, // add the update function
myImg : (function(){ // call a annon function that creates the
// image returning it to myImg
var image = new Image();
image.src = imgUrl;
image.onload = function(){ // flag it as visible only when it has loaded.
sprite.visible = true;
};
return image;
})()
};
return sprite; // return the created sprite
// this is exactly the same as new does except new returns
// this instead of the named object.
}
创建一个精灵。现在您不必调用使用New和使用原型系统的所有开销。
var snitch = createSprite("http://i.imgur.com/IgNKTbW.png");
使用setInterval
是一种非常糟糕的动画制作方法。首先,你有两个setInterval
他们会不同步,并且无法保证它们会在请求的时间间隔内发生。它们也不与显示硬件同步,因此您将受到剪切。另外,因为它们未与浏览器的渲染系统同步,您可能会出现闪烁或更糟的情况。
如果您的渲染时间大于间隔时间,最终会导致您的应用崩溃,并且没有简单的方法可以知道是否发生了这种情况
所以永远不要使用setInterval
。个人永远不要使用setInterval
任何危险的方法,应该从Javascript中删除。
使用requestAnimationFrame
获得稳定的60 fps并同步到显示硬件和浏览器的渲染系统。因为它与显示器同步,所以帧之间的时间将以1/60秒为单位。如果你错过第一帧,你将不得不等待下一次刷新,这将是1/60秒。
创建一个主循环/更新函数,并从同一个函数调用所有动画。
var lastTime = new Date().valueOf(); // for tracking the frame time
function update(time){ // requestAnimationFrame provides the current time
var frameTime = time-lastTime;
// clear the canvas
ctx.clearRect(0, 0, space.width, space.height);
snitch.update(frameTime); // update sprite
snitch.draw(); // draw the sprite
requestAnimationFrame(update); // request the next animation frame
lastTime = time; // save the time this frame was called
}
requestAnimationFrame(update); // start the animation
这应该让这个小报很好地运转。
答案 1 :(得分:0)
我看到的第一个错误是你的sin函数将返回undefined,因为你需要使用以下语法调用它:
Math.sin()
第二个错误是你的snitch变量未定义。以下代码行引发错误。
snitch.x = (space.width/2) + Math.sin(theta)*30;
您的第三个错误是:
snitch.y = (space.height/2) + cos(theta)*30;
我创建了一种更模块化的方法来帮助您完成圆形动画。
现场演示:http://codepen.io/larryjoelane/pen/obGPwY
HTML:
<canvas width ="500" height="500" id="canvasOne"></canvas>
JavaScript的:
var canvas = new Canvas("canvasOne");
var thisCanvas = canvas.instance("canvasOne");
var imageURL = "http://bytewarestudios.com/assets/images/sphere.png";
var image = canvas.createImage(imageURL);
var context = canvas.context2D("canvasOne");
/* Formula to determine x and y points on the circumference of a
* circle
* cx and cy = (origin or center of the circle)
* r = radius of the circle
* a = angle in radians(360deg = 6.285714285714285714285714285714 radian) or 2 * PI
* Formulas examples below for x and y points
* var x = cx + r * Math.cos(a);
* var y = cy + r * Math.sin(a);
*/
//initialize the degree variable
var deg = 0;
//frames per second
var fps = 45;
window.requestAnimationFrame(drawCircle); // start the animation
function drawCircle() { //begin function
setTimeout(function() {
//increment the degrees
deg = deg + 1;
//used to offset the circle radius to bring the circle in from the border of
//the canvas
var offset = 120;
//radius of the circle
var r = ((thisCanvas.width - offset) / 2);
//x coordinate of the circle origin
var cx = ((thisCanvas.width) / 2);
//y coordinate of the circle origin
var cy = ((thisCanvas.height) / 2);
//store the angle in radians
var a = canvas.toRadians(deg);
var x = cx + r * Math.cos(a);
var y = cy + r * Math.sin(a);
//clear the canvas
context.clearRect(0, 0, thisCanvas.width, thisCanvas.height);
//draw the first image
context.drawImage(image, x, y);
//start the animation
window.requestAnimationFrame(drawCircle);
}, 1000 / fps);
} //end function
function Canvas() { //begin canvas constructor
Canvas.prototype.createImage = function(imageURL) {
//create a new image
var image = new Image();
//set the image source
image.src = imageURL;
//return the image object
return image;
};
Canvas.prototype.context2D = function(id) {
var canvas = document.getElementById(id);
var context = canvas.getContext("2d");
return context;
};
Canvas.prototype.instance = function(id) {
var canvas = document.getElementById(id);
return canvas;
};
Canvas.prototype.toRadians = function(angle) {
return angle * (Math.PI / 180);
};
} //end canvas constructor
答案 2 :(得分:0)
你有一个关于动作功能的snitch参数。当它被没有参数的间隔tick调用时,它会作为未定义的对象受到阻碍。
如果您想全局使用它,只需删除参数。
或者你可以这样做
setInterval(function(){theMoves(snitch)}, 1000/FPS);