Python, object after jumping doesn't fall down. Fix? - python

i have a program in which a square is supposed to jump, then fall down. For some reason, the square is jumping but it doesn't fall down. I'm not sure what's the issue is, i hope you could help me fix it. jumping gif
Here i'm displaying the window while the game is being played
#DISPLAY WINDOW
def draw_window(square):
#SCREEEN
WIN.fill(black)
#OBJECTS
#LINE
pygame.draw.line(WIN, white, (0, 400), (900, 400), 10)
#SQUARE
square.draw()
pygame.display.update()
Here i'm defining a square class and it's methods including jumping
#SQUARE
class Square():
def __init__(self):
self.y = 295
self.vel = 10
def draw(self):
pygame.draw.rect(WIN, red, [50, self.y, 100, 100])
def jump(self, jumpCount):
if jumpCount >= -10:
neg = 1
if jumpCount < 0:
neg = -1
self.y -= (jumpCount ** 2) * 0.05 * neg
jumpCount -= 1
else:
jump = False
jumpCount = 10
Here is the main game loop with all functions
def main():
jump = False
jumpCount = 10
square = Square()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#JUMPING
if event.type == pygame.KEYDOWN:
if not jump and event.key == pygame.K_SPACE:
jump = True
if jump:
square.jump(jumpCount)
draw_window(square)
pygame.quit()

Here are some modifications to your code:
In the class Square, draw method should pass in a pygame.Rect as a parameter of pygame.draw.rect.
The jump method of Square created local variable jump and jump_count, changes to these variables will not affect the variable in main(). So you have to return these values and update them in main()
Full Code:
import pygame
clock = pygame.time.Clock()
WIN = pygame.display.set_mode((800, 600))
red = (255, 0, 0)
white = (255, 255, 255)
black = (0, 0, 0)
FPS = 60
class Square():
def __init__(self):
self.y = 295
self.vel = 10
def draw(self):
pygame.draw.rect(WIN, red, pygame.Rect(50, self.y, 100, 100))
def jump(self, jumpCount):
jump = True
if jumpCount >= -10:
neg = 1
if jumpCount < 0:
neg = -1
self.y -= (jumpCount ** 2) * 0.05 * neg
jumpCount -= 1
else:
jump = False
jumpCount = 10
return jump, jumpCount
#DISPLAY WINDOW
def draw_window(square):
#SCREEEN
WIN.fill(black)
#OBJECTS
#LINE
pygame.draw.line(WIN, white, (0, 400), (900, 400), 10)
#SQUARE
square.draw()
pygame.display.update()
def main():
jump = False
jumpCount = 10
square = Square()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#JUMPING
if event.type == pygame.KEYDOWN:
if not jump and event.key == pygame.K_SPACE:
jump = True
if jump:
jump, jumpCount = square.jump(jumpCount)
draw_window(square)
pygame.quit()
main()
Output:

Related

Replaying the main loop with a few changes pygame

