-1

I am trying to learn the basics of pygame by making a simple pacman game with a friend, but I have been having trouble figuring out how to make walls and check collision with the pacman and the wall, and also stopping the movement through a wall. (this is a 2 player pacman, ghost is arrow keys, and pacman is wasd)

This is main.py

import pygame
import random
import time
from Pacman import pacman
from Ghost import ghost

#colors
Yellow = (255,255,0)
Blackish_Blue = (20,0,70)
Red = (255,0,0)
P_B = (40,60,100)



clock = pygame.time.Clock()



#display
pygame.init()
pygame.display.set_caption('  Scuffed Pacman')
width, height = 640, 480
screen = pygame.display.set_mode((width, height))

pacman = pacman(screen)
ghost = ghost(screen)


font = pygame.font.Font('freesansbold.ttf', 32)
text = font.render('Game Over', True, Yellow)
textRect = text.get_rect()
textRect.center = (width / 2, height / 2)

run = True
while run == True:
  pygame.time.delay(10)
  clock.tick(60)
  screen.fill(Blackish_Blue)

  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      run = False

  

  
  
  
  color = (182,163,192)
  #attempt to make wall and check collision
  ghostspawn = pygame.Rect(0,0,60,40)
  ghostspawn.center = (width / 2, (height / 2)-50)
  pygame.draw.rect(screen, color, ghostspawn)
  if ghostspawn.collidepoint(pacman.x, pacman.y):
    print("collision detected")
  
  
  pacman.draw(screen)
  ghost.draw(screen)
  ghost.update()
  pacman.update()


  distance = (((pacman.x - ghost.x)**2) + ((pacman.y - ghost.y)**2))**(1/2)
  sumrad = pacman.radius + ghost.radius

  if distance < sumrad:
    while True:
      screen.fill(P_B)
      screen.blit(text, textRect)
      for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        pygame.display.update()
  
  pygame.display.update()

pygame.quit()

This is the code for pacman:

import pygame

Yellow = (255,255,0)
class pacman(pygame.sprite.Sprite):
  def __init__(self, mainscreen):
    super().__init__()
    self.x = 320
    self.y = 240
    self.radius = 15
    self.velocity = 2
    self.origin = (self.x, self.y)
  
  def draw(self, mainscreen):
    pygame.draw.circle(mainscreen, Yellow, (self.x, self.y), self.radius)
  
  
  def update(self):
    self.movement()
    self.origin = (self.x, self.y)
    
  def movement(self):
    keys = pygame.key.get_pressed()

    if keys[pygame.K_d] and self.velocity > 0 and self.x < 625:
        self.x += self.velocity
    if keys[pygame.K_a] and self.velocity > 0 and self.x > 15:
      self.x -= self.velocity
    if keys[pygame.K_w] and self.velocity > 0 and self.y > 15:
      self.y -= self.velocity
    if keys[pygame.K_s] and self.velocity > 0 and self.y < 465:
      self.y += self.velocity

and this is the code for ghost:

import pygame
Red = (255,0,0)
class ghost(pygame.sprite.Sprite):
  def __init__(self, mainscreen):
    super().__init__()
    self.x = 213
    self.y = 240
    self.radius = 15
    self.velocity = 2
    self.origin = (self.x, self.y)
  
  def draw(self, mainscreen):
    pygame.draw.circle(mainscreen, Red, (self.x, self.y), self.radius)
  
  
  def update(self):
    self.movement()
    self.origin = (self.x, self.y)
    
  def movement(self):
    keys = pygame.key.get_pressed()
    if keys[pygame.K_RIGHT] and self.velocity > 0 and self.x < 625:
      self.x += self.velocity
    if keys[pygame.K_LEFT] and self.velocity > 0 and self.x > 15:
      self.x -= self.velocity
    if keys[pygame.K_UP] and self.velocity > 0 and self.y > 15:
      self.y -= self.velocity
    if keys[pygame.K_DOWN] and self.velocity > 0 and self.y < 465:
      self.y += self.velocity

this is my attempt at checking for wall collision, but I am unaware of how to stop pacman and the ghost from going through. the collision also only checks the middle of the circle.

