How would you go about programming an explosion of pieces? (Tetris like)
Members - Reputation: 453
Posted 09 September 2012 - 10:03 AM
I've been working on a Tetris clone for a while now and I was wondering how I would go about programming the explosion for the pieces once a line has been cleared. Do I need to know any physics for this? The kind of explosion I have in mind is where depending on where the piece is based on the board, it would 'pop out' in that direction.
Crossbones+ - Reputation: 7024
Posted 09 September 2012 - 06:22 PM
"The best comment is a deleted comment."
Crossbones+ - Reputation: 2159
Posted 09 September 2012 - 09:27 PM
Basically F=ma. I chose my force to dissipate 1/r^2 with B as an explosion constant. That gives me an equation of F=B/r^2 and by setting it equal to F=ma I get ma=B/r^2 or a=B/mr^2.
I can integrate the acceleration to get the velocity (Acceleration is the change in velocity per unit time) and I can integrate once more to get the position (Velocity is the change in position per unit time).
A simple Euler integration would work, but for the project mentioned above I chose to use a Velocity Verlet integration because it handled constraints between the particles.
In the words of my comments:
#The logic behind calculating an explosive force is that an explosive force obeys a 1/r^2 law. #We construct a formula for the force A/r^2 where A is some explosive constant by constant absorption #The acceleration is then given using F=ma as a=A/(m*r^2) which gives our acceleration magnitude #Our acceleration vector is given by finding the unit vector in which our acceleration is to take place #using the difference between our particle and the explosive position #The colorization formula shown below is a simple linear interpolation between red and blue colors #The purpose is simply to show the intensity of the force felt by the particle as a function of the 1/r^2 rate def calculate_explosive_force(self, explosive_pos, explosive_const): if self.visible_obj is not None and not self.locked: diff = self.cur_pos - explosive_pos if mag(diff)>0.0: self.inst_accel = norm(diff)*(explosive_const/(self.mass*math.pow(mag(diff), 2.0))) else: self.inst_accel = vector(0.0, 0.0, 0.0) c = mag(norm(diff)/math.pow(mag(diff),2.0)) r = 1.0-5.0*c b = 5.0*c g = 0 self.visible_obj.color = (r,g,b)
Ok so basically (and I am generalizing a lot in this post), we can choose to model our explosion as affecting objects closer to the center of the explosion more than objects that are further away. This may not actually be the case in reality, but for a game it doesn't really matter. You are just looking for a convincing effect. We need some mathematical function that models this desired behavior and that would be the inverse square law I mentioned. As the distance of a piece from the explosive origin (the center point) increases, the force felt by that piece would decrease. This means that pieces that are further away from the explosion origin will experience a much smaller force than pieces closer to the explosion origin.
I then decide that the explosion will start off with some initial force (at ground zero so to speak) and that will be represented by some constant.
There is a problem that we face because using the inverse square law and the constant gives us the magnitude of the desired force, but it does not tell us anything about the direction of the force. By calculating a vector from the origin to the piece, we can find the direction that the explosive force would need to be applied in, and normalizing the vector will give it a unit length of 1 (Effectively removing the magnitude from the vector). We can then multiply the direction by the equation we have for our force's magnitude.
Then we can use the knowledge that a vector can be represented by length/magnitude or x,y (or x,y,z) components to eventually calculate the X and Y position of each piece.
An euler integration would look like this
Delta_Time = 1
Explosive_Force_Amplitude = Explosive_Constant / Distance_From_Origin ^ 2
Explosive_Acceleration_Amplitude = Explosive_Force_Amplitude / Piece_Mass
Explosive_Acceleration_Vector = Normalized_Vector_From_Origin_To_Piece * Explosive_Acceleration_Amplitude
Piece_X_Velocity += Explosive_Acceleration_Vector_X_Component
Piece_Y_Velocity += Explosive_Acceleration_Vector_Y_Component + Gravitational_Acceleration_On_Y_Axis
Piece_X_Position += Piece_X_Velocity
Piece_Y_Position += Piece_Y_Velocity
or something similar...
That is just how I would go about doing something fairly similar. I hope it helps!
Edited by shadowisadog, 09 September 2012 - 09:57 PM.