Python Pygame Platformer

45 views Asked by At

I am just learning OOP with Pygame and have built a platformer where you move around with the arrow keys, up to jump, you can press R to add more blocks for an extra challenge and you can resize the character with aswd, the smaller you are the less you can jump and the larger the higher you can jump, however when resizing it will sometimes teleport to seemingly random places and glitch through blocks like no ones business, ive spent quite a few hours trying out different things and havent been able to find a fix.

HERES MY CODE:

import pygame as py
import random as r


py.init()
#functions


#var
BLACK = (0,0,0)
WHITE = (255,255,255)
RED = (255, 0, 0)
GREEN = (0,255, 0)
BLUE = (0,0,255)
GRAVITY = .03
momentum = 0
momeunt_up = 0


#sprites and classes
class Platform(py.sprite.Sprite):
    def __init__(self, color, width, height):
        super().__init__()
        self.image = py.Surface([width, height])
        self.image.fill(color)
        self.rect = self.image.get_rect()




    def fall(self):
        self.rect.y -= 1


class Player(py.sprite.Sprite):
    change_x = 0
    change_y = 0






    def __init__(self):
        super().__init__()
        self.image = py.Surface([30, 30])
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = (screen_width/2 ) - 75
        self.rect.y = (screen_height - 33) 
        py.draw.rect(self.image, WHITE, [2, 2, self.rect.width - 4, self.rect.height - 4])
        py.draw.circle(self.image, RED, (4, 12), 4)
        py.draw.circle(self.image, RED, (13, 12), 4)
        py.draw.line(self.image, RED, (3.2, 21), (14.5, 21), 2)
    def update(self):
        self.calc_grav()
        if self.rect.right >= screen_width and self.change_x >0:
            self.rect.right = screen_width
            self.change_x = 0


        if self.rect.x <= 0 and self.change_x < 0:
            self.rect.left = 0
            self.change_x = 0
        self.rect.x += self.change_x
        pos = self.rect.x
        
        block_hit_list = py.sprite.spritecollide(self, platform_list, False)
        for block in block_hit_list:
            if self.change_x >0:
                self.rect.right = block.rect.left
            elif self.change_x < 0:
                self.rect.left = block.rect.right
            if self.rect.right >= block.rect.left:
                self.growabler = False
            if self.rect.top <= block.rect.bottom:
                self.growableh = False
        self.rect.y += self.change_y
        block_hit_list = py.sprite.spritecollide(self, platform_list, False)
        for block in block_hit_list:
            if self.change_y > 0:
                self.rect.bottom = block.rect.top
            elif self.change_y < 0:
                self.rect.top = block.rect.bottom
        
            self.change_y = 0
        self.image = py.Surface([self.rect.width, self.rect.height])
        py.draw.rect(self.image, WHITE, [2, 2, self.rect.width - 4, self.rect.height - 4])
        self.image.fill(RED)
        py.draw.rect(self.image, WHITE, [2, 2, self.rect.width - 4, self.rect.height - 4])
        py.draw.circle(self.image, RED, ((self.rect.width/7.5), (self.rect.height/2.5)), (self.rect.width/7.5))
        py.draw.circle(self.image, RED, ((self.rect.width/2.307), (self.rect.height/2.5)), (self.rect.width/7.5))
        line_height = (self.rect.height / 1.42)
        py.draw.line(self.image, RED, (int((self.rect.width/9)), line_height), (int((self.rect.width/2)), line_height), int((self.rect.width/15)))
        
        




    def right(self):
        self.change_x = 6


    def left(self):
        self.change_x = -6








    def jump(self):
        
        self.rect.y += 2
        platform_hit_list = py.sprite.spritecollide(self, platform_list, False)
        self.rect.y -=2


        if len(platform_hit_list) > 0 or self.rect.bottom >= screen_height:
            #self.change_y = -10
            self.change_y = -((self.rect.width + self.rect.height) / 8)
            if self.change_y < -15:
                self.change_y = -15
    def calc_grav(self):
        if self.change_y == 0:
            self.change_y = 1
        else:
            self.change_y += .35


        if self.rect.y >= screen_height - self.rect.height and self.change_y >= 0:
            self.change_y = 0
            self.y = screen_height - self.rect.height
        if self.rect.y <= 0 and self.change_y <= 0:
            self.rect.y = 0
            self.change_y = 0
    def stop(self):
        self.change_x = 0
    def shrink(self, directionh, directionw):
        self.directionh = directionh
        self.directionw = directionw
        if directionh == True:
            if self.rect.height > 1:
                self.rect.height -= 1
        if directionw == True:
            if self.rect.width > 1:
                self.rect.width -= 1
    def grow(self, directionh, directionw):
        block_hit_list = py.sprite.spritecollide(self, platform_list, False)
        for block in block_hit_list:
            if self.rect.right >= block.rect.left and self.rect.top < block.rect.top:
                self.growabler = False
                self.rect.right -= 1
        
            elif self.rect.top <= block.rect.bottom:
                self.growableh = False
                
                
            
            else: 
                self.growableh = True
                self.growabler = True
        if len(block_hit_list) == 0:
            self.growableh = True
            self.growabler = True
        if  self.growableh == True:
            
            if directionh == True:
                if self.rect.height < 100:
                    self.rect.height += 1
        if self.growabler == True:
            if directionw == True:
                if self.rect.width < 100:
                    self.rect.width += 1


    def pulse(self):
        #shoot out beams of light to pinpoint character
        pass






