无法让精灵在圆形路径中移动
Can't get sprite to move in a circle path
我有一个叫做飞贼的精灵,我试图让它绕圈移动,中心在画布/2(画布被命名为空间)和半径30。我正在使用以下代码,但它似乎没有做任何事情,"告密者"只是站在那里对坐标 (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);
对于许多问题,所以我做了重写。已经经历了并解释了我做了什么以及我为什么这样做。
第一行都很好,但不需要FPS,因为这将由浏览器决定。对于游戏,除非您拥有专用硬件和确定性操作系统,否则您永远无法保证任何帧速率。只有专用游戏机才能提供此功能。
var ctx = space.getContext("2d");
使用 new
和 prototypes
不利于游戏设计,因为它们会产生大量不需要的额外开销。事实上,完全避免使用这种类型的构造函数通常是一个好主意。
使用生成器功能,不要直接触摸原型
在变量开头的 Javascript 大写字母生成器 BTW 之前首先声明您的方法,为类类型对象保留,但这是个人风格的选择 仅此而已
// 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
这应该会让飞贼四处走动。
我看到的第一个错误是你的sin函数将返回undefined,因为你需要使用以下语法调用它:
Math.sin()
第二个错误是你的告密变量未定义。错误由以下代码行引发。
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
你在 Moves 函数上有一个告密者参数。当它被没有参数的间隔刻度调用时,它会作为未定义的对象妨碍。
如果要全局使用它,只需删除参数即可。
或者你可以这样做
setInterval(function(){theMoves(snitch)}, 1000/FPS);
- 计算从一个对象到另一个对象的路径并沿其移动
- jquery移动应用程序无法使用jquryMobile框架JS和css文件的相对路径
- 在移动设备上按路径或名称获取二进制图像(Ionic / Ng cordova 应用程序)
- 如何基于力沿弯曲路径移动图元
- 在 HTML5 画布中沿路径旋转移动对象
- 传单.js路径点击移动设备
- 在 Phaser.IO 中沿着预定义的路径移动精灵
- 将对象拖动到特定路径并在同级路径中移动
- 在 threejs 中沿路径或样条移动对象
- (HTML5 画布)填充样式 img 不会随我的地形路径移动
- Javascript 移动到没有 JS 库的 SVG 路径
- 无法让精灵在圆形路径中移动
- D3在鼠标上沿路径移动圆平移X轴上的直线时移动中断
- 钛移动的Commonjs资源路径
- raphaeljs-移动我从svg转换的路径
- Raphael JS:延迟后沿着路径移动图像
- 纯使用JavaScript在圆形路径中移动图像
- 是否有将整个SVG路径移动到新位置的命令
- 在用户滚动时沿弯曲路径移动元素
- 尝试研究如何使用四元数来旋转沿路径移动的相机以寻找新的方向矢量