Code archives/Miscellaneous/2D Collision Physics (bounce)

This code has been declared by its author to be Public Domain code.

Download source code

2D Collision Physics (bounce) by Arska2015
Here is simple bounce physics for asteroids game.

Asteroids game is made by Tibit. http://www.blitzbasic.com/Community/posts.php?topic=48800

Here is package for code and all assets:
https://www.dropbox.com/s/74u5geibos6pm0p/CollisionPhysics.7z?dl=0

All improvements are welcome.
Strict
AppTitle = "Asteroid Wars Example"

Rem

	This is the file of a step by step example of how to make a simple asteroids clone.
	The guide can be found at www.blitzbasic.com - forums - blitzmax - tutorials
	
EndRem



Type TSpaceObject

	Field X#,Y#
	Field XSpeed#,YSpeed#
	Field Direction

	Function Create() EndFunction
	
	Function UpdateAll() EndFunction
	
	Method New() EndMethod
	
	Method Update() EndMethod

	Method Destroy() EndMethod

	Method Draw() EndMethod

End Type

Type TPlayer Extends TSpaceObject

	Global List:TList
	Global Image:Timage

	Field TurnSpeed#
		
	Function Create()
		Local Ship:TPlayer = New TPlayer	 
		If List = Null List = CreateList()
		List.AddLast Ship 'Add Ship Last in List
		
		If Not Image 
			Image = LoadImage("ship.png")
			MidHandleImage( Image )'Center
		EndIf
	EndFunction
	
	Method New()'Starting Values
		X = 300
		Y = 400
	EndMethod
	
	Method Draw()
		SetRotation( Direction )
		DrawImage( Image,X,Y )
	EndMethod

	Method Update()
		Draw()

		'Possible Actions
		Local Up,Down,Left,Right,Fire
		
		'Controls affect actions, Player 1
		If KeyDown(Key_Up) 	  	Up 		= True
		If KeyDown(Key_Down)  	Down 	= True
		If KeyDown(Key_Left)  	Left 	= True
		If KeyDown(Key_Right) 	Right 	= True 
		If KeyDown(Key_Space)  Fire	= True
	
	
		' P H Y S I C S 
		'---------------------------------------
		'Alter these to alter the ships movement
			
			Local Acceleration# 		= 0.04
			Local Friction# 			= 0
			Local TopSpeed# 			= 2.0
			
			Local TurnAcceleration#	= 0.18
			Local TurnFriction#			= 0.0		
			Local TurnMax# 				= 5
	
		'---------------------------------------	
		
								
		'M O V E M E N T  P H Y S I C S
		'--------------------------------------
		'									
		If Up
			'Create a Acceleration Vector and
			'add it to the Speed Vector
			XSpeed:+ Cos(Direction)*Acceleration
			YSpeed:+ Sin(Direction)*Acceleration	
		EndIf
		
		If Down
			'Create a Acceleration Vector and
			'substract it from the Speed Vector
			XSpeed:- Cos(Direction)*Acceleration
			YSpeed:- Sin(Direction)*Acceleration
		EndIf
		
		If Fire TShot.Fire( X, Y, Direction, XSpeed, YSpeed )
		
		'Calculate the length of the Speed Vector
		Local SpeedVectorLength# = Sqr(XSpeed*XSpeed + YSpeed*YSpeed)
		
		If SpeedVectorLength > 0
			'Decrease Speed with Friction if we are moving
			XSpeed:- (XSpeed/SpeedVectorLength)*Friction
			YSpeed:- (YSpeed/SpeedVectorLength)*Friction
		EndIf
		
		If SpeedVectorLength > TopSpeed
			'If we are going beyond the speed barrier then reduce our speed
			'with the amount in which it surpases TopSpeed
			XSpeed:+ (XSpeed/SpeedVectorLength)*(TopSpeed - SpeedVectorLength)
			YSpeed:+ (YSpeed/SpeedVectorLength)*(TopSpeed - SpeedVectorLength)
		EndIf
		
		If X > 800 X = 0
		If Y > 600 Y = 0
		If X < 0 X = 800
		If Y < 0 Y = 600
		
		'Move
		X:+ XSpeed
		Y:+ YSpeed
				
		'Rem 'Visualize the vectors		
		SetRotation 0
		SetColor 255,0,0 'Red 
			DrawLine X,Y,X,Y + YSpeed*50
		SetColor 0,255,0 'Green
			DrawLine X,Y,X+XSpeed*50,Y
		SetColor 0,0,255 'Blue
			'This is the SpeedVector's Length
			'Note that this vector is built by
			'Adding the Red and the Green
			DrawLine X,Y,X+XSpeed*50,Y+YSpeed*50
		SetColor 255,255,255
		'EndRem	
				
		'R O T A T I O N  P H Y S I C S
		'--------------------------------------
		'									
		If Left	TurnSpeed:-TurnAcceleration
		If Right	TurnSpeed:+TurnAcceleration			
		
		'Limit TurnSpeed
		If TurnSpeed >  TurnMax TurnSpeed =  TurnMax
		If TurnSpeed < -TurnMax TurnSpeed = -TurnMax
				
		Direction:+TurnSpeed
		
		If Direction > 360 	Direction:- 360
		If Direction < 0 	Direction:+ 360
		
		'Apply Friction To Rotation
		If TurnSpeed >  TurnFriction	TurnSpeed:- TurnFriction
		If TurnSpeed < -TurnFriction TurnSpeed:+ TurnFriction
		
		'If Friction is Greater than Speed then Stop
		If TurnSpeed < TurnFriction And TurnSpeed > -TurnFriction TurnSpeed = 0
		
	EndMethod

	Function UpdateAll()
		Local Ship:TPlayer
		For Ship = EachIn List
			Ship.Update()
		Next
	EndFunction

