Page 2 of 2
Posted: Mon Aug 27, 2007 8:12 pm
by Demivec
ChebbyShabby wrote:also, i see you used mechanics/physics concepts to make FlightTime equal to 20 when falling down. can i just ask, what do you do in uni and what did you study at school?
I didn't study many things in university. I only had the rough equivalent of one quarter of one year (grades were all A's). My studies in school included 3 years of mechanical physics and mathematics through the calculus level. My personal studies though have included anything and everything, including computer science of course.
An equation that would be better is:
Code: Select all
;FlightTime=20 doesn't work if Power is not 10
FlightTime=Power/Gravity
The collision could be performed as an elastic collision with
Code: Select all
FlightTime=2*(Power/Gravity)-FlightTime
I think the overlap problem is just related to the order of the collision detection.
Posted: Mon Aug 27, 2007 9:08 pm
by ChebbyShabby
do you by any chance know how to make the downward collision elastic so that the player bounces a bit before he stops? i've only been studying advanced maths and physics for a year now (british system) and so i don't have much experience with these.
Posted: Mon Aug 27, 2007 10:17 pm
by Demivec
ChebbyShabby wrote:do you by any chance know how to make the downward collision elastic so that the player bounces a bit before he stops? i've only been studying advanced maths and physics for a year now (british system) and so i don't have much experience with these.
It would work the same way in the british system as it would for any other since we are not using any units of measure besides pixels/frame.
Posted: Mon Aug 27, 2007 10:28 pm
by ChebbyShabby
nono i was talking about the system of education...
Posted: Tue Aug 28, 2007 3:43 am
by Rook Zimbabwe
Actually I think you were talking about reflection... to make a the player reflect a small tangent from hitting a fixed point.
In Blitz we had 3 collision types...
1. Nothing
2. Sliding Type (useful for the floor of the platform)
3. Stop (useful for walls)
I always thoguht there should have been a 4th type like Reflection... People are doing that with a physics engine, but they were doing it long before a physics engine as well...
Let me dig in my old code a bit:
This is what I used for a circular pool game... I didn't write the entire thing but I did polish it for my uses. You should be able to see the math:
Code: Select all
;------------------------------------------
;COLLISION CHECKING
;------------------------------------------
; Check each circle in the loop against
; every other (c against c2)
For c2.circle = Each circle
collisionDistance# = c\radius+c2\radius
actualDistance# = Sqr((c2\x-c\x)^2+(c2\y-c\y)^2)
;Collided or not?
If actualDistance<collisionDistance Then
collNormalAngle#=ATan2(c2\y-c\y, c2\x-c\x)
;Position exactly touching, no intersection
moveDist1#=(collisionDistance-actualDistance)*(c2\mass/Float((c\mass+c2\mass)))
moveDist2#=(collisionDistance-actualDistance)*(c\mass/Float((c\mass+c2\mass)))
c\x=c\x + moveDist1*Cos(collNormalAngle+180)
c\y=c\y + moveDist1*Sin(collNormalAngle+180)
c2\x=c2\x + moveDist2*Cos(collNormalAngle)
c2\y=c2\y + moveDist2*Sin(collNormalAngle)
;------------------------------------------
;COLLISION RESPONSE
;------------------------------------------
;n = vector connecting the centers of the circles.
;we are finding the components of the normalised vector n
nX#=Cos(collNormalAngle)
nY#=Sin(collNormalAngle)
;now find the length of the components of each movement vectors
;along n, by using dot product.
a1# = c\dx*nX + c\dy*nY
a2# = c2\dx*nX + c2\dy*nY
;optimisedP = 2(a1 - a2)
; ----------
; m1 + m2
optimisedP# = (2.0 * (a1-a2)) / (c\mass + c2\mass)
;now find out the resultant vectors
;r1 = c1\v - optimisedP * mass2 * n
c\dx = c\dx - (optimisedP*c2\mass*nX)
c\dy = c\dy - (optimisedP*c2\mass*nY)
;r2 = c2\v - optimisedP * mass1 * n
c2\dx = c2\dx + (optimisedP*c\mass*nX)
c2\dy = c2\dy + (optimisedP*c\mass*nY)
End If
Next
;------------------------------------------
;------------------------------------------
;Simple Bouncing off walls.
If c\x<c\radius Then
c\x=c\radius
c\dx=c\dx*-0.9
End If
If c\x>GraphicsWidth()-c\radius Then
c\x=GraphicsWidth()-c\radius
c\dx=c\dx*-0.9
End If
If c\y<c\radius Then
c\y=c\radius
c\dy=c\dy*-0.9
End If
If c\y>GraphicsHeight()-c\radius Then
c\y=GraphicsHeight()-c\radius
c\dy=c\dy*-0.9
End If
Next
End Function
Don't know if that would help or hinder, meant to help!

