I am making a simple game that requires to do something similar as in the fruit-ninja game. I am now trying to make the objects fly from the bottom to the screen to the right in a curve, like this (but from a random position instead of the middle):
Because I have so little knowledge in mathematics I am stuck on this for quite some time now. How should I calculate this?
I got it to work in a very simplistic and nasty way, but the object had a static speed, instead of nice smoothing, and even I didn't know what I had just made.
Use initial speed, the launch angle, and the acceleration due to gravity in the kinematics equations.
According to Newtons first law of motion, an object moves with a constant speed in a constant direction unless an external force acts on it. That means each object has a position (represented in X and Y coordinate) which is changed by a vector (represented by speed in x-direction and y-direction) each game-frame. When you get that running, you are already halfway there.
for (GameObject object: gameObjects) {
object.position.x += object.vector.x;
object.position.y += object.vector.y;
}
But in this case, you have a force which affects the objects: Gravity. Gravity is a constant acceleration into the Y-direction. That means the vector is changed every frame by the gravity:
for (GameObject object: gameObjects) {
object.vector.y -= GRAVITY;
object.position.x += object.vector.x;
object.position.y += object.vector.y;
}
Related
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.
I'm working in Eclipse, using the Libgdx game framework to develop an Android application, where I'm attempting to move a 2D cursor based on the general movements of the Android device. As I've read from countless sources already, this is a much harder task than it sounds, due to the wide margin of error that appears during calculation.
What I've done so far is pretty primitive; pass across a composite "linear acceleration sensor" from Android, use the acceleration values to calculate velocity, use velocity to calculate displacement, add that onto my cursor's x,y coordinates, and lastly make sure the cursor does not exceed the screen's dimensions. I don't think it really needs a code example, but here's a watered down version of the core code;
//class attributes
Vector2 accel, prevAccel;
Vector2 velocity;
Vector2 cursorPos;
IMyLinearAccelerationSensor las;
//update code
accel = new Vector2(las.getAccelXY); //returns a Vector2 with the x and y acceleration values
velocity.x = (accel.x + prevAccel.x) /2 * deltaTime;
velocity.y = (accel.y + prevAccel.y) /2 * deltaTime;
cursorPos.x += tempAccel.x * deltaTime;
cursorPos.y += tempAccel.y * deltaTime;
prevAccel = accel; //update the "previous acceleration"
if (cursorPos.x < 0)
cursorPos.x = 0;
if (cursorPos.y < 0)
cursorPos.y = 0; //etc.
The main issues I'm encountering are drift, and the fact that the sensor appears to be more sensitive to movements in the positive directions of x, and y (I think). In other words, the cursor accelerates/ drifts off, gets stuck in the top left corner of the screen, and the respective velocities for x and y never really fall back to 0. Even when moving the device in the opposite direction, the velocity only decreases slightly.
Given all of this information, I just wanted to ask some questions, and for some advice. Firstly, is this is normal behavior, or are there any glaring problems with my code?
If not, are there any steps that can be taken with my current setup, to resolve these problems with drift, and remove some margin of error? e.g. applying different filters to remove noise, applying a resistive force to the velocity, etc.
I don't need the movement of the cursor to follow the device's movements too accurately; so long as it moves when the device moves, and stops generally when the device stops, I don't mind if there's some small drifting, or lag.
I was considering to at some point implement more interfaces to get the raw data from the Android hardware sensors (compass, gyroscope, and accelerometer), to generate more accurate results, but even if I do go ahead with this, would this improve much? Knowing that this is a complex problem, I'd rather not spend too much time on it without good reason. (sensor fusion from scratch definitely seems hard...)
Lastly, I'm sorry about the lengthy post, and also sorry if this is considered a repeat question. I've done research, and have seen plenty of other people with similar issues, but I'm not quite sure how their solutions might be applied to my own problem. Given my limited knowledge/ experience, I'd appreciate any helpful insight that can be offered.
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
I need to make a wheel fall on 1 of five angles and I want it to teeter when it gets to the angle. After the user spins the wheel, I have it slow down by multiplying the rotation velocity by .98 per tick. I sort of have it working by finding the closest of the angles and adding a small value in its direction to the velocity. However this looks unrealistic and can be glitchy.
I was thinking of implementing a damped sine wave but i'm not sure how I would do this.
Current Pseudocode:
var rotation, rotationVelocity, stoppingPoints[5];
update(deltaT) {
velocity -= rotationVelocity * 0.5 * dt;
closestAngle = findClosestAngle().angle;
rotationVelocity += (closestAngle - rotation) / 36 * dt;
rotation += rotationVelocity;
}
Edit:
Teeter: move or balance unsteadily; sway back and forth:
subtract a constant amount from it's velocity every iteration until it reaches zero
not only does this actually represent how friction works in real life, but it's easier too.
If you want it to move as though it were connected to a spring:
Hooke's law for springs is F = -kx where k is a constant and x is the distance from the origin if you want it to sway back and forth as though it were on a spring. keep track of it's rotation from an origin, and add -kx where x is it's rotational distance(or angle) from the origin.
Now, if you apply both friction and hooke's law to the spring, it should look realistic.
I think the closest angle that you want is the cloest to where it will stop. You can simulate where it will end, how long it takes to end, and use that to determine how much extra(or less) velocity you'll need.
Not sure what you mean by teetering exactly.
It sounds like you want to model a wheel with weights attached at the stoppingPoints. I mean, from a physics viewpoint. There is the existing rotational velocity, then deceleration from friction, and an unknown acceleration/deceleration caused by the effects of gravity on those points (as translated to a rotational velocity based on the position of the weights). Anyway, that's my interpretation and would probably be my approach (to model the gravity).
I think the teetering you speak of will be achieved when the acceleration caused by the weights exceeds the existing rotational velocity.
I am developing a small Game in Java, and I'm rewriting the Player Movement system to not be Grid-Based. It is a 2D side-scroller, and what I'm trying to achieve is basic Player Movement, so that when the user presses, and holds, the right Key the Player moves right, and the same for the Left Key. The problem I am having is that the Paint Component in another Class draws the image of the Player on the screen, with positions X and Y stored in a Settings Class. Then a KeyListener Class gets when the user is pressing Right, and adds to the X value (And the same for Left, but minuses 1 every time). This creates a slowly moving Character on the screen, and what I want to do is have him move faster without adding more than 1px each time as it would seem like he was skipping pixels (I've already tried).
I was wondering if there was a better way to go about this, as the code I'm using is bare-minimum, and my outcome would be a smoothly moving Player.
KeyListener Snippet:
public void keyPressed(KeyEvent arg0) {
int key = arg0.getKeyCode();
if(key == 39) { // Right Key
Settings.player_pos_x++;
}else if(key == 37) { // Left Key
Settings.player_pos_x--;
}
main.Game.redo();
}
Drawing User on-screen:
g.drawImage(player_image, Settings.player_pos_x, Settings.player_pos_y, this);
Any help is appreciated, if you need any more information or code please feel free to ask.
Let's try again :)
Double buffering
Quote: http://msdn.microsoft.com/en-us/library/b367a457.aspx
Flicker is a common problem when programming graphics. Graphics operations that require
multiple complex painting operations can cause the rendered images to appear to flicker
or have an otherwise unacceptable appearance.
When double buffering is enabled, all paint operations are first rendered to a memory
buffer instead of the drawing surface on the screen. After all paint operations are
completed, the memory buffer is copied directly to the drawing surface associated with
it. Because only one graphics operation is performed on the screen, the image
flickering associated with complex painting operations is eliminated.
Quote: http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html
Suppose you had to draw an entire picture on the screen, pixel by pixel or line by
line. If you were to draw such a thing directly to the screen (using, say,
Graphics.drawLine), you would probably notice with much disappointment that it takes
a bit of time. You will probably even notice visible artifacts of how your picture is
drawn. Rather than watching things being drawn in this fashion and at this pace, most
programmers use a technique called double-buffering.
Perhaps you could write the app to iterate multiple redraws to the right, each only 1 or 2 pixels per keyboard input received. This way, you're kind of artificially setting how fast you want it to move. Otherwise, you'd be limited to how the user has their keyboard iteration speed set up.
Also, java's jPanel is not exactly the place to look for video game efficiency. Just saying; you might want to look to something like openGL for that.
At best, you could optimize it to have a transition buffer outside of the jpanel drawing logic, with the same draw functionality as a jPanel, this way you write to the buffer, then copy the whole buffer during a writeImage call... I don't know if you're already doing that, but I think it avoids flicker or something... read about it a long time ago, it's called double buffering.
While double buffering will probably help you should first address how you are calculating the distance you move each time.
Change in distance (dx) can be defined as the velocity(v) times the change in time(dt), dx = v * dt. From what I can see you are omitting dt (change in time). You should calculate the time difference from the last time the character was moved and multiply that by your velocity. This way if your distance processing code is executed 10 time or 100 times in 10 seconds the character will always move the same distance.
The code will look something like this:
int currentTime = System.nanoTime();
int deltaTime = currentTime - previousTime;
Settings.player_pos_x += velX * deltaTime;
previousTime = currentTime;
With this code you will probably need to significantly increase velX. Typically I would have a constant that I would multiply by the velocity so they are smaller numbers.
Additionally if you want better movement and physics look into JBox2D although it's probably over kill for you right now. Their documentation might also help to understand basic physics.
In order to answer your question about the speed, most games i've seen store a global int for the velocity in each plane (x and y planes), then apply the velocity to the current position rather than simply incrementing it as you have done above.
public int velX = 2;
public int velY = 2;
public void keyPressed(KeyEvent arg0) {
int key = arg0.getKeyCode();
if(key == 39) { // Right Key
Settings.player_pos_x += velX;
}else if(key == 37) { // Left Key
Settings.player_pos_x -= velX;
}
main.Game.redo();
}
Once you have that set up, try adding operations which may increase the velocity (i.e. holding the key down for a long time, or something else);
Also, try to implement a jump operation, where the players Y position goes up, and try to add a gravity field to make it come back down.