How to fix infinite jump bug in pygame? - python

I am trying to make a game, but you can keep spamming "w" (jump) for infinite height which is really bad when you are trying to make a platformer game. This is all my code:
GRAVITY = .2
diedorgameover = False
while not diedorgameover:
for event in pygame.event.get():
if event.type == pygame.QUIT:
diedorgameover = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
x_change = -5
elif event.key == pygame.K_d:
x_change = 5
elif event.key == pygame.K_s:
y_change = 5
elif event.key == pygame.K_w:
y_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
x_change = 0
if event.key == pygame.K_s or event.key == pygame.K_w:
y_change = 0
#adding gravity to y_value
y_change += GRAVITY
x += x_change
y += y_change
if y >= gameDisplay.get_height() - 68:
y = gameDisplay.get_height() - 68
y_change = 0
#draw everything
gameDisplay.blit(background_image,(0,0))
red(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
I would really appreciate it if you have any insight on this problem.

You can define a on_ground variable that you set to True if the player touches the ground. When the user wants to jump (presses 'w') you first check if on_ground: and then change the y_change and set on_ground to False.
import pygame
pygame.init()
gameDisplay = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
GRAVITY = .5
player_img = pygame.Surface((30, 50))
player_img.fill((40, 120, 200))
x = 100
y = 500
x_change = 0
y_change = 0
on_ground = False
diedorgameover = False
while not diedorgameover:
for event in pygame.event.get():
if event.type == pygame.QUIT:
diedorgameover = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
x_change = -5
elif event.key == pygame.K_d:
x_change = 5
elif event.key == pygame.K_s:
y_change = 5
elif event.key == pygame.K_w:
# Only jump if the player is on the ground.
if on_ground:
y_change = -12
on_ground = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
x_change = 0
y_change += GRAVITY
x += x_change
y += y_change
# If the player is on the ground.
if y >= gameDisplay.get_height() - 68:
y = gameDisplay.get_height() - 68
y_change = 0
on_ground = True
gameDisplay.fill((30, 30, 30))
gameDisplay.blit(player_img, (x, y))
pygame.display.update()
clock.tick(60)
pygame.quit()
Also delete these lines, otherwise the player can stop while in the air if the key is released:
if event.key == pygame.K_s or event.key == pygame.K_w:
y_change = 0

for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == KEYDOWN:
if event.key == K_SPACE and y_change == 0: # if spacebar is pressed and y_change is 0
y_change = 18 # set y_change to 18
if y_change > 0 and player_y == 200: # if y_change is greater than 0 and player_y is 200
player_y -= y_change
y_change -= gravity
if player_y > 200:
player_y = 200
if player_y == 200 and y_change < 0:
y_change = 0

Related

How to make enemies fall at random on pygame?

I want enemies to randomly fall from the sky on my game and I do not know how to do this.
I was using this youtube video: Falling Objects in Pygame.
import pygame, random
pygame.init()
screen_width = 800
screen_height = 600
window = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Test')
time = pygame.time.Clock()
bg_color1 = (135, 142, 142) # MAIN BG COLOR
bg_color2 = (255, 0, 0) # red
bg_color3 = (255, 255, 0) # yellow
UFO = pygame.image.load('ufo.png')
bg_pic = pygame.image.load('Letsgo.jpg')
clock = pygame.time.Clock()
playerImg = pygame.image.load('enemy.png')
playerX = random.randrange(0, screen_width)
playerY = -50
playerX_change = 0
player_speed = 5
def player(x, y):
window.blit(playerImg, (playerX, playerY))
crashed = False
rect = UFO.get_rect()
obstacle = pygame.Rect(400, 200, 80, 80)
menu = True
playerY = playerY + player_speed
if playerY > screen_height:
playerX = random.randrange(0,screen_width)
playerY = -10
def ufo(x, y):
window.blit(UFO, (x, y))
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
menu = False
window.fill((0, 0, 0))
time.tick(30)
window.blit(bg_pic, (0, 0))
pygame.display.update()
x = (screen_width * 0.45)
y = (screen_height * 0.8)
x_change = 0
car_speed = 0
y_change = 0
while not crashed:
x += x_change
if x < 0:
x = 0
elif x > screen_width - UFO.get_width():
x = screen_width - UFO.get_width()
y += y_change
if y < 0:
y = 0
elif y > screen_height - UFO.get_height():
y = screen_height - UFO.get_height()
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
############SIDE TO SIDE################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
###########UP AND DOWN#################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
##
x += x_change
y += y_change
##
window.fill(bg_color1)
ufo(x, y)
player(playerX, playerY)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()
So the code that was supposed to make the image fall was this
if playerY > screen_height:
playerX = random.randrange(0,screen_width)
playerY = -10
Move the following code:
if playerY > screen_height:
playerX = random.randrange(0,screen_width)
playerY = -10
To here so it can be within the game loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
############SIDE TO SIDE################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
###########UP AND DOWN#################
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -5
elif event.key == pygame.K_DOWN:
y_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
if playerY > screen_height:
playerX = random.randrange(0,screen_width)
playerY = -10

pygame Sprite Movement

Below I have defined a pygame game loop. I am able to move the sprite in 8 directions.
#player position
def player(x,y):
screen.blit(playerImg, (x, y))
#enemy position
def enemy(x,y):
screen.blit(enemyImg, (x, y))
def fire_bullet(x,y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletImg, (x + 16, y + 10))
# Game Loop
running = True
while running:
#fill values RGB - Red, Green, Blue
screen.fill(bc.goodblue)
#background immage
screen.blit(background, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#if keystroke is pressed
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
playerx_change = -movespeed
if event.key == pygame.K_RIGHT or event.key == ord('d'):
playerx_change = movespeed
if event.key == pygame.K_UP or event.key == ord('w'):
playery_change = -movespeed
if event.key == pygame.K_DOWN or event.key == ord('s'):
playery_change = movespeed
if event.key == pygame.K_SPACE and bullet_state == "ready":
bulletx = playerx
fire_bullet(bulletx, bullety)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == ord('a') or event.key == ord('d'):
playerx_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == ord('s') or event.key == ord('w'):
playery_change = 0
#player movement
playery += playery_change
playerx += playerx_change
if playerx <= 0:
playerx = 0
if playerx >= width - PImgWidth:
playerx = width - PImgWidth
if playery <=0:
playery = 0
if playery >=height - PImgHeight:
playery = height - PImgHeight
#enemy movement
enemyx += enemyx_change
if enemyx <= 0:
enemyx_change = enemyspeed
enemyy += enemyy_change
if enemyx >= width - EImgWidth:
enemyx_change = -enemyspeed
enemyy += enemyy_change
player(playerx, playery)
enemy(enemyx, enemyy)
pygame.display.update()
pygame.quit()
However, there is one small issue.
If I press the left arrow key the sprite moves to the left. If I then also press the right arrow key the sprite starts moving to the right.
If I then let go of the left arrow key the sprite stops. I don't want this to happen. If I'm moving in the right direction and I let go of the left arrow key I want to keep moving in the right direction.
I don't know an efficient way to set this up.
If you release the LEFT, RIGHT, a or d you have to check whether one of these keys is still pressed before you can set playerx_change = 0:. Use pygame.key.get_pressed() to evaluate the state of the keys:
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == ord('a') or event.key == ord('d'):
keys = pygame.key.get_pressed()
if not keys[pygame.K_LEFT] and not keys[pygame.K_RIGHT] and not keys[pygame.K_a] and not keys[pygame.K_d]:
playerx_change = 0
Do the same for UP, DOWN, s respectively w
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
playerx_change = -movespeed
if event.key == pygame.K_RIGHT or event.key == ord('d'):
playerx_change = movespeed
if event.key == pygame.K_UP or event.key == ord('w'):
playery_change = -movespeed
if event.key == pygame.K_DOWN or event.key == ord('s'):
playery_change = movespeed
if event.key == pygame.K_SPACE and bullet_state == "ready":
bulletx = playerx
fire_bullet(bulletx, bullety)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_a or event.key == pygame.K_d:
keys = pygame.key.get_pressed()
if not keys[pygame.K_LEFT] and not keys[pygame.K_RIGHT] and not keys[pygame.K_a] and not keys[pygame.K_d]:
playerx_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_s or event.key == pygame.K_w:
keys = pygame.key.get_pressed()
if not keys[pygame.K_UP] and not keys[pygame.K_DOWN] and not keys[pygame.K_s] and not keys[pygame.K_w]:
playery_change = 0

Block only moves once on KEYDOWN (Python3.6 - Pygame)

My name is Jeremy and I am learning Python. I am a beginner and I just started a couple of days ago.
I am making a simple game in Python, and I would like my block/player to move continuously while the respective arrow key is held down. As of now, it only moves once when pressing down the arrow keys. Any help is greatly appreciated. Thank you!
Here is the code I've written:
import pygame
import time
import random
pygame.init()
display_width = 800
display_height = 600
black = (0,0,0)
white = (255,255,255)
red = (200,0,0)
green = (0,200,0)
bright_red = (255,0,0)
bright_green = (0,255,0)
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Game')
clock = pygame.time.Clock()
blockImg = pygame.image.load('blockpic.png')
def block(x,y):
gameDisplay.blit(blockImg, (x,y))
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
y_change = 0
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -10
if event.key == pygame.K_RIGHT:
x_change = 10
if event.key == pygame.K_UP:
y_change = -10
if event.key == pygame.K_DOWN:
y_change = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
y_change = 0
x += x_change
y += y_change
gameDisplay.fill(white)
block(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Your code is not indented correctly. The line x += x_change and the five lines beneath are inside of the event loop, so they get executed once per event in the event queue. Just dedent these lines to fix the program.
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -10
if event.key == pygame.K_RIGHT:
x_change = 10
if event.key == pygame.K_UP:
y_change = -10
if event.key == pygame.K_DOWN:
y_change = 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
y_change = 0
# The following lines should be executed once per frame not
# once per event in the event queue.
x += x_change
y += y_change
gameDisplay.fill(white)
block(x,y)
pygame.display.update()
clock.tick(60)

Pygame moving objects while pressing key

I have a problem moving the objects continuously while pressing a key.
As far as I know, pygame events only trigger when receiving a new signal and that the key pressed is not a signal that continues with every frame. From the code below, when I press w for example, the object only moves when pressing and when releasing the key. I can't achieve the object to move as long as I keep pressing the key. I've also tried out the if statements by checking event.key instead of checking the get_pressed() list, but I came up with the same result.
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
keys = pygame.key.get_pressed()
print(keys[pygame.K_w])
if keys[pygame.K_w] and keys[pygame.K_d]:
x_change = 3
x += x_change
y_change = -3
y += y_change
elif keys[pygame.K_w] and keys[pygame.K_a]:
x_change = -3
x += x_change
y_change = -3
y += y_change
elif keys[pygame.K_s] and keys[pygame.K_d]:
x_change = 3
x += x_change
y_change = 3
y += y_change
elif keys[pygame.K_s] and keys[pygame.K_a]:
x_change = -3
x += x_change
y_change = 3
y += y_change
elif keys[pygame.K_a]:
x_change = -3
x += x_change
elif keys[pygame.K_d]:
x_change = 3
x += x_change
elif keys[pygame.K_w]:
y_change = -3
y += y_change
elif keys[pygame.K_s]:
y_change = 3
y += y_change
#ERASE OLD
screen.fill(WHITE)
#FILL NEW
all_sprites_list.draw(screen)
wall.changePosition(x,y)
player.draw(start_x,start_y)
pygame.display.update()
clock.tick(60)
It looks like the line keys = pygame.key.get_pressed() and the following lines are in your event loop, and that means they are only executed once per event in the event queue. They should actually be in the outer while loop, so just dedent these lines:
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
keys = pygame.key.get_pressed()
if keys[pygame.K_w] and keys[pygame.K_d]:
x_change = 3
# etc.
You can also shorten your code quite a bit:
x_change = 3
y_change = 3
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
x += -x_change
elif keys[pygame.K_d]:
x += x_change
if keys[pygame.K_w]:
y += -y_change
elif keys[pygame.K_s]:
y += y_change
Another alternative would be to remove the key.get_pressed lines and just set the x_change and y_change in the event loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
x_change = 3
# etc.
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d and x_change > 0:
x_change = 0
# etc.

Pygame won't let me make boundaries on a screen with the event module

So I'm just making a simple game that allows a red rectangle to move around the screen, but the boundaries that should make the red rectangle stop before it gets off the screen won't work. Can someone tell me what I'm doing wrong?
while Game:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
gameDisplay = pygame.display.set_mode((display_width,display_height), pygame.FULLSCREEN)
if event.key == pygame.K_2:
gameDisplay = pygame.display.set_mode((display_width,display_height))
if event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_UP:
y_change = -5
if event.key == pygame.K_DOWN:
y_change = 5
if x > display_width - 100 or x < 0 and event.key == pygame.K_RIGHT:
if event.key == pygame.K_LEFT:
x_change = -5
else:
x_change = 0 #I did this for all directions
x += x_change
y += y_change
Just so you know, clock.tick is 80 and I have imported pygame and did the pygame.init() thing. Also, movement and every thing else works, just not this.
Try this code:
def clamp(value, minimum=0, maximum=1): return max(minimum, min(value, maximum))
maxX = display_width-rectangle_width
maxY = display_height-rectangle_height
if x not in range(maxX): x_change = 0
if y not in range(maxY): y_change = 0
x = clamp(x, maximum=maxX)
y = clamp(y, maximum=maxY)
However, you are changing the velocity and not the position, when it is out of the screen, the velocity is not moving it back, it keeps there or the speed from the pressed key in the next frame moves it again.

Categories

Resources