在这个HTML5代码中,我尝试从对象[0]中的发射器中发射粒子。
这可以在控制台中使用objects[0].play
运行。
然而,发射器跟随粒子射击。
我的问题是,为什么?
HTML代码
<html>
<head>
<style>
#canv{
border: 1px solid black;
}
</style>
<script src = "setup.js"></script>
<script src = "main.js"></script>
</head>
<body onLoad = "start()">
<canvas width = "500" height = "500" id = "canv"></canvas>
</body>
</html>
setup.js
var objects = [];
var sprites = [];
var c;
var ctx;
var time;
var timeInterval;
function newSprite(url){
var a = sprites.length;
var b = new Image();
b.src = url;
b.onload = function(){
sprites[a] = b;
};
}
function randomN(min, max){
return Math.floor((Math.random()*max) - min);
}
function Vector2(x,y){
this.x = x;
this.y = y;
}
function Particle(pos, life, vel, accel){
this.pos = pos;
this.life = life || Infinity;
this.vel = vel || new Vector2(0,0);
this.accel = accel || new Vector2(0,0);
this.update = function(){
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
this.vel.x += this.accel.x;
this.vel.y += this.accel.y;
this.life--;
if(this.life <= 0){
return false;
}else{
return true;
}
};
}
function Emitter(pos){
this.pos = pos;
this.actualPos = this.pos;
this.particles = [];
this.forces = [];
this.playing = false;
this.newParticle = function(life, vel, accel){
var a = this.particles.length;
this.particles[a] = new Particle(this.pos, life, vel, accel);
};
this.update = function(){
console.log("(" + this.actualPos.x + ", " + this.actualPos.y + ") " + "(" + this.pos.x + ", " + this.pos.y + ")");
for(var a = 0; a < this.particles.length; a++){
for(var b = 0; b < this.forces.length; b++){
this.forces[b](this.particles[a]);
}
var that = this.particles[a];
var particleAlive = that.update();
if(particleAlive == false){
this.particles.splice(a, 1);
a--;
}
}
};
this.play = function(){
this.playing = true;
};
}
function timeStep(){
for(var a = 0; a < objects.length; a++){
if(objects[a].__proto__.constructor.name == "Emitter"){
if(objects[a].playing == true){
objects[a].update();
}
}
}
objects[1].newParticle(1000, new Vector2(1, 0), new Vector2(0.1, 0));
time++;
}
function gravity(p){
//p.vel.y += 0.1;
}
main.js
function start(){
c = document.getElementById("canv");
ctx = c.getContext('2d');
newSprite("spark.png");
objects[0] = new Emitter(new Vector2(50, 60));
objects[0].forces.push(gravity);
objects[0].newParticle(1000, new Vector2(1, 0), new Vector2(0.1, 0));
objects[1] = new Emitter(new Vector2(100, 100));
objects[1].forces.push(gravity);
time = 0;
timeInterval = window.setInterval(timeStep, 10);
reDraw();
}
function reDraw(){
ctx.clearRect(0, 0, c.width, c.height);
for(var a = 0; a < objects.length; a++){
if(objects[a].__proto__.constructor.name == "Emitter"){
ctx.beginPath();
ctx.arc(objects[a].pos.x, objects[a].pos.y, 5, 0, 2*Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.closePath();
if(objects[a].playing == true){
for(var b = 0; b < objects[a].particles.length; b++){
ctx.beginPath();
ctx.drawImage(sprites[0], objects[a].particles[b].pos.x, objects[a].particles[b].pos.y, 8,8);
//ctx.arc(objects[a].particles[b].pos.x, objects[a].particles[b].pos.y, 5, 0, 2*Math.PI);
ctx.fillStyle = "black";
ctx.fill();
ctx.closePath();
}
}
}
}
requestAnimationFrame(reDraw);
}
答案 0 :(得分:1)
我没有遵循完整的逻辑,所以如果这不是原因,请对不起,但这有点奇怪:
function newSprite(url){
var a = sprites.length;
var b = new Image();
b.src = url;
b.onload = function(){
sprites[a] = b;
};
}
在onload运行时,a和b的范围更长(我相信):onload事件将作为newSprite之外的新函数调用触发。
你不需要做这样的事情......
b.onload = function(){
sprites[sprites.length] = this;
};
以便函数在调用时正确运行?
答案 1 :(得分:1)
使用对象引用而不是使用对象的值时,您的错误是一个相当经典的错误:当您创建新粒子时,您将其位置设置为非常位置发射器。
因此,后者对粒子位置的任何改变都会改变发射器的位置:同样,位置(pos)对象是同一个物体。
你想要的是每个粒子都有自己的位置,它具有发射器位置的初始值
例如,完成:
function Particle(pos, life, vel, accel){
this.pos = new Vector2(pos.x, pos.y);
//...
请注意,速度和加速度也是引用,因为您调用使用新Vector2
调用构造函数的函数,因此这不是问题。
但是,您可能希望通过同时为这两个属性执行复制来保护您的代码免受未来可能的错误。