Python Forum
Collisions in Arrays - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: Game Development (https://python-forum.io/forum-11.html)
+--- Thread: Collisions in Arrays (/thread-32946.html)



Collisions in Arrays - Prithak - Mar-18-2021

Forgive my incredibly good code buttttt......... The collision works for only one object? Why is that? Any solitions? Please help!

import pygame, sys

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((1280,720))
pygame.display.set_caption("TheGame")
font = pygame.font.Font('C:\Windows\Fonts\Impact.ttf', 32)

class createVector:
    def __init__(self, x, y, oldx, oldy):
        self.x, self.y = x, y

offset = createVector(480,500,0,0)


class Player:
    def __init__(self, x, y, w, h, speed):
        self.x, self.y, self.w, self.h, self.speed = x, y, w, h, speed

    def render(self, color):
        pygame.draw.rect(screen, color, (self.x, self.y, self.w, self.h),0, 10)

class Object:
    def __init__(self, x,y,w,h):
        self.x, self.y, self.w, self.h = x, y, w, h

    def render(self, off, color, thickness, corrad):
        pygame.draw.rect(screen, color, (off.x + self.x, off.y + self.y, self.w, self.h), thickness, corrad)
    
    def Collision(self, off, player):
        if self.x + off.x < player.x + player.w and self.x + off.x + self.w > player.x and self.y + off.y < player.y + player.h and self.y + off.y + self.h > player.y:
            off.x = off.oldx
            off.y = off.oldy
        else:
            off.oldx = off.x
            off.oldy = off.y


def displayText(text, x, y):
    txtSur = font.render(text, True, (255,255,255))
    screen.blit(txtSur, (x,y))

player = Player(1280/2 - 50, 720/2 - 50, 50, 50, 10)

obj = []

obj.append(Object(50, 100, 100, 50))
obj.append( Object(100, 200, 100, 50) )
left_clicking = False

while True:
    screen.fill((20,20,20))

    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    key = pygame.key.get_pressed()

    mx, my = pygame.mouse.get_pos()

    mx += offset.x
    my += offset.y

    left_clicking = False

    mb = pygame.mouse.get_pressed()

    if mb[0]:
        obj.append( Object(mx, my, 100, 50) )

    displayText(str(mx), 0, 0)
    displayText(str(my), 100, 0)

    if key[pygame.K_w] and moveUp:
        offset.y += player.speed
        player.y += 8
    
    if key[pygame.K_s] and moveDown:
        offset.y -= player.speed
        player.y -= 8

    if key[pygame.K_a] and moveLeft:
        offset.x += player.speed
        player.x += 8
    if key[pygame.K_d] and moveRight:
        offset.x -= player.speed
        player.x -= 8

    if key[pygame.K_ESCAPE]:
        pygame.quit()
        sys.exit

    player.render((100,200,255))
    
    player.x = 1280/2
    player.y = 720/2


    for i in range(len(obj)):
        obj[i].render(offset, (100,100,100), 0, 10)

        obj[i].Collision(offset, player)

    pygame.display.flip()
    clock.tick(60)
:)


RE: Collisions in Arrays - nilamo - Mar-18-2021

The issue is that one object didn't collide, so it set new values for oldx/oldy, so when the other object did collide, it set the offset's value to where the offset already was (since the other object just saved that position).

Instead, just have the collision return a True/False of whether it collided, and adjust the offset one time.


Check this out. I moved some things around, and now only change the offset if nothing collided. We do that by tracking where the offset should be based on movement, and then only using that new value if it wouldn't cause a collision.
import pygame
import sys

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("TheGame")
font = pygame.font.Font('C:\Windows\Fonts\Impact.ttf', 32)


class createVector:
    def __init__(self, x, y, oldx, oldy):
        self.x, self.y = x, y


offset = createVector(480, 500, 0, 0)


class Player:
    def __init__(self, x, y, w, h, speed):
        self.x, self.y, self.w, self.h, self.speed = x, y, w, h, speed

    def render(self, color):
        pygame.draw.rect(
            screen, color, (self.x, self.y, self.w, self.h), 0, 10)


class Object:
    def __init__(self, x, y, w, h):
        self.x, self.y, self.w, self.h = x, y, w, h

    def render(self, off, color, thickness, corrad):
        pygame.draw.rect(screen, color, (off.x + self.x, off.y +
                                         self.y, self.w, self.h), thickness, corrad)

    def Collision(self, off, player):
        if (self.x + off.x < player.x + player.w
                and self.x + off.x + self.w > player.x
                and self.y + off.y < player.y + player.h
                and self.y + off.y + self.h > player.y):
            return True
        return False


