0

I know this question has been asked multiple times but I just cant wrap my head around the concept of collisions, now I know I am asking a lot but I will appreciate it greatly!, All I ask is someone to add collisions to my game and explain each step so I can try to understand whats going on,I tried youtube videos and they aren't explained very well or I just get overwhelmed which is what I feel right now, So I just want the player to stop when hitting the tree, something as simple as that! And if possible I want it to get the collision from a list for example I would have trees and other images in the list.

import pygame
import sys
import math
from pygame.locals import *
import tiles_list

pygame.init()
display_w = 800
display_h = 600

window = pygame.display.set_mode((display_w, display_h), HWSURFACE | DOUBLEBUF | RESIZABLE)
pygame.display.set_icon(pygame.image.load("game_icon.png"))
pygame.display.set_caption("Work in progress")
clock = pygame.time.Clock()
background = pygame.image.load("background.png")


class Player(object):
    """The controllable player in game"""

    def __init__(self, x, y, width, height, speed):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.image = pygame.image.load("sprite_sheet.png")
        self.speed = speed
        self.timer = 0
        self.frames = 1
        self.direction = 2

    def animation(self):
        x_coord = 50 * self.frames
        y_coord = 50 * self.direction
        self.character = self.image.subsurface(x_coord, y_coord, self.width, self.height)

        self.timer += 0
        if self.timer >= 10:
            self.timer = 0
            self.frames += 1
            if self.frames >= 9:
                self.frames = 1

    def draw(self):
        window.blit(self.character, (self.x, self.y))
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)

    def movement(self):
        self.keys = pygame.key.get_pressed()
        if self.keys[pygame.K_LEFT] or self.keys[pygame.K_a]:
            self.x -= self.speed
            self.direction = 1
            self.timer += 2
        if self.keys[pygame.K_RIGHT] or self.keys[pygame.K_d]:
            self.x += self.speed
            self.direction = 3
            self.timer += 2
        if self.keys[pygame.K_UP] or self.keys[pygame.K_w]:
            self.y -= self.speed
            self.direction = 0
            self.timer += 2
        if self.keys[pygame.K_DOWN] or self.keys[pygame.K_s]:
            self.y += self.speed
            self.direction = 2
            self.timer += 2
        if self.x >= 780:
            self.x = 780
            self.frames = 0
        if self.y >= 555:
            self.y = 555
            self.frames = 0
        if self.x <= 0:
            self.x = 0
            self.frames = 0
        if self.y <= 0:
            self.y = 0
            self.frames = 0


player = Player(400, 300, 50, 50, 4.5)


class Tree:
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.image = (
            pygame.transform.scale(tiles_list.tiles.subsurface(pygame.Rect(99, 147, self.width, self.height)),
                                   (62, 82)))

    def draw(self):
        window.blit(self.image, (self.x, self.y))


tree = Tree(348, 300, 42, 62)

