Help needed- asteroids collision detection

I am working on a school assignment where we are making “Asteroids” in processing.py
My school uses a slightly modified version of processing.py: for example, mouseX is mouse.x. I need help with my collision detection with the asteroids, which is off

from processing import *
from math import *
from random import *

width, height, pi, lList, aList, mag = 555, 500, 3.14159265359, [], [], 0.05

class P:
    def __init__(self, x, y, r):
        self.cor, self.r, self.rad, self.r_1, self.r_2 = PVector(x, y), r, 0, 160, 150
    def drawPlayer(self):
        stroke(255)
        noFill()
        pushMatrix()
        translate(self.cor.x, self.cor.y)
        pl.rad = atan2(mouse.y - self.cor.y, mouse.x - self.cor.x)
        rotate(self.rad + pi / 2)
        triangle(-self.r, self.r, self.r, self.r, 0, -self.r);
        popMatrix()    
        
class A:
    def __init__(self, x, y, r, t, vel_x, vel_y):
        self.cor, self.r, self.t, self.o, self.vel, self.f = PVector(x, y), r, t, [], PVector(vel_x, vel_y), False
        self.o = [randint(-15, 15) for i in range(0, self.t)]
        
    def drawObstacle(self):
        noFill()     
        pushMatrix()
        translate(self.cor.x, self.cor.y)
        beginShape()

        for i in range(0, self.t):
            angle = map(i, 0, self.t, 0, pi * 2)
            r = self.r + self.o[i]
            vertex(r * cos(angle), r * sin(angle))

        endShape(CLOSE)
        popMatrix()    

    def moveObstacle(self):
        self.cor.x, self.cor.y = self.cor.x + self.vel.x * 0.01, self.cor.y + self.vel.y  * 0.01

        if self.cor.x > width + self.r or self.cor.x < -self.r: self.vel.x = -self.vel.x
        if self.cor.y > height + self.r or self.cor.y < -self.r: self.vel.y = -self.vel.y  
            
        for a in aList: 
            if (self.cor.x + self.r > a.cor.x - a.r and self.cor.x + self.r < a.cor.x + a.r and self.cor.y + self.r > a.cor.y - a.r and self.cor.y + self.r < a.cor.y + a.r):
                self.vel.x, self.vel.y, a.vel.x, a.vel.y = -self.vel.x, -self.vel.y, -a.vel.x, -a.vel.y
            
    def checkRemove(self):       
        if self.f:
            if self.r > 15:
                for i in range(-1, 1): aList.append(A(self.cor.x - i * self.r, self.cor.y + i * self.r, randint(5, int(self.r * 0.75)), int(self.r * 0.25), randint(-50, 50), randint(-50, 50)))
                                
class L:
    def __init__(self, x, y, vel_x, vel_y):
        self.cor, self.vel, self.f = PVector(x, y), PVector(vel_x, vel_y), False
    
    def drawLaser(self):
        if dist(self.cor.x, self.cor.y, pl.cor.x, pl.cor.y) > pl.r: ellipse(self.cor.x, self.cor.y, 5, 5)
    
    def moveLaser(self):
        self.cor.x, self.cor.y = self.cor.x + self.vel.x, self.cor.y + self.vel.y
        if self.f and self.cor.x > width or self.cor.x < 0 or self.cor.y > height or self.cor.y < 0: self.f = True
        
    def checkRemove(self):
        for a in aList:
            if dist(self.cor.x, self.cor.y, a.cor.x, a.cor.y) < a.r: self.f, a.f = True, True
        
def setup():
    global pl
    size(width, height)
    pl = P(width / 2 - 15, height / 2 - 15, 15)
    
    for i in range(5): aList.append(A(randint(0, width), randint(0, height), randint(15, 50), randint(5, 15), randint(-50, 50), randint(-50, 50)))
    
def draw():
    background(0)
    pl.drawPlayer()    
    
    for a in aList: 
        a.drawObstacle()
        a.moveObstacle()
        a.checkRemove()
        if a.f: aList.remove(a)

    for l in lList:
        l.drawLaser()
        l.moveLaser()
        l.checkRemove()
        if l.f: lList.remove(l)

def mouseClicked():
    for i in range(0, 2, 2): lList.append(L(pl.cor.x, pl.cor.y, pl.r_1 * cos(pl.rad + 0.1 * i) * 0.05, pl.r_1 * sin(pl.rad + 0.1 * i) * 0.05))
            
def keyPressed():
    if keyboard.keyCode == UP and dist(pl.cor.x, pl.cor.y, mouse.x, mouse.y) > pl.r: pl.cor.x, pl.cor.y = pl.cor.x + (pl.r_2 * cos(pl.rad) * mag), pl.cor.y + (pl.r_2 * sin(pl.rad) * mag)
    
run()
1 Like

Welcome, commie630!

The laser-asteroid collisions and asteroid-asteroid collisions appear to work fine, so I assume that you’re referring to player-asteroid collisions?

As this is a school assignment, I’m going to avoid giving you any code :speak_no_evil:. But I’ll give you a hint –

The following lines detect asteroid-asteroid collisions:

        ...

        for a in aList: 
            if (self.cor.x + self.r > a.cor.x - a.r and self.cor.x + self.r < a.cor.x + a.r and self.cor.y + self.r > a.cor.y - a.r and self.cor.y + self.r < a.cor.y + a.r):
                ...

Think about how you can use an adapted version of this to detect player-asteroid collisions.

1 Like

I’m still going to code the player asteroid collisions- what I am mainly referring to is the asteroid-asteroid collisions which are off. Since the asteroids are spheres, I tried using collision detection between circles, which proved to work only sometimes.

I moved the collision detection to the draw loop. I’m drawing circles to visualize each collider. Each time there’s a collision, Processing draws a line between the centers of each circle:

    ...
    def moveObstacle(self):
        self.cor.x, self.cor.y = self.cor.x + self.vel.x * 0.01, self.cor.y + self.vel.y  * 0.01

        if self.cor.x > width + self.r or self.cor.x < -self.r: self.vel.x = -self.vel.x
        if self.cor.y > height + self.r or self.cor.y < -self.r: self.vel.y = -self.vel.y  
        '''
        for a in aList: 
            if (self.cor.x + self.r > a.cor.x - a.r and self.cor.x + self.r < a.cor.x + a.r and self.cor.y + self.r > a.cor.y - a.r and self.cor.y + self.r < a.cor.y + a.r):
                self.vel.x, self.vel.y, a.vel.x, a.vel.y = -self.vel.x, -self.vel.y, -a.vel.x, -a.vel.y
        '''
...

def draw():
    background(0)
    pl.drawPlayer()    
    
    for a in aList: 
        # visualize collider
        stroke(0x88FFFF00)
        circle(a.cor.x, a.cor.y,  a.r*2)
        
        for b in aList:
            distance = dist(a.cor.x, a.cor.y + a.r, b.cor.x, b.cor.y + a.r)
            # rebound if collision detected
            if distance > 0 and distance < a.r + b.r:
                stroke(0x8800FF00)
                line(a.cor.x, a.cor.y, b.cor.x, b.cor.y)
                b.vel *= -1
                # for calculating accurate rebound angles, checkout:
                # https://processing.org/examples/circlecollision.html
        
        strokeWeight(1)
        stroke('#FFFFFF')
        
        a.drawObstacle()
        ...

It seems to work okay, and you get a better visual sense of what’s happening (to help with debugging). You’ll need to add some code to your game that prevents asteroids from spawning on top of one another.

I’ve included a comment with a reference for getting your rebound angles accurate (if this is important to you). For greater accuracy, you could look at using a physics library.

1 Like