Falling mechanics (gravity) in pygame - python

How would I get some mechanics for falling when in an empty space, many answers on the internet said to add gravity but I couldn't understand how they did that they just showed me a bunch of equations.
Also, how would I set an image as my background?
Here's my source code:
import pygame
pygame.init()
display_width = 2560
display_height = 1440
white = (255,255,255)
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('RGB')
clock = pygame.time.Clock()
filler = pygame.image.load('filleraftergimp.png')
def fill(x,y):
gameDisplay.blit(filler,(x,y))
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
y_change = 0
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
x += x_change
y += y_change
gameDisplay.fill(white)
fill(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()

To implement gravity in your game (as in a 2D platformer), you can just increase the y_change variable each frame, so that you move the object a bit faster downwards each time. Take a look at this example:
import pygame as pg
pg.init()
LIGHTBLUE = pg.Color('lightskyblue2')
DARKBLUE = pg.Color(11, 8, 69)
display = pg.display.set_mode((800, 600))
width, height = display.get_size()
clock = pg.time.Clock()
player_image = pg.Surface((30, 60))
player_image.fill(DARKBLUE)
x = width * 0.45
y = 0
x_change = 0
y_change = 0
on_ground = False
# A constant value that you add to the y_change each frame.
GRAVITY = .3
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_a:
x_change = -5
elif event.key == pg.K_d:
x_change = 5
elif event.key == pg.K_s:
y_change = 5
elif event.key == pg.K_w:
if on_ground: # Only jump if the player is on_ground.
y_change = -12
on_ground = False
elif event.type == pg.KEYUP:
if event.key == pg.K_a and x_change < 0:
x_change = 0
elif event.key == pg.K_d and x_change > 0:
x_change = 0
# Add the GRAVITY value to y_change, so that
# the object moves faster each frame.
y_change += GRAVITY
x += x_change
y += y_change
# Stop the object when it's near the bottom of the screen.
if y >= height - 130:
y = height - 130
y_change = 0
on_ground = True
# Draw everything.
display.fill(LIGHTBLUE)
pg.draw.line(display, (0, 0, 0), (0, height-70), (width, height-70))
display.blit(player_image, (x, y))
pg.display.update()
clock.tick(60)
pg.quit()

Related

How to make a bullet animation in pygame? [duplicate]

This question already has an answer here:
How do I continuously trigger an action at certain time intervals? Enemy shoots constant beam instead of bullets in pygame [duplicate]
(1 answer)
Closed 2 years ago.
So I wrote my code and everything works how I want it to for now.
The only problem is that my bullet or fireball teleports to the location I set it to.
I am wondering if there is a way to make it look like its actually moving towards the destination using pygame and whatnot.
Thanks a ton!
(width, height) = (1300,800)
screen = pygame.display.set_mode((width, height))
playerImage = pygame.image.load('player.png')
fireballImage = pygame.image.load('fireball.png')
pygame.display.set_caption('Game')
transparent = (0, 0, 0, 0)
#Fireball stats
def player(x ,y):
screen.blit(playerImage, (x, y))
pygame.display.flip()
def fireball(x, y):
screen.blit(fireballImage, (fb_x,fb_y))
pygame.display.flip()
fireball_state = "ready"
print('created')
fb_x = x = width * 0.45
fb_y = y = height * 0.8
x_change = 0
y_change = 0
fb_x_change = 0
fb_y_change = 0
pressed = pygame.key.get_pressed()
#mainloop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
x_change = 1
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
x_change = -1
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
x_change = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
y_change = -2
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_s:
y_change = 2
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
y_change = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
fb_y_change = -400
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
fb_y_change = 0
x += x_change
y += y_change
fireball(x,y)
fb_x = x
fb_y = y
screen.fill((255,255,255))
player(x,y)
fb_x += fb_x_change
fb_y += fb_y_change
fireball(fb_x,fb_y)
pygame.display.update()
First of all remove pygame.display.flip() from player and fireball. That casuse flickering. A single pygame.display.update() at the end of the application loop is sufficient.
Note, the fireballs have to be blit at (x, y) rather than (fb_x, fb_y)
def player(x ,y):
screen.blit(playerImage, (x, y))
def fireball(x, y):
screen.blit(fireballImage, (x, y))
fireball_state = "ready"
Further more use pygame.time.Clock() / tick() to control the flops per second (FPS):
clock = pygame.time.Clock()
#mainloop
running = True
while running:
clock.tick(FPS)
Add a list for the fire balls:
fireballs = []
Spawn a new fireball when space is pressed:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
fireballs.append([x, y, 0, -2])
Update and draw the fireballs in a loop:
for fb in fireballs:
fb[0] += fb[2]
fb[1] += fb[3]
for fb in fireballs:
fireball(fb[0],fb[1])
See the example:
fireballs = []
FPS = 60
clock = pygame.time.Clock()
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
fireballs.append([x, y, 0, -2])
pressed = pygame.key.get_pressed()
if pressed[pygame.K_w]:
y -= 2
if pressed[pygame.K_s]:
y += 2
if pressed[pygame.K_a]:
x -= 2
if pressed[pygame.K_d]:
x += 2
for i in range(len(fireballs)-1, -1, -1):
fb = fireballs[i]
fb[0] += fb[2]
fb[1] += fb[3]
if fb[1] < 0:
del fireballs[i]
screen.fill((255,255,255))
player(x,y)
for fb in fireballs:
fireball(fb[0],fb[1])
pygame.display.update()

Flipping an image with python (pygame)

I'm trying to learn python so I'm messing around with pygame. I'm a complete beginner.
so far I have made it so that I can control an image, moving it in 2d with the arrow keys.
However, I drew the image facing left and it is always facing left and I want to make it face the direction it's moving. I managed to make it rotate 180 degrees when I press right, but that was everytime I press right so I kept flipping the wrong way.
I need it to face right when moving right and left when moving left.
Image attached.
Thank you
import pygame
import time
pygame.init()
display_width = 1000
display_height = 800
black=(0,0,0)
white=(255,255,255)
gamedisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('metal gear python')
clock = pygame.time.Clock()
snakeimg= pygame.image.load('snake.png')
snake_width = 96
snake_height= 79
def snake(x,y):
gamedisplay.blit(snakeimg, (x,y))
discovered = False
while not discovered:
for event in pygame.event.get():
if event.type == pygame.QUIT:
discovered = TRUE
print (event)
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change=0
y_change=0
snake_speed=0
gameExit= False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
print(event)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -3
elif event.key == pygame.K_RIGHT:
x_change = 3
elif event.key == pygame.K_RIGHT:
x_change = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change = 0
elif event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_change = -3
elif event.key == pygame.K_DOWN:
y_change = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
y += y_change
gamedisplay.fill(white)
snake(x,y)
if x > display_width-snake_width or x < 0:
gameExit=True
if y > display_height-snake_height or y < 0:
True
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Mainly i change the snake function, so that it computes the correct rotation and then rotates the image. Also I change a little bit of the logic, especially at event handling so it is easier to read
import pygame
import time
pygame.init()
display_width = 1000
display_height = 800
black = (0, 0, 0)
white = (255, 255, 255)
gamedisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('metal gear python')
clock = pygame.time.Clock()
snakeimg = pygame.image.load('snake.png')
snake_width = 96
snake_height = 79
def snake(x, y):
if x_change == 0 and y_change == 0:
rotation = -90
elif x_change > 0 and y_change == 0:
rotation = 180
elif x_change < 0 and y_change == 0:
rotation = 0
elif x_change == 0 and y_change > 0:
rotation = 90
elif x_change == 0 and y_change < 0:
rotation = -90
elif x_change < 0 and y_change < 0:
rotation = -45
elif x_change < 0 and y_change > 0:
rotation = 45
elif x_change > 0 and y_change < 0:
rotation = -135
elif x_change > 0 and y_change > 0:
rotation = 135
gamedisplay.blit(pygame.transform.rotate(snakeimg, rotation), (x, y))
discovered = False
while not discovered:
for event in pygame.event.get():
if event.type == pygame.QUIT:
discovered = True
print(event)
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
y_change = 0
snake_speed = 0
gameExit = False
while not gameExit:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
gameExit = True
discovered = True # so you can actually quit the game
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -3
elif event.key == pygame.K_RIGHT:
x_change = 3
elif event.key == pygame.K_UP:
y_change = -3
elif event.key == pygame.K_DOWN:
y_change = 3
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
x_change = 0
elif event.key in (pygame.K_UP, pygame.K_DOWN):
y_change = 0
x += x_change
y += y_change
gamedisplay.fill(white)
snake(x, y)
if x > display_width - snake_width or x < 0:
gameExit = True
if y > display_height - snake_height or y < 0:
gameExit = True
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
And still i have the question: Why 2 game loops inside each other?

How to display a different image based on button clicks with pygame?

I am coding a game for a school project. I have coded it so that I use wasd to move my character. I have four different images: one facing left, one right, one forwards, and one backwards. I need to change the image being displayed as the character based on which button I press. I have a function defining each image, and I try to call that function based on which button is pressed, and then when the button goes back up, I want to display the front facing image again. All it does is every time I press, the corresponding facing image is displayed, goes away, and then the front facing image is displayed and then goes away very quickly. This is just the part that actually deals with the character:
howieImg = pygame.image.load('howie front.PNG')
howieImg_back = pygame.image.load('howie back.PNG')
howieImg_left = pygame.image.load('howie left.PNG')
howieImg_right = pygame.image.load('howie right.PNG')
def howie(x, y):
gameDisplay.blit(howieImg, (x, y))
def howie_back(x, y):
gameDisplay.blit(howieImg_back, (x, y))
def howie_left(x, y):
gameDisplay.blit(howieImg_left, (x, y))
def howie_right(x, y):
gameDisplay.blit(howieImg_right, (x, y))
while not gameExit:
startx = (display_width/2)
starty = (display_height/2)
thing_width = 25
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w and y > 0:
howie_back(x, y)
y_change = -3
if event.key == pygame.K_s and y < display_height - character_height:
howie(x, y)
y_change = 3
if event.key == pygame.K_a and x > 0:
howie_left(x, y)
x_change = -3
if event.key == pygame.K_d and x < display_width - character_width:
howie_right(x, y)
x_change = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
howie(x, y)
y_change = 0
if event.key == pygame.K_a or event.key == pygame.K_d:
howie(x, y)
x_change = 0
x += x_change
y += y_change
if x > display_width - character_width or x < 0:
x_change = 0
if y > display_height - character_height or y < 0:
y_change = 0
clock.tick(60)
gameDisplay.blit(background1Img, [0, 0])
button1()
howie(x, y)
things_collected(collected)
pygame.display.update()
I'd get rid of the functions and just store the current image in a variable (howieImg in the example below). When the user presses one of the keys, you can simply assign one of the other images to the current image variable.
import pygame
pygame.init()
gameDisplay = pygame.display.set_mode((800, 600))
# These are just replacement images that allowed me to test the code.
# howieImg_front = pygame.Surface((50, 50))
# howieImg_front.fill((0, 0, 255))
# howieImg_back = pygame.Surface((50, 50))
# howieImg_back.fill((255, 255, 0))
# howieImg_left = pygame.Surface((50, 50))
# howieImg_left.fill((255, 0, 0))
# howieImg_right = pygame.Surface((50, 50))
# howieImg_right.fill((0, 255, 0))
howieImg_front = pygame.image.load('howie front.PNG').convert_alpha()
howieImg_back = pygame.image.load('howie back.PNG').convert_alpha()
howieImg_left = pygame.image.load('howie left.PNG').convert_alpha()
howieImg_right = pygame.image.load('howie right.PNG').convert_alpha()
# Assign the current howie image to this variable.
howieImg = howieImg_front
x = 200
y = 300
x_change = 0
y_change = 0
clock = pygame.time.Clock()
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
howieImg = howieImg_back
y_change = -3
if event.key == pygame.K_s:
howieImg = howieImg_front
y_change = 3
if event.key == pygame.K_a:
howieImg = howieImg_left
x_change = -3
if event.key == pygame.K_d:
howieImg = howieImg_right
x_change = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
howieImg = howieImg_front
y_change = 0
if event.key == pygame.K_a or event.key == pygame.K_d:
howieImg = howieImg_front
x_change = 0
x += x_change
y += y_change
gameDisplay.fill((30, 30, 30))
# Just blit the current `howieImg`.
gameDisplay.blit(howieImg, (x, y))
pygame.display.update()
clock.tick(60)
pygame.quit()

Image not moving for the life of me

import pygame
# Some colors
GREEN = ( 0,255,0)
BLUE = ( 0, 0, 255)
WHITE = ( 255, 255, 255)
BLACK = ( 0, 0, 0)
pygame.init()
clock = pygame.time.Clock()
#Screen
SCREEN = pygame.display.set_mode([1000,700])
#Title
pygame.display.set_caption("Trying to move things")
#Variables
x_position = 100
y_position = 100
x_speed = 0
y_speed = 0
#Positions
image_image_positions = [x_position,y_position]
#Graphics
image_image = pygame.image.load("izzat.png").convert()
image_image.set_colorkey(BLACK)
#Main loop ____
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Keyboard commands.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_speed = -5
elif event.key == pygame.K_DOWN:
y_speed = 5
elif event.key == pygame.K_w:
x_speed = -5
elif event.key == pygame.K_s:
x_speed = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_speed = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_speed = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
x_speed += 0
if y_position + y_speed >=0 and y_position + y_speed + 60 <=500:
y_position += y_speed
x_position += x_speed
SCREEN.fill(GREEN)
SCREEN.blit(image_image, image_image_positions)
print(x_position)
print(y_position)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Hello, I have been having a problem which I'm really not happy at because I have been trying to fix it for a while now. So basically I have a image, and I wish to move the image based on the keyboard inputs, yet whatever I try nothing works. I then wondered maybe the y and x position aren't changing at all which is why the images positions are not changing, well I did print( those positions) but it the positions are definitely changing, the variables, so I do not get how the image positions do not change at all. Then I thought maybe because it's a tuple, so I changed it to parenthesis, that also did not work. I just don't get why my image position doesn't move if the variables for the position of the image do change. Thank you if you could help me in any way. I have looked this up but I couldn't find any help. Thank you for your help if you help me!
Update__________
Ok so apparently the image_image_position stays the same despite the variables changing when I printed the positions of image_image_position. Is there any way to change them and not have them stay at 100,100 all the time and change with the variables being changed?
You haven't assigned the speeds.
image_image_positions[0] = xspeed
image_image_positions[1] = yspeed
You are only changing your variables yspeed and xspeed, but you are not setting the actual positions of the image. Add the following line before the blit:
image_image_positions = [x_position,y_position]
Full code:
import pygame
# Some colors
GREEN = ( 0,255,0)
BLUE = ( 0, 0, 255)
WHITE = ( 255, 255, 255)
BLACK = ( 0, 0, 0)
pygame.init()
clock = pygame.time.Clock()
#Screen
SCREEN = pygame.display.set_mode([1000,700])
#Title
pygame.display.set_caption("Trying to move things")
#Variables
x_position = 100
y_position = 100
x_speed = 0
y_speed = 0
#Positions
image_image_positions = [x_position,y_position]
#Graphics
image_image = pygame.image.load("izzat.png").convert()
image_image.set_colorkey(BLACK)
#Main loop ____
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# Keyboard commands.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y_speed = -5
elif event.key == pygame.K_DOWN:
y_speed = 5
elif event.key == pygame.K_w:
x_speed = -5
elif event.key == pygame.K_s:
x_speed = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_speed = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_speed = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
x_speed += 0
if y_position + y_speed >=0 and y_position + y_speed + 60 <=500:
y_position += y_speed
x_position += x_speed
image_image_positions = [x_position,y_position]
SCREEN.fill(GREEN)
SCREEN.blit(image_image, image_image_positions)
print(x_position)
print(y_position)
pygame.display.flip()
clock.tick(60)
pygame.quit()
While you ARE updating the x/y positions, this isn't changing where the image is being drawn:
SCREEN.blit(image_image, image_image_positions)
image_image_positions, is never changed throughout the life-span of your application (besides startup).
To fix this simply add the update into your loop:
image_image_positions = [x_position,y_position]

Clamping sprites in the screen

I want to clamp my sprite from disappearing from screen, but I am bit confused. I think I didn't understand concept of get_rect method properly. At this stage I'm getting this error:
TypeError: Argument must be rect style object
Thats my code:
import pygame
pygame.init()
finish = False
white = ( 255, 255, 255)
black = (0, 0, 0)
grey = (211, 211, 211)
font = pygame.font.Font("C:/Windows/Fonts/BRITANIC.TTF", 20)
screen = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Game")
line_speed = 2
line_pos_x = 100
line_pos_y = 0
end_pos = 170
player_x = 10
player_y = 10
player_move_x = 0
player_move_y = 0
dog_img = pygame.image.load("dog_brown.png")
dog_rect = dog_img.get_rect()
timer = pygame.time.Clock()
while finish == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
finish = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_move_x = -5
if event.key == pygame.K_RIGHT:
player_move_x = 5
if event.key == pygame.K_UP:
player_move_y = -5
if event.key == pygame.K_DOWN:
player_move_y = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player_move_x = 0
if event.key == pygame.K_RIGHT:
player_move_x = 0
if event.key == pygame.K_UP:
player_move_y = 0
if event.key == pygame.K_DOWN:
player_move_y = 0
player_x += player_move_x
player_y += player_move_y
screen.fill(white)
screen.blit(dog_img,(player_x, player_y))
dog_rect.clamp_ip(screen)
pygame.draw.line(screen,black,[line_pos_x,line_pos_y + line_speed],[100,end_pos + line_speed],5)
line_speed = line_speed + 2
pygame.display.flip()
timer.tick(25)
pygame.quit()
clamp_ip needs another Rect as argument:
...
screen = pygame.display.set_mode((600, 400))
# create a Rect that represents the screen
screen_r = screen.get_rect()
...
while finish == False:
...
# use it instead of screen
dog_rect.clamp_ip(screen_r)
...
Also, to have it work, you should get rid of the player_x and player_y variables and use the dog_rect Rect to keep track of the position of your player.
Instead of
player_x += player_move_x
player_y += player_move_y
...
screen.blit(dog_img,(player_x, player_y))
simply do
dog_rect.move_ip(player_move_x, player_move_y)
...
screen.blit(dog_img, dog_rect)

Categories