0

I've tried everything and cannot get how I check if my two blocks have collided.

Here's my code:

import pygame
import random
pygame.init()

display_width = 600
display_height = 300

class player:#Just info for player
    width = 30
    height = 30
    x = display_width // 2
    y = display_height - height - 5
    a = x + 30
    pic = 'SnakePart.png'
    thing = pygame.image.load(pic)
    def place(x,y):#function for placing player object
        gameDisplay.blit(player.thing, (player.x,player.y))
class enemy:#enemy info class
    width = 30
    height = 30
    x = random.randint(0,display_width - width)
    y = 1
    a = x + 30
    pic = 'Apple.png'
    thing = pygame.image.load(pic)
    speed = 10#sets speed
    def change_x():
        enemy.x = random.randint(0,display_width - enemy.width)
    def change_y():
        enemy.y += enemy.speed
    def make(x,y):#set up funtion
        gameDisplay.blit(enemy.thing, (x,y))
    def respawn():#reseting enemy entity
        enemy.y = 1
        gameDisplay.blit(enemy.thing, (enemy.x,enemy.y))
player.thing#uses the variables in the classes to set up the images for use
enemy.thing

black = (0,0,0)
white = (255,255,255)


player_height = 30
player_width = 30

clock = pygame.time.Clock()

x_change = 0#This is to make movment

gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Bullet Hell.')

dodged = 0#counter will be used in the more polished vesion.

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        if event.type == pygame.KEYDOWN:#Checks for keypress, to make player entity move
            if event.key == pygame.K_RIGHT:
                x_change = 5
            if event.key == pygame.K_LEFT:
                x_change = -5
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT or pygame.K_LEFT:
                x_change = 0

    player.x += x_change
    gameDisplay.fill(black)
    enemy.make(enemy.x,enemy.y)
    player.place(player.x,player.y)
    enemy.change_y()
    if enemy.y > display_height:#Brings enemy back to top once it has gotten to th bottom
        enemy.change_x()
        dodged += 1
        enemy.respawn()
    pygame.display.update()
    clock.tick(60)

It's all really the collision and I think I'll be good. Oh yeah, if you guys could also tell me how to display text that would be great!

skrx
  • 19,980
  • 5
  • 34
  • 48
  • Regarding the text rendering, don't ask two questions at the same time here, and check out this question: https://stackoverflow.com/questions/10077644/python-display-text-w-font-color – skrx Oct 19 '17 at 07:36
  • Your code is wrong in many places and uses questionable programming techniques (like having class attributes for something that clearly should be instance attribute, and etc). Always make sure that your code works (unless you're asking about a bug/error) and that you have a fundamental understanding of your code before asking a question. Otherwise all answers will be incomprehensive and most likely only be used as a copy paste solution. – Ted Klein Bergman Oct 19 '17 at 08:38
  • It does work though. Could you not get it to run? The SnakePart and Apple are just a green a red cube. – Raymond Prince Oct 19 '17 at 13:26

1 Answers1

0

Take a look at the pygame.Rect class and its collision detection methods. Give your objects rects as attributes which you get by calling the .get_rect() method of the images/surfaces. Update the coordinates of these rects each frame and in your main loop call player.rect.colliderect(enemy.rect) to check if the two rects collide.

import pygame
import random


pygame.init()

BLACK = pygame.Color('black')

display = pygame.display.set_mode((600, 300))
# Create a rect with the dimensions of the screen at coords (0, 0).
display_rect = display.get_rect()
clock = pygame.time.Clock()

# SNAKE_IMAGE = pygame.image.load('SnakePart.png').convert_alpha()
# APPLE_IMAGE = pygame.image.load('Apple.png').convert_alpha()
# Replacement images.
SNAKE_IMAGE = pygame.Surface((30, 30))
SNAKE_IMAGE.fill((30, 150, 0))
APPLE_IMAGE = pygame.Surface((30, 30))
APPLE_IMAGE.fill((150, 30, 0))


class Player:

    def __init__(self):
        self.x = display_rect.w // 2
        self.y = display_rect.h - 30 - 5
        self.image = SNAKE_IMAGE
        # Create a rect with the size of the image at coords (0, 0).
        self.rect = self.image.get_rect()
        # Set the topleft coords of the rect.
        self.rect.x = self.x
        self.rect.y = self.y
        self.x_change = 0

    def update(self):
        """Move the player."""
        self.x += self.x_change
        # Always update the rect, because it's
        # needed for the collision detection.
        self.rect.x = self.x

    def draw(self, display):
        display.blit(self.image, self.rect)


class Enemy:

    def __init__(self):
        self.x = random.randint(0, display_rect.w - 30)
        self.y = 1
        self.image = APPLE_IMAGE
        # You can also pass the coords directly to `get_rect`.
        self.rect = self.image.get_rect(topleft=(self.x, self.y))
        self.speed = 10

    def change_x(self):
        self.x = random.randint(0, display_rect.w - self.rect.w)
        self.rect.x = self.x

    def change_y(self):
        self.y += self.speed
        self.rect.y = self.y

    def draw(self, display):
        display.blit(self.image, self.rect)

    def reset(self):
        """Reset self.y position."""
        self.y = -30


player = Player()
enemy = Enemy()
dodged = 0
done = False

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_RIGHT:
                player.x_change = 5
            if event.key == pygame.K_LEFT:
                player.x_change = -5
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_RIGHT or pygame.K_LEFT:
                player.x_change = 0

    # Game logic.
    player.update()
    enemy.change_y()
    # Brings enemy back to top once it has gotten to th bottom
    if enemy.y > display_rect.h:
        enemy.change_x()
        dodged += 1
        enemy.reset()

    # Check if the player and the rect collide.
    if player.rect.colliderect(enemy.rect):
        print('Collided!')

    # Draw everything.
    display.fill(BLACK)
    enemy.draw(display)
    player.draw(display)

    pygame.display.update()
    clock.tick(60)

pygame.quit()

I've changed some more things (btw, better call the images self.image not thing ;)) especially in the classes:

The attributes of the classes should be in __init__ methods to make them instance attributes instead of class attributes (which get shared by all instances). Also, check out how to create instances of your classes.

The methods should all have self as their first parameter (that's a reference to the instance). To access the attributes inside of the classes prepend them with self, e.g. self.x += self.x_change.

The player.x += x_change line fits better inside the Player class' update method, so you can just update the position and other player attributes by calling player.update().

There's a convention that class names should be uppercase MyClass whereas instances should have lowercase names my_instance.

skrx
  • 19,980
  • 5
  • 34
  • 48
  • I recommend to check out chapter 12 and 13 of [Program Arcade Games](http://programarcadegames.com/index.php?chapter=introduction_to_classes&lang=de#section_12) about classes and pygame sprites. – skrx Oct 19 '17 at 07:32
  • Oh, yeah, the 'thing' variable... I only did that in fear because of 'pygame.image.load()' and because im new to programming with pygame there was bound to be a lot of mess ups. P.S. I taught myself how to code. And the funny part is that I tried to use math... didn't end well. – Raymond Prince Oct 19 '17 at 13:29