Python Forum
[PyGame] Players not falling from the platform, and some other errors.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Players not falling from the platform, and some other errors.
#1
Hi, I'm kind of new at both python and pygame. I was trying to make a (very) simple platform fight game, and of course I found some errors I can't fix by myself. The first error I got when I was trying to make the players fall off from the platform whenever they do not stand on it anymore, and now they fall infinitely through it, making the players unable to move. Here's the lines of code I changed to make that happen, because I changed the original code so that does not happen, but players just float in the air if they are not in the platform:
   def apply_gravity(self):
        if self.jumping:
            self.jump_velocity += self.gravity * self.jump_slow
            self.y += self.jump_velocity
            if self.y >= 300:
                self.y = 300
                self.jumping = False
        if not self.check_collision(platform) and self.jumping == False:
            self.y += self.jump_velocity
        if self.y >= 0:
            self.y = 300
            self.deaths += 1
That's inside of the Player's class, and I also put player1.check_gravity() on the main loop.


The second error I got was that once one player dies while being attacked by the other one, both of them can't attack anymore, and the second player's image does not change to dead.png, even though I have put it as you can see here: (The first player's image works fine)
while player1.health <= 0:
        player1.x = 300
        player1.y = 200
        player1.health = 100
        player1.deaths += 1
        player1.state = "idling"
        player1.image = dead_image
    while player2.health <= 0:
        player2.x = 650
        player2.y = 200
        player2.health = 100
        player2.deaths += 1
        player2.image = dead_image
        player2.state = "idling"
The third error I got was that when a player spawns or respawns, it starts floating in the air, until they jump, making them able to even move from side to side.

Here's my entire code. Note that I have a different file for constant variables named constants.py. I will also paste its code here, just in case.

import pygame
import pygame.font
from pygame import display
from constants import *

pygame.init()

screen = pygame.display.set_mode(size)
pygame.display.set_caption("PUXKERBOIS ULTIMATE")
pygame.display.set_icon(icon)

class Player:
    def __init__(self, x, y, image_path, health, deaths):
        self.x = x
        self.y = y
        self.health = health
        self.deaths = deaths
        self.image = pygame.image.load(image_path)
        self.hitbox = pygame.Rect(x, y, self.image.get_width(), self.image.get_height())
        self.health = 100
        self.velocity = 3
        self.gravity = 0.1
        self.jumping = False
        self.jump_velocity = -3
        self.jump_slow = 0.75
        self.attack_image = pygame.image.load("attack.png")
        self.state = "idling"

    def move(self, dx, dy):
        self.x += dx * self.velocity
        self.y += dy * self.velocity
        self.hitbox.x += dx * self.velocity
        self.hitbox.y += dy * self.velocity

    def jump(self):
        if not self.jumping:
            self.jumping = True
            self.jump_velocity = -3.75 * self.jump_slow
    
    def attack(self, enemy):
        if self.hitbox.colliderect(enemy.hitbox):
            enemy.health -= 20
            self.state = "attacking"
            print(enemy.health)

    def apply_gravity(self):
        if self.jumping:
            self.jump_velocity += self.gravity * self.jump_slow
            self.y += self.jump_velocity
            if self.y >= 300:
                self.y = 300
                self.jumping = False

    def check_collision(self, object):
        if self.hitbox.colliderect(object.hitbox):
            self.y = object.y - self.hitbox.height
        if self.y >= height:
            self.deaths += 1
            self.y = 300
    
    def update(self):
        if self.state == "attacking":
            self.image = self.attack_image
            self.state = "idling"

    def draw(self, screen):
        screen.blit(self.image, (self.x, self.y))

    def draw_hitbox(self, screen):
        pygame.draw.rect(screen, (255, 0, 0), self.hitbox, 2)

class Platform:
    def __init__(self, x, y, width, height, image_path):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.image = pygame.image.load(image_path)
        self.hitbox = pygame.Rect(x, y, width, height)

    def draw(self, screen):
        screen.blit(self.image, (self.x, self.y))

def setcoors():
    raw = input("Please insert valid parameters (player: 1|2 x:int y:int): ")
    raw_list = [x for x in raw.split(" ")]
    x = int(raw_list[1])
    y = int(raw_list[2])
    if len(raw_list) > 3:
        print("Please insert valid parameters.")
    else:
        if raw_list[0] == "1":
            player1.x = x
            player1.y = y
        elif raw_list[0] == "2":
            player2.x = x
            player2.y = y
        else:
            print("Please insert valid parameters.")

def show_deaths(deaths):
    text = "Deaths: " + str(deaths)
    return text

def show_winner(winner):
    text = fThe winner is {winner}!"
    return text

player1 = Player(300, 200, "player.png", 100, 0)
player2 = Player(650, 200, "player.png", 100, 0)
player1.jump() #Note that I've called the jump() method here so the players fall to the platform and don't start floating (yet)
player2.jump()

platform = Platform(0, 60, 800, 100, "platform.png")

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        if event.type == pygame.MOUSEBUTTONUP:
            player2.attack(player1)
        else:
            player2.image = pygame.image.load("player.png")
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                player1.attack(player2)
            else:
                player1.image = pygame.image.load("player.png")
 
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_1:
                print(f"Player1: health: {player1.health}, deaths: {player1.deaths}")
                print(f"Player2: health: {player2.health}, deaths: {player2.deaths}")

    keys = pygame.key.get_pressed()
    if keys[pygame.K_a]:
        player1.move(-1, 0)
    if keys[pygame.K_d]:
        player1.move(1, 0)
    if keys[pygame.K_w]:
        player1.jump()
    if keys[pygame.K_LEFT]:
        player2.move(-1, 0)
    if keys[pygame.K_RIGHT]:
        player2.move(1, 0)
    if keys[pygame.K_UP]:
        player2.jump()
    if keys[pygame.K_e]:
        print(player1.x, player1.y)
    if keys[pygame.K_r]:
        print(player2.x, player2.y)
    if keys[pygame.K_x]:
        running = False
    if keys[pygame.K_t]:
        setcoors()
    if keys[pygame.K_2]:
        player1.draw_hitbox(screen)
        player2.draw_hitbox(screen)

    while player1.health <= 0:
        player1.x = 300
        player1.y = 200
        player1.health = 100
        player1.deaths += 1
        player1.state = "idling"
        player1.image = dead_image
    while player2.health <= 0:
        player2.x = 650
        player2.y = 200
        player2.health = 100
        player2.deaths += 1
        player2.image = dead_image
        player2.state = "idling"

    if player1.y > height:
        player1.deaths += 1
        player1.x = 300
        player1.y = 300
        player1.hitbox.x = player1.x
        player1.hitbox.y = player1.y
    if player2.y > height:
        player2.deaths += 1
        player2.x = 650
        player2.y = 300
        player2.hitbox.x = player2.x
        player2.hitbox.y = player2.y

    if player1.health <= 0:
        player2_winner_text = font.render(show_winner(player2), True, (255, 255, 255))
        screen.blit(player2_winner_text, (10, 10))
        player1.health = 20
    if player2.health <= 0:
        player1_winner_text = font.render(show_winner(player2), True, (255, 255, 255))
        screen.blit(player1_winner_text, (10, 10))
        player2.health = 20

    #This does not work
    player1_deaths_text = font.render(show_deaths(player1.deaths), True, (255, 255, 255))
    screen.blit(player1_deaths_text, (10, 10))
    player2_deaths_text = font.render(show_deaths(player2.deaths), True, (255, 255, 255))
    screen.blit(player2_deaths_text, (height - 200, 10))

    player1.check_collision(platform)
    player2.check_collision(platform)
    player1.update()
    player2.update()
    player1.apply_gravity()
    player2.apply_gravity()

    if player1.x <= player_width - 70:
        player1.x = player_width - 70
    if player1.x >= width - player_width:
        player1.x = width - player_width
    if player2.x <= player_width - 70:
        player2.x = player_width - 70
    if player2.x >= width - player_width:
        player2.x = width - player_width

    screen.blit(bg, (0, 0))
    player1.draw(screen)
    player2.draw(screen)

    platform.draw(screen)

    pygame.display.update()

pygame.quit
And here's the constants.py file's code:
import pygame
import pygame.font

pygame.init()

width = 1080
height = 720
size = (width, height)

icon = pygame.image.load("icon.png")
bg = pygame.image.load("bg.png")
player_image = pygame.image.load("player.png")
player_width = player_image.get_width()
dead_image = pygame.image.load("dead.png")

font = pygame.font.Font(None, 30)

running = True
Well, I hope I've been clear enough, any help is appreciated!
Reply
#2
Jumping is fun because it involves physics.

The player is always being pulled downward by gravity. When your player jumps, you give the player an upward velocity. Gravity slows the upward velocity over time. When the velocity is zero, the player is at the apex of the jump. Gravity is still pulling, so the player begins moving downward after reaching the apex. The player's downward fall gets faster and faster until it reaches terminal velocity or collides with something that prevents falling. Colliding with a platform stops the player's vertical motion and sets the players vertical speed to zero.

I modified you code to focus on jumping and falling. No deaths or health or even a second player. When posting code to the forum you should only post enough code to demonstrate the problem. My example only requires one image file to run. I removed the background image and special attack images because I don't have those, and they aren't needed to demonstrate jumping or falling. Same goes for the icom. Try to post examples that other people can run.
import pygame

width = 1080
height = 720
player_image = "games/dice0.png"
platform_image = "games/dice0.png"
screen = pygame.display.set_mode((width, height))
gravity = 0.025  # Acceleration due to gravity


class Player:
    def __init__(self, x, y, image):
        self.image = pygame.image.load(image)
        w, h = self.image.get_size()
        self.rect = pygame.Rect(x, y, w, h)
        self.velocity = 1  # How fast I can run
        self.jump_velocity = 4  # How fast I move when I jump
        self.terminal_velocity = 2  # Fastest I fall
        self.dx = 0  # X velocity
        self.dy = 0  # Y velocity

    def move(self, direction):
        """Move horizontally"""
        self.dx = direction * self.velocity

    def jump(self):
        """Move vertically.  Just be standing on something to jump"""
        if self.dy == 0:
            self.dy = -self.jump_velocity

    def update(self, platforms):
        """Update player position"""
        # Move player.  Cannot exceed terminal velocity while falling
        self.dy = min(self.terminal_velocity, self.dy + gravity)
        self.rect.x += self.dx
        self.rect.y += self.dy

        # Check if player going off edge of screen
        if self.rect.y > height:
            self.rect.y = 0  # For demo purposes jump up to top of screen
        if self.rect.x < 0:
            self.rect.x = 0
        elif self.rect.right > width:
            self.rect.right = width

        # Check for collisions with platforms
        for platform in platforms:
            if self.rect.colliderect(platform.rect):
                if self.dy > 0:
                    self.dy = 0
                    self.rect.bottom = platform.rect.top
                elif self.dy < 0:
                    self.dy = 0
                    self.rect.top = platform.rect.bottom

    def draw(self, screen):
        screen.blit(self.image, (self.rect.x, self.rect.y))


class Platform:
    def __init__(self, x, y, width, height, image):
        self.image = pygame.image.load(image)
        self.image = pygame.transform.scale(self.image, (width, height))
        self.rect = pygame.Rect(x, y, width, height)

    def draw(self, screen):
        screen.blit(self.image, (self.rect.x, self.rect.y))


platforms = (
    Platform(0, 300, 600, 20, platform_image),
    Platform(500, 600, 600, 20, platform_image),
)
player1 = Player(300, -100, player_image)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    keys = pygame.key.get_pressed()
    if keys[pygame.K_a]:
        player1.move(-1)
    elif keys[pygame.K_d]:
        player1.move(1)
    else:
        player1.move(0)  # Stop running
    if keys[pygame.K_w]:
        player1.jump()

    player1.update(platforms)

    screen.fill("black")
    player1.draw(screen)
    for platform in platforms:
        platform.draw(screen)
    pygame.display.update()

pygame.quit
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyGame] Having 4 players(Sprites) all being able to jump ElijahCastle 5 4,015 May-07-2019, 05:04 PM
Last Post: SheeppOSU

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020