# Collision Detection Between Rectangles

Page 1 of 1

## 3 Replies - 6455 Views - Last Post: 12 October 2011 - 09:25 AMRate Topic: //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'http://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=250857&amp;s=62aeaf60a43ba5f5c8f3d73f66d81c6d&md5check=' + ipb.vars['secure_hash'], cur_rating: 0, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

### #1 Airi-n

Reputation: 0
• Posts: 7
• Joined: 24-September 11

# Collision Detection Between Rectangles

Posted 11 October 2011 - 03:53 PM

I'm working on a program where a cannonball is shot from a cannon and that part works, but I now had to put in a target (which I did), but I'm having problems with getting the reaction I want for when the ball collides with the target. For now, I just made the collision method take in a few extra parameters such as the window to just draw a blue square somewhere on the screen for now before implementing what it needs to do, which is make the target disappear (I'm not sure how to do that either, and that's why I just went for something I do know how to do just for testing).

I've implemented code for it in the Target and Gui classes, but I'm posting the code for the other classes (minus the game_controller file that just runs the game) since the cannonball and the target have to interact with each other in some way.

```from cannonball import Cannonball
import math

class Cannon():
'''
Makes a cannon for the active cannonball
'''

def __init__(self, x_pos, y_pos, velocity, angle_degrees):
'''
Initializes the x position, y position, launch velocity, and launch angle in degrees
'''
self.x_pos = x_pos
self.y_pos = y_pos
self.velocity = velocity
self.angle = (math.pi * angle_degrees) / 180.0

self.active_cannonball = None

def fire(self, time_interval):
'''
Shoots the cannon, initializes the active cannonball with the x position, y position,
angle, velocity, and time interval so that it can move on its path
'''
self.active_cannonball = Cannonball(self.x_pos, self.y_pos, self.angle, self.velocity, time_interval)
```

```import math

class Cannonball(object):
'''
Represents the cannonball that will be shot out of the cannon
'''

def __init__(self, x_pos, y_pos, angle, velocity, time_interval):
'''
Initializes the instance variables, calculates the horizontal distance that the ball travels at,
and sets the ball's status to 'flying'
'''

self.x_pos = x_pos
self.y_pos = y_pos
self.x_velocity = velocity * math.cos(angle)
self.y_velocity = velocity * math.sin(angle)
self.time_interval = time_interval
self.x_delta = self.time_interval * self.x_velocity
self.is_flying = True

def move(self):
'''
Changes the ball's x and y location using the formulas for ballistic trajectory.
'''

prev_y_velocity = self.y_velocity
self.y_velocity = self.y_velocity - (9.8 * self.time_interval)
self.y_pos = (self.y_pos + (self.time_interval * ((prev_y_velocity + self.y_velocity)/2)))
self.y_pos = max(self.y_pos, 0)
self.x_pos += (self.x_delta)
self.is_flying = (self.y_pos > 0)

```

```import pygame
from cannonball import Cannonball

'''
Created on Oct 10, 2011

@author: Ilene Peguero
'''

class Target(object):
'''
Represents the target to be hit by the cannonball
'''

BLUE = (0, 0, 255)

def __init__(self, height, width, x_pos, y_pos):
'''
Constructor
'''
self.height = height
self.width = width
self.x_pos = x_pos
self.y_pos = y_pos

def collision_detect(self, cannonball, cannonball_rect, target_rect, window):
if cannonball_rect.colliderect(target_rect):
pygame.draw.rect(self.window, Target.BLUE, 100, 100, 30, 30)

```

```class FireController(object):
'''
Controller for the method fire in cannon, which shoots the cannon and moves the cannonball
through its trajectory
'''

def __init__(self, cannon, time_interval):
'''
Initializes the cannon with specified values
'''
self.cannon = cannon
self.time_interval = time_interval

def fire_cannon(self):
'''
Tells the cannon to shoot and sets active cannonball to the one being shot by the cannon
'''
self.cannon.fire(self.time_interval)
self.active_cannonball = self.cannon.active_cannonball

def move_cannonball(self):
'''
Tells the cannonball to move to the next position in its trajectory
'''
self.active_cannonball.move()
```

