Closed BaumanDev closed 8 years ago
but do you know any way 2 fix this?
Removing cell.ignoreCollision until we can get the function that @AgarioCheats says "he has"
another example:
just put // behind it: //cell.ignoreCollision = true;
Sure, or that.
Credits to @Ogarunite and @AgarioCheats Hopefully this will help a bit towards achieving what we wish to achieve. It's still not perfect though and the collision engine must be recoded or atleast changed in order for it to work a LOT better. This is a temporary, weak, way of achieving the smooth slow split. Magic formula included:
var split = new Entity.PlayerCell(this.getNextNodeId(), client, startPos, newMass);
split.setAngle(angle);
var increase = -3.61 + 13.6*Math.log(cell.mass);
cell.setMoveEngineData(0, 18, 1); //OgarUnite -> Important for smooth, slow split
if (cell.mass < 200) {
split.setMoveEngineData(splitSpeed -5, 20, 0.91);
}
else if (cell.mass < 500 && cell.mass > 201) {
split.setMoveEngineData(increase -2, 18, 0.90);
}
else if (cell.mass < 4000 && cell.mass > 2000) {
split.setMoveEngineData(increase - 15, 18, 0.90);
}
else {
split.setMoveEngineData(increase - 27, 18, 0.9);
}
split.calcMergeTime(this.config.playerRecombineTime);
split.ignoreCollision = true;
cell.ignoreCollision = true;
this.setAsMovingNode(cell);
this.setAsMovingNode(split);
this.addNode(split);
//[Edited - changed values a bit to better fit the default values of Ogar]
@Ogarunite Omg. This isn't half bad at all. A little bit more tweaks and we have agar.io splitting xP
Add this to ogar like right now, I would love to see this added ASAP! :dancer:
origin cell would freeze during a splitting, this feels bizarre
@mrmarktyy Hmm? Can you show me a picture?
this line of code,
cell.setMoveEngineData(0, 18, 1); //OgarUnite -> Important for smooth, slow split
@mrmarktyy What about it? xD
@mrmarktyy THAT FIXED MY PROBLEM! cell.setMoveEngineData(0, 18, 1); PUT IT UNDER(in gameserver.js):
cell.mass = newMass;
SHOULD LOOK LIKE THIS:
var splitSpeed = cell.getSpeed() * 6;
var newMass = cell.mass / 2;
var newMass = cell.mass / 2;
cell.mass = newMass;
cell.setMoveEngineData(0, 18, 1);
@mrmarktyy Would you happen to know how to simulate the collision of ejected mass? You are a code expert and i'm sorta bad at big coding lol. i just stick with basic coding. But still i want to know how to simulate ejected mass collision.
@mrmarktyy That's due to using an edited version of Ogar. If you use the clean version (download the latest source of Ogar) and include the code, the origin cell won't stop.
@Agarian, Glad it worked.
@Ogarunite yeah, maybe you're right, i'll try that. I did test this in edited version of Ogar.
@Agarian I'll give it a shot when I got some time. but not sure how to do it yet. ;(
ok good luck and tell me if you succeed. i was actually thinking that an ignoreCollision function would do it but it did not.
@mrmarktyy Goodluck man!
@Ogarunite I found out what's still wrong with the splitting. The big cell get pushed by smaller cells when they are separated.
(In case you don't know what I mean) When you split and you have a small cell inside you that comes out, it only should come out, but it comes out and the big split cells gets pushed. Can you try to fix this?
@NatsuTheGreat I know what you mean. Unfortunately that's rooted deeper, in the collision engine and the way that works. After cells split -> They calculate merge time -> Check for collision, and that's when the process is where mainly two problems appear: 1) Small cells push the larger cells. Solution -> Prioritize larger cells when splitting, and eventually the smaller ones afterwards?
2) cell-collision is ignored very roughly and the cells simply pop back from being on top of each other, to the sides very roughly. This process needs to be recoded so that it will be smooth and slower, and also reduced angle so that they won't move so "far away" from each other.
@Ogarunite Can you code this man?
@Ogarunite that "weak" fix worked nicely with the line of code offered by @mrmarktyy
Hello all.
I'm using kind of a different approach for the smooth split which also works great. I don't use "cell.ignoreCollision = true" as it creates it's own problems. Code still needs a bit more collision rewriting though. Already got the smoother collisions and got the big cells pushing harder against the smaller cells. But still have to work out a few other unwanted side-effects. Will post the complete code changes when i'm finished and happy with the end result (probably somewhere end this week or so, haven't got much time next couple of days to work on this).
@Agarian you also wanted the ejected mass collision. Already got that one working. Will post code for that in the appropriate issue #345 after i'm done on the above playercell collision.
@restlac What did you do instead of cell.ignoreCollision?
Well, I guess I would have to give you the complete code changes for it to work properly, but basically i changed this line of code in PlayerCell.js:
if ((this.nodeId == cell.nodeId) || (this.ignoreCollision)) {
in this:
if ((this.nodeId == cell.nodeId) || (this.ignoreCollision) || (cell.ignoreCollision)) {
@retslac Wish you luck man!
Finished the code. Here's my version of smooth physics. Gotta say, it's a bunch of code changes because of the rewrite of the collision engine. As many of you've probably made previous changes to the original code, you might have to undo some of that work to make this code work correctly.
I will start by summing up all the new features included in this code. If you don't want them all you'll have to filter out and change the parts you don't want yourself.
Included in this code:
Also, i tweaked the settings a little bit to fit as close as possible to vanilla agar.io style. Personally, i'm using different settings as i like a bit faster and further cell splitting. I'll include my personal preference settings at the end of this post. You can try them out or you can tweak the values to fit your own style if you wish.
ok, here we go:
PlayerCell.prototype.calcMove = function(x2, y2, gameServer) {
var config = gameServer.config;
var r = this.getSize(); // Cell radius
// Get angle
var deltaY = y2 - this.position.y;
var deltaX = x2 - this.position.x;
var angle = Math.atan2(deltaX,deltaY);
if(isNaN(angle)) {
return;
}
// Distance between mouse pointer and cell
var dist = this.getDist(this.position.x,this.position.y,x2,y2);
var speed = Math.min(this.getSpeed(),dist);
var x1 = this.position.x + (speed * Math.sin(angle));
var y1 = this.position.y + (speed * Math.cos(angle));
var xd = 0;
var yd = 0;
// Collision check for other cells
for (var i = 0; i < this.owner.cells.length;i++) {
var cell = this.owner.cells[i];
if ((this.nodeId <= cell.nodeId) || (this.ignoreCollision) || (cell.ignoreCollision)) {
continue;
}
if ((cell.recombineTicks > 0) || (this.recombineTicks > 0)) {
// Cannot recombine - Collision with your own cells
var r1 = cell.getSize();
var collisionDist = r + r1 + 5; // Minimum distance between the 2 cells (add a little distance in between which looks a bit better for multi-split cells)
if (!this.simpleCollide(x1,y1,cell,collisionDist)) {
// Skip
continue;
}
// First collision check passed... now more precise checking
dist = this.getDist(x1,y1,cell.position.x,cell.position.y);
// Calculations
if (dist < collisionDist) { // Collided
var newDeltaY = cell.position.y - y1;
var newDeltaX = cell.position.x - x1;
var newAngle = Math.atan2(newDeltaX,newDeltaY);
var maxMove = Math.max(Math.ceil(Math.max(r,r1) / 2), 360); //for smaller cells use push out speed 360, for bigger cells add some speed
var move = Math.min(collisionDist - dist, maxMove);
var moveCell = move * this.mass / (this.mass + cell.mass); //big cells push harder against smaller cells
var moveThis = move - moveCell;
var sin = Math.sin(newAngle);
var cos = Math.cos(newAngle);
cell.position.x += (moveCell * sin) >> 0;
cell.position.y += (moveCell * cos) >> 0;
xd += (moveThis * -sin);
yd += (moveThis * -cos);
}
}
}
var xSave = this.position.x;
var ySave = this.position.y;
gameServer.gameMode.onCellMove(x1,y1,this);
x1 += xd + (this.position.x - xSave);
y1 += yd + (this.position.y - ySave);
gameServer.gameMode.onCellMove(x1,y1,this);
// Check to ensure we're not passing the world border
if (x1 < config.borderLeft) {
x1 = config.borderLeft;
}
if (x1 > config.borderRight) {
x1 = config.borderRight;
}
if (y1 < config.borderTop) {
y1 = config.borderTop;
}
if (y1 > config.borderBottom) {
y1 = config.borderBottom;
}
this.position.x = x1 >> 0;
this.position.y = y1 >> 0;
};
function PlayerCell() {
Cell.apply(this, Array.prototype.slice.call(arguments));
this.cellType = 0;
this.recombineTicks = 0; // Ticks until the cell can recombine with other cells
this.ignoreCollision = false; // This is used by player cells so that they dont cause any problems when splitting
this.restoreCollisionTicks = 0; // Ticks after which collision is restored on a moving cell
}
PlayerCell.prototype.onAutoMove = function(gameServer) {
// Restore collision
if (this.restoreCollisionTicks > 0) {
this.restoreCollisionTicks--;
if (this.restoreCollisionTicks <= 0) {
this.ignoreCollision = false;
}
}
};
GameServer.prototype.splitCells = function(client) {
var len = client.cells.length;
for (var i = 0; i < len; i++) {
if (client.cells.length >= this.config.playerMaxCells) {
// Player cell limit
continue;
}
var cell = client.cells[i];
if (!cell) {
continue;
}
if (cell.mass < this.config.playerMinMassSplit) {
continue;
}
// Get angle
var deltaY = client.mouse.y - cell.position.y;
var deltaX = client.mouse.x - cell.position.x;
var angle = Math.atan2(deltaX,deltaY);
// Get starting position
var startPos = {x: cell.position.x, y: cell.position.y};
// Calculate mass and speed of splitting cell
var newMass = cell.mass / 2;
cell.mass = newMass;
// Create cell
var split = new Entity.PlayerCell(this.getNextNodeId(), client, startPos, newMass, this);
split.setAngle(angle);
var splitSpeed = 130; //150 * Math.max(Math.log10(newMass) - 2.2, 1); //for smaller cells use splitspeed 150, for bigger cells add some speed
split.setMoveEngineData(splitSpeed, 32, 0.85); //vanilla agar.io = 130, 32, 0.85
split.calcMergeTime(this.config.playerRecombineTime);
split.ignoreCollision = true;
split.restoreCollisionTicks = 10; //vanilla agar.io = 10
// Add to moving cells list
this.setAsMovingNode(split);
this.addNode(split);
}
};
Virus.prototype.onConsume = function(consumer,gameServer) {
var client = consumer.owner;
var maxSplits = Math.floor(consumer.mass/16) - 1; // Maximum amount of splits
var numSplits = gameServer.config.playerMaxCells - client.cells.length; // Get number of splits
numSplits = Math.min(numSplits,maxSplits);
var splitMass = Math.min(consumer.mass/(numSplits + 1), 36); // Maximum size of new splits
// Cell consumes mass before splitting
consumer.addMass(this.mass);
// Cell cannot split any further
if (numSplits <= 0) {
return;
}
// Big cells will split into cells larger than 36 mass (1/4 of their mass)
var bigSplits = 0;
var endMass = consumer.mass - (numSplits * splitMass);
if ((endMass > 300) && (numSplits > 0)) {
bigSplits++;
numSplits--;
}
if ((endMass > 1200) && (numSplits > 0)) {
bigSplits++;
numSplits--;
}
if ((endMass > 3000) && (numSplits > 0)) {
bigSplits++;
numSplits--;
}
// Calculate endmass and virus splitspeed
endMass = consumer.mass - (numSplits * splitMass);
for (var k = 0; k < bigSplits; k++) {
endMass *= 0.75;
}
var endSize = Math.ceil(Math.sqrt(100 * endMass));
var virusSplitSpeed = (endSize + Math.min(200 / endSize, 1) * 500) / 3.6;
// Splitting
var angle = 0; // Starting angle
for (var k = 0; k < numSplits; k++) {
angle += 6.28/numSplits; // Get directions of splitting cells
gameServer.newCellVirused(client, consumer, angle, splitMass, virusSplitSpeed);
consumer.mass -= splitMass;
}
for (var k = 0; k < bigSplits; k++) {
angle = Math.random() * 6.28; // Random directions
splitMass = consumer.mass / 4;
gameServer.newCellVirused(client, consumer, angle, splitMass, virusSplitSpeed);
consumer.mass -= splitMass;
}
// Prevent consumer cell from merging with other cells
consumer.calcMergeTime(gameServer.config.playerRecombineTime);
};
Keep the original function newCellVirused in GameServer.js I'll add the correct version here because i suspect many of you might have already changed it.
GameServer.prototype.newCellVirused = function(client, parent, angle, mass, speed) {
// Starting position
var startPos = {
x: parent.position.x,
y: parent.position.y
};
// Create cell
newCell = new Entity.PlayerCell(this.getNextNodeId(), client, startPos, mass, this);
newCell.setAngle(angle);
newCell.setMoveEngineData(speed, 15);
newCell.calcMergeTime(this.config.playerRecombineTime);
newCell.ignoreCollision = true; // Remove collision checks
// Add to moving cells list
this.addNode(newCell);
this.setAsMovingNode(newCell);
};
Teams.prototype.onCellMove = function(x1,y1,cell) {
var team = cell.owner.getTeam();
var r = cell.getSize();
var xd = 0;
var yd = 0;
// Find team
for (var i = 0; i < cell.owner.visibleNodes.length;i++) {
// Only collide with player cells
var check = cell.owner.visibleNodes[i];
if ((check.getType() != 0) || (cell.owner == check.owner) || ((cell.nodeId <= check.nodeId) && (check.owner.disconnect <= -1)) || (cell.ignoreCollision) || (check.ignoreCollision)){
continue;
}
// Collision with teammates
if (check.owner.getTeam() == team) {
// Check if in collision range
var r1 = check.getSize();
var collisionDist = r + r1; // Minimum distance between the 2 cells
if (!cell.simpleCollide(x1,y1,check, collisionDist)) {
// Skip
continue;
}
// First collision check passed... now more precise checking
dist = cell.getDist(x1,y1,check.position.x,check.position.y);
// Calculations
if (dist < collisionDist) { // Collided
var newDeltaY = check.position.y - y1;
var newDeltaX = check.position.x - x1;
var newAngle = Math.atan2(newDeltaX,newDeltaY);
var maxMove = Math.max(Math.ceil(Math.max(r,r1) / 2), 360); //for smaller cells use push out speed 360, for bigger cells (5.2K+ mass) add some speed
var move = Math.min(collisionDist - dist, maxMove);
var moveCheck = move * cell.mass / (cell.mass + check.mass); //bigger cells push harder against smaller cells
var moveCell = move - moveCheck;
var sin = Math.sin(newAngle);
var cos = Math.cos(newAngle);
check.position.x += (moveCheck * sin) >> 0;
check.position.y += (moveCheck * cos) >> 0;
xd += (moveCell * -sin);
yd += (moveCell * -cos);
}
}
}
cell.position.x += xd;
cell.position.y += yd;
};
This change assumes you also have the change for ejected mass collisions i posted earlier in #345. You'll have to make your own small adjustments if you don't have that code.
...
// Calculate new position
var sin = Math.sin(this.angle);
var cos = Math.cos(this.angle);
if (this.cellType == 0) {
//split movement and consume check for player cells
var maxTravel = r; //check inbetween places (is needed when cell has higher speed than cell radius) - max inbetween move before next check is cell radius
var totTravel = 0;
do {
totTravel = Math.min(totTravel + maxTravel, speed);
var x1 = this.position.x + (totTravel * sin);
var y1 = this.position.y + (totTravel * cos);
var xSave = this.position.x;
var ySave = this.position.y;
this.position.x = x1;
this.position.y = y1;
var list = this.gameServer.getCellsInRange(this);
for (var j = 0; j < list.length ; j++) {
var check = list[j];
check.onConsume(this,this.gameServer);
check.setKiller(this);
this.gameServer.removeNode(check);
}
this.position.x = xSave;
this.position.y = ySave;
}
while (totTravel < speed);
} else if (this.cellType == 3) {
//movement and collision check for ejected mass cells
...
var cell = new Entity.PlayerCell(this.getNextNodeId(), player, pos, mass, this);
newCell = new Entity.PlayerCell(this.getNextNodeId(), client, startPos, mass, this);
I think that's all!
Hope you like the new physics. If something doesn't work or you have any other issue with it, please let me know.
Oh, and here's my personal preference: in function splitCells in GameServer.js i'm using a different formula for splitSpeed which is just a bit faster and has a further splitdistance than vanilla agar.io
var splitSpeed = 150 * Math.max(Math.log10(newMass) - 2.2, 1);
Have fun with it!
C:\Users\Lucas\Desktop\Ogar-master\src>node index.js C:\Users\Lucas\Desktop\Ogar-master\src\entity\Cell.js:228 }); ^
SyntaxError: Unexpected token )
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:414:25)
at Object.Module._extensions..js (module.js:442:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
at Module.require (module.js:366:17)
at require (module.js:385:17)
at Object.
C:\Users\Lucas\Desktop\Ogar-master\src>pause Errors...
@Lukkez hmm, strange. I'm guessing you have a missing closing } bracket somewhere in Cell.js
Here's the whole calcMovePhys function from Cell.js
Cell.prototype.calcMovePhys = function(config) {
// Movement engine (non player controlled movement)
var speed = this.moveEngineSpeed;
var r = this.getSize();
this.moveEngineSpeed *= this.moveDecay; // Decaying speed
this.moveEngineTicks--;
// Calculate new position
var sin = Math.sin(this.angle);
var cos = Math.cos(this.angle);
if (this.cellType == 0) {
//split movement and consume check for player cells
var maxTravel = r; //check inbetween places (is needed when cell has higher speed than cell radius) - max inbetween move before next check is cell radius
var totTravel = 0;
do {
totTravel = Math.min(totTravel + maxTravel, speed);
var x1 = this.position.x + (totTravel * sin);
var y1 = this.position.y + (totTravel * cos);
var xSave = this.position.x;
var ySave = this.position.y;
this.position.x = x1;
this.position.y = y1;
var list = this.gameServer.getCellsInRange(this);
for (var j = 0; j < list.length ; j++) {
var check = list[j];
check.onConsume(this,this.gameServer);
check.setKiller(this);
this.gameServer.removeNode(check);
}
this.position.x = xSave;
this.position.y = ySave;
}
while (totTravel < speed);
} else if (this.cellType == 3) {
//movement and collision check for ejected mass cells
var collisionDist = r * 2 - 5; // Minimum distance between the 2 cells (allow cells to go a little inside eachother before moving them)
var maxTravel = r; //check inbetween places for collisions (is needed when cell still has high speed) - max inbetween move before next collision check is cell radius
var totTravel = 0;
var xd = 0;
var yd = 0;
do {
totTravel = Math.min(totTravel + maxTravel, speed);
var x1 = this.position.x + (totTravel * sin) + xd;
var y1 = this.position.y + (totTravel * cos) + yd;
for (var i = 0; i < this.gameServer.nodesEjected.length; i++) {
var cell = this.gameServer.nodesEjected[i];
if (this.nodeId == cell.nodeId) {
continue;
}
if (!this.simpleCollide(x1,y1,cell,collisionDist)) {
continue;
}
var dist = this.getDist(x1,y1,cell.position.x,cell.position.y);
if (dist < collisionDist) { // Collided
var newDeltaY = cell.position.y - y1;
var newDeltaX = cell.position.x - x1;
var newAngle = Math.atan2(newDeltaX,newDeltaY);
var move = (collisionDist - dist + 5) / 2; //move cells each halfway until they touch
var xmove = move * Math.sin(newAngle);
var ymove = move * Math.cos(newAngle);
cell.position.x += xmove >> 0;
cell.position.y += ymove >> 0;
xd += -xmove;
yd += -ymove;
if (cell.moveEngineTicks == 0) {
cell.setMoveEngineData(0, 1); //make sure a collided cell checks again for collisions with other cells
if (this.gameServer.movingNodes.indexOf(cell) == -1) {
this.gameServer.setAsMovingNode(cell);
}
}
if (this.moveEngineTicks == 0) {
this.setMoveEngineData(0, 1); //make sure a collided cell checks again for collisions with other cells
}
}
}
}
while (totTravel < speed);
x1 = this.position.x + (speed * sin) + xd;
y1 = this.position.y + (speed * cos) + yd;
} else {
//movement for viruses
var x1 = this.position.x + (speed * sin);
var y1 = this.position.y + (speed * cos);
}
// Border check - Bouncy physics
var radius = 40;
if ((x1 - radius) < config.borderLeft) {
// Flip angle horizontally - Left side
this.angle = 6.28 - this.angle;
x1 = config.borderLeft + radius;
}
if ((x1 + radius) > config.borderRight) {
// Flip angle horizontally - Right side
this.angle = 6.28 - this.angle;
x1 = config.borderRight - radius;
}
if ((y1 - radius) < config.borderTop) {
// Flip angle vertically - Top side
this.angle = (this.angle <= 3.14) ? 3.14 - this.angle : 9.42 - this.angle;
y1 = config.borderTop + radius;
}
if ((y1 + radius) > config.borderBottom) {
// Flip angle vertically - Bottom side
this.angle = (this.angle <= 3.14) ? 3.14 - this.angle : 9.42 - this.angle;
y1 = config.borderBottom - radius;
}
// Set position
this.position.x = x1 >> 0;
this.position.y = y1 >> 0;
};
Retslac, i'm very fond of your work! Can I contact you by E-mail, I have a project i need some features to be added. I'll pay.
By the way: This bug: fixed bug: sometimes when you tried to splitkill someone you never caught your opponent and it appeared you went right through him
I believe it only occurs on bots, and not normal players. Well sometimes it occurs to normal players too, but i think it shouldn't with slower split.
what about this?
@ItzLevvie @Agarian don't know why that happens. Can't exactly see what happens either as it's a static image. Doesn't happen on my side. What did you guys do for this to happen. Is it possible you guys are using some modified version?
@Ogarunite You can contact me if you wish, although don't know if you have my email. No need to pay, everything free. I'll help you if I can. But not sure if i have the time for it.
nope its fresh from github
that worked^
@retslac Is there a way to E-mail through github?
but pressing w crashes server: TypeError: Cannot read property 'nodesEjected' of undefined at Cell.calcMovePhys (C:\Users\owner\Downloads\Ogar-master\Ogar-master\src\entity\Cell.js:181:48) at GameServer.updateMoveEngine (C:\Users\owner\Downloads\Ogar-master\Ogar-master\src\GameServer.js:575:19) at GameServer.cellTick (C:\Users\owner\Downloads\Ogar-master\Ogar-master\src\GameServer.js:352:10) at GameServer.mainLoop (C:\Users\owner\Downloads\Ogar-master\Ogar-master\src\GameServer.js:386:29) at wrapper as _onTimeout at Timer.listOnTimeout (timers.js:92:15)
is there a way to keep ejected mass collision with this? for that collision the calcmovephys here would be overwritten by the one discussed in issue #345
@Agarian @ItzLevvie ok, thx ItzLevvie. It's on my part. I am using a previous version of Ogar. It seems the SimpleCollide function has changed since then. I hope not too much of them have changed. I will have to investigate further. The ejected mass collision should also still work. Will look into that too.
@ItzLevvie i'll go with your build since it worked. idk why mine didn't work.
@Ogarunite Don't know. I'm kinda new on github. Maybe you can send pm's on github? Don't really wanna post my email here in public.
Okay yeah I understand. I'll check.
@retslac you are an amazing coder no lie.
thx
I suggest anybody who wants to try this to use ItzLevvie's version until I have the time to make the appropriate adjustments so it'll also work with the latest version of Ogar. Can't really do that at my current location, so will have to wait for now. Hope I can fix it soon. I'll post update when ready.
i wish you good luck :+1:
@retslac I tried using @ItzLevvie 's version but it made no difference :(
@ItzLevvie I have no idea how to.. New to github aswell.
@ItzLevvie Alright, I'll try.
Basicly when you added cell.ignoreCollision you made it ignore the collision for the cells themselves, nt the splitting, because cell. is reffering to the player cells.