End Type

Type TShot Extends TSpaceObject

	Global List:TList
	Global Image:TImage

	Function Fire( X, Y, Direction, XSpeed, YSpeed 	)
		Local Shot:TShot = New TShot	 
		If List = Null List = CreateList()
		List.AddLast Shot
		
		If Not Image'First Time
			Image = LoadImage("bullet2.png")
			MidHandleImage( Image )
		EndIf

		Local ShotSpeed#= 8
		Shot.X 			= X
		Shot.Y 			= Y
		Shot.Direction 	= Direction
		
		'Add Shot Start Speed
		Shot.XSpeed= Cos(Direction)*ShotSpeed + XSpeed
		Shot.YSpeed= Sin(Direction)*ShotSpeed + YSpeed
	EndFunction
	
	Method Draw()
		SetRotation( Direction )
		DrawImage( Image,X,Y )
	EndMethod
	
	Method Update()
		Draw()
		X:+ XSpeed
		Y:+ YSpeed					
		If X > 800 Or Y > 600 Or X < 0 Or Y < 0 Destroy()
	EndMethod

	Function UpdateAll()
		If Not List Return 
		
		Local Shot:TShot
		For Shot = EachIn List
			Shot.Update()
		Next
	EndFunction

	Method Destroy() 
		List.Remove( Self )
	EndMethod
	
EndType	