ghostspawn = pygame.Rect(0,0,60,40)
ghostspawn.center = (width / 2, (height / 2)-50)
pygame.draw.rect(screen, color, ghostspawn)
if ghostspawn.collidepoint(pacman.x, pacman.y):
  print("allowed")

here is how i detect collision between pacman and ghost, as it may be helpful for doing it with walls, but i don't know how.

distance = (((pacman.x - ghost.x)**2) + ((pacman.y - ghost.y)**2))**(1/2)
sumrad = pacman.radius + ghost.radius

ive looked at a few similar questions on here, but I can't quite grasp how it works. So, if anyone could help, I'm having trouble with checking collision between a circle and rectangle, and also preventing the circle/pacman from moving through.

  • 1
    Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – another victim of the mouse May 12 '22 at 18:52
  • "ive looked at a few similar questions on here, but I can't quite grasp how it works. So, if anyone could help, I'm having trouble with checking collision between a circle and rectangle, and also preventing the circle/pacman from moving through." Welcome to Stack Overflow. Please read [ask] and try to *ask a specific question*. "I'm having trouble with XYZ" [doesn't qualify](https://meta.stackoverflow.com/questions/284236). Start by removing as much as possible from your program that *isn't* the circle-rectangle collision problem that you are trying to solve; see [mre]. – Karl Knechtel May 12 '22 at 18:53
  • Then, find out these things and tell us: how do you test the resulting program? When you do that, what is supposed to happen? What does happen instead, and how is that different? What is your understanding of why the wrong thing happens? Finally, use a question, starting with a question word like "why" or "how" and ending with a question mark (`?`), to ask us for the specific information you need. – Karl Knechtel May 12 '22 at 18:54
  • "but I am unaware of how to stop pacman and the ghost from going through." Well, try to think about it logically. *Why* does it go through? Because it is *moving in that direction*, right? To fix that, it would have to move in a *different* direction, right? (What direction makes physical sense?) So, when the collision occurs, what should *change* about the object? Alternately, should it *stop*? Slow down? something else? – Karl Knechtel May 12 '22 at 18:57

1 Answers1

0

To check if a circle is colliding with a wall you just need to do 2 things

Get the distance between the circle and the wall

Then check if the distance is smaller or equal to the circles distance

Pretty much like this:

distance = abs(circle.x - wall.x) + abs(circle.y - wall.y)
if distance <= circle.radius: # abs() Makes the value in the brackets positive
    circle.x = oldX
    circle.y = oldY

To implement this I with your game would first add a self.oldX and a self.oldY in the self.__init__() in both of the pacman and ghost classes. And I would set them to 0 for now.

Then I would update the oldX and oldY in the movement function before I move the object, like this:

def movement(self):
    keys = pygame.key.get_pressed()
    self.oldX = self.x
    self.oldY = self.y

    if keys[pygame.K_d] and self.velocity > 0 and self.x < 625:
        self.x += self.velocity
    if keys[pygame.K_a] and self.velocity > 0 and self.x > 15:
        self.x -= self.velocity
    if keys[pygame.K_w] and self.velocity > 0 and self.y > 15:
        self.y -= self.velocity
    if keys[pygame.K_s] and self.velocity > 0 and self.y < 465:
        self.y += self.velocity

Then I would have a list that containes every wall in the game and a list that containes every ghost in the game (That's if you want to have more than one ghost).

Then I would go in the main loop (The while loop that you have) and I would add this After calling the movement function of the ghosts and the pacman:

for wall in walls:
    distance = abs(pacman.x - wall.x) + abs(pacman.y - wall.y)
       if distance <= pacman.radius:
           pacman.x = pacman.oldX
           pacman.y = pacman.oldY

    for ghost in ghosts:
        distance = abs(ghost.x - wall.x) + abs(ghost.y - wall.y)
           if distance <= ghost.radius:
               ghost.x = ghost.oldX
               ghost.y = ghost.oldY

and that should work, Thanks.

ZiyadCodes
  • 379
  • 3
  • 10
  • Thanks! This worked but for only one point. I expanded and made what I think is a very inefficient way to check every point on the rectangle/wall, but it works. – blank blanks May 12 '22 at 23:49