您好,我正在制作一款类似agar.io的二维游戏,该游戏使用了碰撞检测。
它使用SAT.js来检测碰撞,并且正在做一个膨胀的工作,除了一件事。
碰撞工作正常,除非你"拆分"你的单元格,在阵列中向你的玩家添加另一个单元格(或圆圈)。
因此,对于一个圆圈,碰撞工作正常,但不止一个,它不会记录碰撞,除非所有大圆圈完全以对手为中心,注册检测。
(而不是使用其中一个圆圈的中心点,它基本上使用了所有圆圈的中心点)
function check(user) {
for(var i=0; i<user.cells.length; i++) {
if(user.cells[i].mass > 10 && user.id !== currentPlayer.id) {
var response = new SAT.Response();
var collided = SAT.testCircleCircle(playerCircle,
new C(new V(user.cells[i].x , user.cells[i].y), user.cells[i].radius),
response);
if (collided) {
response.aUser = currentCell;
response.bUser = {
id: user.id,
name: user.name,
x: user.cells[i].x,
y: user.cells[i].y,
num: i,
mass: user.cells[i].mass,
money: user.cells[i].money
};
playerCollisions.push(response);
}
}
}
return true;
}
for(var z=0; z<currentPlayer.cells.length; z++) {
var currentCell = currentPlayer.cells[z];
var playerCircle = new C(
new V(currentCell.x, currentCell.y),
currentCell.radius
);
function splitCell(cell) {
if(cell.mass >= c.defaultPlayerMass*2) {
//io.emit('playSplitSound');
cell.mass = cell.mass/2;
cell.money = cell.money/2;
cell.radius = util.massToRadius(cell.mass);
currentPlayer.cells.push({
mass: cell.mass,
money: cell.money,
x: cell.x,
y: cell.y,
radius: cell.radius,
speed: 25
});
}
}
function check(user) {
for(var i=0; i<user.cells.length; i++) {
if(user.cells[i].mass > 10 && user.id !== currentPlayer.id) {
var response = new SAT.Response();
var collided = SAT.testCircleCircle(playerCircle,
new C(new V(user.cells[i].x , user.cells[i].y), user.cells[i].radius),
response);
if (collided) {
response.aUser = currentCell;
response.bUser = {
id: user.id,
name: user.name,
x: user.cells[i].x,
y: user.cells[i].y,
num: i,
mass: user.cells[i].mass,
money: user.cells[i].money
};
playerCollisions.push(response);
}
}
}
return true;
}
function collisionCheck(collision) {//Here is where to fix eating bug, try to make it so if at least half of victim is in predator, then get eaten.
if (collision.aUser.mass > collision.bUser.mass * 1.1 && collision.aUser.radius > Math.sqrt(Math.pow(collision.aUser.x - collision.bUser.x, 2) + Math.pow(collision.aUser.y - collision.bUser.y, 2))*1.75) {
console.log('[DEBUG] Killing user: ' + collision.bUser.id);
console.log('[DEBUG] Collision info:');
console.log(collision);
var numUser = util.findIndex(users, collision.bUser.id);
if (numUser > -1) {
if(users[numUser].cells.length > 1) {
users[numUser].massTotal -= collision.bUser.mass;
users[numUser].moneyTotal -= collision.bUser.money;
users[numUser].cells.splice(collision.bUser.num, 1);
} else {
users.splice(numUser, 1);
io.emit('playerDied', { name: collision.bUser.name });
sockets[collision.bUser.id].emit('RIP');
}
}
currentPlayer.massTotal += collision.bUser.mass;
collision.aUser.mass += collision.bUser.mass;
currentPlayer.moneyTotal += collision.bUser.money;
collision.aUser.money += collision.bUser.money;
}
}
for(var z=0; z<currentPlayer.cells.length; z++) {
var currentCell = currentPlayer.cells[z];
var playerCircle = new C(
new V(currentCell.x, currentCell.y),
currentCell.radius
);
var foodEaten = food.map(funcFood)
.reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
foodEaten.forEach(deleteFood);
var massEaten = massFood.map(eatMass)
.reduce(function(a, b, c) {return b ? a.concat(c) : a; }, []);
var virusCollision = virus.map(funcFood)
.reduce( function(a, b, c) { return b ? a.concat(c) : a; }, []);
if(virusCollision > 0 && currentCell.mass > virus[virusCollision].mass) {
sockets[currentPlayer.id].emit('virusSplit', z);
virus.splice(virusCollision, 1);
}
var masaGanada = 0;
for(var m=0; m<massEaten.length; m++) {
masaGanada += massFood[massEaten[m]].masa;
massFood[massEaten[m]] = {};
massFood.splice(massEaten[m],1);
for(var n=0; n<massEaten.length; n++) {
if(massEaten[m] < massEaten[n]) {
massEaten[n]--;
}
}
}
if(typeof(currentCell.speed) == "undefined")
currentCell.speed = 6.25;
masaGanada += (foodEaten.length * c.foodMass);
currentCell.mass += masaGanada;
currentPlayer.massTotal += masaGanada;
currentCell.radius = util.massToRadius(currentCell.mass);
playerCircle.r = currentCell.radius;
tree.clear();
users.forEach(tree.put);
var playerCollisions = [];
var otherUsers = tree.get(currentPlayer, check);
playerCollisions.forEach(collisionCheck);
}
}
所以我做了很多事情来尝试找到问题。
我首先使用console.log();
来确保识别每个单元格的x,y和半径。他们都被认可了。
接下来,我用它来确保没有识别到碰撞,只是没有执行。
碰撞未被识别,因此它与check(user);
函数有关。
我甚至试过制作我自己的碰撞检测,每次检查都有一个圆圈,但是对于多个圆圈也有同样的问题。
我因此而痛苦地死去,真的需要帮助。
如果您需要更多代码,请在下面给我发消息,我可能会将其添加到Google驱动器中。
谢谢!
-Patrick