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.