I've just begun to fiddle with game creation again. I haven't touched the subject
in 20 years, so my math are (at best) extremely rusty.
Well, my point is this: Event though I can figure most of the math out, there
are situation, when it simply doesn't make any sense to me...(Age related I think)
Doing a search forum wide for a specific explanation or example
can be pretty tedious and many times the search returns nada either due to
wrong words used or the specific topic is embedded into waaaay too much
other code, that it may not be recognized as what you need.
My hope is, that all you excellent and helpfull users out there would appreciate
this idea.
Well, I cannot just ask without providing myself, so I've dusted off my ooold codes
and tried to convert it to Purebasic:
It's a mix of everything and hopefully it will work as expected.
Please feel free to point out/correct typoes, mistakes, or wrong conversion. But please, do not
flame me..I did the best I could.
Code looks a bit messy and is a direct translation from C/C++..
I hope a dedicated area will be made just for small Game Math issues/examples/snippits.
Best regards
Peter.
Oh...Boy..Here we go
Code: Select all
;
Surface Friction (mK) Static Friction (mS) Kinetic
;-------------------------------------------------------
; Steel on steel (dry) 0.6 0.4
; Steel on steel (greasy) 0.1 0.05
; Teflon on steel 0.041 0.04
; Brake lining on cast iron 0.4 0.3
; Rubber on concrete (dry) 1.0 0.9
; Rubber on concrete (wet) 0.30 0.25
; Metal on ice 0.022 0.02
; Steel on steel 0.74 0.57
; Aluminum on steel 0.61 0.47
; Copper on steel 0.53 0.36
; Nickel on nickel 1.1 0.53
; Glass on glass 0.94 0.40
; Copper on glass 0.68 0.53
; Oak on oak (parallel To grain) 0.62 0.48
; Oak on oak (perpendicular To grain) 0.54 0.32
; List of Conversion Factors Length Time
; 1m = 39.37in = 3.281ft 1s = 1000ms
; 1in = 2.54cm 1min = 60s
; 1km = 0.621mi 1hr = 3600s
; 1mi = 5,280ft = 1.609km 1 year = 365.242 days
Structure vector2D
x.f
y.f
EndStructure
Structure vector3D
x.f
y.f
z.f
EndStructure
Procedure.d radtodeg(Rad.d)
ProcedureReturn Rad * 180 / #PI
EndProcedure
Procedure.d PointDirection(x.d, y.d, x2.d, y2.d)
ProcedureReturn radtodeg(ATan2(y-y2, x2-x))
EndProcedure
Procedure OrgMath()
Define x.d, y.d
Angle = 45
AngleRad = Radian(Angle)
x + Sin(AngleRad)
y - Cos(AngleRad)
EndProcedure
;returns the distance between two supplied points p and q
Procedure.d distance(*p.POINT, *q.POINT)
dx.d = *p\x - *q\x; ;horizontal difference
dy.d = *p\y - *q\y; ;vertical difference
dist.d = Sqr(dx*dx + dy*dy ) ;distance using Pythagoras theorem
ProcedureReturn dist;
EndProcedure
;distance from a point to a vertical line
Procedure.i FindDist2VertLine(px.f,lx.f)
distance = Abs(Px) - Abs(Lx)
ProcedureReturn distance
EndProcedure
;distance from a point to a horizontal line
Procedure.i FindDist2HorizLine(py.f,ly.f)
distance = Abs(Py) - Abs(Ly)
ProcedureReturn distance
EndProcedure
;Find the slope of a line
Procedure.i FindSlopeOfLine(*p1.POINT,*p2.POINT)
slope = (*p1\y - *p2\y) / (*p1\x + *p2\x)
EndProcedure
;Degree to radians
Procedure.f Degree2Rad(degr.f)
myRad.f = (#PI * degr) / 180
ProcedureReturn myRad
EndProcedure
;Radians to degree
Procedure.f Rad2degree(Rad.f)
myRad.f = (180 * Rad) / #PI
ProcedureReturn myRad
EndProcedure
;/////////////////////////////////////////////////
; VELOCITY, ACCELERATION - MOVEMENT
;/////////////////////////////////////////////////
;purpose: calculate final velocity, given initial velocity, acceleration and time
; input: vi initial velocity
; a acceleration
; t time
; output: our final velocity
Procedure.f eqOne_vf(vi.f, a.f, t.f)
ProcedureReturn vi + a * t
EndProcedure
;purpose: calculate change in distance, given final velocity, initial
; velocity and time
; input: vf final velocity
; vi initial velocity
; t time
; output: our change in distance
Procedure.f eqTwo_x(vf.f, vi.f, t.f)
ProcedureReturn 0.5 * (vf - vi) /t
EndProcedure
;purpose: calculate change in distance, given initial velocity,
; acceleration andnd time
; input: vi initial velocity
; t time
; a acceleration
; output: our change in distance
Procedure.f eqThree_x(vi.f, t.f, a.f)
ProcedureReturn vi * t + 0.5 * a * t * t
EndProcedure
;purpose: To determine whether an object on an incline will slide
; input: angle - the current angle of the incline
; weight - the weight of the object
; fric_coeff - the coefficient of Static friction between surfaces
; output: true If the object should slide, Else false
Procedure checkForMotion(angle.f, weight.f, fric_coeff.f)
; Calculate the normal force being exerted by the ramp
normal.f = weight * Cos(angle * #PI / 180)
; Calculate the force perpendicular To the normal
perpForce.f = weight * Sin(angle * #PI / 180)
; Calculate the amount of Static friction keeping the object at rest
stat_friction.f = fric_coeff * normal
; Return true If the object should slide, Else false
ProcedureReturn perpForce > stat_friction
EndProcedure
;purpose: To determine whether an object on an incline will slide
; input: angle - the current angle of the incline
; weight - the weight of the object
; fric_coeff - the coefficient of kinetic friction between surfaces
; mass - the mass of the object
; output: the acceleration of the object
Procedure.f calcAccel(angle.f, weight.f, fric_coeff.f, mass.f)
;Calculate the normal force being exerted by the object
normal.f = weight * Cos(angle * PI / 180)
; Calculate the force perpendicular To the normal
perpForce.f = weight * Sin(angle * PI / 180)
;Calculate the amount of Static friction keeping the object at rest
kin_friction.f = fric_coeff * normal
;Calculate the sum of forces acting upon the object
total_force.f = perpForce - kin_friction
;Return the acceleration of the object
ProcedureReturn total_force / mass
EndProcedure
;//////////////////////////////////////////////////////////////////
;
; KINETIC ENERGY
;
;//////////////////////////////////////////////////////////////////
;Here is a procedure that returns the amount of work done given a force,
;a friction force, And a displacement
Procedure.f calculateWork(force.f, friction.f, displacement.f)
;calculate the difference of the forces.
netForce.f = force-friction
;multiply by displacement
temp.f = displacement*netForce
ProcedureReturn temp
EndProcedure
;Calculating Work with Angled Force
;Procedure that will return the amount of work done considering an angled force
;
Procedure.f calculateAngledWork(*obj.vector2D, friction.f, displacement.f)
;don't forget to convert to rads....
temp.f = Cos(Degree2Rad(*obj\y)) ;Degree2Rad(degr.f) see procedure further up
;calculate the horizontal force;
horizForce.f = *obj\x * temp
work.f = calculateWork(horizForce,friction, displacement) ; Procedure is above
ProcedureReturn work
EndProcedure
Procedure.f calculateKineticEnergy(mass.f, speed.f)
KE.f = (mass/2)*(Pow(speed,2))
ProcedureReturn KE;
EndProcedure
Procedure.f calculateWorkEnergy(force.f, mass.f, displacement.f, velocityInitial.f, friction.f)
;NOTE: I'M NOT SURE IF THIS IS CORRECT......
work.f = calculateWork(force,friction,displacement); See procedure above
vFinal.f = work/((mass/2) - calculateKineticEnergy(mass, velocityInitial)); See procedure above
velocityFinal.f = Sqr(vFinal)
ProcedureReturn velocityFinal
EndProcedure
;calculation For potential energy
#GRAVITY = 9.81 ;<--- A book weighs 1.5 pounds, and it is raised 2 meters off the ground
; formula: 1.5lbs (1N/0.2248lbs) - 1N = 1kg*m/s2
Procedure.f calculatePotentialEnergy(mass.f,height.f)
;PE = Potential energy
PE.f = mass * #GRAVITY * height
ProcedureReturn PE;
EndProcedure
;///////////////////////////////////////////////////////////////////////
; Everything else...
;///////////////////////////////////////////////////////////////////////
;move an object based on its angles and distance
Procedure OrbitCalc3D(CenterX.f,CenterY.f,CenterZ.f, AngleX.f,AngleY.f, Radius.i)
X = CenterX + Radius*Cos(AngleY)*Cos(AngleX)
Y = CenterY + Radius*Sin(AngleX)
Z = CenterZ + Radius*Sin(AngleY)*Cos(AngleX)
EndProcedure
Procedure Projectile_Trajectory(Screen_Bottom.i,Initial_vel.f,Initial_Angle.f)
x_pos.f = 0 ;starting point of projectile
y_pos.f = Screen_Bottom ;bottom of screen
y_velocity.f = 0 ;initial y velocity
x_velocity.f = 0 ;constant x velocity
gravity.f = 1 ;do want To fall too fast
velocity.f = Initial_vel ;whatever
angle.f = Initial_Angle ;whatever, must be in radians
;compute velocities in x,y
x_velocity = velocity*Cos(angle)
y_velocity = velocity*Sin(angle)
;do projectile loop Until object hits
;bottom of screen at SCREEN_BOTTOM
While(y_pos < SCREEN_BOTTOM)
; update position
x_pos + x_velocity
y_pos + y_velocity
;update velocity
y_velocity + gravity
Wend
EndProcedure
;/////////////////////////////////////////////////////////////////
; Just added
;/////////////////////////////////////////////////////////////////
;Converting from Cartesian to polar coordinates.
;structure for holding vector
Structure _2Dvector
x.f
y.f
EndStructure
;vector in magnitude/direction
Structure _2Dvector_pol
mag.f
dir.f
EndStructure
;purpose: To convert a vector from magnitude/direction To component form
;input: vec- a vector in magnitude/direction form
;output: our converted vector
Procedure v2Dvector_comp_PolarToCompConversion(*vec._2Dvector_pol)
;temporary variable which will hold the answer
temp._2Dvector
;Fill in our values
temp\x = *vec\mag * Cos(*vec\dir * #PI / 180)
temp\y = *vec\mag * Sin(*vec\dir * #PI / 180)
ProcedureReturn @temp
EndProcedure
;purpose: To convert a vector from component To magnitude/direction form
;input: vec- a vector in component form
;output: our converted vector
Procedure v2Dvector_polar_CompToPolarConversion(*vec._2Dvector)
;temporary variable which will hold our answer
temp._2Dvector_pol
;Calculate our magnitude using the Pythagorean theorom
temp\mag = Sqr(*vec\x * *vec\x + *vec\y * *vec\y)
;Error check To prevent a divide-by-zero
If temp\mag = 0
ProcedureReturn @temp
EndIf
;Calculate our angle. We are using ASin() which will Return an angle
;in either the 1st Or the 4th quadrant
temp\dir = (180 / #PI) * ASin(*vec\y / temp\mag)
;Adjust our angle in the event that it lies in the 2nd Or 3rd quadrant
If *vec\x < 0
temp\dir + 180
;Adjust our angle in the event that it lies in the 4th quadrant
ElseIf *vec\x > 0 And *vec\y < 0
temp\dir + 360
EndIf
ProcedureReturn @temp
EndProcedure
;calculate the angular displacement given the arc length and radius
Procedure.f angleDisplacement(arc.f, radius.f)
theta.f
theta = arc/radius
ProcedureReturn theta
EndProcedure
;Average Angular Velocity
Procedure.f avgAngularVelocity(arcStart.f, arcEnd.f, time.f, radius.f)
Protected initialDisplacement.f, endDisplacement.f,omega.f
;calculate the angular displacement.
initialDisplacement = arcStart/radius
endDisplacement = arcEnd/radius
omega = (endDisplacement - initialDisplacement) / time;
ProcedureReturn omega;
EndProcedure
Procedure.f avgAngAcceleration(angVelBegin.f, angVelEnd.f, time.f)
Protected alpha.f
alpha = (angVelEnd - angVelBegin)/time
ProcedureReturn alpha
EndProcedure
;Tangential velocity
Procedure.f tangVelocity(omega.f, radius.f)
Protected velT.f
velT = omega*radius
ProcedureReturn velT
EndProcedure
;Procedure that will calculate the linear speed of a ball given the height, mass, And inertia
Procedure.f LinearSpeed(mass.f,initialHeight.f,inertia.f)
Protected energy.f = 0.0, halfMass.f, halfInertiaMass.f, linearSpeed.f ,temp.f = 0.0
;first figure out what is known For sure.
energy = mass*initialHeight*#GRAVITY
;this term is used To hold the math equivalent of 1/2(m)vf^2
halfMass = mass/2
;this term hold on To the formula equivalent of
;1/2(inertia)*(mass) r^2 * wf^2
halfInertiaMass = inertia*mass/2
;make a holding place.
temp = energy/(halfMass+halfInertiaMass)
;take the square root To find the speed in m/s
linearSpeed = Sqr(temp)
ProcedureReturn linearSpeed
EndProcedure
Best regards
Peter