I can't move my player in pygame, can you figure why? - python
I'm trying to make a little game, and I came across a problem which I can't seem to figure out. The problem is that my sprite isn't moving after creating the game loop and the if statements with the keyup's and what not. Can you guys figure it out and tell me why it's not working?
Here's my code so far:
import pygame, sys, random
from pygame.locals import *
pygame.init()
mainClock = pygame.time.Clock()
windowWidth = 600
windowHeight = 400
windowSize = (600, 400)
windowSurface = pygame.display.set_mode((windowWidth, windowHeight), 0, 32)
display = pygame.Surface((300, 200))
black = (0, 0, 0)
white = (225, 225, 255)
green = (0, 255, 0)
moveRight = False
moveLeft = False
moveSpeed = 6
level= [['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','2','2','2','2','2','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['2','2','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','2'],
['1','1','2','2','2','2','2','2','2','2','2','2','0','0','2','2','2','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1'],
['1','1','1','1','1','1','1','1','1','1','1','1','0','0','1','1','1','1','1']]
grass = pygame.image.load('grass.png')
dirt = pygame.image.load('dirt.png')
player = pygame.image.load('player.png').convert()
playerRect = pygame.Rect(100, 100, 5, 13)
player.set_colorkey((255,255,255))
while True:
display.fill((214, 42, 78))
#display.blit(player,(playerRect.x,playerRect.y))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
moveRight = True
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
moveLeft = False
if event.type == pygame.KEYUP:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
moveRight = False
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
moveLeft = False
display.blit(player,(playerRect.x,playerRect.y))
playerMovement = [0, 0]
if moveRight == True:
playerMovement[0] += 2
if moveLeft == True:
playerMovement[0] -= 2
tileRect = []
y = 0
for row in level:
x = 0
for col in row:
if col == '2':
display.blit(grass, (x*16, y*16))
if col == '1':
display.blit(dirt, (x*16, y*16))
if col != '0':
tileRect.append(pygame.Rect(x*16,y*16,16,16))
x += 1
y += 1
#pygame.draw.rect(windowSurface, black, player)
windowSurface.blit(pygame.transform.scale(display, windowSize),(0,0))
pygame.display.update()
mainClock.tick(60)
I've restructured your main loop to fix the problems. I change the playerMovement (velocity) in the event loop now and use it to update the playerRect in the main loop with the pygame.Rect.move_ip method.
By the way, you can pass the playerRect to blit to blit the image at the topleft (x, y) coords.
# The player's velocity. Define it outside of the main loop.
playerMovement = [0, 0]
while True:
# Handle events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
playerMovement[0] = 2 # Set the x-velocity to the desired value.
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
playerMovement[0] = -2
if event.type == pygame.KEYUP:
if event.type == pygame.K_RIGHT or event.key == pygame.K_d:
playerMovement[0] = 0 # Stop the player when the button is released.
if event.type == pygame.K_LEFT or event.key == pygame.K_a:
playerMovement[0] = 0
# Game logic.
playerRect.move_ip(playerMovement)
# Draw everything.
display.fill((214, 42, 78))
tileRect = []
y = 0
for row in level:
x = 0
for col in row:
if col == '2':
display.blit(grass, (x*16, y*16))
if col == '1':
display.blit(dirt, (x*16, y*16))
if col != '0':
tileRect.append(pygame.Rect(x*16,y*16,16,16))
x += 1
y += 1
display.blit(player, playerRect)
windowSurface.blit(pygame.transform.scale(display, windowSize), (0, 0))
pygame.draw.rect(windowSurface, black, playerRect)
pygame.display.update()
mainClock.tick(60)
Related
Rect not moving in Pygame
I am trying to make a pong game in pygame. So I needed to make a rectangle controlled by player. I defined some variables for this purpose. The variables player = pygame.Rect(s_width - 10, s_height/2 - 35, 5, 70) player_speed = 0 In the loop player.y += player_speed for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if pygame.key == pygame.K_DOWN: player_speed += 5 if pygame.key == pygame.K_UP: player_speed -= 5 if event.type == pygame.KEYUP: if pygame.key == pygame.K_DOWN: player_speed = 0 if pygame.key == pygame.K_UP: player_speed = 0
There is just one problem in your code; you don't check if pygame.key == pygame.K_... You need to replace the pygame.key to event.key: if event.key == pygame.K_... import pygame pygame.init() s_width, s_height = 600, 600 wn = pygame.display.set_mode((s_width, s_height)) player = pygame.Rect(s_width - 10, s_height/2 - 35, 5, 70) player_speed = 0 clock = pygame.time.Clock() while True: clock.tick(60) player.y += player_speed for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_DOWN: player_speed += 5 print(player_speed) if event.key == pygame.K_UP: player_speed -= 5 if event.type == pygame.KEYUP: if event.key == pygame.K_DOWN: player_speed = 0 if event.key == pygame.K_UP: player_speed = 0 wn.fill((0, 0, 0)) pygame.draw.rect(wn, (255, 0, 0), player) pygame.display.update() Output:
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()
Why wont this blit on my screen?
I know this is going to be (hopefully) an easy fix, but I cannot get the gameover screen to blit on my screen. I have thought through this for the past two hours, and none of my tweaks are working. Any help would be greatly appreciated! This file contains the main file loop as while as sprite group updates and general updates/renders for the program import pygame, sys import player import random import math from constants import * from bullet import * from block import * pygame.init() screen = pygame.display.set_mode((800,600)) pygame.display.set_caption("Open") clock = pygame.time.Clock() def main(): moveX = 0 moveY = 0 sprite_list = pygame.sprite.Group() bullet_list = pygame.sprite.Group() block_list = pygame.sprite.Group() main_player = player.Player() sprite_list.add(main_player) main_player.rect.x = 400 main_player.rect.y = 550 for i in range(1,10): blocks = Block() blocks.center_x = random.randrange(760) blocks.center_y = random.randrange(400) blocks.radius = random.randrange(10,200) blocks.angle = random.random() * 4 * math.pi blocks.speed = 0.04 block_list.add(blocks) sprite_list.add(blocks) font = pygame.font.Font(None, 36) game_over = False score = 0 level = 1 gameLoop = True while gameLoop: 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_RIGHT: moveX = 5 if event.key == pygame.K_LEFT: moveX = -5 if event.key == pygame.K_DOWN: moveY = 5 if event.key == pygame.K_UP: moveY = -5 if event.key == pygame.K_SPACE: bullets = Bullet() bullets.rect.x = main_player.rect.x + 16 bullets.rect.y = main_player.rect.y + 16 sprite_list.add(bullets) bullet_list.add(bullets) if event.type == pygame.KEYUP: if event.key == pygame.K_RIGHT and moveX >= 0: moveX = 0 if event.key == pygame.K_LEFT and moveX <= 0: moveX = 0 if event.key == pygame.K_DOWN and moveY >= 0: moveY = 0 if event.key == pygame.K_UP and moveY <= 0: moveY = 0 for bullets in bullet_list: block_hit_list = pygame.sprite.spritecollide(bullets, block_list, True) for block in block_hit_list: score += 1 bullet_list.remove(bullets) sprite_list.remove(bullets) if bullets.rect.y < 0: bullet_list.remove(bullets) sprite_list.remove(bullets) if pygame.sprite.spritecollide(main_player, block_list, True): gameLoop = False game_over = True sprite_list.update() screen.fill(BLACK) sprite_list.draw(screen) main_player.rect.x += moveX main_player.rect.y += moveY score_text = font.render("Score: "+str(score), True, WHITE) screen.blit(score_text,[10,10]) level_text = font.render("Level: "+str(level), True, WHITE) screen.blit(level_text,[115,10]) if game_over == True: you_lose_text = font.render("YOU SUCK", True, RED) screen.blit(you_lose_text, [300,300]) pygame.time.wait(1000) break clock.tick(60) pygame.display.update() pygame.quit() if __name__ == "__main__": main() HERE IS MY ISSUE: if game_over == True: you_lose_text = font.render("YOU SUCK", True, RED) screen.blit(you_lose_text, [300,300]) pygame.time.wait(1000) break I am getting no error, and the pygame.time.wait function is working correctly? Why is it just skipping over displaying the text?
Maybe it is not the best solution but your code doesn't need better. blit draws in buffer. You have to use update before wait to send data from buffer to screen. if game_over == True: you_lose_text = font.render("YOU SUCK", True, RED) screen.blit(you_lose_text, [300,300]) pygame.display.update() # send on screen pygame.time.wait(1000) break clock.tick(60) pygame.display.update() pygame.quit()
pygame - Key pressed
I am kinda stuck with a supposed to be simple code to check if the user has pressed "w" or "s". Below you can see my code: import pygame pygame.init() while True: for event in pygame.event.get(): if event.type == pygame.KEYDOWN and event.key == pygame.K_w: print('Forward') elif event.type == pygame.KEYDOWN and event.key == pygame.K_s: print('Backward') Am I forgetting something here? Thanks!
A window needs to be created to receive key presses, the following works. import pygame import sys pygame.init() pygame.display.set_mode((100, 100)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_w: print('Forward') elif event.key == pygame.K_s: print('Backward')
This is what seems to me the most simple and understandable way to do it: import pygame pygame.init() pygame.display.set_mode((300, 300)) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False pygame.quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_w: print('Forward') elif event.key == pygame.K_s: print('Backward') Instead of using the sys.exit() method I prefer to just use pygame.quit()
it is no good to ask the gamer to keep hitting w to get the response. If you want to read the "pressed" state. You could consider the followings: from pygame import * import time flag = False # The flag is essential. DONE = False screen = display.set_mode((500,500)) # 1180, 216 count=0 while not DONE: event.pump() # process event queue keys = key.get_pressed() # It gets the states of all keyboard keys. #print("%d"%count,keys) count+=1 if keys[ord('w')]: # And if the key is K_DOWN: print("%d w down"%count) if keys[ord('s')]: # And if the key is K_DOWN: print("%d s down"%count) time.sleep(0.1)
Try this: import pygame pygame.init() key = pygame.key.get_pressed() while True: for event in pygame.event.get(): if event.type == KEYDOWN and event.key == pygame.K_w: print('Forward') elif event.type == KEYDOWN and event.key == pygame.K_s: print('Backward')
Sample code to understand how key press events work. import pygame from pygame.locals import * def main(): pygame.init() pygame.display.set_caption("Move Box With Arrow Keys") wndsize = (320, 240) display = pygame.display.set_mode(wndsize) x = 5 y = 5 black = (0, 0, 0) white = (255, 255, 255) rectpos = (x, y) rectdim = (50, 50) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT: x += 5 print("K_RIGHT") if event.key == pygame.K_LEFT: x -= 5 print("K_LEFT") if event.key == pygame.K_UP: y -= 5 print("K_UP") if event.key == pygame.K_DOWN: y += 5 print("K_DOWN") # Don't allow coords below 0 if 0 > x: x = 5 if 0 > y: y = 5 # Don't allow overflow if x + rectdim[0] > wndsize[0]: x = wndsize[0] - rectdim[0] - 5 if y + rectdim[1] > wndsize[1]: y = wndsize[1] - rectdim[1] - 5 rectpos = (x, y) display.fill(white) rect = pygame.draw.rect(display, black, ((rectpos), (rectdim))) pygame.display.update() main()
This might work: from pygame import * init() if key.get_pressed()[K_w] == True: print('Forwards') if key.get_pressed()[K_s] == True: print('Backwards')`
My character won't move in python
This is the code I used. import pygame, sys from pygame.locals import * pygame.init() def game(): width, height = 1000, 600 screen = pygame.display.set_mode((width,height)) pygame.display.set_caption('My game far now :P') #This command allows you make a title. background=pygame.image.load('AE.jpg') background = pygame.transform.scale(background, (width,height)) screen.blit(background, (0,0)) #Load target image and player player = pygame.image.load('little.png') player = pygame.transform.scale(player, (40,40)) px,py = width/2,height/2 screen.blit(player, (px,py)) movex = movey = 0 #Running of the game loop while True: screen.blit(background, (0,0)) #screen.blit(target,targetpos) screen.blit(player, (px,py)) pygame.display.update() #keyboard an/or mouse movements for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() elif event.type == pygame.KEYDOWN: if event.key == K_RIGHT: movex = 2 if event.key == K_LEFT: movex = -2 if event.key == K_UP: movey = -2 if event.key == K_DOWN: movey = 2 elif event.type == pygame.KEYUP: if event.key == K_RIGHT: movex = 0 if event.key == K_LEFT: movex = 0 if event.key == K_UP: movey = 0 if event.key == K_DOWN: movey = 0 px = px + movex py = py + movey #Python 's way of running the main routine if __name__=='__main__': game() When I run the program it all starts right, the screen opens with background and player spawning in the middle of the screen, but when I try to move nothing happends, no errors nothing. Would apriciate any help I can get :) Thx for taking time to help me.
You seem to have code indentation problem in last two lines which may be causing the bug. Your curent code is equivalent to this if code block: elif event.type == pygame.KEYUP: if event.key == K_RIGHT: movex = 0 if event.key == K_LEFT: movex = 0 if event.key == K_UP: movey = 0 if event.key == K_DOWN # IF BLOCK STARTS movey = 0 px = px + movex # THIS FALLS IN THE PREVIOUS IF BLOCK py = py + movey Correct code would be : elif event.type == pygame.KEYUP: if event.key == K_RIGHT: movex = 0 if event.key == K_LEFT: movex = 0 if event.key == K_UP: movey = 0 if event.key == K_DOWN # IF BLOCK STARTS movey = 0 #IF BLOCK ENDS px = px + movex # NOW THIS IS OUT OF THE IF BLOCK py = py + movey
Take this code, the movement is optimized. Useles code removed. I hope you understand it ;) import pygame, sys from pygame.locals import * pygame.init() width, height = 1000, 600 screen = pygame.display.set_mode((width,height)) pygame.display.set_caption('My game far now :P') background=pygame.image.load('AE.png') background = pygame.transform.scale(background, (width,height)) player = pygame.image.load('little.png') player = pygame.transform.scale(player, (40,40)) px,py = width/2,height/2 movex = movey = 0 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: px -= 2 if keys[pygame.K_RIGHT]: px += 2 if keys[pygame.K_UP]: py -= 2 if keys[pygame.K_DOWN]: py += 2 screen.blit(background, (0,0)) screen.blit(player, (px,py)) pygame.display.update()
Two problems. You don't render in your loop You are updating the location only in the if statement. fixed: while True: # input for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() elif event.type == pygame.KEYDOWN: # ...snip... # physics px += movex py += movey # drawing screen.blit(background, (0,0)) screen.blit(player, (px,py)) pygame.display.update()