pygame collisions while character is on a tile

16 views Asked by At

i am making a python platformer using pygame (and tkinter but no problem there) I dont know what the cause is.

The problem is that when the character is on a tile (self.rect.bottom = tile.rect.top) then both the horizontal collision and the vertical collision arent working properly( when jumping from the top of one tiles the character teleports to the top of the tile his head touches also does the same when colliding horizontally while on a tile ) here is the full code

(i am very sorry if this is laid out wrong or is bad im new)

(i do know about parts that arent in use and things that arent named properly like lava)

import pygame
import os
import random
import math
import time
from os import listdir
from os.path import isfile, join

pygame.init()

pygame.display.set_caption("FLAMING FELLOW AND LIQUID LADY")#name



WIDTH,HEIGHT=1500,700
FPS=240
CHARACTER_VEL=5
window=pygame.display.set_mode((WIDTH,HEIGHT))
GROUND_LEVEL = HEIGHT - 0
JUMP_STRENGTH=-60
TILES_size=50
tileset_img=pygame.image.load("stone small.png")
tileset_img2=pygame.image.load("Capture1.png")
tileset_img3=pygame.image.load("lava2.png")
start_time=pygame.time.get_ticks()//1000
#sprite_sheet=pygame.image.load("New Piskel.png")
def flip(sprites):
    return[pygame.transform.flip(sprite,True,False)for sprite in sprites]
