Player colliding with screen sides not working

Viewed 35

So I tried to make it so that if the player collides with one of the sides of the screen, lets say right, the player will start moving to the left side. This is the same case for the left side but the player will move right. I have tried to write this code[bellow] in different ways but most of the time the player will just be stuck like this:https://gyazo.com/9e769e32f9e91e8dffc2fdc5ee6f4457

The code I wrote to try to make player move left or right when it touches one of the sides of the screen

if playerman.x < 30:
        px += playerman.speed
    elif playerman.x < 670:
        px -= playerman.speed
    else:
        px -= playerman.speed

My full code

import pygame
import random
pygame.init()

window = pygame.display.set_mode((700,500))
pygame.display.set_caption(("Noobs First Game"))

# Player class
class Player:
    def __init__(self,x,y,width,height,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.speed = 6
        self.fall = 0
        self.run = [pygame.image.load("Player_run1.png"),
                    pygame.image.load("Player_run2.png"),
                    pygame.image.load("Player_run3.png"),
                    pygame.image.load("Player_run4.png"),
                    pygame.image.load("Player_run5.png"),
                    pygame.image.load("Player_run6.png"),
                    pygame.image.load("Player_run7.png"),
                    pygame.image.load("Player_run8.png")]
        
        self.jump = [pygame.image.load("Player_Jump.png")]

        self.lrun = [pygame.image.load("Player_lrun1.png"),
                    pygame.image.load("Player_lrun2.png"),
                    pygame.image.load("Player_lrun3.png"),
                    pygame.image.load("Player_lrun4.png"),
                    pygame.image.load("Player_lrun5.png"),
                    pygame.image.load("Player_lrun6.png"),
                    pygame.image.load("Player_lrun7.png"),
                    pygame.image.load("Player_lrun8.png")]

        self.ljump = [pygame.image.load("Player_lJump.png")]

        self.direction = "run"
        self.direction = "jump"
        self.direction = "lrun"
        self.direction = "ljump"
        self.run = [pygame.transform.scale(image,(image.get_width()//6,image.get_height()//6))for image in self.run]
        self.jump = [pygame.transform.scale(image,(image.get_width()//6,image.get_height()//6))for image in self.jump]
        self.lrun = [pygame.transform.scale(image,(image.get_width()//6,image.get_height()//6))for image in self.lrun]
        self.ljump = [pygame.transform.scale(image,(image.get_width()//6,image.get_height()//6))for image in self.ljump]

        self.isJump = False
        self.JumpCount = 10
        self.rect = pygame.Rect(x,y,width,height)
        self.next_frame_time = 0
        self.fps = 10
        self.clock = pygame.time.Clock()
        self.anim_index = 0
    def get_rect(self):
        self.rect.topleft = (self.x,self.y)
        return self.rect
    def draw(self):
        if self.direction == "run":
            image_list = self.run
        if self.direction == "jump":
            image_list = self.jump
        if self.direction == "lrun":
            image_list = self.lrun
        if self.direction == "ljump":
            image_list = self.ljump

        # Is it time to show next frame?
        time_now = pygame.time.get_ticks()
        if (time_now > self.next_frame_time):
            # seconds till next frame
            inter_time_delay = 1000 // self.fps
            self.next_frame_time = time_now + inter_time_delay
            # switch to next frame
            self.anim_index += 1
            if self.anim_index >= len(image_list):
                self.anim_index = 0

        if self.anim_index >= len(image_list):
            self.anim_index = 0
        player_image = self.run[self.anim_index]

        pygame.draw.rect( window, self.color, self.get_rect(), 2 )
        player_image = image_list[self.anim_index]

        player_rect = player_image.get_rect(center = self.get_rect().center)
        player_rect.centerx += 3
        player_rect.centery -= 17
        window.blit(player_image, player_rect)

# Platform class
class Platform:
    def __init__(self,x,y,width,height,color):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.color = color
        self.rect = pygame.Rect(x,y,width,height)
    def draw(self):
        self.rect.topleft = (self.x,self.y)
        pygame.draw.rect(window,self.color,self.rect)


# displaying Color
white = (255,255,255)

# Drawing player
playerman = Player(255,255,40,40,white)

# Drawing Platform
platform1 = Platform(200,300,700,30,white)

# Putting Platform in a list
platforms = [platform1]


# redrawing window
def redrawwindow():
    window.fill((0,0,0))
    
    # bliting a counter the game
    window.blit(text,textRect)
    # showing player on the screen
    playerman.draw()

    # Drawing Platform
    for Platform in platforms:
        Platform.draw()

# The conter and how its going look like
font = pygame.font.Font("freesansbold.ttf",30)
score = 0
text = font.render(" = "+str(score),True,(255,255,255))
textRect = text.get_rect()
textRect.center = ((150,40))


fps = 30
clock = pygame.time.Clock()

x = 10
y = 10

x_change = 0
y_change = 0

old_x = x
old_y = y

# Space down = False
spcdown = False
run = True
while run:
    clock.tick(fps)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()


    



            


        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_d:
                x_change = -7
            if event.key == pygame.K_a:
                x_change = 7

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_d or event.key == pygame.K_a:
                x_change = 0

            x += x_change
            if x > 500 - playerman.width or x < 0:
                x = old_x

            
        

    # If keys get pressed
    keys = pygame.key.get_pressed()
    px,py = playerman.x,playerman.y

    if playerman.x < 30:
        px += playerman.speed
    elif playerman.x < 670:
        px -= playerman.speed
    else:
        px -= playerman.speed

    # Adding one to score every time player jumps
    if not keys[pygame.K_SPACE]:
        spcdown = False  # space released
    
    if keys[pygame.K_SPACE]:
        if not spcdown:
            score += 1  # if space pressed first time
        spcdown = True  # space key is pressed
        text = font.render(" = "+str(score),True,(255,255,255))
        textRect.center = ((150,40))
        


    # Player movment
    if keys[pygame.K_a] and playerman.x > playerman.speed:
        px -= playerman.speed
        playerman.direction = "lrun"

    if keys[pygame.K_d] and playerman.x < 700 - playerman.width - playerman.speed:
        px += playerman.speed
        playerman.direction = "run"

    if keys[pygame.K_w] and playerman.y > playerman.speed:
        py -= playerman.speed

    if keys[pygame.K_s] and playerman.y < 500 - playerman.height - playerman.speed:
        py += playerman.speed

    # animation for player jump
    if playerman.direction == "run":
        if keys[pygame.K_SPACE]: 
            playerman.direction = "jump"
    else:
        if playerman.direction == "lrun":
            if keys[pygame.K_SPACE]:
                playerman.direction = "ljump"


    platform_rect_list =[p.rect for p in platforms]
    player_rect = playerman.get_rect()
    playerman.rect.topleft = (px,py)


    playerman.y = py
    if player_rect.collidelist(platform_rect_list) < 0:
        playerman.x = px
        
    # About isJump
    if not playerman.isJump:
        playerman.y += playerman.fall
        playerman.fall += 1
        playerman.isJump = False

            # this part lets you jump on platform only the top 
        collide = False
        for Platform in platforms:
            if playerman.get_rect().colliderect(Platform.rect):
                collide = True
                playerman.isJump = False
                playerman.y = Platform.rect.top - playerman.height
                if playerman.rect.right > Platform.rect.left and playerman.rect.left < Platform.rect.left - playerman.width:
                    playerman.x = Platform.rect.left - playerman.width
                if playerman.rect.left < Platform.rect.right and playerman.rect.right > Platform.rect.right + playerman.width:
                    playerman.x = Platform.rect.right
                           
                # colliding with floor      
            if playerman.rect.bottom >= 500:
                collide = True
                playerman.isJump = False
                playerman.Jumpcount = 10
                playerman.y = 500 - playerman.height

            # Jumping
        if collide:
            if keys[pygame.K_SPACE]:
                playerman.isJump = True
            playerman.fall = 0

    # Jump Count

    else:
        if playerman.JumpCount >= 0:
            playerman.y -= (playerman.JumpCount*abs(playerman.JumpCount))*0.3
            playerman.JumpCount -= 1
        else:
            playerman.isJump = False
            playerman.JumpCount = 10

        
            
    redrawwindow()
    pygame.display.update()
quit_game

1 Answers

Consider your updating logic:

px,py = playerman.x,playerman.y

if playerman.x < 30:
    px += playerman.speed
elif playerman.x < 670:
    px -= playerman.speed
else:
    px -= playerman.speed

Thinking this through as-if we were Rubber Duck debugging, say the player is in the middle of the screen playerman.x == 250. We walk through the code manually, as the python interpreter does, calling it out to our duck:

when playerman.x equals 250
is playerman.x < 30 ... FALSE
is playerman.x < 670 ... TRUE
    move player left

It looks like that should be > not < !?

But please consider always adding playerman.speed, and then simply inverting it to change directions. So when going right, the speed is +5 but when going left it's -5. That way on a collision you can invert the speed:

playerman.speed *= -1    # reverse direction

Your code would be a lot simpler if you used a single PyGame Rect for your player position. Right now you've got:

playerman.rect
playerman.x, playerman.y
px, py
player_rect
player_image.get_rect()

All vying to take part in the position of the player. It's making your code confusing to both write and debug. Take some time now to remove unnecessary co-ordinates and rects, using either a single x,y pair, or a rect. Then do everything with that. It will save your future-self a lot of boring toil.

Related