I have been trying to make a Fangame for Undertale with pygame but i am stuck. This is my first project. I want to replay the main loop with a few changes, for example i want the knife movement to be different, but i dont know how to do it. I have tried with attack2 to replay everything but it doesnt work, for example the player can't move and the knife is also not moving. I also tried defining the main loop but then i can't change anything. Please comment if you can help me. This is the code i have:
import math
import pygame
from pygame import mixer
pygame.init()
screen = pygame.display.set_mode((1000, 800))
# FPS
FPS = 60
clock = pygame.time.Clock()
# Title and icon
pygame.display.set_caption("CharaFight")
icon = pygame.image.load('Chara.png')
pygame.display.set_icon(icon)
# images
fight_button = pygame.image.load('Fight.png')
fight_button2 = pygame.image.load('Fight2.png')
hp_bar1 = pygame.image.load('hp_bar.png')
hp_bar2 = pygame.image.load('hp_bar2.png')
# music and sounds
background_muziek = mixer.music
damage_sound = mixer.Sound('Undertale Sound Effect - Taking Damage.wav')
background_muziek.load('Prepare for Battle!.wav')
background_muziek.set_volume(0.4)
background_muziek.play(-1)
# backgrounds
background = pygame.image.load("Background1.png")
background2 = pygame.image.load("Background2.png")
# Player
playerImg = pygame.image.load("Soul.png")
PlayerX = 450
PlayerY = 550
PlayerX_change = 0
PlayerY_change = 0
HP = 0
# Enemy
enemyImg = pygame.image.load("Chara2.png")
charaImg = pygame.image.load("Chara3.png")
EnemyX = 390
EnemyY = 50
EnemyX_change = 0
EnemyY_change = 0
# Knife
knifeImg = pygame.image.load("knife.png")
KnifeX = 350
KnifeY = 580
KnifeX_change = 5
KnifeY_change = 0
Knife_state = "ready"
# Game over text
over_font = pygame.font.Font('8-BIT WONDER.TTF', 64)
det_font = pygame.font.Font('8-BIT WONDER.TTF', 30)
emy_font = pygame.font.Font('Determination_text.ttf', 45)
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
det_text = det_font.render(" Stay Determined ", True, (255, 255, 255))
screen.blit(over_text, (230, 250))
screen.blit(det_text, (280, 400))
def enemy_text():
chara_text = emy_font.render(" * Give me your SOUL! ", True, (255, 255, 255))
screen.blit(chara_text, (150, 500))
def fade(width, height):
fade1 = pygame.Surface((width, height))
fade1.fill((0, 0, 0))
for alpha in range(0, 150):
fade1.set_alpha(alpha)
screen.blit(fade1, (0, 0))
pygame.display.update()
pygame.time.delay(5)
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y):
screen.blit(enemyImg, (x, y))
def fire_knife(x, y):
global Knife_state
Knife_state = "fire"
screen.blit(knifeImg, (x, y))
def isCollision(PlayerX, PlayerY, KnifeX, KnifeY):
distance = math.sqrt(math.pow(PlayerX - KnifeX, 2) + (math.pow(PlayerY - 37 - KnifeY, 2)))
if distance < 27:
return True
else:
return False
# Here is my attempt to replay the main loop
def attack2():
screen.fill((0, 0, 0))
player(PlayerX, PlayerY)
enemy(EnemyX, EnemyY)
fire_knife(KnifeY, KnifeX)
screen.blit(background, (100, 300))
pygame.display.flip()
# main loop
running = True
while running:
screen.fill((0, 0, 0))
screen.blit(background, (100, 300))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
PlayerX_change = -2.5
if event.key == pygame.K_RIGHT:
PlayerX_change = 2.5
if event.key == pygame.K_UP:
PlayerY_change = -2.5
if event.key == pygame.K_DOWN:
PlayerY_change = 2.5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
PlayerX_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
PlayerY_change = 0
# Boundaries for player
PlayerY += PlayerY_change
if PlayerY >= 700:
PlayerY = 700
elif PlayerY <= 520:
PlayerY = 520
PlayerX += PlayerX_change
if PlayerX <= 370:
PlayerX = 370
elif PlayerX >= 570:
PlayerX = 570
# Knife movement
if KnifeX >= 550:
KnifeX = 340
KnifeY += 20
Knife_state = "ready"
if KnifeY >= 680:
KnifeY = 480
Knife_state = "ready"
if Knife_state == "fire":
fire_knife(KnifeX, KnifeY)
KnifeX += KnifeX_change
# collision and game over screen
collision = isCollision(PlayerX, PlayerY, KnifeX, KnifeY)
if collision:
Knife_state = "ready"
damage_sound.set_volume(1.5)
damage_sound.play()
HP += 1
if HP > 100:
fade(1000, 800)
screen.fill((0, 0, 0))
game_over_text()
background_muziek.stop()
game_over_sound = mixer.music
game_over_sound.load('Undertale Game Over Theme.wav')
game_over_sound.play(-1)
pygame.display.flip()
pygame.time.wait(5000)
while True:
if pygame.key.get_pressed():
running = True
pygame.quit()
# Fight screen
if pygame.time.get_ticks() > 21700:
fade(1000, 800)
screen.fill((0, 0, 0))
enemy_text()
screen.blit(background2, (140, 250))
screen.blit(charaImg, (390, 50))
screen.blit(fight_button, (330, 630))
screen.blit(hp_bar1, (440, 350))
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
screen.blit(fight_button2, (330, 630))
screen.blit(hp_bar2, (440, 350))
damage_sound.set_volume(10)
damage_sound.play()
pygame.display.flip()
pygame.time.wait(5000)
attack2()------------------> here i try to replay the main loop but i cant move and the knife is also not moving.
if pygame.key.get_pressed():
running = True
clock.tick(FPS)
player(PlayerX, PlayerY)
enemy(EnemyX, EnemyY)
fire_knife(KnifeX, KnifeY)
pygame.display.update()
You can use a class like this to animate stuff:
import pygame
from os import listdir, path
def load_animations(folder_path: str) -> tuple:
animation = listdir(folder_path)
animation = tuple(pygame.image.load(path.join(folder_path, frame)).convert_alpha() for frame in animation)
return animation
class Animation:
def __init__(self, FPS: int, animation_folder: str, speed: float, pos: tuple):
self.animation = load_animations(animation_folder)
self.speed = speed
self.FPS = FPS
self.current_frame = 0
self.image = None
self.rect = None
self.pos = pos
def get_frame(self) -> pygame.Surface:
self.current_frame += self.speed * 10 / self.FPS
if self.current_frame >= len(self.animation):
return
return self.animation[int(self.current_frame)]
def play(self, screen: pygame.Surface):
self.image = self.get_frame()
if not self.image:
return
self.rect = self.image.get_rect(center=self.pos)
screen.blit(self.image, self.rect)
And to use this you would do something like:
animation = Animation(60, "path to the folder", 1, (100, 100))
# Put this inside the main loop.
animation.play(# Put the display surface in here)
And you should make a draw function for your whole game and put this code inside of the draw function (This function should handle all the graphics of your game).

I need to be able to pause the whole game, but only my car sprite pauses when I press the p key on my keyboard

I implemented a pause feature in my game in the while loop at the end of my code, but the problem is that only my car sprite pauses. I have tried a bunch of different ways setting up my pause code but none of the ways I arrange it seems to pause the whole game.
I want to be able to pause my whole game when I press the p key on my keyboard, not just my car sprite. Can someone please tell me how I can fix this code? The code that will pause the whole game will be nice. Please, the rearranged code that will pause the whole game will help. Also I don't just want the answer, I want a quick explanation of why only my car sprite would pause instead of the whole game.
My code:
import random
import pygame
import pygame.freetype
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
self.score = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#check collision
def collision(self, debris_group):
for debris in debris_group:
if debris.health > 0 and pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
self.score += 1
#player stats/score
def stats(self):
myfont = pygame.font.SysFont('comicsans', 30)
scoretext = myfont.render("Score: " + str(self.score), 1, (0,0,0))
screen.blit(scoretext, (100,10))
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.centery < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self,scale,speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = random.randrange(100,800)
self.speed_y = 10
self.y = 15
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
self.velocity = random.randrange(1,2)
self.speed_x = random.randrange(-3,3)
self.moving_down = True
self.is_destroyed = False
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.rect.center = (self.x,self.y)
#load explosion
self.img_explosion_00 = pygame.image.load('explosion/0.png').convert_alpha()
self.img_explosion_00 = pygame.transform.scale(self.img_explosion_00, (self.img_explosion_00.get_width() * 2,
self.img_explosion_00.get_height() * 2))
self.img_explosion_01 = pygame.image.load('explosion/1.png').convert_alpha()
self.img_explosion_01 = pygame.transform.scale(self.img_explosion_01, (self.img_explosion_01.get_width() * 2,
self.img_explosion_01.get_height() * 2))
self.img_explosion_02 = pygame.image.load('explosion/2.png').convert_alpha()
self.img_explosion_02 = pygame.transform.scale(self.img_explosion_02, (self.img_explosion_02.get_width() * 2,
self.img_explosion_02.get_height() * 2))
self.img_explosion_03 = pygame.image.load('explosion/3.png').convert_alpha()
self.img_explosion_03 = pygame.transform.scale(self.img_explosion_03, (self.img_explosion_03.get_width() * 2,
self.img_explosion_03.get_height() * 2))
#explosion list
self.anim_explosion = [self.img_explosion_00,
self.img_explosion_01,
self.img_explosion_02,
self.img_explosion_03]
self.anim_index = 0
self.frame_len = 20 #frames before explosion animation disappears
#spawn new debris
def spawn_new_debris(self):
self.rect.x = random.randrange(100, 800)
self.rect.y = random.randrange(-150, -100)
self.velocity = random.randrange(1, 2)
self.speed_x = random.randrange(-3, 3)
#respawn debris when they go of the screen
def boundaries(self):
if self.rect.left > WIDTH + 10 or self.rect.right < -10 or self.rect.top > HEIGHT + 10:
self.spawn_new_debris()
#update image
def update(self):
self.rect.y += self.velocity
self.rect.x += self.speed_x
self.boundaries()
if self.health <= 0:
max_index = len(self.anim_explosion) - 1
if self.anim_index > max_index:
self.kill()
else:
if self.frame_len == 0:
self.image = self.anim_explosion[self.anim_index]
self.anim_index += 1
self.frame_len = 20
else:
self.frame_len -= 1
#make debris fall down
def falldown(self):
self.rect.centery += self.velocity
if self.moving_down and self.rect.y > 350:
self.kill()
######################CAR/DEBRIS##########################
player = Player(1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
for x in range(100):
d = Debris(1, 5)
debris_group.add(d)
all_sprites.add(d)
#game runs here
run = True
paused = False
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
player.collision(debris_group)
player.stats()
#update all sprites
all_sprites.update()
all_sprites.draw(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#pause game
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = not paused
if paused == True:
continue
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
Move your
for event in pygame.event.get():
right below the while loop, and move your
if paused:
continue
below the for loop, like so:
run = True
paused = False
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#pause game
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = not paused
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
if paused:
continue
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
player.collision(debris_group)
player.stats()
#update all sprites
all_sprites.update()
all_sprites.draw(screen)
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
The reason only your car sprite paused when you pressed the q key is because, as you can see in your original code here:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#pause game
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = not paused
if paused == True:
continue
you put the
if paused == True:
continue
inside the for loop, not the while loop, so the lines that move the car would be blocked, but the rest of the code within the while loop will still get executed.

How do I fix my 'Jump'?

I am new to this website and pygame so bear with me. I am experimenting with pygame and made a simple platformer. However, whenever I 'Jump', the block jumps frame by frame, so I have to hold down the spacebar. Any help would be greatly appreciated!
here is my code:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
x = 0
y = 490
width = 10
height = 10
vel = 5
pygame.key.set_repeat(1)
isjump = False
jumpcount = 10
while True:
pygame.time.delay(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and x>vel-5:
x -= vel
if keys[pygame.K_d] and x < 500 - width:
x += vel
if not(isjump):
if keys[pygame.K_SPACE]:
isjump = True
else:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= (jumpcount ** 2) /2 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
pygame.quit()
You are mixing your keyboard event handling with your jump-logic. I've done two things, change the spacebar detection to trigger isjump and handle the jump logic irregardless of whether there is a key pressed or not:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
x = 0
y = 490
width = 10
height = 10
vel = 5
pygame.key.set_repeat(1)
isjump = False
jumpcount = 10
while True:
pygame.time.delay(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and x>vel-5:
x -= vel
if keys[pygame.K_d] and x < 500 - width:
x += vel
# if we're not already jumping, check if space is pressed to start a jump
if not isjump and keys[pygame.K_SPACE]:
isjump = True
jumpcount = 10
# if we're supposed to jump, handle the jump logic
if isjump:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= (jumpcount ** 2) /2 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
pygame.quit()
The line keys = pygame.key.get_pressed() and the whole game logic and drawing code should not be in the event loop (for event in pygame.event.get():), otherwise the code gets executed once per event in the queue, and if no events are in the queue, it won't be executed at all.
You could just dedent keys = pygame.key.get_pressed() and all lines beneath.
Alternatively, you could check in the event loop if the space key was pressed (with if event.type == pygame.KEYDOWN:) and then set isjump to True (that means the player will only jump once per keypress).
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
x = 0
y = 490
width = 10
height = 10
vel = 5
isjump = False
jumpcount = 10
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
isjump = True
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and x > vel - 5:
x -= vel
elif keys[pygame.K_d] and x < 500 - width:
x += vel
if isjump:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= jumpcount**2 / 2 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
clock.tick(30)
pygame.quit()
I also recommend adding a pygame.time.Clock instance and call clock.tick(FPS) to regulate the frame rate.
And I'd rather implement the jumping in this way, with a gravity constant which gets added to the y-velocity each frame.

how can I reflect the screen in pygame

I want to make rectangles out from the right edge
How can I make these rectangles move horizontally?
I tried to understand it from this tutorial but I couldn't here
so any ideas about this
my little character ghost
btata.png
import pygame
from pygame.locals import *
import sys
import time
import random
pygame.init()
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((800,600))
pygame.display.set_caption('FullMarx')
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
crashed = False
ghostImg = pygame.image.load('btata.png')
clock = pygame.time.Clock()
def ghost(x,y):
gameDisplay.blit(ghostImg, (x,y))
def things(thingx, thingy, thingw, thingh, color):
pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',20)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
def gameOver():
message_display('Game Over')
def rect():
pygame.draw.rect(screen, color, (x,y,width,height), thickness)
def event():
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
def game():
ghost_width = 50
x = 20
y = 180
isJump = False
jumpCount = 9
#x_change = 0
thing_startx = random.randrange(0, display_width)
thing_starty = -300
thing_speed = 7
thing_width = 30
thing_height = 30
while True:
event()
gameDisplay.fill(white)
ghost(x,y)
#____Ghost_Motion___________#
keys = pygame.key.get_pressed()
if not(isJump):
if keys[pygame.K_UP] or keys[pygame.K_SPACE] or keys[pygame.K_w]:
isJump = True
walkCount = 0
else:
if jumpCount >= -9:
neg = 1
if jumpCount < 0:
neg = -1
y -= (jumpCount ** 2) * 0.5 * neg
jumpCount -= 1
else:
isJump = False
jumpCount = 9
clock.tick(50)
#____Ghost_Motion___________#
# things(thingx, thingy, thingw, thingh, color)
things(thing_startx, thing_starty, thing_width, thing_height, black)
thing_starty += thing_speed
ghost(x,y)
if thing_starty > display_height:
thing_starty = 0 - thing_height
thing_startx = random.randrange(0,display_width)
if y < thing_starty+thing_height:
print('y crossover')
if x > thing_startx and x < thing_startx + thing_width or x+ghost_width > thing_startx and x + ghost_width < thing_startx+thing_width:
print('x crossover')
gameOver()
pygame.display.update()
#clock.tick(60)
game()
pygame.quit()
quit()
You move a rect (and therefore a player/an image) by modifying its x and y coordinates.
Here's a rudimentary and commented example to help you visualize:
import pygame
from pygame.locals import *
# Initialize a screen
SCREEN = pygame.display.set_mode((700, 500))
# Fill it with black
SCREEN.fill((0, 0, 0))
# Create a rect that'll represent our player
# Arguments: x, y, width, height
player = pygame.rect.Rect(100, 100, 20, 50)
# Keep track of which direction
# the player is moving in
moving_left = False
moving_right = False
moving_up = False
moving_down = False
# Loop
while True:
for event in pygame.event.get():
# Go through every event that pygame
# records, the 'event queue' and
# react accordingly
# User closed the window
if event.type == QUIT:
pygame.quit()
# If the user presses any key, a
# KEYDOWN event is placed into the
# event queue, and we detect it here
if event.type == KEYDOWN:
# The pressed key is 'd'
if event.key == K_d:
moving_right = True
# The pressed key is 'a'
if event.key == K_a:
moving_left = True
# The pressed key is 'w'
if event.key == K_w:
moving_up = True
# The pressed key is 's'
if event.key == K_s:
moving_down = True
# However, if the user lifts stops
# pressing the keyboard,
# a KEYUP event will be placed into
# the event queue
if event.type == KEYUP:
# The unpressed key is 'd'
if event.key == K_d:
moving_right = False
# The unpressed key is 'a'
if event.key == K_a:
moving_left = False
# The unpressed key is 'w'
if event.key == K_w:
moving_up = False
# The unpressed key is 's'
if event.key == K_s:
moving_down = False
# Increment/decrement the players
# coordinates, its 'position'
# this is akin to movement
if moving_left:
player.x -= 2
if moving_right:
player.x += 2
if moving_up:
player.y -= 2
if moving_down:
player.y += 2
# Repaint our screen black,
SCREEN.fill((0, 0, 0))
# draw our player (the rect)
# onto the SCREEN, at its coordinates
# in white.
# You'd simply use SCREEN.blit
# here in order to place an image
pygame.draw.rect(
SCREEN, (255, 255, 255),
player
)
# refresh the screen to show our changes
pygame.display.update()
You've got to conceptualize movement on a 2D surface like so:

Gravity in pygame [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I'm making a platform game with pygame, and I would like to add gravity to it.
Right now I only have a picture which moves when I press the arrow keys, and my next step would be gravity. Here's my code:
import pygame, sys
from pygame.locals import *
pygame.init()
FPS = 30
fpsClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((400, 300), 0, 32)
pygame.display.set_caption("Jadatja")
WHITE = (255, 255, 255)
catImg = pygame.image.load("images/cat.png")
catx = 10
caty = 10
movingRight = False
movingDown = False
movingLeft = False
movingUp = False
while True: #main game loop
#update
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_RIGHT:
#catx += 5
movingRight = True
movingLeft = False
elif event.key == K_DOWN:
#caty += 5
movingDown = True
movingUp = False
elif event.key == K_LEFT:
#catx -= 5
movingLeft = True
movingRight = False
elif event.key == K_UP:
#caty -= 5
movingUp = True
movingDown = False
if event.type == KEYUP:
if event.key == K_RIGHT:
movingRight = False
if event.key == K_DOWN:
movingDown = False
if event.key == K_LEFT:
movingLeft = False
if event.key == K_UP:
movingUp = False
#actually make the player move
if movingRight == True:
catx += 5
if movingDown == True:
caty += 5
if movingLeft == True:
catx -= 5
if movingUp == True:
caty -= 5
#exit
for event in pygame.event.get():
if event.type == KEYUP:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == QUIT:
pygame.quit()
sys.exit()
#draw
DISPLAYSURF.fill(WHITE)
DISPLAYSURF.blit(catImg, (catx, caty))
pygame.display.update()
fpsClock.tick(FPS)
I'm not 100% sure if this code is as smooth as I think it is, but I hope you guys can make something of it.
Thanks
There is a tutorial for creating a bouncing ball which I think might be helpful to you.
Now, to add gravity to that simulation, you'd simply add some extra speed in the y-direction every time through the loop:
speed[1] += gravity
What you end up with is kind of goofy however, since the image quickly descends below the bottom of the window never to be seen again :)
The next step is therefore to clip the position of the ball so it must remain in the window:
import os
import sys, pygame
pygame.init()
size = width, height = 320, 240
speed = [1, 1]
black = 0, 0, 0
gravity = 0.1
screen = pygame.display.set_mode(size)
image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png")
ball = pygame.image.load(image_file)
ballrect = ball.get_rect()
def clip(val, minval, maxval):
return min(max(val, minval), maxval)
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
speed[1] += gravity
ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]
# clip the position to remain in the window
ballrect.left = clip(ballrect.left, 0, width)
ballrect.right = clip(ballrect.right, 0, width)
ballrect.top = clip(ballrect.top, 0, height)
ballrect.bottom = clip(ballrect.bottom, 0, height)
screen.fill(black)
screen.blit(ball, ballrect)
pygame.display.flip()
Okay, now you can incorporate that in your current code and you'll be off and running. However, there are some things you can do to make your code more organized and less repetitive.
For example, consider the massive if...then blocks that follow
for event in pygame.event.get():
You could rewrite it as something like:
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
You could also benefit from putting all the logic associated with the movement of your image into a class:
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.speed = [0, 0]
area = pygame.display.get_surface().get_rect()
self.width, self.height = area.width, area.height
def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.height:
self.speed[1] = -self.speed[1]
self.rect.left = clip(self.rect.left, 0, self.width)
self.rect.right = clip(self.rect.right, 0, self.width)
self.rect.top = clip(self.rect.top, 0, self.height)
self.rect.bottom = clip(self.rect.bottom, 0, self.height)
Notice the update method is very similar to the code presented by the tutorial. One of the nice things about creating a Ball class is that the rest of your program does not need to know much about how a Ball moves. All the logic is in Ball.update. Moreover, it makes it easy to instantiate many balls. And you could create other classes (airplanes, birds, paddles, etc.) that move differently too and add them to your simulation relatively painlessly.
So, putting it all together, you would end up with something like this:
"""
http://stackoverflow.com/a/15459868/190597 (unutbu)
Based on http://www.pygame.org/docs/tut/intro/intro.html
Draws a red ball bouncing around in the window.
Pressing the arrow keys moves the ball
"""
import sys
import pygame
import os
image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png")
delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
gravity = +1
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.speed = [0, 0]
area = pygame.display.get_surface().get_rect()
self.width, self.height = area.width, area.height
def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.height:
self.speed[1] = -self.speed[1]
self.rect.left = clip(self.rect.left, 0, self.width)
self.rect.right = clip(self.rect.right, 0, self.width)
self.rect.top = clip(self.rect.top, 0, self.height)
self.rect.bottom = clip(self.rect.bottom, 0, self.height)
def clip(val, minval, maxval):
return min(max(val, minval), maxval)
class Main(object):
def __init__(self):
self.setup()
def setup(self):
pygame.init()
size = (self.width, self.height) = (640,360)
self.screen = pygame.display.set_mode(size, 0, 32)
self.ball = Ball()
self.setup_background()
def setup_background(self):
self.background = pygame.Surface(self.screen.get_size())
self.background = self.background.convert()
self.background.fill((0, 0, 0))
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
def draw(self):
self.screen.blit(self.background, (0, 0))
self.screen.blit(self.ball.image, self.ball.rect)
pygame.display.flip()
def event_loop(self):
ball = self.ball
friction = 1
while True:
for event in pygame.event.get():
if ((event.type == pygame.QUIT) or
(event.type == pygame.KEYDOWN and
event.key == pygame.K_ESCAPE)):
sys.exit()
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
friction = 1
elif event.type == pygame.KEYUP:
friction = 0.99
ball.speed = [friction*s for s in ball.speed]
ball.speed[1] += gravity
ball.update()
self.draw()
pygame.time.delay(10)
if __name__ == '__main__':
app = Main()
app.event_loop()

Categories

Resources