Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Collisions in Arrays
#1
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)
:)
Reply
#2
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)
Reply
#3
(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!!
nilamo likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Brick [PyGame] How to make collisions in isometrick game? Grigory 1 2,275 Jul-01-2021, 01:54 PM
Last Post: Windspar
  Can someone help me with collisions ? CUKEMAN 2 1,968 Jun-22-2020, 09:54 AM
Last Post: JudyLarose
  Help with collisions. ghost0fkarma 5 5,975 Mar-11-2019, 12:09 AM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020