How to move Sprite in Pygame - python

im trying to get my image (bird) to move up and down on the screen but i cant figure out how to do it here is what i tried im sure its way off but im trying to figure it out if anyone can help that would be great!
import pygame
import os
screen = pygame.display.set_mode((640, 400))
running = 1
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
screen.fill([255, 255, 255])
clock = pygame.time.Clock()
clock.tick(0.5)
pygame.display.flip()
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
screen.blit( bird, ( 0, 0 ) )
pygame.display.update()
class game(object):
def move(self, x, y):
self.player.center[0] += x
self.player.center[1] += y
if event.key == K_UP:
player.move(0,5)
if event.key == K_DOWN:
player.move(0,-5)
game()
im trying to get it to move down on the down button press and up on the UP key press

As stated by ecline6, bird is the least of your worries at this point.
Consider reading this book..
For now, First let's clean up your code...
import pygame
import os
# let's address the class a little later..
pygame.init()
screen = pygame.display.set_mode((640, 400))
# you only need to call the following once,so pull them out of the while loop.
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
clock = pygame.time.Clock()
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255)) # fill the screen
screen.blit(bird, (0, 0)) # then blit the bird
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
Now the reason that your "bird" is not moving is:
When you blit the image, ie: screen.blit(bird, (0, 0)),
The (0,0) is constant, so it won't move.
Here's the final code, with the output you want (try it) and read the comments:
import pygame
import os
# it is better to have an extra variable, than an extremely long line.
img_path = os.path.join('C:\Python27', 'player.png')
class Bird(object): # represents the bird, not the game
def __init__(self):
""" The constructor of the class """
self.image = pygame.image.load(img_path)
# the bird's position
self.x = 0
self.y = 0
def handle_keys(self):
""" Handles Keys """
key = pygame.key.get_pressed()
dist = 1 # distance moved in 1 frame, try changing it to 5
if key[pygame.K_DOWN]: # down key
self.y += dist # move down
elif key[pygame.K_UP]: # up key
self.y -= dist # move up
if key[pygame.K_RIGHT]: # right key
self.x += dist # move right
elif key[pygame.K_LEFT]: # left key
self.x -= dist # move left
def draw(self, surface):
""" Draw on surface """
# blit yourself at your current position
surface.blit(self.image, (self.x, self.y))
pygame.init()
screen = pygame.display.set_mode((640, 400))
bird = Bird() # create an instance
clock = pygame.time.Clock()
running = True
while running:
# handle every event since the last frame.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # quit the screen
running = False
bird.handle_keys() # handle the keys
screen.fill((255,255,255)) # fill the screen with white
bird.draw(screen) # draw the bird to the screen
pygame.display.update() # update the screen
clock.tick(40)

The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.
If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement.
See also Key and Keyboard event and How can I make a sprite move when key is held down.
Minimal example:
import pygame
import os
class Bird(object):
def __init__(self):
self.image = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
self.center = [100, 200]
def move(self, x, y):
self.center[0] += x
self.center[1] += y
def draw(self, surf):
surf.blit(self.image, self.center)
class game(object):
def __init__(self):
self.screen = pygame.display.set_mode((640, 400))
self.clock = pygame.time.Clock()
self.player = Bird()
def run(self):
running = 1
while running:
self.clock.tick(60)
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
keys = pygame.key.get_pressed()
move_x = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
move_y = keys[pygame.K_DOWN] - keys[pygame.K_UP]
self.player.move(move_x * 5, move_y * 5)
self.screen.fill([255, 255, 255])
self.player.draw(self.screen)
pygame.display.update()
g = game()
g.run()

Related

Pygame character movement

