Phaser P2 Sprite Scale Change 不适用于所有组子项
Phaser P2 Sprite Scale Change not working properly for all group children
我希望这段代码能解释我正在尝试做的事情。我有一个台球 table,如果球离得足够近,我希望球能加速进入球袋。此时我还没有检查距离,只是想弄清楚如何去做。
我相信有更好的方法!
balls.forEachAlive(
pockets.forEachAlive( moveBallTowardPocket, this), this);
更新:除了一件事,下面的代码是有效的,前五个口袋的球的比例变化。加速度适用于所有球到所有口袋。比例变化仅适用于最后一个口袋,不适用于前五个。
function update() {
pockets.forEachAlive(function(pocket) {
accelerateBallToPocket(flipper, pocket, 60);
balls.forEachAlive(function(ball) {
accelerateBallToPocket(ball, pocket, 60);
});
});
//...
}
function accelerateBallToPocket(ball, pocket, speed) {
if (typeof speed === 'undefined') {
var speed = 120;
}
var pocket_body_x = pocket.body.x;
var pocket_body_y = pocket.body.y;
var ball_body_x = ball.body.x;
var ball_body_y = ball.body.y;
// move ball toward pocket if close enough
var dx = ball_body_x - pocket_body_x; //distance ship X to enemy X
var dy = ball_body_y - pocket_body_y; //distance ship Y to enemy Y
var dist = Math.sqrt(dx*dx + dy*dy); //pythagoras
if (dist < pocket_radius * pocket_leniency_factor) {
// accelerate ball to pocket on right angle
var angle = Math.atan2(pocket.y - ball.y,
pocket.x - ball.x);
ball.body.rotation = angle + game.math.degToRad(90);
ball.body.force.x = Math.cos(angle) * speed;
ball.body.force.y = Math.sin(angle) * speed;
// change scale
// FIXME only works on the last pocket lower right
if (ball === flipper) {
ball.scale.setTo(Math.tan(pocket.x - ball.x),
Math.tan(pocket.y - ball.y));
} else {
ball.scale.setTo(Math.sin(pocket.x - ball.x),
Math.cos(pocket.y - ball.y));
}
} else {
// reset the scale when the ball is out of range of the pocket
ball.scale.setTo(1.0, 1.0);
}
}
第二次更新:
以下,基于解决方案,让我再次朝着正确的方向前进,我认为...
for (var i = 0; i < pockets.children.length; i++) {
accelerateBallToPocket(cue, pockets.children[i], 60);
if (cue.pocketing) break;
}
for (var i = 0; i < balls.children.length; i++) {
if (balls.children[i].pocketing) continue;
for (var j = 0; j < pockets.children.length; j++) {
accelerateBallToPocket(balls.children[i], pockets.children[j], 60);
if (balls.children[i].pocketing) return;
}
}
好的,问题是如果球不靠近口袋,您将比例设置为 1。而且,当你检查每个球与每个口袋时,总会有一个口袋(在循环中稍后检查)球没有靠近,除了口袋列表中的最后一个口袋。因此,即使球刻度设置为正确的值,在检查下一个 pocket
时也会重置。
你可以做的是检查一个球是否靠近至少一个口袋,如果是,那么它就不能靠近其他口袋,所以你不要再次检查其他口袋。
// Consider that every ball is not inside a pocket
balls.forEachAlive(function(ball) {
ball.inPocket = false;
});
flipper.inPocket = false; // You should really add the flipper to the balls group to remove duplicate code
pockets.forEachAlive(function(pocket) {
if(!flipper.inPocket) accelerateBallToPocket(flipper, pocket, 60);
balls.forEachAlive(function(ball) {
if(!ball.inPocket) accelerateBallToPocket(ball, pocket, 60);
});
});
然后,在您的移动函数中,如果球靠近袋口,您必须将 inPocket
成员设置为 true。
function accelerateBallToPocket(ball, pocket, speed) {
...
if (ball === flipper) {
ball.scale.setTo(Math.tan(pocket.x - ball.x),
Math.tan(pocket.y - ball.y));
ball.inPocket = true;
} else {
ball.scale.setTo(Math.sin(pocket.x - ball.x),
Math.cos(pocket.y - ball.y));
ball.inPocket = true;
}
} else {
// reset the scale when the ball is out of range of the pocket
ball.scale.setTo(1.0, 1.0);
}
}
另一种方法是反转循环顺序,首先遍历所有球,并为每个球检查每个口袋,一旦发现它在口袋中,就继续外循环(跳过对其他口袋的检查)。为了做到这一点,你的 accelerateBall
函数应该 return true
或 false
,当球足够靠近口袋时 true
和 false
否则。
我会像这样重写你的迭代:
for (var i = 0; i < pockets.children.length; i++) {
accelerateBallToPocket(cue, pockets.children[i], 60);
if (cue.pocketing) break;
}
// Stumped...
for (var i = 0; i < balls.children.length; i++) {
// No need for the check here, each ball should have pocketing=false, set at the top of the update loop
// This means, that balls.children[i].pocketing will always be false here
for (var j = 0; j < pockets.children.length; j++) {
accelerateBallToPocket(balls.children[i], pockets.children[j], 60);
if (balls.children[i].pocketing) break; // stop checking the rest of the pockets for this ball
}
}
我希望这段代码能解释我正在尝试做的事情。我有一个台球 table,如果球离得足够近,我希望球能加速进入球袋。此时我还没有检查距离,只是想弄清楚如何去做。
我相信有更好的方法!
balls.forEachAlive(
pockets.forEachAlive( moveBallTowardPocket, this), this);
更新:除了一件事,下面的代码是有效的,前五个口袋的球的比例变化。加速度适用于所有球到所有口袋。比例变化仅适用于最后一个口袋,不适用于前五个。
function update() {
pockets.forEachAlive(function(pocket) {
accelerateBallToPocket(flipper, pocket, 60);
balls.forEachAlive(function(ball) {
accelerateBallToPocket(ball, pocket, 60);
});
});
//...
}
function accelerateBallToPocket(ball, pocket, speed) {
if (typeof speed === 'undefined') {
var speed = 120;
}
var pocket_body_x = pocket.body.x;
var pocket_body_y = pocket.body.y;
var ball_body_x = ball.body.x;
var ball_body_y = ball.body.y;
// move ball toward pocket if close enough
var dx = ball_body_x - pocket_body_x; //distance ship X to enemy X
var dy = ball_body_y - pocket_body_y; //distance ship Y to enemy Y
var dist = Math.sqrt(dx*dx + dy*dy); //pythagoras
if (dist < pocket_radius * pocket_leniency_factor) {
// accelerate ball to pocket on right angle
var angle = Math.atan2(pocket.y - ball.y,
pocket.x - ball.x);
ball.body.rotation = angle + game.math.degToRad(90);
ball.body.force.x = Math.cos(angle) * speed;
ball.body.force.y = Math.sin(angle) * speed;
// change scale
// FIXME only works on the last pocket lower right
if (ball === flipper) {
ball.scale.setTo(Math.tan(pocket.x - ball.x),
Math.tan(pocket.y - ball.y));
} else {
ball.scale.setTo(Math.sin(pocket.x - ball.x),
Math.cos(pocket.y - ball.y));
}
} else {
// reset the scale when the ball is out of range of the pocket
ball.scale.setTo(1.0, 1.0);
}
}
第二次更新: 以下,基于解决方案,让我再次朝着正确的方向前进,我认为...
for (var i = 0; i < pockets.children.length; i++) {
accelerateBallToPocket(cue, pockets.children[i], 60);
if (cue.pocketing) break;
}
for (var i = 0; i < balls.children.length; i++) {
if (balls.children[i].pocketing) continue;
for (var j = 0; j < pockets.children.length; j++) {
accelerateBallToPocket(balls.children[i], pockets.children[j], 60);
if (balls.children[i].pocketing) return;
}
}
好的,问题是如果球不靠近口袋,您将比例设置为 1。而且,当你检查每个球与每个口袋时,总会有一个口袋(在循环中稍后检查)球没有靠近,除了口袋列表中的最后一个口袋。因此,即使球刻度设置为正确的值,在检查下一个 pocket
时也会重置。
你可以做的是检查一个球是否靠近至少一个口袋,如果是,那么它就不能靠近其他口袋,所以你不要再次检查其他口袋。
// Consider that every ball is not inside a pocket
balls.forEachAlive(function(ball) {
ball.inPocket = false;
});
flipper.inPocket = false; // You should really add the flipper to the balls group to remove duplicate code
pockets.forEachAlive(function(pocket) {
if(!flipper.inPocket) accelerateBallToPocket(flipper, pocket, 60);
balls.forEachAlive(function(ball) {
if(!ball.inPocket) accelerateBallToPocket(ball, pocket, 60);
});
});
然后,在您的移动函数中,如果球靠近袋口,您必须将 inPocket
成员设置为 true。
function accelerateBallToPocket(ball, pocket, speed) {
...
if (ball === flipper) {
ball.scale.setTo(Math.tan(pocket.x - ball.x),
Math.tan(pocket.y - ball.y));
ball.inPocket = true;
} else {
ball.scale.setTo(Math.sin(pocket.x - ball.x),
Math.cos(pocket.y - ball.y));
ball.inPocket = true;
}
} else {
// reset the scale when the ball is out of range of the pocket
ball.scale.setTo(1.0, 1.0);
}
}
另一种方法是反转循环顺序,首先遍历所有球,并为每个球检查每个口袋,一旦发现它在口袋中,就继续外循环(跳过对其他口袋的检查)。为了做到这一点,你的 accelerateBall
函数应该 return true
或 false
,当球足够靠近口袋时 true
和 false
否则。
我会像这样重写你的迭代:
for (var i = 0; i < pockets.children.length; i++) {
accelerateBallToPocket(cue, pockets.children[i], 60);
if (cue.pocketing) break;
}
// Stumped...
for (var i = 0; i < balls.children.length; i++) {
// No need for the check here, each ball should have pocketing=false, set at the top of the update loop
// This means, that balls.children[i].pocketing will always be false here
for (var j = 0; j < pockets.children.length; j++) {
accelerateBallToPocket(balls.children[i], pockets.children[j], 60);
if (balls.children[i].pocketing) break; // stop checking the rest of the pockets for this ball
}
}