Posted: Tue Aug 28, 2007 8:19 am
by Demivec
Demivec wrote:I think the overlap problem is just related to the order of the collision detection.
To correct the order of collisions causing a problem the data for platform placement should be sorted by the y position in descending order then by the x position in either ascending or descending order. This means the platforms will be listed with the bottomost ones first always from the left (or right) and proceeding across the screen in order.
I also need to post a correction to a mistake I made by not entering the correct range for collisions from the left or right directions with respect to the y direction. Replace the corresponding lines with:
Code: Select all
If (xx - diffWidth)<x And x<(xx + platformWidth) And (yy - playerHeight)<y And y<(yy+platformHeight) ;Collision with RIGHT of platform
Code: Select all
If (xx - playerWidth)<x And x<(xx - diffWidth) And (yy - playerHeight)<y And y<(yy+platformHeight) ;Collision with LEFT of platform
Posted: Wed Aug 29, 2007 1:05 am
by Demivec
I simplified the code for velocity so that changes in velocity would be easier to code, especially for collisions. This allows other changes to occur in the environment besides jumping. I also included a lengthy description at the beginning for how the values were determined for gravity, velocity and so forth because I know you would probably want to tinker with them
Code: Select all
;-Physics variables
;Gravity is based on the largest value that will keep the velocity <=43 pixels/frame when player is dropped
;from a height of 480 pixels (screen height). If velocity>43 the player will move through a platform and
;collide with the next platform instead. Using formula "Vf^2 = Vi^2 + 2 * g * d" where Vi = 0,d = 480,Vf = 43
;and solving for "g = (Vf^2) / (2 * d)". This produces a range of 0<Gravity<=1.925. The value is further
;limited by the method for collision detection. It limits the velocity that can be obtained when the player
;is "not moving" for a single frame while on top of a platform (this value is 0.5 which will be rounded up to
;a 1 because of floating point to integer conversion). The change in velocity is greatest during a collison
;because the direction of the velocity changes. It uses formula "(dV) = gt and/(1 + 1 / c)" where
;dV = 0.5,t = 1,c = 5 (higher values of c represent a less elastic collision), simplifying and solving
;for "g = .6". The value for g is therefore now limited to the more restrictive range of 0<Gravity<=0.6
;due to the collision method used.
;Velocity for a Jump is based on what is range of values that will not cause the velocity to exceed
;43 pixels/frame if the player Jumps from the highest point on the screen (y = 0). Solving the above equation
;for Vi gives us "Vi = sqr(Vf^2 - 2 * g * d)". Substituting we get "Vi = sqr(1849 - 960 * g)". The legal
;values of velocity are 0 to the max value based on substituting our Gravity value and solving the equation
;for Vi.
#Elasticity = 1.0 / 5.0 ;what fraction of velocity remains after a collision
#Gravity = 0.5 + 0.5 * #Elasticity ;legal values are 0<Gravity<=0.6
#VelocityJump = 11 ;if (maxVelocity,Gravity)=(mV,g), maximum legal values are (35,0.6)<=(mV,g)<(43,0)
Gravity.f = #Gravity ;
Velocity.f = 0
newVelocity.f = 0
;-Load the level
Procedure CountLines(file$)
If ReadFile(0,file$)
l = Lof(0)
m = AllocateMemory(l)
ReadData(0,m,l)
m$ = PeekS(m)
FreeMemory(m)
CloseFile(0)
EndIf;
ProcedureReturn CountString(m$,Chr(10))/2
EndProcedure;
n = CountLines("Level.txt")-1
Dim p.POINT(n)
ReadFile(1,"Level.txt")
For I=0 To n
p(I)\x=Val(ReadString(1))
p(I)\y=Val(ReadString(1))
Next
CloseFile(1)
;-Prepare the screen
InitKeyboard()
InitSprite()
OpenScreen(640,480,32,"")
SetFrameRate(60)
;-Prepare the sprites
Enumeration
#Player
#Platform
EndEnumeration
LoadSprite(#Player,"Eraser.bmp")
LoadSprite(#Platform,"Platform.bmp")
playerHeight = SpriteHeight(#Player)
playerWidth = SpriteWidth(#Player)
platformHeight = SpriteHeight(#Platform)
platformWidth = SpriteWidth(#Platform)
diffWidth = (playerWidth - platformWidth) / 2
diffHeight = (playerHeight - platformHeight) / 2
x = 30
Repeat
FlipBuffers()
ClearScreen(RGB(0,0,0))
;-Display the level
For I = 0 To n
xx = p(I)\x
yy = p(I)\y
DisplayTransparentSprite(#Platform,xx,yy)
Next
DisplayTransparentSprite(#Player,x,y)
;-Jump
;If KeyboardPushed(#PB_Key_Space): Power = 10: EndIf
If KeyboardPushed(#PB_Key_Space) And Ground=1: Velocity = #VelocityJump: EndIf
;-Jump physics
;Velocity = Power - (Gravity * FlightTime) ;Adaptation of "v = u + at"
Velocity - Gravity ;Adaptation of "v=u+dV", change in velocity(dV) = at, where t=1
Ground - 1 ;if equal to 1 then player is on a surface he can jump from
y - Velocity
;-Horizontal movement
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
x - 5
ElseIf KeyboardPushed(#PB_Key_Right)
x + 5
EndIf
WriteStringN(0,StrF(Velocity,4)+" ("+Str(x)+","+Str(y)+")")
;-Collision detection
For I = 0 To n
xx = p(I)\x
yy = p(I)\y
If (xx - 19)<x And x<(xx + 15) And (yy - playerHeight)<y And y<(yy + platformHeight) And Velocity<0 ;Collision with TOP of platform
Ground=1
newVelocity = -Velocity * #Elasticity
y = yy - playerHeight
EndIf
If (xx - 19)<x And x<(xx + 15) And (yy - playerHeight)<y And y<(yy + platformHeight) And Velocity>0 ;Collision with BOTTOM of platform
newVelocity= - Velocity * #Elasticity
y = yy + platformHeight
EndIf
If (xx - diffWidth)<x And x<(xx + platformWidth) And (yy - playerHeight)<y And y<(yy+platformHeight) ;Collision with RIGHT of platform
x = xx + platformWidth
EndIf
If (xx - playerWidth)<x And x<(xx - diffWidth) And (yy - playerHeight)<y And y<(yy+platformHeight) ;Collision with LEFT of platform
x = xx - playerWidth
EndIf
Next I
If newVelocity <>0: Velocity = newVelocity: newVelocity = 0:EndIf
Until KeyboardPushed(#PB_Key_Escape)
End
Posted: Wed Aug 29, 2007 3:14 pm
by ChebbyShabby
interesting math, rook

, but i don't think i'll need precise circular collision in a platform game with blocks lol. anyway, since this is turning to a modify-the-code thread, for anyone following/using this code, i've added a double-jump feature; new things are indicated with "*****":
Code: Select all
;-Physics variables
;Gravity is based on the largest value that will keep the velocity <=43 pixels/frame when player is dropped
;from a height of 480 pixels (screen height). If velocity>43 the player will move through a platform and
;collide with the next platform instead. Using formula "Vf^2 = Vi^2 + 2 * g * d" where Vi = 0,d = 480,Vf = 43
;and solving for "g = (Vf^2) / (2 * d)". This produces a range of 0<Gravity<=1.925. The value is further
;limited by the method for collision detection. It limits the velocity that can be obtained when the player
;is "not moving" for a single frame while on top of a platform (this value is 0.5 which will be rounded up to
;a 1 because of floating point to integer conversion). The change in velocity is greatest during a collison
;because the direction of the velocity changes. It uses formula "(dV) = gt and/(1 + 1 / c)" where
;dV = 0.5,t = 1,c = 5 (higher values of c represent a less elastic collision), simplifying and solving
;for "g = .6". The value for g is therefore now limited to the more restrictive range of 0<Gravity<=0.6
;due to the collision method used.
;Velocity for a Jump is based on what is range of values that will not cause the velocity to exceed
;43 pixels/frame if the player Jumps from the highest point on the screen (y = 0). Solving the above equation
;for Vi gives us "Vi = sqr(Vf^2 - 2 * g * d)". Substituting we get "Vi = sqr(1849 - 960 * g)". The legal
;values of velocity are 0 to the max value based on substituting our Gravity value and solving the equation
;for Vi.
#Elasticity = 1.0 / 5.0 ;what fraction of velocity remains after a collision
#Gravity = 0.5 + 0.5 * #Elasticity ;legal values are 0<Gravity<=0.6
#VelocityJump = 13 ;if (maxVelocity,Gravity)=(mV,g), maximum legal values are (35,0.6)<=(mV,g)<(43,0)
Gravity.f = #Gravity ;
Velocity.f = 0
newVelocity.f = 0
;***** - Double jump variables
DJTimer = 30 ;interval between double jumps
DJump = 2 ;2 jumps initially available
;-Load the level
Procedure CountLines(file$)
If ReadFile(0,file$)
l = Lof(0)
m = AllocateMemory(l)
ReadData(0,m,l)
m$ = PeekS(m)
FreeMemory(m)
CloseFile(0)
EndIf;
ProcedureReturn CountString(m$,Chr(10))/2
EndProcedure;
n = CountLines("Level.txt")-1
Dim p.Point(n)
ReadFile(1,"Level.txt")
For I=0 To n
p(I)\x=Val(ReadString(1))
p(I)\y=Val(ReadString(1))
Next
CloseFile(1)
;-Prepare the screen
InitKeyboard()
InitSprite()
OpenScreen(640,480,32,"")
SetFrameRate(60)
;-Prepare the sprites
Enumeration
#Player
#Platform
EndEnumeration
LoadSprite(#Player,"Eraser.bmp")
LoadSprite(#Platform,"Platform.bmp")
playerHeight = SpriteHeight(#Player)
playerWidth = SpriteWidth(#Player)
platformHeight = SpriteHeight(#Platform)
platformWidth = SpriteWidth(#Platform)
diffWidth = (playerWidth - platformWidth) / 2
diffHeight = (playerHeight - platformHeight) / 2
Delay(2000)
y = -200
x = 30
Repeat
FlipBuffers()
ClearScreen(RGB(0,0,0))
;-Display the level
For I = 0 To n
xx = p(I)\x
yy = p(I)\y
DisplayTransparentSprite(#Platform,xx,yy)
Next
DisplayTransparentSprite(#Player,x,y)
;-Jump
;If KeyboardPushed(#PB_Key_Space): Power = 10: EndIf
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Space)
If DJump = 2: Velocity = #VelocityJump: DJump = 1: EndIf ;***** 1 jump remaining
If DJTimer <= 0 And DJump = 1: Velocity = (#VelocityJump / 2): DJTimer = 30: DJump = 0: EndIf ;***** if the timer has reached 0
;and there is 1 remaining jump,
;jump again (with half the velocity)
;and reset settings
EndIf
;-Jump physics
;Velocity = Power - (Gravity * FlightTime) ;Adaptation of "v = u + at"
Velocity - Gravity ;Adaptation of "v=u+dV", change in velocity(dV) = at, where t=1
Ground - 1 ;if equal to 1 then player is on a surface he can jump from
y - Velocity
;-Horizontal movement
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
x - 5
ElseIf KeyboardPushed(#PB_Key_Right)
x + 5
EndIf
;WriteStringN(0,StrF(Velocity,4)+" ("+Str(x)+","+Str(y)+")")
StartDrawing(ScreenOutput())
DrawText(1, 1, Str(DJump))
StopDrawing()
If Velocity<>0: If DJTimer => 0: DJTimer-1: EndIf: EndIf ;***** the timer goes down if we are not on a platform
;-Collision detection
For I = 0 To n
xx = p(I)\x
yy = p(I)\y
If (xx - 19)<x And x<(xx + 15) And (yy - playerHeight)<y And y<(yy + platformHeight) And Velocity<0 ;Collision with TOP of platform
Ground=1
newVelocity = -Velocity * #Elasticity
y = yy - playerHeight
DJump = 2 ;***** 2 jumps available
DJTimer = 30 ;***** reset the delay for the second jump
EndIf
If (xx - 19)<x And x<(xx + 15) And (yy - playerHeight)<y And y<(yy + platformHeight) And Velocity>0 ;Collision with BOTTOM of platform
newVelocity= - Velocity * #Elasticity
y = yy + platformHeight
EndIf
If (xx - diffWidth)<x And x<(xx + platformWidth) And (yy - playerHeight)<y And y<(yy+platformHeight) ;Collision with RIGHT of platform
x = xx + platformWidth
EndIf
If (xx - playerWidth)<x And x<(xx - diffWidth) And (yy - playerHeight)<y And y<(yy+platformHeight) ;Collision with LEFT of platform
x = xx - playerWidth
EndIf
Next I
If newVelocity <>0: Velocity = newVelocity: newVelocity = 0:EndIf
Until KeyboardPushed(#PB_Key_Escape)
End