Эти хит-боксы пересекаются, хотя они буквально не с утверждениями if - PullRequest
1 голос
/ 15 июня 2019

Я пытаюсь столкнуть свои фигуры, и когда я подпрыгиваю в воздухе, персонажи не должны сталкиваться.Вот видео, объясняющее проблему: https://drive.google.com/file/d/1a26Vmd6TF4C3dJ0DpnFLTR1d3a_lEfn4/view?usp=sharing

Столкновение с гоблином.Кроме того, мы можем видеть, что гоблин сталкивается, даже если ящики не соприкасаются и когда он находится на вершине хитбокса.

Я попытался изменить условие цикла, например, изменил «>» вокругна «<» и попытался сделать прыжок выше.И то, и другое не решило проблему, и я не опытный кодер. </p>

Вот основная проблема:

if (adventurer.hitbox_running[0] > attacker.hitbox[0] and adventurer.hitbox_running[0] < attacker.hitbox[0]+70) or (adventurer.hitbox_running[0]+70 > attacker.hitbox[0] and adventurer.hitbox_running[0]+90 < attacker.hitbox[0]+70):
            if  (adventurer.hitbox_running[1] > attacker.hitbox[1] and adventurer.hitbox_running[1] < attacker.hitbox[1]+70) or (adventurer.hitbox_running[1]+90 > attacker.hitbox[1] and adventurer.hitbox_running[1]+90 < attacker.hitbox[1]+70):
                window.fill((255,255,255))
                death()
                pygame.display.update()
                s(0.1)
                print("hit")

Вот весь код со всеми классами и всем:

from time import sleep as s
import random
import pygame
import time

#Loads and plays the music
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
pygame.mixer.music.load("Music.mp3")
pygame.mixer.music.set_volume(0.0)
pygame.mixer.music.play(-1)

score = 0

#sets the dimension of the window and loads in the background
window = pygame.display.set_mode((1000, 500))
pygame.display.set_caption("Practice Game")
background = pygame.image.load('pixel6.png')

#Transforms the background to desired dimensions
background = pygame.transform.scale(background, (1000, 500))

