Post by u9 on May 21, 2007 16:05:28 GMT -5
So here is a ball you can grap and throw around using the mouse. Can anyone make this into a game of any kind? I dear you
P.s. The air friction is not so realistic. When the object gets lighter it still falls pretty fast to the ground.
P.s. The air friction is not so realistic. When the object gets lighter it still falls pretty fast to the ground.
' Physical ball simulation may 2007 by u9
' u9 4T kallnet D0T fo
'
' Forces declaration of variables
Option explicit
' --------------------------------------------------
' Classes
' --------------------------------------------------
' This is a 2 dimensional point or vector
class Point
Public x
Public y
Public Sub class_initialize
x = 0
y = 0
End Sub
' Length of the vector
Public Function length()
length = sqr( x*x + y*y )
End Function
' Length of the vector in squared space
Public Function lengthSQ()
lengthSQ = x*x + y*y
End Function
Public Sub setLength( newLength )
Dim curLength
curLength = length()
If curLength > 0 Then
x = x * newLength / curLength
y = y * newLength / curLength
End If
End Sub
End Class
class Object
' Physics parameters
Public pos'ition
Public vel'ocity
Private tmpvel ' Temporary variable containing velocity
Public acc'eleration
Public mass
Public size ' Radius of object
Public Sub initialize( posx, posy, velx, vely, startMass, radius )
Set pos = New Point : pos.x = posx : pos.y = posy
Set vel = New Point : vel.x = velx : vel.y = vely
Set tmpvel = New Point
Set acc = New Point
mass = startMass
size = radius
End Sub
' Methods
' Update physics. dt is change in time since last call. Formulas available at: http://en.wikipedia.org/wiki/Equations_of_motion
Public Sub update( dt )
tmpvel.x = vel.x + acc.x * dt
tmpvel.y = vel.y + acc.y * dt
' Limit object speed if needed. Note: Comparison done in squared distances
If tmpvel.lengthSQ() > OBJECT_MAX_VELOCITY^2 Then
Call tmpvel.setLength( OBJECT_MAX_VELOCITY )
End If
pos.x = pos.x + 1/2 * (vel.x + tmpvel.x) * dt
pos.y = pos.y + 1/2 * (vel.y + tmpvel.y) * dt
vel.x = tmpvel.x
vel.y = tmpvel.y
acc.x = 0
acc.y = 0
End Sub
' Change acceleration of object by applying a force. Newton's second law of motion. F = ma
Public Sub addForce( forcex, forcey )
acc.x = acc.x + forcex / mass
acc.y = acc.y + forcey / mass
End Sub
' Apply acceleration directly to object. Good for adding gravity
Public Sub addAcc( accx, accy )
acc.x = acc.x + accx
acc.y = acc.y + accy
End Sub
End class
' --------------------------------------------------
' Program itself
' --------------------------------------------------
' Initialize needed sub-systems
Const WIDTH = 1024
Const HEIGHT = 768
Const BOUNCE_FRICTION = 0.85 ' How much velocity should get lost in a collision with edge of screen
Const OBJECT_MAX_VELOCITY = 1000 ' units/second
Const BALL_SIZE = 5
Const BALL_MASS = 100
Graphics.initialize WIDTH, HEIGHT, True
Key.initialize
Mouse.initialize
Timers.initialize
' Needed variables
Dim font ' For writing text on screen
Dim myTimer ' Timer index
Dim isRunning ' False when user presses escape
Dim dt ' Change in time between frames (delta-time)
Dim totalTime ' Total elapsed time (updated every frame)
Dim canvas ' canvas for rendering the game on (instead of using the screen)
Dim ball ' The ball object to throw around :)
' Make a canvas for the motion blur effect (not so important)
canvas = graphics.createimage( WIDTH, HEIGHT )
' Populate variables
font = Graphics.createfont( "Courier new", 12 )
myTimer = Timers.create()
Timers.start myTimer
isRunning = True
Set ball = New Object
Call ball.initialize( mouse.x, mouse.y, 0, 0, BALL_MASS, BALL_SIZE )
' The main loop
Do While isRunning
' Get change in time since last call
dt = Timers.splitTime( myTimer )
totalTime = Timers.appTime( myTimer )
' Exit if window closed or escape pressed
If Key.pressed(vk_escape) Or Key.pressed(vk_windowx) Then isRunning = False
' React on mouse
mouse.update
If Mouse.LeftButton Then
ball.pos.x = mouse.x
ball.pos.y = mouse.y
ball.vel.x = -mouse.dx / dt ' These should not be negated but there is a bug in B2D v.1.7
ball.vel.y = -mouse.dy / dt
ElseIf Mouse.RightButton Then
Else
mouse.dx
mouse.dy
End If
' Update ball's position by moving it the required amount given the time passed
Call ball.addAcc( 0, 9.8 * 100 ) ' 100 pixels i say here is 1 meter. Gravity constant is 9.8
' Air resistance by adding force in opposite direction of the velocity
Call ball.addForce( -ball.vel.x, -ball.vel.y )
' Update ball physics
Call ball.update( dt )
' Possible pre-calculation of ball bounciness (used if ball is on edge of screen)
Dim newLength : newLength = ball.vel.length() * BOUNCE_FRICTION
' Avoid possible jittering when movement is very little
If newLength < 45 Then
newLength = 0
End If
' Bounce ball at edge of screen
If ball.pos.x < 0 Then
ball.pos.x = -ball.pos.x
ball.vel.x = -ball.vel.x
ball.vel.setLength( newLength )
ElseIf ball.pos.x >= WIDTH Then
ball.pos.x = ball.pos.x - (ball.pos.x-WIDTH)
ball.vel.x = -ball.vel.x
ball.vel.setLength( newLength )
End If
If ball.pos.y < 0 Then
ball.pos.y = -ball.pos.y
ball.vel.y = -ball.vel.y
ball.vel.setLength( newLength )
ElseIf ball.pos.y >= HEIGHT Then
ball.pos.y = ball.pos.y - (ball.pos.y-HEIGHT)
ball.vel.y = -ball.vel.y
ball.vel.setLength( newLength )
End If
' Draw the circle to the canvas (instead of screen)
graphics.renderimage canvas
Graphics.setrect 0, 0, WIDTH, HEIGHT, argb(25,10,10,10)
graphics.setcircle ball.pos.x, ball.pos.y, ball.size, argb(255,255,255,255)
graphics.rendernormal
' Draw canvas on screen
graphics.clear
graphics.setimage canvas
' Write some user feedback
Graphics.settext "FPS: " & graphics.fps & " (" & formatnumber( dt, 3 ) & ")", 10, 10, font, argb(255,255,255,255)
Graphics.settext "Pos: " & formatnumber( ball.pos.x ) & " " & formatnumber( ball.pos.y ), 10, 24, font, argb(255,255,255,255)
Graphics.settext "Vel: " & formatnumber( ball.vel.x ) & " " & formatnumber( ball.vel.y ), 10, 38, font, argb(255,255,255,255)
Graphics.settext "100 pixels = 1 meter", 10, 52, font, argb(255,255,255,255)
' Display buffer on screen
graphics.display
Do
system.processMessages
Loop While totalTime + 0.01 > Timers.appTime( myTimer )
Loop
' Clean up
Mouse.terminate
Key.terminate
Graphics.terminate