```import pygame
from cannon import Cannon
from target import Target
from fire_controller import FireController

class Gui():
'''
Gui defines the GUI for the cannon shooting game
'''

BLACK = (0, 0, 0)
GRAY = (105, 105, 105)
GRASS_COLOR = (77, 189, 51)
SKY_BLUE = (0, 191, 255)
RED = (255, 0, 0)

def __init__(self, width, height, velocity, angle, time_interval):
'''
Creates the display surface, the window title, and the instance variables
'''

self.width = width
self.height = height
self.velocity = velocity
self.angle = angle
self.time_interval = time_interval
self.ground_y = self.height - 50

self.window = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption("Cannonball Shooting Game")

self.cannon = Cannon(x_pos=50, y_pos=0, velocity=self.velocity, angle_degrees=self.angle)
self.active_cannonball = None

self.fire_controller = FireController(self.cannon, self.time_interval)

self.target = Target(30, 30, 1050, self.ground_y - 25)

self.cannonball_rect = None
self.target_rect = None

def display_grass(self):
'''
Draws the grass
'''
ground_start_pos = (0, self.ground_y + 50)
ground_end_pos = (self.width, self.ground_y + 50)
pygame.draw.line(self.window, Gui.GRASS_COLOR, ground_start_pos, ground_end_pos, 100)

def display_cannon(self):
'''
Draws the cannon as a thick gray line with a black circle as its wheel
'''
barrel_start_pos = (round(self.cannon.x_pos), round(self.cannon.y_pos + self.ground_y))
barrel_end_pos = (round(self.cannon.x_pos + 20), round(self.cannon.y_pos + self.ground_y - 20))

pygame.draw.line(self.window, Gui.GRAY, barrel_start_pos, barrel_end_pos, 10)

wheel_pos = (self.cannon.x_pos + 4, self.cannon.y_pos + self.ground_y)

pygame.draw.circle(self.window, Gui.BLACK, wheel_pos, 7)

def display_cannonball(self):
'''
Draws the cannonball as a black circle
'''
ball_pos = (round(self.active_cannonball.x_pos), round(self.ground_y - self.active_cannonball.y_pos))

pygame.draw.circle(self.window, Gui.BLACK, ball_pos, 4)

rect_pos = (round(self.active_cannonball.x_pos), round(self.ground_y - self.active_cannonball.y_pos),
5, 5)
self.cannonball_rect = pygame.draw.rect(self.window, Gui.BLACK, rect_pos)

def display_target(self):
'''
Draws the target as a red square
'''
target_pos = (self.target.x_pos, self.target.y_pos, self.target.height, self.target.width)
self.target_rect = pygame.draw.rect(self.window, Gui.RED, target_pos)

def display(self):
'''
Draws the grass, cannon, and if it has been initialized, the cannonball
'''
self.window.fill(Gui.SKY_BLUE)
self.display_grass()
self.display_cannon()
self.display_target()
if self.active_cannonball:
self.display_cannonball()
pygame.display.flip()

def handle_move_cannonball_event(self):
'''
Tells the controller to move the cannonball until it is not flying
'''
while self.active_cannonball.is_flying:
self.fire_controller.move_cannonball()
self.display()

def handle_fire_event(self):
'''
Tells the controller to fire the cannon, which creates the active cannonball
'''
self.fire_controller.fire_cannon()
self.active_cannonball = self.cannon.active_cannonball

def handle_target_collision_event(self):
while self.active_cannonball.is_flying == False:
self.target.collision_detect(self.active_cannonball, self.cannonball_rect, self.target_rect, self.window)

def run(self):
'''
Executes the animation loop, handling the "fire cannon" and "move
active cannonball" events. Exits when the user clicks the quit button.
'''
self.display()

keepPlaying = True

while keepPlaying:
for event in pygame.event.get():
if event.type == pygame.QUIT:
keepPlaying = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_f:
self.handle_fire_event()
self.handle_move_cannonball_event()

```