running = True
while running:
    window.blit(background, (0, 0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == VIDEORESIZE:
            screen = pygame.display.set_mode((event.w, event.h), RESIZABLE)
        elif event.type == pygame.KEYUP:
            if player.keys:
                player.frames = 0

    dist_x = math.hypot(tree.x - player.x)
    dist_y = math.hypot(tree.y - player.y)  # Does nothing except calculate the distence
    print("distx", dist_x, "disty", dist_y)

    tree.draw()
    player.movement()
    player.animation()
    player.draw()

    clock.tick(60)
    pygame.display.flip()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Dragon20C
  • 307
  • 2
  • 11
  • why dont you use dist_x and dist_y if they are = 0 then your required thing. Or else you can check when they come to same pixel range – DARK_C0D3R May 23 '20 at 17:30
  • How would I stop the movement of the character setting x or y to 0 would just teleport the sprite to the top left corner and also this wouldnt be accurate enough and clipping would happen, I did think about using it but I have no idea on what to do with it – Dragon20C May 23 '20 at 17:49
  • See [How to detect collisions between two rectangular objects or images in pygame](https://stackoverflow.com/questions/63561028/how-to-detect-collision-between-two-images-in-pygame/63561152#63561152) – Rabbid76 Oct 14 '20 at 10:02

2 Answers2

0

I am willing to explain you the process of collisions. In your game you have two objects - the tree and the player. So, you can say that if the x and y coordinates of the player are the same , then there occurs a collisions. You can use this concept and create variables for detecting collisions. Thanks

  • 1
    I understand the concept of when it reaches 0 stop movement but the x and y are only one point on the screen meaning it would clip how would I get a rectangle instead of a dot, I guess I should of said how the game looks, its like a pokemon game style. – Dragon20C May 23 '20 at 17:52
  • Could you please explain what exactly you wish to do?? –  May 25 '20 at 06:41
0

Fist of all I suggest that you start to try to implement the collision test, before you ask a question. If you get stuck, you can ask a question about the code that gets you stuck.
Anyway I'll give you some hints.

In common the collision detection is based on pygame.Rect. For instance create a rectangle from pygaem.Surface objects player.image and tree.image by get_rect(). Evaluate if the 2 objects are colliding by colliderect():

player_rect = player.image.get_rect(topleft = (player.x, player.y))
tree_rect = tree.image.get_rect(topleft = (tree.x, tree.y))
if player_rect.colliderect(tree_rect):
    print("hit")

If you "just want the player to stop when hitting the tree", the store the position of the player and move the player. After that evaluate if the player hits the tree. If the player is hitting, then restore the position:

while running:
    # [...]

    # store position of player
    player_pos = (player.x, player.y)
    
    # move player
    player.movement()

    player_rect = player.image.get_rect(topleft = (player.x, player.y))
    tree_rect = tree.image.get_rect(topleft = (tree.x, tree.y))
    
    # test collision of player and tree
    if player_rect.colliderect(tree_rect):

        # restore player position
        (player.x, player.y) = player_pos 

See also How to detect collisions between two rectangular objects or images in pygame

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Hello! to answer your first question, I got overwhelmed with how many people did theirs I know code can look completely different but do the same job which was what was hurting my head, but this looks amazing because I understand since its using my code! I only have one issue which I actually have a rough clue on fixing, pretty much the tree image is well on a tile sheet so when I try to go around it I cant because its trying to find 0 , 0 on the axis which is completely blank, any clues on fixing this? – Dragon20C May 23 '20 at 19:28
  • sorry I don't no if you read my last comment since I was in mid editing it, also thank you very much for adding # to the code It makes it easier for me to remember since I am a beginner – Dragon20C May 23 '20 at 19:36
  • @Dragon20C Please note, neither I can see the images, nor I can test, the code, because it is not complete. All I can do is use my experience to guess. But the sentence *"it I cant because its trying to find 0 , 0 on the axis "* exceeds my imagination – Rabbid76 May 23 '20 at 19:42
  • sorry I wrote that without thinking, pretty much the tree is drawn with a extended rect, here is a gif for visuals, in the gif I am trying to move to the middle https://media.giphy.com/media/hrpyEtaN7mNR5wOPb3/giphy.gif – Dragon20C May 23 '20 at 19:52
  • @Dragon20C So actually the image is much bigger than the tree? Why? You copy a part form the sheet (`tiles_list.tiles.subsurface`), isn't it? – Rabbid76 May 23 '20 at 20:01
  • Yes that's correct, I have a sprite sheet that has multiple sprite art, it's the same for the player but for the player its made different for animation purposes, would I need to make a custom rect instead of it trying to load the full image? I did cut it but I'm not sure why it has the extra bit hmm. – Dragon20C May 23 '20 at 20:09
  • 1
    Okay it took some time but I figured it out, its not the tree its the player!, the player.image is a full 500 x 500 resolution picture so I couldnt pass the tree creating a custom rect made it work! – Dragon20C May 24 '20 at 10:43