def displayText(text, x, y):
    txtSur = font.render(text, True, (255, 255, 255))
    screen.blit(txtSur, (x, y))


player = Player(1280/2 - 50, 720/2 - 50, 50, 50, 10)

obj = []

obj.append(Object(50, 100, 100, 50))
obj.append(Object(100, 200, 100, 50))
left_clicking = False

while True:
    screen.fill((20, 20, 20))

    key = pygame.key.get_pressed()
    for event in pygame.event.get():
        if event.type == pygame.QUIT or key[pygame.K_ESCAPE]:
            pygame.quit()
            sys.exit()

    player.render((100, 200, 255))
    player.x = 1280/2
    player.y = 720/2

    next_offset = createVector(offset.x, offset.y, 0, 0)
    if key[pygame.K_w]:
        next_offset.y += player.speed
    if key[pygame.K_s]:
        next_offset.y -= player.speed
    if key[pygame.K_a]:
        next_offset.x += player.speed
    if key[pygame.K_d]:
        next_offset.x -= player.speed

    collision = False
    for item in obj:
        collision = item.Collision(next_offset, player) or collision
    if not collision:
        offset = next_offset

    for item in obj:
        item.render(offset, (100, 100, 100), 0, 10)

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



RE: Collisions in Arrays - Prithak - Mar-19-2021

(Mar-18-2021, 07:00 PM)nilamo Wrote: The issue is that one object didn't collide, so it set new values for oldx/oldy, so when the other object did collide, it set the offset's value to where the offset already was (since the other object just saved that position).

Instead, just have the collision return a True/False of whether it collided, and adjust the offset one time.


Check this out. I moved some things around, and now only change the offset if nothing collided. We do that by tracking where the offset should be based on movement, and then only using that new value if it wouldn't cause a collision.
import pygame
import sys

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("TheGame")
font = pygame.font.Font('C:\Windows\Fonts\Impact.ttf', 32)


class createVector:
    def __init__(self, x, y, oldx, oldy):
        self.x, self.y = x, y


offset = createVector(480, 500, 0, 0)


class Player:
    def __init__(self, x, y, w, h, speed):
        self.x, self.y, self.w, self.h, self.speed = x, y, w, h, speed

    def render(self, color):
        pygame.draw.rect(
            screen, color, (self.x, self.y, self.w, self.h), 0, 10)


class Object:
    def __init__(self, x, y, w, h):
        self.x, self.y, self.w, self.h = x, y, w, h

    def render(self, off, color, thickness, corrad):
        pygame.draw.rect(screen, color, (off.x + self.x, off.y +
                                         self.y, self.w, self.h), thickness, corrad)

    def Collision(self, off, player):
        if (self.x + off.x < player.x + player.w
                and self.x + off.x + self.w > player.x
                and self.y + off.y < player.y + player.h
                and self.y + off.y + self.h > player.y):
            return True
        return False


def displayText(text, x, y):
    txtSur = font.render(text, True, (255, 255, 255))
    screen.blit(txtSur, (x, y))


player = Player(1280/2 - 50, 720/2 - 50, 50, 50, 10)

obj = []

obj.append(Object(50, 100, 100, 50))
obj.append(Object(100, 200, 100, 50))
left_clicking = False

while True:
    screen.fill((20, 20, 20))

    key = pygame.key.get_pressed()
    for event in pygame.event.get():
        if event.type == pygame.QUIT or key[pygame.K_ESCAPE]:
            pygame.quit()
            sys.exit()

    player.render((100, 200, 255))
    player.x = 1280/2
    player.y = 720/2

    next_offset = createVector(offset.x, offset.y, 0, 0)
    if key[pygame.K_w]:
        next_offset.y += player.speed
    if key[pygame.K_s]:
        next_offset.y -= player.speed
    if key[pygame.K_a]:
        next_offset.x += player.speed
    if key[pygame.K_d]:
        next_offset.x -= player.speed

    collision = False
    for item in obj:
        collision = item.Collision(next_offset, player) or collision
    if not collision:
        offset = next_offset

    for item in obj:
        item.render(offset, (100, 100, 100), 0, 10)

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

THANK YOU!! That totally makes sense! I should have thought about that earlier. Anyways thank you so much!!