def load_sprite_sheets(dir1,width,height,direction=False):
    path = join(r"C:\game1",dir1)
   
    images=[f for f in listdir(join(path)) if isfile(join(path,f))]
 

    all_sprites={}

    for image in images:
      sprite_sheet=pygame.image.load(join(path,image)).convert_alpha()
      sprites=[]
      for i in range(sprite_sheet.get_width()//width):
        surface = pygame.Surface((width,height),pygame.SRCALPHA,32)
        rect= pygame.Rect(i * width, 8, width, height)
        surface.blit(sprite_sheet,(0,0),rect)
        sprites.append(pygame.transform.scale2x(surface))
      if direction:
        all_sprites[image.replace(".png","")+ "_right"]=sprites
        all_sprites[image.replace(".png","")+ "_left"]=flip(sprites)
      else:
          all_sprites[image.replace(".png","")]=sprites
    return all_sprites
   
    print(all_sprites)
    #not end result sprites very hard to draw or find for blood boy and mud man

def get_block(size):
    
    image = pygame.image.load("stone small.png").convert_alpha()
    surface = pygame.Surface((size,size),pygame.SRCALPHA,32)
    rect = pygame.Rect(0,0,size,size)
    surface.blit(image,(0,0),rect)
    return pygame.transform.scale2x(surface)

class Character(pygame.sprite.Sprite):
    COLOR = (255,255,0)
    GRAVITY=100
    ANIMATION_DELAY = 15
    SPRITES = load_sprite_sheets("spriteee",25,25,True)
    #colour cant be class veriable as two distinst colours
    def __init__(self,x,y,width,height):
        self.rect = pygame.Rect(x,y,width,height)
        self.x_vel=0
        self.y_vel=0
        self.mask=None
        self.direction= "left"
        self.animation_count=0 #stops making it look goofy
        self.fall_count=0

    def move(self,dx,dy):
      self.rect.move_ip(dx, dy)
        #self.rect.x+=dx
        #self.rect.y+=dy

    def move_left(self,vel):#knowing what direction facing
        self.x_vel=-vel
        if self.direction!= "left":
            self.direction= "left"
            self.animation_count=0

    def move_right(self,vel):
        self.x_vel=vel
        if self.direction!="right":
            self.direction="right"
            self.animation_count=0

    def move_up(self,vel):
        self.y_vel=-vel
        if self.direction!="up":
            self.direction= "up"
            self.direction_count=0
       

    def move_down(self,vel):
        self.y_vel=vel
        if self.direction!="down":
            self.direction="down"
            self.direction_count=0
    def on_ground(self):
        return self.rect.bottom >= GROUND_LEVEL
    #def on_tile(self):
        #return self.rect.bottom
    def on_tiles_top(self, tiles):
        for tile in tiles:
            if self.rect.colliderect(tile.rect) and self.rect.bottom == tile.rect.top:

               return True
        return False
    def jump(self,tiles):
        if self.on_ground() or self.on_tiles_top(tiles):
            self.y_vel = JUMP_STRENGTH
        #self.y_vel=JUMP_STRENGTH

    def hit_bottom(self,tiles):
        for tile in tiles:
            while self.on_tiles_top ==False and self.rect.colliderect(tile.rect):
                if self.rect.top == tile.rect.bottom:
                   return True
    def hit_head(self,tiles):
        if self.hit_bottom ==True:
            time.sleep(1)
            self.y_vel = 3

    def loop(self, FPS,tiles):
     self.y_vel+=min(5,(self.fall_count/FPS)*self.GRAVITY)
     self.fall_count+=1


     self.move(self.x_vel, self.y_vel)


     if self.rect.bottom > GROUND_LEVEL :
            self.rect.bottom = GROUND_LEVEL
            self.y_vel = 0

    #  boundary collisions
     if self.rect.left < 0:  # Left boundary
         self.rect.left = 0
     elif self.rect.right > WIDTH:  # Right boundary
         self.rect.right = WIDTH
     if self.rect.top < 0:  # Top boundary
         self.rect.top = 0
     elif self.rect.bottom > HEIGHT:  # Bottom boundary
         self.rect.bottom = HEIGHT
     for tile in tiles:
         if self.rect.colliderect(tile.rect):
             keys=pygame.key.get_pressed()
             if self.x_vel < 0 and self.on_tiles_top==False :  
                 print("heeelo")       
                 self.rect.left = tile.rect.right
             if self.x_vel > 0 and self.on_tiles_top==False :
                  self.rect.right = tile.rect.left
             if self.y_vel < 0 and keys[pygame.K_w]:
                  print("hit")
                  self.rect.top = tile.rect.bottom
             if self.y_vel > 0 and not keys[pygame.K_w]:
                 self.rect.bottom  = tile.rect.top
       
           

    def get_hits(self,tiles):
        hits = []
        for tile in tiles:
            if self.rect.colliderect(tile):
                hits.append(tile)
            return hits
    def checkcollionsx(self,tiles):
        colliosions = self.get_hits(tiles)
        for tile in colliosions:
            if self.x_vel > 0:
                self.rect.left = tile.rect.left
            elif self.x_vel < 0:
                self.rect.right = tile.rect.right
               
               
   
    def update_sprite(self):
      sprite_sheet = "idle"
      if self.x_vel != 0:
         sprite_sheet="run"
      sprite_sheet_name = sprite_sheet + "_" + self.direction
      sprites = self.SPRITES[sprite_sheet_name]
      sprite_index = (self.animation_count //
                      self.ANIMATION_DELAY) % len(sprites)
      self.sprite = sprites[sprite_index]
      self.animation_count += 1
      self.update()
 
    def draw(self,win):
       
        
        win.blit(self.sprite,(self.rect.x,self.rect.y))



   



with open("rogan.txt","r") as world_file:
     world_cont=[line.strip() for line in world_file]






def get_backround(name):
    image=pygame.image.load(join(name))#loads bg image
    _,_,width,height=image.get_rect()
    tiles=[]  
#making sure backround is full of bakround pic
    for w in range(WIDTH//width+1):
        for h in range(HEIGHT//height+1):
            pos=(w*width,h*height)
            tiles.append(pos)
           
    return tiles,image

def draw(window,backround,bg_image,character,character2,tiles,tiles2,tile3,):
   
    for tile in backround:
        window.blit(bg_image,tile)
    character.update_sprite()
    character.draw(window)

   
    for tile in tiles:
        if tile.type=="1":
            window.blit(tileset_img,tile.rect.topleft)
        #window.blit(tileset_img, tile)
   
    for tile in tiles2:
        window.blit(tileset_img2,tile.rect.topleft)
    pygame.display.update()

    for tile in tile3:
        window.blit(tileset_img3,tile.rect.topleft)
    pygame.display.update()


def handle_move(character):
    keys=pygame.key.get_pressed()
    character.x_vel=0
    if keys[pygame.K_a]:
        character.move_left(CHARACTER_VEL)          
    if keys[pygame.K_d]:
        character.move_right(CHARACTER_VEL)





def handle_move_up(character,tiles):
    keys=pygame.key.get_pressed()
    character.y_vel=0
    if keys[pygame.K_w]:
         character.jump(tiles)
   
       

def handle_move_down(character):
    keys=pygame.key.get_pressed()  
    character.y_vel=0  
    if keys[pygame.K_s]:
        character.move_down(CHARACTER_VEL)

def tile_jump(character,tiles):
   keys=pygame.key.get_pressed()
   for tile in tiles:
       if character.rect.colliderect(tile.rect) and keys[pygame.K_w]:
          character.rect.bottom=tile.rect.top -60
     



class Tile:
    def __init__(self, x, y, width, height,tile_type):
        self.rect = pygame.Rect(x, y, width, height)
        self.type = tile_type
       
 
               
def lava(character,tile3):
    for tile in tile3:
        if character.rect.colliderect(tile.rect):
            current_time = pygame.time.get_ticks()// 1000
            elapsed_time = current_time - start_time
            print(elapsed_time)
            with open("leader.txt","a") as file:
                file.write(str(elapsed_time)+"\n")




def main(window):
    clock = pygame.time.Clock()
    backround,bg_image=get_backround("background.PNG")
    character =Character(450,100,25,30)
    character2=Character(0,725,25,40)
   
    tiles=[]
    tiles2=[]
    tile3=[]
   

    character.y_vel=0
    
    


    for row,row_tiles in enumerate(world_cont):
        for col, tile in enumerate(row_tiles):
            x,y = col * TILES_size , row * TILES_size
            if tile == '1':
                tile = Tile(x, y, TILES_size, TILES_size,"1")
                tiles.append(tile)
            elif tile =="2":
                tile = Tile(x, y, TILES_size, TILES_size,"2")
                tiles2.append(tile)
            elif tile =="3":
                tile = Tile(x, y, TILES_size, TILES_size,"3")
                tile3.append(tile)
                 
   

    run=True
    while run:




        clock.tick(FPS)

        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                run=False
                break
       
        character.loop(FPS,tiles)
        handle_move_down(character)
        handle_move_up(character,tiles)
        handle_move(character)
        tile_jump(character,tiles)
        draw(window,backround,bg_image,character,character2,tiles,tiles2,tile3,)
        lava(character,tile3)
        character.update_sprite()
        #dcharacter.get_hits(tiles)
        #character.checkcollionsx(tiles)
        for tile in tiles:
            if character.rect.colliderect(tile.rect):
                if character.rect.bottom > tile.rect.top>character.rect.top:
                   character.rect.bottom = tile.rect.top
                character.y_vel=0
                character.x_vel=0
               
        

        for tile in tiles2:
           if character.rect.colliderect(tile.rect):
              character.y_vel = 0
              tile.rect.top = character.rect.bottom

       

       
        pygame.display.flip()
    pygame.quit()
    quit()
#quits gamer mode

if __name__=="__main__":
    main(window)

i have tried to make exceptions to collision when on a tile as well as i have made print statements to see if collision has occurred and when on a tile the only collision that happens is the character being on the tile but when on the ground all of them can occur

0

There are 0 answers