Collisions.

12wwood

New Member
Joined
Mar 5, 2019
Hey guys, im trying to create code that when a bullet in the bullet list collides with one of the swarm objects, they both delete from the list. I have tried many ways of tackling this problem but i can never get it right. could someone give me a hand?
Cerberus X:
Import mojo


Class MyGame Extends App
    Global GameState:String = "Menu"
    Global PlayerLife:Int
    Global PlayerScore:Int
    Global HiScore:Int
    Global GameTime:Int
    Field EndGameTime:Int
    Field Accuracy:Int
    Field PlaneShootNum:Int
    Field Menu:Image
    Field Instruction1:Image
    Field Instruction2:Image
    Field Background:Image
    Field Paused:Image
    Field Player:Plane
    Field Swarm_List:List<Swarm>
    Field Bullet_List:List<Bullet>
    

    

    Method OnUpdate()
    
        Select GameState
            Case "Menu"
                If KeyHit (KEY_1) Then GameState = "Initialise"
                If KeyHit (KEY_2) Then GameState = "Instruction1"
                If KeyHit (KEY_3) Then GameState = "Scoreboard"
                If KeyHit (KEY_4) Then GameState = "Exit"
            Case "Exit"
                Error("you have exited")
            Case "Initialise"
                GameState = "Playing"
            Case "Playing"
                If KeyHit(KEY_P) Then GameState = "Paused"
                If KeyHit(KEY_ENTER) Then GameState = "EndScore"
                If KeyHit(KEY_SPACE) Then Bullet_List.AddLast(New Bullet(Player.X,Player.Y))
                If KeyDown(KEY_A) Then Player.Movement(-6,0)
                If KeyDown(KEY_D) Then Player.Movement(6,0)
                If KeyDown(KEY_W) Then Player.Movement(0,-5)
                If KeyDown(KEY_S) Then Player.Movement(0,5)
                For Local Bullet:=Eachin Bullet_List
                    Bullet.Move(10)
                    If Bullet.Y < 5 Then Bullet_List.Remove Bullet
                Next
            Case "EndScore"
                If KeyHit(KEY_ENTER) Then GameState = "Scoreboard"
            Case "Scoreboard"
                If KeyHit(KEY_ENTER) Then GameState = "Menu"
            Case "Instruction1"
                If KeyHit(KEY_ENTER) Then GameState = "Instruction2"
            Case "Instruction2"
                If KeyHit(KEY_ENTER) Then GameState = "Menu"
            Case "Paused"
                If KeyHit(KEY_2) Then GameState = "Playing"
                If KeyHit(KEY_1) Then GameState = "Menu"
        End       
            
    End
    
    
    Method OnCreate()
        Bullet_List = New List<Bullet>
        Swarm_List = New List<Swarm>
        Swarm_List.AddLast(new Swarm(320,160))
        SetUpdateRate(60)
        Player = New Plane
        Menu = LoadImage("MenuScreen.png")
        Instruction1 = LoadImage("Instruction1.png")
        Instruction2 = LoadImage("Instruction2.png")
        Background = LoadImage("sea_background.png")
        Paused = LoadImage("PausedMenu.png")
    End
    
    
    Method OnRender()
        Cls(0,0,0)
        Select GameState
            Case "Menu"
                DrawImage(Menu,0,0)
            Case "Playing"
                DrawImage(Background,0,0)
                For Local Bullet:= Eachin Bullet_List
                    DrawImage(Bullet.BulletImage,Bullet.X,Bullet.Y)
                Next
                DrawImage(Player.PlayerImage,Player.X,Player.Y)
                For Local enemy:=Eachin Swarm_List
                    DrawImage (enemy.SwarmImage,enemy.X,enemy.Y)
                Next
                DrawText("SCORE"+" "+PlayerScore,8,15,0,0.5)
                DrawText("HI-SCORE"+" "+ HiScore, 320,15,0.5,0.5)
                DrawText("LIVES"+" "+PlayerLife,610,15,0.5,0.5)
            Case "EndScore"
                DrawText("GAME OVER",320,160,0.5,0.5)
                DrawText("SCORE"+" "+PlayerScore, 320,200,0.5,0.5)
                DrawText("HI-SCORE"+" "+HiScore,320,220,0.5,0.5)
                DrawText("PLANES SHOT DOWN"+" "+PlaneShootNum,320,240,0.5,0.5)
                DrawText("% ACCURACY"+" "+Accuracy+"%",320,260,0.5,0.5)
                DrawText("GAME TIME"+" "+EndGameTime,320,280,0.5,0.5)
            Case "Scoreboard"
                DrawText("This Is ScoreBoard",320,240,0.5,0.5)
            Case "Instruction1"
                DrawImage(Instruction1,0,0)
            Case "Instruction2"
                DrawImage(Instruction2,0,0)
            Case "Paused"
            DrawImage(Paused,0,0)
        End
    End