#Loads all the jump animation
jumpv1 = [pygame.image.load('adventurer-jump-00.png'),pygame.image.load('adventurer-jump-01.png'),pygame.image.load('adventurer-jump-02.png'),pygame.image.load('adventurer-jump-03.png'), pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jumpv2 = [pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jumpv3 = [pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jumpv4 = [pygame.image.load('adventurer-smrslt-00.png'),pygame.image.load('adventurer-smrslt-01.png'),pygame.image.load('adventurer-smrslt-02.png'),pygame.image.load('adventurer-smrslt-03.png')]
jump = jumpv1+jumpv2+jumpv3+jumpv4

#running animation
run = [pygame.image.load('adventurer-run-00.png'), pygame.image.load('adventurer-run-01.png'),pygame.image.load('adventurer-run-02.png'),pygame.image.load('adventurer-run-03.png')]

#sliding animation
slide = [pygame.image.load('adventurer-slide-00.png'),pygame.image.load('adventurer-slide-01.png'),pygame.image.load('adventurer-stand-00.png'),pygame.image.load('adventurer-stand-01.png'),pygame.image.load('adventurer-stand-02.png')]

#attacking animation
firstattack = [pygame.image.load('adventurer-attack3-00.png'),pygame.image.load('adventurer-attack3-01.png'),pygame.image.load('adventurer-attack3-02.png'),pygame.image.load('adventurer-attack3-03.png'),pygame.image.load('adventurer-attack3-04.png'),pygame.image.load('adventurer-attack3-05.png')]
secondattack = [pygame.image.load('adventurer-attack2-00.png'),pygame.image.load('adventurer-attack2-01.png'),pygame.image.load('adventurer-attack2-02.png'),pygame.image.load('adventurer-attack2-03.png'),pygame.image.load('adventurer-attack2-04.png'),pygame.image.load('adventurer-attack2-05.png')]
thirdattack = [pygame.image.load('adventurer-attack1-00.png'),pygame.image  .load('adventurer-attack1-01.png'),pygame.image.load('adventurer-attack1-02.png'),pygame.image.load('adventurer-attack1-03.png'), pygame.image.load('adventurer-attack1-04.png')]
attack = firstattack+secondattack+ thirdattack

#falling animation
falling = [pygame.image.load('adventurer-fall-00.png'), pygame.image.load('adventurer-fall-01.png')]                               

score = 0
run_program = True

#resizes all the adventuruer images to specified dimensions
for i in range (20):
    jump[i] = pygame.transform.scale(jump[i],(90,90))
for i in range(3):
    run[i] = pygame.transform.scale(run[i],(90,90))
for i in range (4): 
    slide[i] = pygame.transform.scale(slide[i],(90,90))
for i in range (1):
    falling[i] = pygame.transform.scale(falling[i],(90,90))
for i in range(16):
    attack[i] = pygame.transform.scale(attack[i],(90,90))

background_x = 0
background_2 = background.get_width()
clock = pygame.time.Clock()

ghost_image = pygame.image.load('imgg.png')
def text_objects(text, font):
    textSurface = font.render(text, True, (0,0,0))
    return textSurface, textSurface.get_rect()

def message_display(text):
    largeText = pygame.font.Font('freesansbold.ttf',115)
    TextSurf, TextRect = text_objects(text, largeText)
    TextRect.center = ((1000/2),(500/2))
    window.blit(TextSurf, TextRect)
    pygame.display.update()

def death():
    message_display('You DIED')

class ghost(object):
    ghost_animation = [pygame.image.load('imgg.png'),pygame.image.load('imgg.png')]
    def __init__(self, x,y,height):
        self.x = x
        self.y =y
        self.height = height
        self.hitbox = (x,y,100,100)
        self.count = 0

    def draw(self, window):
        self.hitbox = (self.x, self.y, 45, 60)
        if self.count >=1:
            self.count = 0
        self.count +=1
        window.blit(pygame.transform.scale(self.ghost_animation[self.count], (45,60)), (self.x, self.y)) 
        pygame.draw.rect(window, (255,0,0), self.hitbox, 2)

    def hit(self):
            print ("hit")

class eye(object):
    eye_load = pygame.image.load('obstc2.png')
    def __init__(self, x,y,width2, height2):
        self.x = x
        self.y =y
        self.hitbox_enemy = (x,y,200,100)
        self.count1 = 0

    def draw(self, window):
        self.hitbox_enemy = (self.x, self.y, 65, 65)
        window.blit(pygame.transform.scale(self.eye_load, (65,65)), (self.x, self.y)) 
        pygame.draw.rect(window, (255,0,0), self.hitbox_enemy, 2)

class player(object):
    def __init__(self, x,y):
        self.vel = 0.5
        self.running = True
        self.jumping = True
        self.sliding = True
        self.attacking = True
        self.isJump = False
        self. jumps = True
        self.fall = True
        self.player_x = 40
        self.player_y = 378
        self.x = 40
        self.y = 378
        self.width = 378
        self.speed = 0.6
        self.jumpcount = 10
        self.jumpingcount = 0
        self.runcount = 0
        self.attackcount = 0
        self.slidecount = 0       
        self.fallspeed = 0.3
        self.fallingcount = 0
        self.hitbox_running = (self.player_x,self.player_y,90,90)
        self.hitbox_sliding = (45,self.player_y+47,65,45)
        self.hitbox_falling = (self.player_x+30,self.player_y,35,80)
        self.hitbox_jumping = (self.player_x+20,self.player_y+20,52,55)
        self.hitbox_attacking = (58,405,47,70)
        self.hitbox_sword = (108, 405, 20, 50)


    def movement(self, window):
        pygame.time.delay(20)
        if self.runcount >= 3:
            self.runcount = 0

        if self.running == True:
            window.blit(run[self.runcount],(int(self.player_x),int(self.player_y)))
            self.runcount +=1
            self.hitbox_running = (self.player_x+30,self.player_y+20,48,70)
            pygame.draw.rect(window,(255,0,0),self.hitbox_running, 2)

        if (keys[pygame.K_DOWN]) or ((keys[pygame.K_DOWN]) and keys[pygame.K_p]):
            if self.player_y == 378:
                self.running = False
                if self.slidecount >= 4:
                    self.slidecount = 0

                if self.sliding:  
                    window.blit(slide[self.slidecount],(int(self.player_x),int(self.player_y)))
                    self.slidecount +=1
                    pygame.draw.rect(window,(255,0,0),self.hitbox_sliding, 2)

        if event.type == pygame.KEYDOWN:
            if (event.key == pygame.K_DOWN )and self.player_y < self.width:

                self.running = False
                self.jumping = False
                self.fallspeed += 0.2

                if self.fallingcount >= 1:
                    self.fallingcount = 0
                if self.fall:
                    window.blit(falling[self.fallingcount], (int(self.player_x),int(self.player_y)))
                    self.hitbox_falling = (self.player_x+30,self.player_y,35,80)
                    pygame.draw.rect(window,(255,0,0),self.hitbox_falling, 2)                    
                    self.fallingcount +=1
        if keys[pygame.K_UP] and keys[pygame.K_p] :
            self.fallspeed = 0.3
            self.running = False
            self.jumping = False
            self.sliding = False
            if self.attackcount >= 16:
                self.attackcount = 0
            if self.attacking: 
                window.blit(attack[self.attackcount],(int(self.player_x),int(self.player_y)))
                self.attackcount += 1
                self.hitbox_attacking = (self.player_x+30,self.player_y+20,38,70)
                self.hitbox_sword = (self.player_x+72, self.player_y+20, 20, 50)
                pygame.draw.rect(window,(255,0,0),self.hitbox_attacking, 2)
                pygame.draw.rect(window,(255,0,0),self.hitbox_sword, 2)
            if self.jumpingcount >= 20:
                self.jumpingcount = 0
            if self.jumping and self.player_y < self.width:  
                window.blit(jump[self.jumpingcount],(int(self.player_x),int(self.player_y)))
                self.hitbox_jumping = (int(self.player_x+20),int(self.player_y+20),52,55)
                pygame.draw.rect(window,(255,0,0),self.hitbox_jumping, 2)
                self.jumpingcount +=1
                self.fallspeed = 0.3

        if keys[pygame.K_UP]:
            self.fallspeed = 0.3
            self.running = False
            if self.jumpingcount >= 20:
                self.jumpingcount = 0

            if self.jumping and self.player_y < self.width:  
                window.blit(jump[self.jumpingcount],(int(self.player_x),int(self.player_y)))
                self.hitbox_jumping = (int(self.player_x+20),int(self.player_y+20),52,55)
                pygame.draw.rect(window,(255,0,0),self.hitbox_jumping, 2)
                self.jumpingcount +=1
                self.fallspeed = 0.3

        if keys[pygame.K_p] and not keys[pygame.K_UP]:
            self.running = False
            self.jumping = False
            self.sliding = False
            if self.attackcount >= 16:
                self.attackcount = 0

            if self.attacking:
                self.hitbox_attacking = (self.player_x+30,self.player_y+20,38,70)
                self.hitbox_sword = (self.player_x+72, self.player_y+20, 20, 50)
                window.blit(attack[self.attackcount],(int(self.player_x),int(self.player_y)))
                self.attackcount += 1
                pygame.draw.rect(window,(255,0,0),self.hitbox_attacking, 2)
                pygame.draw.rect(window,(255,0,0),self.hitbox_sword, 2)
        if keys[pygame.K_DOWN] and keys[pygame.K_UP]:
            self.running = False

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                self.running = True
                self.jumping = True
                self.fallspeed = 0.3

            if event.key == pygame.K_UP:
                self.running=True
            if event.key == pygame.K_p:
                self.running = True
                self.jumping = True
                self.sliding = True

class enemy(object):
    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')]
    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')]
    for i in range (10):
        walkright[i] = pygame.transform.scale(walkright[i],(70,70))
    for i in range(10):
        walkleft[i] = pygame.transform.scale(walkleft[i],(70,70))

    def __init__(self,enemy_x,enemy_y, end):
        self.x = enemy_x
        self.y = enemy_y             
        self.end = end

        self.path = [self.x,self.end]
        self.walkcount = 0
        self.vel = 7
        self.hitbox = (self.x,self.y-15,90,90)

    def draw_enemy(self,window):
        self.move()
        if self.walkcount+1 >= 33:
            self.walkcount = 0
            self.vel+=0.2
        #walking right
        if self.vel > 0:
            window.blit(self.walkleft[self.walkcount//3], (self.x,self.y-15))
            self.walkcount += 1
        #walking left
        if self.vel < 0:
##            window.blit(self.walkleft[self.walkcount//3], (self.x,self.y))
            self.walkcount -= 1
        if self.x < -100:
            self.x = 1050
        self.hitbox = (self.x+25,self.y-15,41,70)
        pygame.draw.rect(window, (255,0,0),self.hitbox,2)

    def move(self):
        if self.vel > 0:
            #see if position + movement space is < the end, then it is able to move
            if self.x + self.vel < self.path[1]:
                self.x -= self.vel
            #past end point and turns 180
            else:
                self.vel = self.vel*-1
                self.walkcount = 0
        #see if position is smaller than starting position
        else:
            if self.x - self.vel > self.path[0]:
                #vel is already negative
                self.x += self.vel
            else:
               #Truns 180 agian
               self.vel = self.vel* -1
               self.walkcount = 0

class wizard(object):
    walkleft = [pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_05.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_05.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_05.gif'),pygame.image.load('wizard-fly-forward_04.gif'), pygame.image.load('wizard-fly-forward_04.gif'),pygame.image.load('wizard-fly-forward_05.gif')]

    for i in range(16):
        walkleft[i] = pygame.transform.scale(walkleft[i],(70,70))

    def __init__(self,enemy_x,enemy_y, end):
        self.x = enemy_x
        self.y = enemy_y             
        self.end = end

        self.path = [self.x,self.end]
        self.walkcount = 0
        self.vel = 7
        self.hitbox = (self.x,self.y-15,90,90)  

    def draw_enemy(self,window):
        self.move()
        if self.walkcount >= 16:
            self.walkcount = 0
        #walking left
        if self.vel > 0:
            window.blit(self.walkleft[self.walkcount], (self.x,self.y-15))
            self.walkcount += 1
            self.vel+=0.002

        if self.x < -120:
            self.x = 1100
        self.hitbox = (self.x+25,self.y-15,41,70)
        pygame.draw.rect(window, (255,0,0),self.hitbox,2)

    def move(self):
        if self.vel >   0:
            #see if position + movement space is < the end, then it is able to move
            if self.x + self.vel < self.path[1]:
                self.x -= self.vel
            #past end point and turns 180
            else:
                self.vel = self.vel*-1
                self.walkcount = 0
        #see if position is smaller than starting position
        else:
            if self.x - self.vel > self.path[0]:
                #vel is already negative
                self.x += self.vel
            else:
               #Truns 180 agian
               self.vel = self.vel* -1
               self.walkcount = 0

class dragon(object):
    walkleft = [pygame.image.load('dragon_1.gif'), pygame.image.load('dragon_2.gif'), pygame.image.load('dragon_3.gif'), pygame.image.load('dragon_4.gif'), pygame.image.load('dragon_5.gif'), pygame.image.load('dragon_6.gif')]

    for i in range (6):
        walkleft[i] = pygame.transform.scale(walkleft[i],(200,176))
    def __init__(self,enemy_x,enemy_y, end):
        self.x = enemy_x
        self.y = enemy_y             
        self.end = end

        self.path = [self.x,self.end]
        self.walkcount = 0
        self.vel = 7
        self.hitbox = (self.x,self.y-15,90,90)  

    def draw_enemy(self,window):
        self.move()
        if self.walkcount >= 6:
            self.walkcount = 0
        #walking left
        if self.vel > 0:
            window.blit(self.walkleft[self.walkcount], (self.x,300))
            self.walkcount += 1
            self.vel+=0.002

        if self.x < -120:
            self.x = 1100
        self.hitbox = (self.x+25,self.y-15,41,70)
        pygame.draw.rect(window, (255,0,0),self.hitbox,2)

    def move(self):
        if self.vel >   0:
            #see if position + movement space is < the end, then it is able to move
            if self.x + self.vel < self.path[1]:
                self.x -= self.vel
            #past end point and turns 180
            else:
                self.vel = self.vel*-1
                self.walkcount = 0
        #see if position is smaller than starting position
        else:
            if self.x - self.vel > self.path[0]:
                #vel is already negative
                self.x += self.vel
            else:
               #Truns 180 agian
               self.vel = self.vel* -1
               self.walkcount = 0

ghost_list = []
eye_list = []

def keepdrawing():
    window.blit(background, (background_x,0))
    window.blit(background, (background_2,0))

    for draw_ghost in ghost_list:
        draw_ghost.draw(window)
    for draw_eye in eye_list:
        draw_eye.draw(window)

    adventurer.movement(window)
    attacker.draw_enemy(window)
    wizard.draw_enemy(window)
    dragon.draw_enemy(window)

    score_text = score_font.render("score: " + str(score), 1, (0,0,0))
    window.blit(score_text,(470,10))
    pygame.display.update()

score_font = pygame.font.SysFont("Arial",30,True)
attacker = enemy(950,407,951)
adventurer = player(40,387)
wizard = wizard(905,407,951)
dragon = dragon(905,407, 951)
vel_background = 2
pygame.time.set_timer(pygame.USEREVENT+1,random.randint(1000, 2000))
pygame.time.set_timer(pygame.USEREVENT+2,random.randint(2000, 3000))
while run:
    while run_program:
        clock.tick(60)
        background_x -= vel_background
        background_2 -= vel_background
        if background_x < background.get_width() * -1:
            background_x = background.get_width()
        if background_2 < background.get_width() * -1:
            background_2 = background.get_width()
        keys = pygame.key.get_pressed()
        if (adventurer.hitbox_running[0] > attacker.hitbox[0] and adventurer.hitbox_running[0] < attacker.hitbox[0]+70) or (adventurer.hitbox_running[0]+70 > attacker.hitbox[0] and adventurer.hitbox_running[0]+90 < attacker.hitbox[0]+70):
            if  (adventurer.hitbox_running[1] > attacker.hitbox[1] and adventurer.hitbox_running[1] < attacker.hitbox[1]+70) or (adventurer.hitbox_running[1]+90 > attacker.hitbox[1] and adventurer.hitbox_running[1]+90 < attacker.hitbox[1]+70):
                window.fill((255,255,255))
                death()
                pygame.display.update()
                s(0.1)
                print("hit")

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                exit()
            if event.type == pygame.USEREVENT+1:
                vel_background+=0.2
            if event.type == pygame.USEREVENT+2:
                r = random.randint(0,1)
                if r==0:
                    new_eye = eye(1050, 390, 64,64)
                    eye_list.append(new_eye)
                if r==1:
                    new_ghost = ghost(1050,390,64)
                    ghost_list.append(new_ghost)

        if not(adventurer.isJump):

            if keys[pygame.K_UP]:
                adventurer.isJump =True

        else:

            if adventurer.jumpcount >= -10:

                neg=1
                if adventurer.player_y > adventurer.width:
                    adventurer.player_y = adventurer.width
                if adventurer.jumpcount <0:
                    neg = -1
    ##                s(0.01)
                adventurer.player_y -= (adventurer.jumpcount**2)*adventurer.fallspeed*neg*2
    ##            s(0.01)
                adventurer.jumpcount -=1

                if adventurer.player_y > adventurer.width:
                    adventurer.player_y=adventurer.width

            else:
                adventurer.isJump = False
                adventurer.jumpcount = 10
                if adventurer.player_y > adventurer.width:
                    player_y = adventurer.width
                    adventurer.fallspeed = 0.05
        keepdrawing()

Ожидаемые результаты должны заключаться в том, что на выходе не должно быть дерьма, если блоки попаданий не соприкасаются.

1 Ответ

1 голос
/ 16 июня 2019

Основная проблема заключается в том, что у вас разные "хитбоксы", которые имеют разные значения в разных состояниях игры, но вы используете adventurer.hitbox_running для события теста на столкновение, если adventurer равно .running или .falling.

Наилучшим решением будет заданный атрибут .hitbox, который всегда содержит правильное расположение adventurer в методе player.movement.
Но также возможно выбрать правильный хит-бокс:

if adventurer.running:
    hitbox = adventurer.hitbox_running
elif adventurer.jumping:
    hitbox = adventurer.hitbox_jumping
elif adventurer.falling:
    hitbox = adventurer.hitbox_falling

Далее я рекомендую использовать pygame.Rect объекты и .colliderect() для испытания на столкновение:

rect_adventurer = pygame.Rect(*hitbox)
rect_attacker = pygame.Rect(*attacker.hitbox)
if rect_adventurer.colliderect(rect_attacker):

        window.fill((255,255,255))
        death()
        pygame.display.update()
        s(0.1)
        print("hit")
...