Проблема в том, что когда персонаж находится на плитке ( self.rect.bottom = tile.rect.top), то и горизонтальное столкновение, и вертикальное столкновение не работают должным образом (при прыжке с вершины одной плитки персонаж телепортируется на вершину плитки, к которой прикасается его голова, и делает то же самое, когда горизонтальное столкновение на плитке)
вот полный код
(мне очень жаль, если это неправильно или плохо, я новичок)
(я знаю о деталях, которые не используются, и о вещах, которые не называются правильно, например лава)
Код: Выделить всё
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)
Подробнее здесь: https://stackoverflow.com/questions/781 ... -on-a-tile