Type TRock Extends TSpaceObject

	Global List:TList
	Global Image:TImage
	Field Size
	Field Rotation#
	
	Const LARGE  = 3
	Const MEDIUM = 2
	Const SMALL = 1
	
	Function Spawn( X, Y ,Size )
		Local Rock:TRock = New TRock	 
		If Not List List = CreateList()
		List.AddLast Rock
		
		If Not Image'First Time
			Image = LoadImage("asteroid01.png")
			MidHandleImage( Image )
		EndIf
				
		Local RockSpeed# = 0
		Select Size
			Case LARGE'Large		
				RockSpeed = 0.2
			Case MEDIUM'Medium
				RockSpeed = 0.5
			Case SMALL'Small	
				RockSpeed = 1
		EndSelect
		
		Rock.X 			 = X
		Rock.Y 			 = Y
		Rock.Direction 	 = Rand(360)
		Rock.Rotation 	 = Rock.Direction
		Rock.Size 		 = Size
		
		'Add Rock Start Speed
		Rock.XSpeed= Cos(Rock.Direction)*RockSpeed
		Rock.YSpeed= Sin(Rock.Direction)*RockSpeed
	EndFunction
	
	Method Draw()

		Select Self.Size
			Case LARGE		
				SetScale 1.2, 1.2
			Case MEDIUM'Medium
				SetScale 0.8, 0.8
			Case SMALL'Small	
				SetScale 0.4, 0.4
		EndSelect
			
		SetRotation( Rotation )
		Rotation:+0.5
		DrawImage( Image,X,Y )
		SetScale 1,1
	EndMethod
	
	Method Update()
		Draw()
		X:+ XSpeed
		Y:+ YSpeed			
		
		Collision()
				
		If X > 800 X = 0
		If Y > 600 Y = 0
		If X < 0 X = 800
		If Y < 0 Y = 600 	
	EndMethod

	Function UpdateAll()
		If Not List Return 
		
		For Local Rock:TRock = EachIn List
			Rock.Update()
		Next
	EndFunction

	Method Destroy() 
		List.Remove( Self )
	EndMethod
	
	Method Collision()
		Local Radius
		Select Size
			Case LARGE		
				Radius = 100
			Case MEDIUM'Medium
				Radius = 50
			Case SMALL
				Radius = 20
		EndSelect
	
		' Player collision to asteroid
		If TPlayer.list
			For Local Ship:TPlayer = EachIn TPlayer.list
			
				If ImagesCollide(Image, X, Y, 0, ship.image, ship.X, ship.Y, 0)
					
					Local collisionAngle:Float = AngleTO:Float( x, y, Ship.X, Ship.Y )
					Local collisionForce:Float = (XSpeed + YSpeed) - (Ship.XSpeed + Ship.YSpeed)
					If collisionForce < 0 Then collisionForce = collisionForce * - 1
					
					
					Ship.XSpeed:- ( Cos(collisionAngle) / 2)
					Ship.YSpeed:- ( Sin(collisionAngle) / 2)
					
					' If asteroid is small change also it's direction
					If size = SMALL Then
						XSpeed:+ ( Cos(collisionAngle) / 2)
						YSpeed:+ ( Sin(collisionAngle) / 2)
					EndIf
					
				EndIf
				
			Next
		EndIf
	
		
		
		'If a shot hit a rock
		If Not TShot.List Return
		For Local Shot:TShot = EachIn TShot.List
			If Distance( X, Y, Shot.X, Shot.Y ) < Radius
				
				Shot.Destroy()
				
				Select Size
					Case LARGE	
						Destroy()'Destory the rock	
						Spawn( X, Y , MEDIUM )
						Spawn( X, Y , MEDIUM )
					Case MEDIUM
						Destroy()	
						Spawn( X, Y , SMALL )
						Spawn( X, Y , SMALL )
					Case SMALL
						Destroy()'
				EndSelect
	
			EndIf
		Next	
	EndMethod
EndType


Graphics 800,600,0


Const Intro 	= 1
Const Death 	= 2
Const Playing	= 3

Global Mode = Intro
Global Score, HighestScore
Global Level , Rank$

TRock.Spawn( 50,50, TRock.LARGE )
For Local NR = 1 To 20
	TRock.Spawn( 400,300, TRock.SMALL )
Next	

