Kolizje obiektów

0

Hej, mam problem z kodem, który opiera się na serii tego youtubera https://youtu.be/2BikxsbkuIU
Przy kolizji gracza z zombie (moment kiedy gracz skacze na zombie) po wyświetleniu wyniku przez kilka sekund i kontynuacji pętli, gracz "rodzi się" około 50 pikseli niżej. W czym w może być problem?

import pygame
import sys
pygame.init()

okno = pygame.display.set_mode((500,480))
pygame.display.set_caption("Gra")

walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
                  pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
                  pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
                 pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'),
                 pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]

bg = pygame.image.load('bg.jpg')
char = pygame.image.load('standing.png')

clock = pygame.time.Clock()

score = 0

bulletSound = pygame.mixer.Sound('bullet.wav')
hitSound = pygame.mixer.Sound('punch.wav')

music = pygame.mixer.music.load('music.mp3')
pygame.mixer.music.play(-1)

class player(object):
    def __init__(self, x, y, width, height,):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5
        self.jump = False
        self.jumpCount = 10
        self.left = False
        self.right = False
        self.walkCount = 0
        self.standing = True
        self.hitbox = (self.x + 17, self.y+11, 29, 52)

    def draw(self, okno):
        if self.walkCount + 1 >= 27:
            self.walkCount = 0

        if not self.standing:
            if self.left:
                okno.blit(walkLeft[self.walkCount // 3], (self.x, self.y))
                self.walkCount += 1
            elif self.right:
                okno.blit(walkRight[self.walkCount // 3], (self.x, self.y))
                self.walkCount += 1
        else:
            if self.right:
                okno.blit(walkRight[0], (self.x, self.y))
            else:
                okno.blit(walkLeft[0], (self.x, self.y))
        self.hitbox = (self.x + 17, self.y+11, 29, 52)
        #pygame.draw.rect(okno, (255, 0, 0), self.hitbox, 2)

    def hit(self):
        self.x = 60
        self.y = 410
        self.walkCount = 0
        font1 = pygame.font.SysFont('comicsans', 100)
        text = font1.render('-5', 1, (255, 0, 0))
        okno.blit(text, (250 - (text.get_width()/2), 200))
        pygame.display.update()
        i = 0
        while i < 300:
            pygame.time.delay(10)
            i += 1
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    i = 301
                    pygame.quit()


class projectile(object):
    def __init__(self, x, y, radius, color, facing):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.facing = facing
        self.vel = 8*facing

    def draw(self, okno):
        pygame.draw.circle(okno, self.color, (self.x, self.y), self.radius)


class enemy(object):

    def __init__(self, x, y, width, height, end):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.walkCount = 0
        self.vel = 3
        self.end = end
        self.path = [self.x, self.end]
        self.hitbox = (self.x + 17, self.y + 2, 31, 57)
        self.health = 50
        self.visible = True
        self.walkRight = [pygame.image.load('R1E.png'), pygame.image.load('R2E.png'), pygame.image.load('R3E.png'),
                     pygame.image.load('R4E.png'), pygame.image.load('R5E.png'), pygame.image.load('R6E.png'),
                     pygame.image.load('R7E.png'), pygame.image.load('R8E.png'), pygame.image.load('R9E.png'),
                     pygame.image.load('R10E.png'), pygame.image.load('R11E.png')]
        self.walkLeft = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'),
                    pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'),
                    pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png'),
                    pygame.image.load('L10E.png'), pygame.image.load('L11E.png')]

    def draw(self, okno):

        if self.visible:
            self.move()
            if self.walkCount + 1 >= 33:
                self.walkCount = 0

            if self.vel > 0:
                okno.blit(self.walkRight[self.walkCount // 3], (self.x, self.y))
                self.walkCount += 1
            else:
                okno.blit(self.walkLeft[self.walkCount // 3], (self.x, self.y))
                self.walkCount += 1

            pygame.draw.rect(okno, (255, 0, 0), (self.hitbox[0], self.hitbox[1] - 20, 50, 10))
            pygame.draw.rect(okno, (0, 125, 0), (self.hitbox[0], self.hitbox[1] - 20, self.health, 10))
            self.hitbox = (self.x + 17, self.y + 2, 31, 57)
            #pygame.draw.rect(okno, (255,0,0), self.hitbox, 2)

    def move(self):
        if self.vel > 0:
            if self.x + self.vel < self.path[1]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkCount = 0
        else:
            if self.x - self.vel > self.path[0]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkCount = 0

    def hit(self):
        if self.health > 0:
            self.health -= 1
        else:
            self.visible = False


def redrawGameWindow():
    global walkCount
    okno.blit(bg,(0,0))
    text = font.render('Wynik: ' + str(score), 1, (0, 0, 0))
    okno.blit(text, (390, 10))
    Krispekowy.draw(okno)
    zombie.draw(okno)
    for bullet in bullets:
        bullet.draw(okno)
    pygame.display.update()

# Pętla główna


Krispekowy = player(300, 410, 64, 64)
zombie = enemy(100, 410, 64, 64, 450)
shootLoop = 0
bullets = []
run = True
font = pygame.font.SysFont('comicsans', 30, True, True)

while run:
    clock.tick(27)
    print(Krispekowy.y)
    if Krispekowy.hitbox[1] < zombie.hitbox[1] + zombie.hitbox[3] and Krispekowy.hitbox[1] + Krispekowy.hitbox[3] > \
            zombie.hitbox[1]:
        if Krispekowy.hitbox[0] + Krispekowy.hitbox[2] > zombie.hitbox[0] and Krispekowy.hitbox[0] < zombie.hitbox[0] + \
                zombie.hitbox[
            2]:
            Krispekowy.hit()
            score -= 5

    if shootLoop > 0:
        shootLoop += 1
    if shootLoop > 3:
        shootLoop = 0

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

    for bullet in bullets:
        if bullet.y - bullet.radius < zombie.hitbox[1] + zombie.hitbox[3] and bullet.y + bullet.radius > zombie.hitbox[1]:
            if bullet.x + bullet.radius > zombie.hitbox[0] and bullet.x - bullet.radius < zombie.hitbox[0] + zombie.hitbox[2]:
                zombie.hit()
                hitSound.play()
                score += 1
                bullets.pop(bullets.index(bullet))

        if bullet.x < 500 and bullet.x > 0:
            bullet.x += bullet.vel
        else:
            bullets.pop(bullets.index(bullet))

    keys = pygame.key.get_pressed()

    if keys[pygame.K_SPACE] and shootLoop == 0:
        bulletSound.play()
        if Krispekowy.left:
            facing = -1
        else:
            facing = 1
        if len(bullets) < 5:
            bullets.append(projectile(round(Krispekowy.x + Krispekowy.width // 2), round(Krispekowy.y + Krispekowy.height //2), 6, (0,0,0), facing))

    if keys[pygame.K_LEFT] and Krispekowy.x > Krispekowy.vel:
        Krispekowy.x -= Krispekowy.vel
        Krispekowy.left = True
        Krispekowy.right = False
        Krispekowy.standing = False
    elif keys[pygame.K_RIGHT] and Krispekowy.x < 500 - Krispekowy.width - Krispekowy.vel:
        Krispekowy.x += Krispekowy.vel
        Krispekowy.left = False
        Krispekowy.right = True
        Krispekowy.standing = False
    else:
        Krispekowy.standing = True
        Krispekowy.walkCount = 0

    if not Krispekowy.jump:
        if keys[pygame.K_UP]:
            Krispekowy.jump = True
            Krispekowy.right = False
            Krispekowy.left = False
            Krispekowy.walkCount = 0
    else:
        if Krispekowy.jumpCount >= -10:
            neg = 1
            if Krispekowy.jumpCount < 0:
                neg = -1
            Krispekowy.y -= (Krispekowy.jumpCount ** 2) * 0.5 * neg
            Krispekowy.jumpCount -= 1
        else:
            Krispekowy.jump = False
            Krispekowy.jumpCount = 10
    redrawGameWindow()


pygame.quit()
0

Przejechałeś to debuggerem?

0
lion137 napisał(a):

Przejechałeś to debuggerem?

A co mi wskaże debugger? To nie błąd kodu, program wykonuje się i kończy. Problem polega na tym, że w pewnym miejscu kodu zmienna przyjmuje złe wartości przez co obiekt niepoprawnie wyświetla się na ekranie.

Podsyłam githuba:
https://github.com/Krispekowy/first_game

1
Krispekowy napisał(a):
lion137 napisał(a):

Przejechałeś to debuggerem?

A co mi wskaże debugger?

To, co się dokładnie dzieje w trakcie wykonania. Stos wywołań, wartości zmiennych, atrybutów obiektów, flagi, cokolwiek.

To nie błąd kodu, program wykonuje się i kończy.

Oczywiście że kodu, przecież nie monitora :P

Błąd niekoniecznie musi oznaczać, że kod się nie skopiluje (albo interpreter się wyłoży na analizie składni) albo wywali soczysty stack trace w runtime. Po to są właśnie debuggery, by śledzić co się dzieje w trakcie wykonania

Problem polega na tym, że w pewnym miejscu kodu zmienna przyjmuje złe wartości przez co obiekt niepoprawnie wyświetla się na ekranie.

A co to jest, jeśli nie błąd w kodzie?

Użyj tego debuggera, postaw breakpointy, prześledź gdzie mniej-więcej pojawia się błędna wartość, postaw więcej breakpointów, zawęź obszar poszukiwań i do brzegu. Twój kod przewija się przez kilka ekranów, osobom trzecim ciężko spojrzeć na to i powiedzieć "o, patrz, to w tej linijce dodałeś zamiast odejmować" ;)

0

@Krispekowy: Twój problem wynika z tego że w metodzie hit() ustawiasz pozycje y swojego bohatera, jednak cały czas znajduje się on w skoku więc jego opadanie jest dalej przeliczane. Na szybko wystarczy że dodasz w metodzie hit() bohatera:

def hit(self):
        self.x = 60
        self.y = 410
        self.walkCount = 0
        self.jump = False # bohater sie odrodzil wiec juz nie jest w trakcie skoku

0 użytkowników online, w tym zalogowanych: 0, gości: 0