I'm practicing with pygame and don't know how to make my character move. If I put 'print' statement, it works, and prints whatever I want when I press 'a' for example, but character stays on his place. I know little about classes, so I think that's the problem
import pygame
pygame.init()
pygame.font.init()
width, height = 924, 500
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Priest Beast')
clock = pygame.time.Clock()
BG = pygame.transform.scale2x(pygame.image.load('art/background.png')).convert_alpha()
music = pygame.mixer.Sound('sound/music.mp3')
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.transform.scale2x(pygame.image.load('art/Player.png')).convert_alpha()
self.rect = self.image.get_rect(center = (800, 300))
self.x = x
self.y = y
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.rect.x += 5
def update(self):
self.move()
#Loop and exit
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# Sounds
music.play()
music.set_volume(0.1)
screen.blit(BG, (0, 0))
player = pygame.sprite.GroupSingle()
player.add(Player(800,200))
#Update everything
player.draw(screen)
player.update()
pygame.display.update()
clock.tick(60)
You continuously recreate the object in its initial position. You need to create the Sprite and Group before the application loop:
player = pygame.sprite.GroupSingle() # <-- INSERT
player.add(Player(800,200))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# [...]
screen.blit(BG, (0, 0))
# DELETE
# player = pygame.sprite.GroupSingle()
# player.add(Player(800,200))
# [...]

How to overwrite the y position of the bird in the game? [duplicate]

im trying to get my image (bird) to move up and down on the screen but i cant figure out how to do it here is what i tried im sure its way off but im trying to figure it out if anyone can help that would be great!
import pygame
import os
screen = pygame.display.set_mode((640, 400))
running = 1
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
screen.fill([255, 255, 255])
clock = pygame.time.Clock()
clock.tick(0.5)
pygame.display.flip()
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
screen.blit( bird, ( 0, 0 ) )
pygame.display.update()
class game(object):
def move(self, x, y):
self.player.center[0] += x
self.player.center[1] += y
if event.key == K_UP:
player.move(0,5)
if event.key == K_DOWN:
player.move(0,-5)
game()
im trying to get it to move down on the down button press and up on the UP key press
As stated by ecline6, bird is the least of your worries at this point.
Consider reading this book..
For now, First let's clean up your code...
import pygame
import os
# let's address the class a little later..
pygame.init()
screen = pygame.display.set_mode((640, 400))
# you only need to call the following once,so pull them out of the while loop.
bird = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
clock = pygame.time.Clock()
running = True
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255)) # fill the screen
screen.blit(bird, (0, 0)) # then blit the bird
pygame.display.update() # Just do one thing, update/flip.
clock.tick(40) # This call will regulate your FPS (to be 40 or less)
Now the reason that your "bird" is not moving is:
When you blit the image, ie: screen.blit(bird, (0, 0)),
The (0,0) is constant, so it won't move.
Here's the final code, with the output you want (try it) and read the comments:
import pygame
import os
# it is better to have an extra variable, than an extremely long line.
img_path = os.path.join('C:\Python27', 'player.png')
class Bird(object): # represents the bird, not the game
def __init__(self):
""" The constructor of the class """
self.image = pygame.image.load(img_path)
# the bird's position
self.x = 0
self.y = 0
def handle_keys(self):
""" Handles Keys """
key = pygame.key.get_pressed()
dist = 1 # distance moved in 1 frame, try changing it to 5
if key[pygame.K_DOWN]: # down key
self.y += dist # move down
elif key[pygame.K_UP]: # up key
self.y -= dist # move up
if key[pygame.K_RIGHT]: # right key
self.x += dist # move right
elif key[pygame.K_LEFT]: # left key
self.x -= dist # move left
def draw(self, surface):
""" Draw on surface """
# blit yourself at your current position
surface.blit(self.image, (self.x, self.y))
pygame.init()
screen = pygame.display.set_mode((640, 400))
bird = Bird() # create an instance
clock = pygame.time.Clock()
running = True
while running:
# handle every event since the last frame.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit() # quit the screen
running = False
bird.handle_keys() # handle the keys
screen.fill((255,255,255)) # fill the screen with white
bird.draw(screen) # draw the bird to the screen
pygame.display.update() # update the screen
clock.tick(40)
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.
If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement.
See also Key and Keyboard event and How can I make a sprite move when key is held down.
Minimal example:
import pygame
import os
class Bird(object):
def __init__(self):
self.image = pygame.image.load(os.path.join('C:\Python27', 'player.png'))
self.center = [100, 200]
def move(self, x, y):
self.center[0] += x
self.center[1] += y
def draw(self, surf):
surf.blit(self.image, self.center)
class game(object):
def __init__(self):
self.screen = pygame.display.set_mode((640, 400))
self.clock = pygame.time.Clock()
self.player = Bird()
def run(self):
running = 1
while running:
self.clock.tick(60)
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
keys = pygame.key.get_pressed()
move_x = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
move_y = keys[pygame.K_DOWN] - keys[pygame.K_UP]
self.player.move(move_x * 5, move_y * 5)
self.screen.fill([255, 255, 255])
self.player.draw(self.screen)
pygame.display.update()
g = game()
g.run()