'Main Loop
Repeat' - - - - - - - - - - - - - - - - - 
	
	TShot.UpdateAll()	
	TRock.UpdateAll()
	
	Select Mode

		Case Intro
		
			DrawText "Welcome to Asteroids Wars Beta Version",50,100
			
			DrawText "Highest Score this run: "+HighestScore+" rocks.",50,130
			
			DrawText "Steer with LEFT, RIGHT      ",50,170
			DrawText "Thrust with UP and DOWN     ",50,190
			DrawText "Fire with SPACE             ",50,210
			
			DrawText " ---------  P R E S S   S P A C E   T O  S T A R T  ---------- ",50,260
		
			If KeyHit(Key_Space) StartGame()
			
		Case Playing
			DrawText "Score: "+Score, 20, 20
			TPlayer.UpdateAll()
			If TPlayer.List.Count() = 0 
				Mode = Death
				GetRanking()
				Level = 0
				FlushKeys
			EndIf
			If TRock.List.Count() = 0 StartGame()
			
			
		Case Death
		
			DrawText "~~ You Lost Your Ship - G A M E  O V E R ~~ ",50,100
			
			DrawText "You managed to destroy "+Score+" rocks in "+level+" different zones.",50,130
			
			DrawText "------------------------  ",50,170
			DrawText " Your RANK : "+Rank$		 ,50,190
			DrawText "------------------------  ",50,210
			
			DrawText " ---------  P R E S S  [R]  T O   R E T R Y  ---------- ",50,260					
			
			If KeyHit(KEY_R) Mode = Intro
		
	EndSelect	
			
Flip
Cls
		If KeyHit(Key_Q) End
Until KeyHit(Key_Escape)'- - - - - - - - 
End 
Function StartGame()
	
	If TRock.List.Count() > 0 'First Time
		'Clear
		For Local Rock:TRock = EachIn TRock.List
			Rock.Destroy()
		Next
			
		'Start
		TPlayer.Create()

	Else'In play
	
		Level:+1
		Score:+13		

	EndIf
		
	CreateRocks()
	
	Mode = Playing
						
EndFunction

Function CreateRocks()

	Local Danger = Level*20 + Rand(0,10)
	Local Ship:TPlayer = TPlayer( TPlayer.List.First() )
		
	Repeat 
	
		Local X,Y	
		
		Repeat 
			X = Rand(0,800)
			Y = Rand(0,600)	
		Until Distance(Ship.X, Ship.Y, X, Y ) > 200

		Select Rand(1,2)		
			Case 1
				TRock.Spawn( X, Y, TRock.LARGE )  ;Danger:- 5
			Case 2
				TRock.Spawn( X, Y, TRock.MEDIUM ) ;Danger:- 3
		EndSelect	
			
	Until Danger <= 0
	
EndFunction

Function GetRanking()

	Rank$ = "Classified"
	If Level = 1 Rank = "You didn't get a single one?!" 		
	If Level = 1 Rank = "ROFL" 
	If Level = 2 Rank = "LOL"	
	If Level = 3 Rank = "Newbie"
	If Level = 4 Rank = "Beginner"
	If Level = 5 Rank = "Average"
	If Level = 6 Rank = "Fair"
	If Level = 7 Rank = "Almost got one"	
	If Level = 8 Rank = "Starfighter"
	If Level = 9 Rank = "Rock Destroyer"
	If Level = 10 Rank = "Duplicator"
	'...
	'....
	
	HighestScore = Score
EndFunction

Function Distance#( X1, Y1, X2, Y2 )
	Local DX# = X2 - X1
	Local DY# = Y2 - Y1
	Return Sqr(Dx*Dx + Dy*Dy)
EndFunction

Function AngleTO:Float(X1:Float, Y1:Float, X2:Float, Y2:Float)
	Local dx:Float=x2-x1
	Local dy:Float=y2-y1
	Local Angle:Float=(ATan2(dy,dx)) + 180
	
	If Angle>0 Then
		While(Angle>= 360)
			Angle:-360
		Wend
	ElseIf Angle<0 Then
		While(Angle<0)
			Angle:+360
		Wend
	End If
	Return Angle 
End Function

Comments

None.

Code Archives Forum