If anyone can help me out with this problem, I'd really appreciate it, as I have no idea what other angle to take on this.

Is This A Good Question/Topic? 0

## Replies To: Collision Detection Between Rectangles

### #2 Martyr2

• Programming Theoretician

Reputation: 4925
• Posts: 13,317
• Joined: 18-April 07

## Re: Collision Detection Between Rectangles

Posted 11 October 2011 - 04:19 PM

So you now have a move method that moves your cannonball through its trajectory. Great! Now for each movement through the air we have to detect if the cannonball has come into contact with any targets. Right now we have one, but the idea would be to allow a given cannonball to detect if it has run into any one of a number of targets.

One way you might approach this is simply store a list of target rectangles. Then as the ball moves, you give the current cannonball instance to a function which will run a colliderect against it and each target in the list. If any of them come back true, a collision has been detected and you can have it fire off a function which will set off the animation of the target being destroyed (passing the function the actual target instance so it knows which one to destroy).

In short....

1) Move cannonball one space
2) Give cannonball instance to function which loops through targets looking for a collision between the ball and one of the targets.
3) If collision found, give target to some animation function to destroy that target. (And stop or destroy the cannonball)

So the idea here is that for a thousand points in the trajectory you are checking "Did I hit something?" If you didn't, you continue on your merry way.

Targets in the list of targets may include the ground, other balls, enemy ship, wall etc.

Since you focus on one target, put that single target in a list, pass the cannonball object in motion to it, check with colliderect to see if the two hit one another and if they do, call your animation to destroy target. Stop cannonball's motion.

This post has been edited by Martyr2: 11 October 2011 - 04:20 PM

### #3 Airi-n

Reputation: 0
• Posts: 7
• Joined: 24-September 11

## Re: Collision Detection Between Rectangles

Posted 11 October 2011 - 06:21 PM

Thank you for your post After reading what you had said, I changed a bit of my code. I changed the Terget class a bit, changed the display_target and handle_target_collision_event methods from my Gui class, and I'm glad there are no errors, but it still doesn't seem to be doing what it should be doing. I'm still working on it, but I wanted to go ahead and post this update.

```import pygame
from cannonball import Cannonball

class Target(object):
'''
Represents the target to be hit by the cannonball
'''

BLUE = (0, 0, 255)
target_list = []

def __init__(self, height, width, x_pos, y_pos):
'''
Constructor
'''
self.height = height
self.width = width
self.x_pos = x_pos
self.y_pos = y_pos

def collision_detect(self, cannonball, cannonball_rect, window):
'''
if cannonball_rect.colliderect(target_rect):
pygame.draw.rect(self.window, Target.BLUE, 100, 100, 50, 50)
pygame.display()
'''

while cannonball.is_flying:
for target in self.target_list:
if target.colliderect(cannonball_rect) == True:
pygame.draw.rect(self.window, Target.BLUE, 100, 100, 50, 50)
pygame.display()
else:
return False
```

```def display_target(self):
'''
Draws the target as a red square
'''
target_pos = (self.target.x_pos, self.target.y_pos, self.target.height, self.target.width)
self.target_rect = pygame.draw.rect(self.window, Gui.RED, target_pos)
self.target.target_list.append(self.target_rect)

def handle_target_collision_event(self):
self.target.collision_detect(self.active_cannonball, self.cannonball_rect, self.window)
```

### #4 Martyr2

• Programming Theoretician

Reputation: 4925
• Posts: 13,317
• Joined: 18-April 07

## Re: Collision Detection Between Rectangles

Posted 12 October 2011 - 09:25 AM

Honestly I would have probably put the detect on the cannonball class itself (so you can do something like cannonball.collision_detect() to find out if it hit anything), but that code is looking much more promising and I think you will get much more mileage out of it for the future.