Object only being drawn when the game window is dragged around

I'm trying to recreate Agar.io in Python using pygame. So far I've been able to somewhat simulate the player movement, but then I tried to generate some "food cells" at a given interval using the pygame.time.set_timer() method, but even though the rest of the game elements are being drawn, such as the screen and the player, these food cells are only drawn (and added to the "food_list" list) when I drag the game window around. I think this might be an issue of me not really knowing how to deal with the event queue.
main.py, which is where the game loop is located:
import sys, pygame
from player import Player
from food import Food
import random
pygame.init()
SCREEN_SIZE = [1024, 768]
WHITE = (255, 255 , 255)
generate_food = pygame.USEREVENT + 1
screen = pygame.display.set_mode(SCREEN_SIZE)
screen.fill(WHITE)
player = Player()
food_list = []
## TODO: Make a separate GameScreen class.
## TODO: Make a list of constants
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == generate_food:
food_x = random.randrange(0, 760)
food_y = random.randrange(0, 1000)
food_list.append(Food(food_x, food_y))
pygame.time.set_timer(generate_food, 200)
screen.fill(WHITE)
for f in food_list:
f.draw(screen)
player.update()
player.draw(screen)
pygame.display.flip()
food.py:
import pygame
import random
from cell import Cell
DARK_GREEN = (0, 102, 0)
class Food(Cell):
def __init__(self, x, y):
super().__init__()
self.size = 2
self.image = pygame.Surface([2, 2])
self.image.fill(DARK_GREEN)
self.rect = self.image.get_rect()
self.x = x
self.y = y
def draw(self, screen):
pygame.draw.circle(screen, DARK_GREEN, (self.x, self.y), self.size, 0)
def getX(self):
return self.x
def getY(self):
return self.y
Actually the timer is restarted continuously in the application loop. However pygame.time.set_timer() crates a timer that repeatedly create a USEREVENT in the event queue. Hence it is sufficient to start the timer once before the application loop:
pygame.time.set_timer(generate_food, 200) # <--- ADD
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == generate_food:
food_x = random.randrange(0, 760)
food_y = random.randrange(0, 1000)
food_list.append(Food(food_x, food_y))
# pygame.time.set_timer(generate_food, 200) <--- DELTE

How do i get my game to resize with the window

