What's a good algorithm for "bouncing cards" like the ones you see in solitaire games?
What's the coolest card animation you've seen?
Edit - Any besides the Windows game?
The x-axis velocity is constant. The y-velocity is incremented by some value every frame. Each frame, the current x and y positions are incremented by the respective velocities. If the card would end up below the window, y-velocity is multiplied by something like -0.9. (negative number > -1) This produces the series of descending bounces.
Two parts:
motion in the vertical direction is
governed by a second order equation,
like d=1/2at². For Earth, of
course, a= 32 ft/sec² but
you'll have to twiddle the
constants.
When the card hits the edge, as
"recursive" says, the velocity
vector is multiplied by -1 times the
component normal to the surface. If
you want it to bounce nicely to a
stop, make the -1 some slightly
smaller value, like -0.9.
Animate it by updating and redrawing the card some number of times a second, changing the position of the card each time. The easy way is to compute something like (pseudo-Python):
vel_x = # some value, units/sec
vel_y = # some value, units/sec
acc_x = # some value in units/sec^2
acc_y = # some value in units/sec^2
while not_stopped():
x = x+vel_x
y = y+vel_y
# redraw the card here at new position
if card_collided():
# do the bounce calculation
vel_x = x + (0.5 * acc_x) # 1st derivative, gives units/sec
vel_y = y + (0.5 * acc_y)
As long as the cards are staying four-square with the sides, then you collide with the sides when the distance between the card center and the wall is 1/2 the width or hieght as appropriate.
After struggling with the code Charlie provided for an hour or so, I came up with the proper algorithm (after reading recursive's response thoroughly). In real Python:
def bouncing_cards():
x = 0.0
y = 0.0
vel_x = 3.0
vel_y = 4.0
while x < windowWidth:
drawImage(img, x, y)
x += vel_x
y += vel_y
vel_y += 1.0
if y + cardHeight >= windowHeight:
y = windowHeight - cardHeight
vel_y *= -0.9
Gives the following using wxPython: http://i.imgur.com/t51SXVC.png :)
Related
I am trying to simulate noble gas interactions based on the Lennar Jones Potential.
And I ran into the problem that the interactions of the particles is apparently calculated in discrete steps so that the acceleration tends to either jump to unreasonably high values or doesn't change significantly when two particles approach each other.
The detection algorithm that I'm using looks as follows:
def accerlation(self):
index = 0
for particle, particle2 in itertools.combinations(self.particles, 2):
index += 1
x_diff = (particle.r[0] - particle2.r[0])*S
y_diff = (particle.r[1] - particle2.r[1])*S
distance = np.sqrt(x_diff**2 + y_diff**2)
if distance < criticaldistance1 and distance> criticaldistance2:
print("Interaction")
particle.a[0] -= 1/(Particle().m) *(LennardJones_Force(x_diff))
particle.a[1] -= 1/Particle().m *(LennardJones_Force(y_diff))
print(particle.a)
(The print commands are for debugging)
The Lennard Jones Force is simply a function that returns (24*epsilon*sigma**6*(Distance**6 - 2*sigma**6))/Distance**13, where epsilon and sigma are constant values.
If you can't spot a mistake there, the problem might also be in this part:
def Changeovertime(self):
self.Collision_Box() #elaxtic collsions with box
for particle in self.particles:
particle.r += self.dt * particle.v + self.dt**2*particle.a
particle.a_prior = particle.a
self.accerlation() #
particle.a = np.zeros(2) #
particle.v = (particle.v + self.dt/2 * (particle.a + particle.a_prior)) *self.scaling()
When I print the acceleration of a pair of particles during the animation it looks as follows:
[-3.21599405e-01 -1.05489024e-18]\
Interaction\
[-3.35299415e-14 2.61407475e-19]\
Interaction\
[-2.52825200e+31 -1.05489024e-07]\
Interaction\
[-6.70598831e-14 5.22814950e-19]\
Interaction\
[ 1.57188229e-01 -5.51566856e-19]\
Interaction\
[-6.70598831e-03 5.22814950e-08]\
Interaction\
[ 3.14376458e-01 -1.10313371e-18]\
Interaction\
[-3.35299416e-14 2.72195193e-19]\
Interaction\
[-6.70598831e-14 5.44390386e-19]\
(Note the jump from entry 2 to entry 3)
Without commenting on the rest of the code, the problem you see is due to the lines:
particle.a[0] -= 1/(Particle().m) *(LennardJones_Force(x_diff))
particle.a[1] -= 1/Particle().m *(LennardJones_Force(y_diff))
The force, and the acceleration, are vectors: you can not break them into x and y components like that. You have to calculate the force and project it into x and y (you can work with acceleration if you want).
force = LennardJones_Force(distance)
particle.a[0] -= 1/(particle.m) * force * x_diff/distance
particle.a[1] -= 1/(particle..m) * force * y_diff/distance
Please check the signs (they should be opposite for particle and particle2).
The huge jump you see is because two particles had a very similar x or y coordinate (even if they were far apart), and the miscalculated force was huge.
It seems that physics is not obeyed.
Verify that Newton's third law is implemented.\
Note that the moment these particles interact, an action-reaction pair is formed, so to ensure conservation of energy the force acting on particle j must be the same force acting on particle i (in direction and absolute value): Fx[i] = -Fx[j] (imagine i red and j blue!).
Here's a note: if the masses of these particles are equal and their values are 1, you can assume that acceleration equals force Fx[i] = ax[i]/1. Then, all that remains is to decompose these forces (Fr[i] and Fr[j]) into their components (Fx[i], Fy[i] and Fz[i] for Fr[i] and Fx[j], Fy[j] and Fz[j] for Fr[j]), always remembering that the force that particle j does on particle i is equal to the force that particle i does on particle j, being different only by their signs (different senses).
In computer practice, you do it this way:
def acceleration():
for i in range(0,N_particles):
for j in range(i+1,N_particles):
rij = np.sqrt((x[i] - x[j])**2 + (y[i] - y[j])**2 + (z[i] - z[j])**2)
if (rij < rmaxlj):
flj = (48*epsilon*(sigma**12/rij**13) + 24*self.epsilon*(sigma**6/rij**7))/rij**2
Fx[i] += flj*(x[i] - x[j])
Fy[i] += flj*(y[i] - y[j])
Fz[i] += flj*(z[i] - z[j])
Fx[j] -= flj*(x[i] - x[j])
Fy[j] -= flj*(y[i] - y[j])
Fz[j] -= flj*(z[i] - z[j])
return Fx, Fy, Fz
Note that all forces that are added to each component of particle j are "removed" from each component of particle i. This is actually Newton's third law in action!
PS.: these rmaxlj works as if you were using criticaldistance and also you can use i as 0 and j as 1
Test this and tell me later!
I am writing a simulation in which an object moves in a 2D world towards a target position, stored as vector target(x,y). The object position is stored as position vector pos(x,y) as well. The object contains two more vectors, the desired movement velocity dv(x,y), as well as the current movement velocity cv(x,y). At the start of the simulation both these velocity vectors are initial, i.e. set to (0,0).
When the object should move towards the target position, I calcuate the desired velocity vector dv, normalize it, and scale it by a movement speed value:
dv.set(target).sub(pos).normalize()
dv.scale(speed)
I want to make the movement look more realistic, that's why I use two velocity vectors. dv tells the full speed I want to move the object, and cv holds the real speed the object currently moves at.
Then at each frame (update step) the current velocity cv is set based on the desired velocity dv and an acceleration value acc. This is done by simply calculating the difference between cv and dv and clamping this difference to acc. That way the object starts to move slowly and accelerates gradually to eventually reach full speed.
So far this is working fine. Now I want to make use of acc for deceleration as well. When the distance between pos and target is at a certain value, the desired velocity dv should be set to (0,0), so that the object gradually decelerates until it comes to a full stop at the target position.
My question is: How can I calculate at which distance I need to set dv to (0,0) (i.e. tell the system to stop movement), so that the object decelerates correctly to stop exactly at the target position?
Use the kinematic equations:
vf2 = vi2 + 2 * a * d
vf is your final velocity, or 0 (the speed you want to be going)
vi is your initial velocity, given (the speed your object is currently moving).
a is acceleration
d is distance.
Solve for d:
2*a*d = vf2 - vi2
2*a*d = 0 - vi2
assume acceleration is negative, so multiply both sides by -1
2*|a|*d = vi2
|a| is the absolute value of your acceleration (deceleration in your case)
d = vi2 / (2*|a|)
You're doing a discrete time simulation of motion. One way to keep things simple is to perform the calculations in a way that makes acceleration and deceleration symmetrical. In other words, the distance traveled while accelerating should be the same as the distance traveled while decelerating. As an example, assume
acceleration is 5
top speed is 13
the object begins decelerating as soon as it reaches top speed
Here's how the discrete time simulation would progress
first tick
old speed = 0
new speed = 5
distance = 5
second tick
old speed = 5
new speed = 10
distance = 15
third tick
old speed = 10
new speed = 13
distance = 28 <-- total distance while accelerating
fourth tick
old speed = 13
distance = 41
new speed = 10 <-- not 8!!!
fifth tick
old speed = 10
distance = 51
new speed = 5
sixth tick
old speed = 5
distance = 56 <-- Yay, twice the distance, we have symmetry
new speed = 0
There are two key points here
While accelerating the speed is updated first and then the distance is updated. While decelerating the order is reversed, the distance is updated first, and then the speed.
When decelerating, it's important to keep the adjusted speed as a multiple of the acceleration
In the C programming language, the following code could be used to update the speed during deceleration
if ( old_speed % acceleration != 0 ) // if speed is not a multiple of acceleration
new_speed = old_speed - old_speed % acceleration; // reduce speed to a multiple of acceleration
else // otherwise
new_speed = old_speed - acceleration; // reduce speed by acceleration
If acceleration and deceleration are symmetrical, then computing the deceleration distance is the same as computing the acceleration distance.
distance = acceleration * (1+2+3+ ... +N) + fudge_factor
where
N is top_speed / acceleration truncated to an integer, e.g. 13/5 ==> 2
fudge_factor is 0 if top speed is a multiple of acceleration, or
top_speed otherwise
The computation can be simplified by noting that
1+2+3+ ... +N = N * (N+1) / 2
In C, the total distance travelled while decelerating could be computed as follows
int top_speed = 13;
int acceleration = 5;
int N = top_speed / acceleration; // Note: in C, integer division truncates
int fudge = 0;
if ( top_speed % acceleration != 0 )
fudge = top_speed;
int distance = acceleration * (N * (N+1)) / 2 + fudge;
I am currently doing a small turn based cannon game with XNA 4.0. The game is very simple: the player chooses the speed and angle at which he desires to shoot his rocket in order to hit another player. There is also a randomly generated wind vector that affects the X trajectory of the rocket. I would like to add an AI so that the player could play against the computer in a single player mode.
The way I would like to implement the AI is very simple: find the velocity and angle that would make the rocket hit the player directly, and add a random modifier to those fields so that the AI doesn't hit another player each time.
This is the code I use in order to update the position and speed of the rocket:
Vector2 gravity = new Vector2(0, (float)400); // 400 is the sweet spot value that i have found works best for the gravity
Vector2 totalAcceleration = gravity + _terrain.WindDirection;
float deltaT = (float)gameTime.ElapsedGameTime.TotalSeconds; // Elapsed time since last update() call
foreach (Rocket rocket in _instantiatedRocketList)
{
rocket.RocketSpeed += Vector2.Multiply(gravity, deltaT); // Only changes the Y component
rocket.RocketSpeed += Vector2.Multiply(_terrain.WindDirection, deltaT); // Only changes the X component
rocket.RocketPosition += Vector2.Multiply(rocket.RocketSpeed, deltaT) + Vector2.Multiply(totalAcceleration, (float)0.5) * deltaT * deltaT;
// We update the angle of the rocket accordingly
rocket.RocketAngle = (float)Math.Atan2(rocket.RocketSpeed.X, -rocket.RocketSpeed.Y);
rocket.CreateSmokeParticles(3);
}
I know that the basic equations to find the final X and Y coordinates are:
X = V0 * cos(theta) * totalFlightTime
Y = V0 * sin(theta) * totalFlightTime - 0.5 * g * totalFlightTime^2
where X and Y are the coordinates of the player I want to hit, V0 the initial speed, theta the angle at witch the rocket is shot, totalFlightTime is, like the name says, the total flight time of the rocket until it reaches (X, Y) and g is the gravity (400 in my game).
Questions:
What I am having problems with, is knowing where to add the wind in those formulas (is it just adding "+ windDirection * totalFlightTime" in the X = equation?), and also what to do with those equations in order to do what I want to do (finding the initial speed and theta angle) since there are 3 variables (V0, theta and totalFlightTime) and only 2 equations?
Thanks for your time.
You can do this as follows:
Assuming there is no specific limit to V0 (i.e. the robot can fire the rocket at any desired speed) and using the substitutions
T=totalFlightTime
Vx=V0cos(theta)
Vy=V0sin(theta)
Choose an arbitrary value for Vx. Now your first equation simplifies to
X=VxT so T=X/Vx
to solve for T. Now substitute the value of T into the second equation and solve for Vy
Y=VyT + gT^2/2 so Vy = (Y - gT^2/2)/T
Finally you can now solve for V0 and theta
V0 = Sqrt(Vx^2 + Vy^2) and Theta = aTan(Vy/Vx)
Note that your initial choice of Vx will determine the trajectory the missile will take - if Vx is large then T will be small and the trajectory will be almost a straight line (like a bullet fired at a nearby target) - if Vx is small then T will be large and the trajectory will be an arc (like a mortar round's path). You dis start with three variables (V0, totalFlightTime, and theta) but they are dependent variables so choosing any one (or in this case Vx) plus the two equations solves for the other two. You could also pre-determine flight time and solve for Vx, Vy, theta and V0, or predetermine theta (although this would be tricky as some theta wouldn't provide a real solution.
I'm working on an iris recognition algorithm that processes these kind of images into unique codes for identification and authentication purposes.
After filtering, intelligently thresholding, then finding edges in the image, the next step is obviously to fit circles to the pupil and iris. I've looked around the the technique to use is the circular Hough Transform. Here is the code for my implementation. Sorry about the cryptic variable names.
print "Populating Accumulator..."
# Loop over image rows
for x in range(w):
# Loop over image columns
for y in range(h):
# Only process black pixels
if inp[x,y] == 0:
# px,py = 0 means pupil, otherwise pupil center
if px == 0:
ra = r_min
rb = r_max
else:
rr = sqrt((px-x)*(px-x)+(py-y)*(py-y))
ra = int(rr-3)
rb = int(rr+3)
# a is the width of the image, b is the height
for _a in range(a):
for _b in range(b):
for _r in range(rb-ra):
s1 = x - (_a + a_min)
s2 = y - (_b + b_min)
r1 = _r + ra
if (s1 * s1 + s2 * s2 == r1 * r1):
new = acc[_a][_b][_r]
if new >= maxVotes:
maxVotes = new
print "Done"
# Average all circles with the most votes
for _a in range(a):
for _b in range(b):
for _r in range(r):
if acc[_a][_b][_r] >= maxVotes-1:
total_a += _a + a_min
total_b += _b + b_min
total_r += _r + r_min
amount += 1
top_a = total_a / amount
top_b = total_b / amount
top_r = total_r / amount
print top_a,top_b,top_r
This is written in python and uses the Python Imaging Library to do image processing. As you can see, this is a very naive brute force method of finding circles. It works, but takes several minutes. The basic idea is to draw circles from rmin to rmax wherever there is a black pixel (from thresholding and edge-detection), the build an accumulator array of the number of times a location on the image is "voted" on. Whichever x, y, and r has the most votes is the circle of interest. I tried to use the fact that the iris and pupil have about the same center (variables ra and rb) to reduce some of the complexity of the r loop, but the pupil detection takes so long that it doesn't matter.
Now, obviously my implementation is very naive. It uses a three dimensional parameter space (x, y, and r), which unfortunately makes it run slower than is acceptable. What kind of improvements can I make? Is there any way to reduce this to a two-dimensional parameter space? Is there a more efficient way of accessing and setting pixels that I'm not aware of?
On a side note, are there any other techniques for improving the overall runtime of this algorithm that I'm not aware of? Such as methods to approximate the maximum radius of the pupil or iris?
Note: I've tried to use OpenCV for this as well, but I could not tune the parameters enough to be consistently accurate.
Let me know if there's any other information that you need.
NOTE: Once again I misinterpreted my own code. It is technically 5-dimensional, but the 3-dimensional x,y,r loop only operates on black pixels.
Assuming you want the position of the circle rather than a measure of R.
If you have a decent estimate of the possible range of R then a common technique is to run the algorithm for a first guess of fixed R, adjust it and try again.
I'm currently developing a script for a map in COD4. I think that the language is so simple that I'm tagging this as language-agnostic since the problem is in the algorithm for this situation.
There is a room which is 960 units wide. And inside it there's an object in the middle, which we'll count as the axis. The ball is supposed to move to a random position each time it is hit, but should not traverse further than the walls. Here's a diagram:
The API of the game only allows the moving of objects relative to its position, as far as I know, so here's code that I came up with. The problem is that after the second call to head_move() it begins to produce unexpected results and this is crashing my head. Could somebody help me out?
movementThink():
while (1)
{
self waittill ("trigger", player); //Wait till player hits the object
head_origin thread head_move();
}
head_move()
{
/* level.prevx is a global variable which I use to store
the distance traveled in the previous shot. Defaults to 0 */
/*This works in the first and second hit, but then it begins to show
incorrect max and min values*/
x_min = (0-480) + level.prevx;
x_max = x_min + 960;
x_units = RandomIntRange( x_min, x_max ); //Create a random integrer
log2screen("MIN: " + x_min + " and MAX: " + x_max + " and MOVED " + x_units);
log2screen("Moved " + x_units);
//Movement function, first parameter is the distance to be traveled, and the second one is the speed
self movex (x_units , level.movespeed);
level.prevx = x_units;
}
EDIT: Just to clarify. When the user shoots the ball, its position changes to a certain value. Now, if he hits it again, the min and max values of the random int generator should change to prevent the ball from moving outside the walls. Example:
Level starts. The ball is in the middle of the room. The min and max ranges are -480 and 480 respectively
The user hits the ball and its moved -200 units (200 units to the left).
Now, the min and max range should be -280 and 680.
I hope this is clear enough.
EDIT 2: Edited the sign as FlipScript suggested. Here's the output from the log2screen functions, what is actually happening:
MIN: -480 and MAX 480. MOVED 67
MIN: -413 and MAX 547. MOVED 236
MIN: -244 and MAX 716. MOVED 461
Just a sample case. Something is backwards I believe, these aren't the right calculations to do.
Your code works only when self.prevx contains your displacement from the starting position, i.e. your absolute position. However, what you are storing is your displacement from your current position. It works the first two times because that displacement happens to be the same as your absolute position, but once you move again, you lose all track of where you are.
What you should do instead is get rid of min and max, and start by calculating a random absolute position within the bounds. Then use your previously stored absolute position to calculate the relative movement needed to get you there, and store the new absolute position.
head_move()
{
new_x = RandomIntRange( -480, 480 ); //create a random location
delta_x = new_x - level.prev; //determine relative movement needed to get there
self movex (delta_x , level.movespeed); //move to new position
level.prevx = new_x; //store new position
}
I dont know much about the programming environment, but this line
head_origin thread head_move();
is suspicious for troublemaking. What are these tokens? Anything that says thread could be duplicating data structures and throwing your local variables astray.
And why do x_min and x_max change? Where's y_min and y_max?
Something doesn't look right in this line here:
x_max = x_min - 960;
Is the MAX really the MIN MINUS 960? From your description, it sounds like that should be a '+' sign.
EDIT:
In your additional comments, the minus sign wouldn't allow these truths:
Level starts....The min and max ranges are -480 and 480 respectively
...
Now, the min and max range should be -280 and 680.
Comments 1 and 3 point to that sign needing to be '+' sign.