clock = py.time.Clock()


screen_width = 1400
screen_height = 700
screen = py.display.set_mode((screen_width, screen_height))
done = False
velocity = 0
platform_list = py.sprite.Group()
all_sprites_list = py.sprite.Group()
player = Player()
player_list = py.sprite.Group()
player_list.add(player)
all_sprites_list.add(player)
directionh = False
directionw = False
platform = Platform(BLUE, screen_width, 3)
platform.rect.x = 0 
platform.rect.y = screen_height - 3
all_sprites_list.add(platform)
platform_list.add(platform)
def make_bricks():
    for i in range(r.randint(20, 30)):
        collisions = 0
        collide = True
        infinite = False
        platform = Platform(GREEN, r.randint(40,200), 40)
        platform.rect.x = r.randrange(screen_width)
        platform.rect.y = r.randint(150, (screen_height))
        while collide == True:
            collisions += 1
            if collisions > 100:
                infinite = True
            if infinite == False:
                if py.sprite.spritecollide(platform, all_sprites_list, False):
                    platform.rect.x = r.randrange(screen_width)
                    platform.rect.y = r.randint(80, (screen_height - 40))
                    
                else:
                    collide = False
            else:
                if py.sprite.spritecollide(platform, player_list, False):
                    platform.rect.x = r.randrange(screen_width)
                    platform.rect.y = r.randint(150, (screen_height - 40))
                    
                else:
                    collide = False
        platform_list.add(platform)
        all_sprites_list.add(platform)


make_bricks()
make_bricks()


while not done:
    
    direcitonh  = False
    directionw = False
    for event in py.event.get():
        if event.type == py.QUIT:
            done = True
        if event.type == py.KEYDOWN:
            if event.key == py.K_LEFT:
                player.left()
            if event.key == py.K_RIGHT:
                player.right()
            if event.key == py.K_UP:
                player.jump()
            if event.key == py.K_r:
                make_bricks()
        if event.type == py.KEYUP:
            if event.key == py.K_LEFT and player.change_x <0:
                player.stop()
            if event.key == py.K_RIGHT and player.change_x > 0:
                player.stop()
    keys = py.key.get_pressed()
    if keys[py.K_s]:
        directionw = False
        directionh = True
        player.shrink(directionh, directionw)
    if keys[py.K_a]:
        directionh = False
        directionw = True
        player.shrink(directionh, directionw)
    directionh = False
    direcitonw = False
    if keys[py.K_w]:
        directionh = True
        direcitonw = False
        player.grow(directionh, directionw)
    if keys[py.K_d]:
        directionh = False
        directionw = True
        player.grow(directionh, directionw)






    screen.fill(WHITE)
    player.update()
    all_sprites_list.draw(screen)




    py.display.flip()
    clock.tick(60)






py.quit()`

Ive tried like block collisions but ive had issues detecting exactly which side actually collided and still really have no clue what the actual problem is.

0

There are 0 answers