Im wokring on my own version of Pacman and am currently trying to get the window to resize. i read an answer here :https://reformatcode.com/code/python/pygame-how-do-i-resize-a-surface-and-keep-all-objects-within-proportionate-to-the-new-window-size. but it didnt help me in my case. at the i have 2 screen, screen and fake screen. if i set everything to blit on fake screen they appear but dont update themselces (pacman wont move). if i set them to screen they appear and update but dont resize. any help or suggestions would be greatly appreciated. btw its still a work on progress
import pygame
from Variables import pelletspawns #imports pellet spwans list from different script
from pygame.locals import *
#Initialisation
pygame.init()
pygame.display.set_caption("Pacman")
myfont = pygame.font.SysFont("monospace", 15)
screen = pygame.display.set_mode((448, 576)) #Creates screen object
fake_screen = screen.copy()
pic = pygame.surface.Surface((50,50))
pic.fill((255,100,100))
clock = pygame.time.Clock() #Creates clock object
Fin = False
#Declaring Variables
FPS = 60
MoveLeft = pygame.K_LEFT
MoveRight = pygame.K_RIGHT
MoveUp = pygame.K_UP
MoveDown = pygame.K_DOWN
#Load images
PACMAN_MAP = pygame.image.load("images/pacman_map.png").convert_alpha()
PACMANSPRITE = pygame.image.load("images/pacman.png").convert_alpha()
#pacmans class
class SpriteClass(pygame.sprite.Sprite):
def __init__(self, image, x, y):
self.image = image
self.y=y
self.x=x
self.rect = self.image.get_rect()
self.rect.left = self.x
self.rect.top = self.y
self.rect.width=16
self.rect.height=16
#draws Pacman
def draw(self, surface):
# blit yourself at your current position
surface.blit(self.image, (self.x, self.y))
# move pacman
def movement(self):
pressed= pygame.key.get_pressed()
if pressed[MoveUp]:
self.y -= 2
print('key pressed')
if pressed[MoveDown]:
self.y += 2
print('key pressed')
if pressed[MoveLeft]:
self.x -= 2
print('key pressed')
if pressed[MoveRight]:
self.x += 2
print('key pressed')
self.rect.left = self.x
self.rect.top = self.y
print(self.x,self.y)
#instances Pacman
Pacman = SpriteClass(PACMANSPRITE, 216 ,416)
#Function to spawn pellets
def SpawnPellets(pelletspawns):
pelletx=0 #the temp x co-ordinate for the pellet to spawn
pellety= -8 #the temp y co-ordinate for the pellet to spawn (starts at -ve 0.5(gridscpare) for allignment
for row in pelletspawns:
#adds 1 grid space to correctly align spawns
pellety += 16
for pellet in row:
pelletx= 16*pellet
pelletx -=8
pygame.draw.circle(screen,(255, 204, 153), (pelletx, pellety) , 5)
#main game loop
while not Fin:
#For event is used to close the program
for event in pygame.event.get():
if event.type == QUIT:
pygame.display.quit()
if event.type == VIDEORESIZE:
screen = pygame.display.set_mode(event.dict['size'],RESIZABLE)
screen.blit(pygame.transform.scale(fake_screen, event.dict['size']), (0, 0))
pygame.display.flip()
#calls movement function
Pacman.movement()
#blits pacman map as background
screen.blit(PACMAN_MAP, (0, 0))
#draws pacman
Pacman.draw(screen)
#Spawns pellets
SpawnPellets(pelletspawns)
#draws screen
pygame.display.flip()
clock.tick(FPS)
I figured it out, i needed to move
screen.blit(pygame.transform.scale(fake_screen, event.dict['size']), (0, 0))
into the core game loop just above clock.tick. i tried this before but ran into a key error as there was no event for event.dict['size'] to get a size from, so i made a variable in the for event in pygame.event.get(): loop, and then passed that variable where it was asking for event.dict['size']. Here is the section of code i changed:
#main game loop
while not Fin:
#For event is used to close the program
for event in pygame.event.get():
if event.type == QUIT:
pygame.display.quit()
if event.type == VIDEORESIZE:
size = event.dict['size']
screen = pygame.display.set_mode(size,RESIZABLE)
#calls movement function
Pacman.movement()
#blits pacman map as background
fake_screen.blit(PACMAN_MAP, (0, 0))
#draws pacman
Pacman.draw(fake_screen)
#Spawns pellets
SpawnPellets(pelletspawns)
#draws screen
screen.blit(pygame.transform.scale(fake_screen, size), (0, 0))
pygame.display.flip()
clock.tick(FPS)

