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