End


Class Plane
    Field PlayerImage:Image = LoadImage("Player.png")
    Field X:Int = 265
    Field Y:Int = 320
    
    Method Movement(X_distance:Int,Y_distance:Int)
    X = X + X_distance
    Y = Y + Y_distance
    If X <= -15 Then X = -15
    If X >= 535 Then X = 535
    If Y <=  60 Then Y = 60
    If Y >= 410 Then Y = 410
    End
End


Class Swarm
    Field SwarmImage:Image = LoadImage("SwarmPlane.png")
    Field X:Int
    Field Y:Int
    
    Method New(X_spawn:Int,Y_spawn:Int)
        X = X_spawn
        Y = Y_spawn
    End
End


Class Bullet
    Field X:Int
    Field Y:Int
    Field BulletImage:Image = LoadImage("Bullet.png",Image.MidHandle)
    
    Method New(X_spawn:Int,Y_spawn:Int)
    X = X_spawn + 37
    Y = Y_spawn - 5
    End
    
    Method Move(Y_distance:Int)
    Y = Y - Y_distance
    End
End


Function Main()
    New MyGame
End
 

Holzchopf

Moderator
Staff member
Joined
Jul 31, 2017
Location
Bern, Switzerland
Basically:

You'll need two nested loops that check all bullets against all swarms, pseudocode:
Cerberus X:
For Local bullet := Eachin bullets
    For Local swarm := Eachin swarms
        If bullet.CollidesWithSwarm( swarm ) Then
            swarms.Remove( swarm )
        Endif
    Next
Next
Next up, you need to implement the CollidesWithSwarm( coll:Swarm ) method that takes a swarm and returns true if they collide. How you check for collision depends on your requirements. You can:
  • do a rectangle-overlap check, by checking if the right edge of the bullet is right of the left edge of the swarm, the left edge of the bullet left of the right edge of the swarm and so on.
  • do a distance check, by calculating the distance between the two objects using Pythagoras and comparing it against the sum of the two objects' radii
  • do some sort of polygon-overlap check
I usually go for the the Pythagoras approach. If your objects are very un-round, you can't use that. But for the start, go with that ;) for simplicity:
Cerberus X:
Local dx := x - coll.x
Local dy := y - coll.y
Local dist := Sqrt( dx*dx + dy*dy )
If dist < SAVEDISTANCE Then Return True

Advanced:

Make a base class for all your object that can potentially collide with each other in the same way. This class has to provide fields for the position and collision radius. And the CollidesWith( coll:MyBaseClass ) method. Then all your Swarms and Bullets extend that base class and if you want to add a new class that must be able to collide with the other objects, that one too extends the base class.
 

12wwood

New Member
Joined
Mar 5, 2019
Basically:

You'll need two nested loops that check all bullets against all swarms, pseudocode:
Cerberus X:
For Local bullet := Eachin bullets
    For Local swarm := Eachin swarms
        If bullet.CollidesWithSwarm( swarm ) Then
            swarms.Remove( swarm )
        Endif
    Next
Next
Next up, you need to implement the CollidesWithSwarm( coll:Swarm ) method that takes a swarm and returns true if they collide. How you check for collision depends on your requirements. You can:
  • do a rectangle-overlap check, by checking if the right edge of the bullet is right of the left edge of the swarm, the left edge of the bullet left of the right edge of the swarm and so on.
  • do a distance check, by calculating the distance between the two objects using Pythagoras and comparing it against the sum of the two objects' radii
  • do some sort of polygon-overlap check
I usually go for the the Pythagoras approach. If your objects are very un-round, you can't use that. But for the start, go with that ;) for simplicity:
Cerberus X:
Local dx := x - coll.x
Local dy := y - coll.y
Local dist := Sqrt( dx*dx + dy*dy )
If dist < SAVEDISTANCE Then Return True

Advanced:

Make a base class for all your object that can potentially collide with each other in the same way. This class has to provide fields for the position and collision radius. And the CollidesWith( coll:MyBaseClass ) method. Then all your Swarms and Bullets extend that base class and if you want to add a new class that must be able to collide with the other objects, that one too extends the base class.
Thanks man, I literally just coded it and it worked perfectly with a couple tweaks to fit my code. you were a massive help.
 
Top Bottom