Pygame display multiple images randomly

I am working with pygame and I was able to draw multiple lines on a screen. I made with this command:
for x in range(60,940,20):
pygame.draw.line(screen, white, [x, 0], [x, 500], 1)
I now need to draw multiple images on the screen. I was able to draw one image by doing:
player_two = pygame.image.load("player_two.png").convert()
player_two.set_colorkey(white)
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.blit(player_two, [60, 240])
pygame.display.flip()
clock.tick(20)
pygame.quit()
I need to draw multiple of this object EITHER randomly within a range of [60, 0], [220, 475] #OR within the same range but with set coordinates. BOTH instances I need these images to move #randomly within that range in either x and/or y direction with a distance of the size of the #image (jump).
To create multi players
import random
multi_players = []
multi_players_pos = []
player = pygame.image.load("player_two.png").convert()
player.set_colorkey(white)
#create 10 players 0...9
for i in range(10):
multi_players.append(player)
pos = [random.randint(60,220+1), random.randint( 0, 475+1)]
multi_players_pos.append(pos)
or load player_0.png ... player_9.png:
multi_players = []
multi_players_pos = []
for i in range(10):
temp = pygame.image.load("player_"+str(i)+".png").convert()
temp.set_colorkey(white)
multi_players.append(temp)
pos = [random.randint(60,220+1), random.randint( 0, 475+1)]
multi_players_pos.append(pos)
draw it:
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
for i in range(len(multi_players)):
screen.blit(multi_players[i], multi_players_pos)
pygame.display.flip()
clock.tick(20)
pygame.quit()
The same way you can change players position.
But better way is to make Player class with all needed function.
(it is not full code - so not tested)
import random
class Player():
def __init__(self, image, x, y):
self.image = pygame.image.load(image).convert()
self.image.set_colorkey(white)
image_rect = image.get_rect()
self.rect = Rect(x, y, image_rect.width, image_rect.height)
def draw(self, screen):
screen.blit(self.image, self.rect.topleft)
def update(self):
# here change randomly positon
#--------------------------------------------
multi_players = []
#create 10 players 0...9
for i in range(10):
x, y = random.randint(60,220+1), random.randint( 0, 475+1)
multi_players.append(Player("player_"+str(i)+".png", x, y))
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# changes position
for player in multi_players:
player.update()
# draws
for player in multi_players:
player.draw(screen)
pygame.display.flip()
clock.tick(20)
pygame.quit()
EDIT:
Full working example - if you press any key (except ESC) images change position.
I use transparent PNG ball1.png, ball2.png, ball3.png so I don't use .convert() and .set_colorkey().
Images you can find (and download) in answer to questions:
Space invaders project
Pygame- window and sprite class - python
.
import random
import pygame
WHITE = (255,255,255)
BLACK = (0 ,0 ,0 )
#----------------------------------------------------------------------
class Player():
def __init__(self, image, x=0, y=0):
self.image = pygame.image.load(image)#.convert()
#self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.centery = y
#------------
def draw(self, screen):
screen.blit(self.image, self.rect)
#------------
def update(self):
# here change randomly positon
self.rect.topleft = random.randint(60,220+1), random.randint( 0, 475+1)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((800,600))
self.background = pygame.image.load("background.jpg").convert()
self.multi_players = []
# create 3 balls 1...3
for i in range(1,4):
player = Player("ball"+str(i)+".png")
player.update() # set random position on start
self.multi_players.append(player)
#------------
def run(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
# changes position when key is pressed
for player in self.multi_players:
player.update()
# --- updates ----
# place for updates
# --- draws ---
self.screen.fill(BLACK)
self.screen.blit(self.background, self.background.get_rect())
for player in self.multi_players:
player.draw(self.screen)
pygame.display.flip()
# --- FPS ---
clock.tick(20)
# --- quit ---
pygame.quit()
#----------------------------------------------------------------------
Game().run()

Categories