I am currently working on a game in LibGDX. You may have seen another post. I have solved that problem, but now, I am facing the fact that I can't seem to move my player towards (it always moves up instead of pointing towards its front). I have tried everything, from using Box2D to answers I found online that suggested to use trig functions. Has anyone managed to do this before?
The movement of objects is usualy done by setting their x (left and right) and y (up and down) coordinates.
To know how to manipulate them, you need to know the direction he is faicng.
In a top-down game it could be a Vector2, a normalized Vector (a Vector of length=1), which gives you the relative movement in x and y direction. In a platformer instead it could be only a boolean, which defines if you are facing the rigth or the left. The up/down movement is then defined by jumping and other "up-forces" and the gravitation.
I think in your case it is a top-down-game, so you need a Vector2.
When you rotate your character you need to rotate the Vector2 to. To make sure, your Vector2 is normalized allways call nor() after manipulating it.
In the update or render method you should the set the x and y coordinates of your character like this:
player.x = direction.x*delta*speed;
player.y = direction.y*delta*speed;
Where delta is the Gdx.Graphics.getDeltaTime() and speed is the movementspeed of your player.
Hope it helps
Related
I'm working on a brick breaker game in JavaFX (FXGL). The collision detecting is working like this:
Bricks and players have a x, y position in the game world (placed in LEFT, TOP).
When a collision is detected (this is done by the engine) I use the x, y position to detect where the ball is colliding with the brick to calculate the next direction. The ball direction is created by a velocity vector with (x, y) speed. The collisionLogicSecurityPadding is a small padding which is added since the collision is only detected inside the box. (It's not possible to get the ball and brick exactly at the same x, y coordinates)
if (ball.getX() > levelBrick.getX() - ball.getWidth() + collisionLogicSecurityPadding &&
ball.getX() < levelBrick.getX() + levelBrick.getWidth() - collisionLogicSecurityPadding) {
//velocity.getX(), -velocity.getY()
} else {
//-velocity.getX(), velocity.getY()
}
So I measure if the ball is inside the brick with it x position. If this is the case the collision is TOP or BOTTOM. If not RIGHT or LEFT.
However this is causing the issue when the ball is hitting near the edge it detects wrong. Here a short clip: https://i.imgur.com/U8ybhRl.mp4
The issue is that the x is smaller than the area where it thinks it's TOP or BOTTOM so it's switching the X direction which is causing an issue.
My question here is how to avoid this? Is there any way I can solve the collision that it's working correctly? When I'm looking online the most tutorials are only checking top or bottom collision.
I think you could change the detection of TOP, BOTTOM, LEFT, RIGHT collisions to where the collision happened relative to the ball. Assuming the preservation of momentum you just need to negate the X- or Y-velocity.
In the example above the ball clearly generates a collision TOP and LEFT to his center of mass. Therefore it is impossible to generate a RIGHT collision which would generate the behavior you described. This leaves the Problem, that you do not know yet whether it was a collision on the LEFT or TOP. But since the Vector was pointing to the RIGHT (positive X-Movement), it is impossible to generate a collision on the LEFT. The collision must have happened at the TOP and therefore the Y-velocity needs to be multiplied by -1.
As long as the ball is the only moving object this method cannot generate weird behavior. As soon as you have an Object moving faster then the ball, you need additional checks: An Object hitting the ball on its left, while it is already in a general movement towards right will increase the X-velocity.
As I understood your question it seems to me like your issue is that the red box goes in an incorrect direction after bouncing on an edge.
I think you need to detect collision in three instances.
Top/Bottom
Left/Right
An Edge
If the collision occurs at an edge you need to send it in the same x direction as before with reducing the speed it goes in the direction y. y speed should always be less than initial speed and in the same direction as before.
I think above would solve your issue.
I am hoping someone could point me in the direction of a libGDX example that shows how the rebound angle is calculated when a polygon hits another (which is fixed) - The questions/answers I've found on StackOverflow have all been to general (abstract), I'm hoping for a more libGDX specific answer :)
Currently, I am using Intersector.MinimumTranslationVector to check whether the moving polygon has hit another fixed-stationary polygon and then using the resultant values to shift the objects back out of each other.
When the collision occurs virtually or horizontally, the bounce calculation is easy and currently works well. What I am having troubles with are the diagonal collisions - working out which face was actually hit and the direction in which to bounce.
The moving polygon uses a Vector2 object for it's velocity, so the question is how is the new velocity calculated? I'm assuming it can be done using the Intersector class, but how?
In Java, I'm writing a mobile app for Android to interact with some dynamic balls with some classes I wrote myself. Gravity is determined on the tilt of the phone.
I noticed when I have a bunch of balls bunched up in a corner that some of them will begin to jitter, or sometimes slide while colliding with other balls. Could this be because I'm executing steps in the wrong order?
Right now I have a single loop going through each ball to:
Sim an iteration
Check collisions with other balls
Check collisions against scene bounds
I should add that I have friction with the bounds and when a ball to ball collision occurs, just to lose energy.
Here's a portion of code of how collision is being handled:
// Sim an iteration
for (Ball ball : balls) {
ball.gravity.set(gravity.x, gravity.y);
if (ball.active) {
ball.sim();
// Collide against other balls
for (Ball otherBall : balls) {
if (ball != otherBall) {
double dist = ball.pos.distance(otherBall.pos);
boolean isColliding = dist < ball.radius + otherBall.radius;
if (isColliding) {
// Offset so they aren't touching anymore
MVector dif = otherBall.pos.copy();
dif.sub(ball.pos);
dif.normalize();
double difValue = dist - (ball.radius + otherBall.radius);
dif.mult(difValue);
ball.pos.add(dif);
// Change this velocity
double mag = ball.vel.mag();
MVector newVel = ball.pos.copy();
newVel.sub(otherBall.pos);
newVel.normalize();
newVel.mult(mag * 0.9);
ball.vel = newVel;
// Change other velocity
double otherMag = otherBall.vel.mag();
MVector newOtherVel = otherBall.pos.copy();
newOtherVel.sub(ball.pos);
newOtherVel.normalize();
newOtherVel.mult(otherMag * 0.9);
otherBall.vel = newOtherVel;
}
}
}
}
}
If this is the only code that checks for interactions between balls, then the problem seems pretty clear. There is no way for a ball to rest atop another ball, in equilibrium.
Let's say that you have one ball directly on top of another. When you compute the acceleration of the top ball due to gravity, you should also be doing a collision check like the one you posted, except this time checking for dist <= ball.radius + otherBall.radius. If this is the case, then you should assume a normal force between the balls equal to that of gravity, and negate the component of gravity in line with the vector connecting the two balls' centers. If you fail to do this, then the top ball will accelerate into the bottom one, triggering the collision code you posted, and you'll get the jitters.
Similar logic must be used when a ball is in contact with a scene bound.
Since I've been experimenting with my own Phys2D engine (just for fun), I know you're talking about. (Just in case - you may check my demo here: http://gwt-dynamic-host.appspot.com/ - select "Circle Collisions Demo" there, and corresponding code here: https://github.com/domax/gwt-dynamic-plugins/tree/master/gwt-dynamic-main/gwt-dynamic-module-bar).
The problem is in a nature of iterations and infinite loop of colliding consequences. When e.g. ball is reached the scene corner, it experiences at least 3 vectors of force: impulse of bounce from the wall, impulse of bounce from the floor and impulse of gravity - after you summarize all 3 impulses, reduce it according loosing energy algorithm, you have to have the new vector where your ball should be. But, e.g. this impulse directs it into wall - then you have to recompute the set of vectors again according to all the stuff: energy of bounce, impulses, gravity, etc. Even in case if all these impulses are small, you never get all of them 0, because of precision of doubles and your tolerance comparison constants - that because you have the "jitter" and "sliding" effects.
Actually, most of existing 2D engines have these effects one kind or another: you may see them here: http://brm.io/matter-js/demo/#wreckingBall or here: http://box2d-js.sourceforge.net/index2.html - they actually just make the small impulses to be absorbed faster and stop iterating when the whole system becomes more or less stable, but it is not always possible.
Anyway, I'd just recommend do not reinvent your own wheel unless it is just for your fun - or for your better understanding this stuff.
For last one (JFF) - here is good tutorial: http://gamedevelopment.tutsplus.com/tutorials/how-to-create-a-custom-2d-physics-engine-the-basics-and-impulse-resolution--gamedev-6331
For real things, I'd recommend to use the existing engines, e.g. Unity (https://unity3d.com/learn/tutorials/modules/beginner/2d/physics2d) or Box2d (http://box2d.org/)
Hope this helps.
Iterating through all the balls and changing the balls position for each iteration is probably the cause for the instability, you move a ball left to avoid collision on the right, and then you pushed the ball into another ball on the left, and then the left ball tries to push it back again.
From the top of my head I could recommend trying to sum up all the forces on each ball before doing anything about positioning. And if you iterate from the ball "on top" (furthest away from gravity source/direction) you can probably achieve a stable situation.
Basically, the top ball needs to first calculate forces between itself and the ball(s) under it, plus gravity, then the ball under will know how much force is coming from the top ball, and added with gravity it would also add to the force of which it is pushing the balls under it. When all balls know the forces they're pushed with you can transform that force into motion.
The way you are simulating the physics of the balls is bound to cause instabilities. Your collision resolution tries to separate the balls by projecting one of them in the opposite direction by the collision depth. This may fix the overlap for those two balls but chances are(especially when the balls are stacked) that the ball is now overlapping with another ball.
There are many ways to fix penetration. One of the simplest ways is to add a "bias" or a bit of a push to both bodies to force them to separate over the next couple of frames. This allows that energy to propagate and force all of the bodies apart. Problem is, the bias will often overestimate and cause a bit of a bounce. To fix that problem I'd recommend reading up on sequential impulse.
Making physics look realistic is not as easy as it may seem. Unless you don't mind instabilities I'd recommend spending some time reading up on different techniques or using an engine such as Box2D.
im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.
I'm programming a 2D tile based game in Java like Bomberman (my first game).
I use a 2D array to represent the map where I keep track of walls, walkable spaces, etc. By now I was able to make the player move smoothly swaping sprites depending on the direction key he presses (but not interacting with the background/map, it can walk randomly and get out of the screen).
My problem comes when I want to keep track of the player's position in the array. Logically the character always belongs to only one tile but graphically it can be between two tiles. How can I solve this issue?
I already tried this:
currentTileArrayX = x / tileWidth;
currentTileArrayY = y / tileHeight;
Where x and y are the top-left coordinates of the sprite.
But everything became very buggy because the player's sprites aren't the same size as the tiles.
I had another option in mind that would solve the previous problem: When the player presses a direciton key, move the character to the next tile like an animation. This wouldn't let the player stop in the middle of two tiles... But what if he interrupts it with another key press? How can I stop user's action while the animation is executing? I think this is the easiest solution but I don't know how to implement it.
I already tried to find the solution in other questions but I had no luck. I hope you can help me.
Thanks a lot.
Aaaaaaaaaaaaaaah! Encountering the 'discrete space problem' :) Your logic map is discrete but your UI movements are in the continuous space. I don't the user can actually be in both tiles "at the same time" - visually yes, but never 'internally'. Now you are getting the position of the player and that can be "anywhere" within the tile or "on the boundary" of 2 tiles so to speak...
You have two solutions to this problem, IMO:
Use simple rounding: If the player position is < tile-boundary just keep him on the previous tile. If Greater on the next. Now the problem of boundary - you can use a heuristic, since you shouldn't trust the accuracy of the floating point comparisons (i.e, comparing to 0 is not a good thing to do). So you can try something like this if(currentPosition - boundary <= 0.000000001) then assume it's the next tile else stay on the same one.
Well #Jay beat me to it. So the second one is to actually have a
movement speed defined and move the character that many steps per
'click'/'button press' - but you say you have the problem of key
pressed in "between". I'm guessing if you code is designed like this
then it shouldn't be a problem:
update()
{
calculate(); //update all datastructures/calculations
draw(); //update the visual representation based on calculations
}
update() is a.k.a, gameLoop. I think this should solve your problem...
I'd try to keep the logic part (tile the player belongs to) and the visualization part (animation between tiles) as seperate as possible. My approach would be to have a logical location (tile the player is set on) and a movement speed (which essentially means an amount of time the player isn't allowed to move on to the next tile after moving to a tile). Then the animation from one tile to another would mean that your sprite is always moving towards the screen coordinates of your tile - the time this takes could easily be determined by the movement speed (one full tile movement should take as long as the player has to rest on the current tile).
The only special case would be this "turning around", where you would allow the player to return to the tile he came from at any time, taking only (timeToRecoverOnTile - (timeToRecoverOnTile - timeSinceMovementStarted)).
I once did basically the same thing in AS3, but the concept transfers to Java. I decided to create two main values to help keep track of movement, a Point containing the player's x/y value (by tile), and a direction Point for the movement's direction. Here's some pseudo-code:
if(direction.x == 0 && direction.x == 0) {
if (up) direction.y = -1;
else if (down) direction.y = 1;
else if (left) direction.x = -1;
else if (right) direction.x = 1;
} else {
player.x += direction.x;
player.y += direction.y;
distance--;
if(distance == 0) {
direction.x = direction.y = 0;
distance = tileWidth;
}
}
Obviously, you'd have to tweak that to fit your needs, but that's the basics. Also, tileWidth can be replaced with an integer literal that simply is equal to the width of a single tile.