im new to programming so im following some tutorials online to make a basic game. in order to create the movement for my character, i followed this tutorial
https://www.youtube.com/watch?v=4aZe84vvE20&t=692s&ab_channel=ClearCode
after following the rotation part of the video, i tried testing it out. however, it does not work for some reason. im not sure why this is. i do not get an error, but the character stays in one place and does not rotate once i press the left and right arrow keys. could somebody have a look at my code and let me know what i have done wrong? thanks a lot
import pygame
pygame.init()
window = pygame.display.set_mode((650, 650))
pygame.display.set_caption ("Game")
green = (0,255,0)
window.fill(green)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.og_image = pygame.image.load("player1.png")
self.image = self.og_image
self.rect = self.image.get_rect (center = (345,345))
self.angle = 0
self.rotate_speed = 1
self.direction = 0
def rotate(self):
if self.direction == 1:
self.angle -= self.rotate_speed
print(self.angle)
elif self.direction == -1:
self.angle += self.rotate_speed
print(self.angle)
self.image = pygame.transform.rotozoom(self.og_image, self.angle, 1)
self.rect = self.image.get_rect(center = (self.rect.center))
def update(self):
self.rotate()
player_1 = Player()
players = pygame.sprite.GroupSingle()
players.add(player_1)
players.draw(window)
run = True
while run == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
players.sprite.direction += 1
if event.key == pygame.K_LEFT:
players.sprite.direction -= 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
players.sprite.direction -= 1
if event.key == pygame.K_LEFT:
players.sprite.direction += 1
players.update()
pygame.display.update()
pygame.quit()
You have to draw the Sprites in the Group (players.draw(window)) and you have to clear the display (window.fill(green)) before drawing the objects. Note, you have to do this in the application loop rather than the event loop (It's a matter of Indentation):
run = True
while run == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
players.sprite.direction += 1
if event.key == pygame.K_LEFT:
players.sprite.direction -= 1
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
players.sprite.direction -= 1
if event.key == pygame.K_LEFT:
players.sprite.direction += 1
# INDENTATION
#<--|
players.update()
window.fill(green)
players.draw(window)
pygame.display.update()
Related
import pygame, sys
pygame.init()
pygame.display.set_caption("test 1")
#main Variables
clock = pygame.time.Clock()
window_size = (700, 700)
screen = pygame.display.set_mode(window_size, 0, 32)
#player variables
playerx = 150
playery = -250
player_location = [playerx, playery]
player_image = pygame.image.load("player/player.png").convert_alpha()
player_rect = player_image.get_rect(center = (80,50))
#button variables
move_right = False
move_left = False
move_up = False
move_down = False
while True:
screen.fill((4, 124, 32))
screen.blit(player_image, player_location, player_rect)
if move_right == True:
playerx += 4
if move_left == True:
playerx -= 4
if move_up == True:
playery -= 4
if move_down == True:
playery += 4
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
move_right = True
if event.key == pygame.K_a:
move_left = True
if event.key == pygame.K_w:
move_up = True
if event.key == pygame.K_s:
move_down = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_d:
move_right = False
if event.key == pygame.K_a:
move_left = False
if event.key == pygame.K_w:
move_up = False
if event.key == pygame.K_s:
move_down = False
pygame.display.update()
clock.tick(120)
I cant get it to work. I pressed the button but it wont go up or down. It worked well when i used no rectangle for the player. I wanter so i can move the character up and down in the y axis also. I just started to learn how to use PyGame so please help me thanks.
As you move the player, you change the playerx and playery variables. However, the player id drawn to the position that is stored in player_location. You must update player_location before drawing the player:
while True:
screen.fill((4, 124, 32))
player_location = [playerx, playery]
screen.blit(player_image, player_location, player_rect)
# [...]
Note that you don't need player_location at all. Draw the player at [playerx, playery]:
while True:
screen.fill((4, 124, 32))
screen.blit(player_image, [playerx, playery], player_rect)
Okay so I started a project today where I created Space Invaders. The only I'm personally having issues with is the pause and unpause button. I'm using Python 3.7.4 and Pygame 1.9.6.
paused = False
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_p: # Pausing
paused = True
if event.key == pygame.K_u: # Unpausing
paused = False
if not paused:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if bullet_state is "ready":
bullet_Sound = mixer.Sound('laser.wav')
bullet_Sound.play()
# Get the current x coordinate of the spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
So I don't know if I should have the pause button first or not.
I've tried:
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_p: # Pausing
paused = True
if event.key == pygame.K_u: # Unpausing
paused = False
if not paused:
while running:
'''The rest of the code'''
Where the # Pausing is:
I've tried:
if event.key == pygame.K_p:
paused = not paused # for pause and unpausing
No 'u' key.
So I'm just lost on where I should put it at. So it would be nice with the help. I looked at question: pausing/ Unpausing in Pygame for help. So anything else let me know.
Here's a minimal, complete example of a ball moving. You can pause and unpause its movement by pressing P. You can change its speed using ←↑→↓. Pressing Spacebar will reset the speed.
import pygame
WIDTH = 640
HEIGHT = 480
FPS = 30
class Ball(pygame.sprite.Sprite):
"""Moving ball sprite"""
def __init__(self, color="white", size=20, speedx=-5, speedy=-5):
pygame.sprite.Sprite.__init__(self)
self.color = pygame.color.Color(color)
# instead of loading an image from file, draw a circle.
self.image = pygame.Surface((size * 2, size * 2), pygame.SRCALPHA)
pygame.draw.circle(self.image, self.color, (size, size), size)
self.rect = self.image.get_rect()
# start ball in the middle of the screen
self.rect.x = WIDTH / 2 - self.rect.width / 2
self.rect.y = HEIGHT / 2 - self.rect.height / 2
self.speedx = speedx
self.speedy = speedy
self.size = size
def update(self):
# reverse direction if out of bounds
if not (0 < self.rect.x < WIDTH - self.size*2):
self.speedx *= -1
if not (0 < self.rect.y < HEIGHT - self.size*2):
self.speedy *= -1
# update position
self.rect.x += self.speedx
self.rect.y += self.speedy
pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
ball = Ball()
balls = pygame.sprite.Group()
balls.add(ball)
paused = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_p:
paused = not paused
elif event.key == pygame.K_UP:
ball.speedy += 5
elif event.key == pygame.K_DOWN:
ball.speedy -= 5
if event.key == pygame.K_RIGHT:
ball.speedx += 5
elif event.key == pygame.K_LEFT:
ball.speedx -= 5
elif event.key == pygame.K_SPACE:
# reset speed
ball.speedx = 2
ball.speedy = 0
# update game elements
if not paused:
pygame.display.set_caption('Running')
ball.update()
else:
pygame.display.set_caption('Paused')
# draw surface - fill background
window.fill(pygame.color.Color("grey"))
## draw sprites
balls.draw(window)
# show surface
pygame.display.update()
# limit frames
clock.tick(FPS)
pygame.quit()
Note that whilst paused, events are still being handled, so you can still adjust the speed. To change this behaviour, you'd need to discard specific events when paused is True.
I wrote this simple code that draws and then lets you move a rectangle, but even after I change the coordinates of the rectangle by calling the move_player_x_ function, it doesn't move at all. I don't understand why. I came here looking for clarification and a detailed solution to my problem.
Here's the code:
import pygame
white = (255, 255, 255)
black = (0, 0, 0)
class Game():
width = 800
height = 600
screen = pygame.display.set_mode((width, height))
def __init__(self):
pass
def fill_screen(self, color):
self.color = color
self.screen.fill(self.color)
def update_method(self):
pygame.display.update()
game = Game()
class Player(pygame.sprite.Sprite):
lead_x = game.width/2
lead_y = game.height/2
lead_x_change = 0
lead_y_change = 0
velocity = 0.2
block_size = 10
def __init__(self):
pygame.sprite.Sprite.__init__(self)
def move_player_x_left(self):
self.lead_x_change += -self.velocity
def move_player_x_right(self):
self.lead_x_change += self.velocity
def move_player_y_up(self):
self.lead_y_change += -self.velocity
def move_player_y_down(self):
self.lead_y_change += self.velocity
def draw_player(self):
pygame.draw.rect(game.screen, black, [self.lead_x, self.lead_y, self.block_size, self.block_size])
def key_up_x_stop(self):
self.lead_x = 0
def key_up_y_stop(self):
self.lead_y = 0
def constant_x_movement(self):
self.lead_x += self.lead_x_change
def constant_y_movement(self):
self.lead_y += self.lead_y_change
player = Player()
exitGame = False
while not exitGame:
game.fill_screen(white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exitGame = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
player.move_player_y_up()
if event.key == pygame.K_s:
player.move_player_y_down()
if event.key == pygame.K_a:
player.move_player_x_left()
if event.key == pygame.K_d:
player.move_player_x_right()
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
player.key_up_y_stop()
if event.key == pygame.K_a or event.key == pygame.K_d:
player.key_up_x_stop()
player.constant_x_movement()
player.constant_y_movement()
player.draw_player()
game.update_method()
pygame.quit()
quit()
The code in the event loop is not indented correctly. Here's a corrected version:
while not exitGame:
game.fill_screen(white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exitGame = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
player.move_player_y_up()
if event.key == pygame.K_s:
player.move_player_y_down()
if event.key == pygame.K_a:
player.move_player_x_left()
if event.key == pygame.K_d:
player.move_player_x_right()
if event.type == pygame.KEYUP:
if event.key == pygame.K_w or event.key == pygame.K_s:
player.key_up_y_stop()
if event.key == pygame.K_a or event.key == pygame.K_d:
player.key_up_x_stop()
Also, in the ...stop methods, you have to set lead_x_change and lead_y_change to 0 not lead_x and lead_y.
def key_up_x_stop(self):
self.lead_x_change = 0
def key_up_y_stop(self):
self.lead_y_change = 0
I edited your code, i added a function in the player object move_player with local booleans bUp,bDown,bLeft,bRight. If python had enumerations, it would be so much better. Any how, on event KEY DOWN and KEY UP, they toggle these booleans in the player. after the input is calculated and these booleans are toggled/set, it called move_player() in player object that checks its booleans and sets a while loop while one is true and adds velocity in the respected location and redraws player.
Here the source i got for you...
import pygame
white = (255, 255, 255)
black = (0, 0, 0)
class Game():
width = 800
height = 600
screen = pygame.display.set_mode((width, height))
def __init__(self):
pass
def fill_screen(self, color):
self.color = color
self.screen.fill(self.color)
def update_method(self):
pygame.display.update()
class Player(pygame.sprite.Sprite):
lead_x = 800/2
lead_y = 600/2
velocity = 0.002
block_size = 10
bUp = false
bDown = false
bLeft = false
bRight = false
def __init__(self):
pygame.sprite.Sprite.__init__(self)
def draw_player(self):
pygame.draw.rect(game.screen, black, [self.lead_x, self.lead_y, self.block_size, self.block_size])
def move_player(self):
while bLeft:
self.lead_x += -self.velocity
self.draw_player()
while bRight:
self.lead_x += self.velocity
self.draw_player()
while bUp:
self.lead_y += -self.velocity
self.draw_player()
while bDown:
self.lead_y += self.velocity
self.draw_player()
game = Game()
player = Player()
exitGame = False
while not exitGame:
game.fill_screen(white)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exitGame = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
player.bUp = true
if event.key == pygame.K_s:
player.bDown = true
if event.key == pygame.K_d:
player.bRight = true
if event.key == pygame.K_a:
player.bLeft = true
elif event.type == pygame.KEYUP:
if event.key == pygame.K_w:
player.bUp = false
if event.key == pygame.K_s:
player.bDown = false
if event.key == pygame.K_d:
player.bRight = false
if event.key == pygame.K_a:
player.bLeft = false
player.move_player()
game.update_method()
pygame.quit()
quit()
I am relatively new in python and started coding in pygame. For some reason, when I am rendering some images on a surface, it doesn't blit the images. But when I minimize it and then open it again, it works fine. Is there any fix to this problem? Thanks in adavance.
Non-fullscreen error: https://youtu.be/q_2FT8OD7O4
Fullscreen error: https://youtu.be/9XKnhtN5s5k
My code, just in case if something's wrong in it:
import pygame
displayWidth = 1920
displayHeight = 1080
pygame.init()
gameDisplay = pygame.display.set_mode((displayWidth,displayHeight),pygame.FULLSCREEN)
pygame.display.set_caption('Road Fighters')
clock = pygame.time.Clock()
car = pygame.image.load('Car.png')
grassLeft = pygame.image.load('Grass Left.png')
grassRight = pygame.image.load('Grass Right.png')
blank = pygame.image.load('Left.png')
lining = pygame.image.load('Lining.png')
miniMap = pygame.image.load('Progress.png')
miniCar = pygame.image.load('Small Car.png')
road = pygame.image.load('Road.png')
def car(x,y):
gameDisplay.blit(car, (x,y))
def draw():
gameDisplay.blit(blank,(0,0))
gameDisplay.blit(miniMap,(670,0))
gameDisplay.blit(grassLeft,(720,0))
gameDisplay.blit(lining,(1020,0))
gameDisplay.blit(road,(1030,0))
gameDisplay.blit(lining,(1610,0))
gameDisplay.blit(grassRight,(1620,0))
def gameloop():
while True:
for event in pygame.event.get():
## if event.type == 2 or event.type == 12:
## pygame.quit()
## quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dx = -3
elif event.key == pygame.K_RIGHT: dx = 3
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT: dx += 3
elif event.key == pygame.K_RIGHT: dx += -3
draw()
gameloop()
You need to add a pygame.display.flip() to your game loop.
I am messing around with pygame and I am eventually working towards a pong clone. I implemented player movement with the arrow keys and when ever I switch from going up to immediately going down, my player freezes and won't move again until I press that direction key again. Here is my code:
import sys, pygame
pygame.init()
display_width = 640
display_height = 480
display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Test Game")
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
running = True
class Player:
def __init__(self,x,y,hspd,vspd,color,screen):
self.x = x
self.y = y
self.hspd = hspd
self.vspd = vspd
self.color = color
self.screen = screen
def draw(self):
pygame.draw.rect(self.screen,self.color,(self.x,self.y,32,32))
def move(self):
self.x += self.hspd
self.y += self.vspd
player = Player(0,0,0,0,black,display)
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
player.hspd = 0
if event.key == pygame.K_LEFT:
player.hspd = 0
if event.key == pygame.K_UP:
player.vspd = 0
if event.key == pygame.K_DOWN:
player.vspd = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.hspd = 4
if event.key == pygame.K_LEFT:
player.hspd = -4
if event.key == pygame.K_UP:
player.vspd = -4
if event.key == pygame.K_DOWN:
player.vspd = 4
#Clear the screen
display.fill(white)
#Move objects
player.move()
#Draw objects
player.draw()
#Update the screen
pygame.display.flip()
print "I made it!"
pygame.quit()
sys.exit()
I suggest you work with key.get_pressed() to check for the current set of pressed keys.
In your scenario - when you press down and release up (in that order) - the speed is set to 0, so you need to inspect the keys pressed not just by the current event.
Here is a working version of the relevant part:
def current_speed():
# uses the fact that true = 1 and false = 0
currently_pressed = pygame.key.get_pressed()
hdir = currently_pressed[pygame.K_RIGHT] - currently_pressed[pygame.K_LEFT]
vdir = currently_pressed[pygame.K_DOWN] - currently_pressed[pygame.K_UP]
return hdir * 4, vdir * 4
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
player.hspd, player.vspd = current_speed()
#Clear the screen
display.fill(white)
#Move objects
player.move()
#Draw objects
player.draw()
#Update the screen
pygame.display.flip()
To expand on LPK's answer, your key down (for event.key == pygame.K_DOWN) is likely being processed before your key up (from event.key == pygame.K_UP) is processed. So while both are down (and you can confirm this), you may experience movement, until you release the up key.
your problem is here:
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
player.hspd = 0
if event.key == pygame.K_LEFT:
player.hspd = 0
if event.key == pygame.K_UP:
player.vspd = 0
if event.key == pygame.K_DOWN:
player.vspd = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.hspd = 4
if event.key == pygame.K_LEFT:
player.hspd = -4
if event.key == pygame.K_UP:
player.vspd = -4
if event.key == pygame.K_DOWN:
player.vspd = 4
I am guessing that your key event down is still consumed when u switch the keys immediately, meaning no other key down event is getting triggered as long as the first event didn't fire its key up event yet.
EDIT: maybe its better to check if the player is moving and if so just reverse speed . Then you would only need to check the down event.
Otherwise your event will be consumed and not checked properly.
For your method you would need to store the occurred key events since the last frame and check that list.