How to remove this duplicate of balloon while moving
Here's my code
lead_x = 0
lead_y = 400
balloonR_x = 400
balloonR_y = 400
balloonP_x = 500
balloonP_y = 400
balloonR_move = 50
#balloonB_x = 550
#balloonB_Y = 400
lead_y_change = 0
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_UP:
lead_y_change -= 10
elif event.key == pygame.K_DOWN:
lead_y_change += 10
if event.type == pygame.KEYUP:
lead_y_change = 0
lead_y += lead_y_change
gamedisplay.blit(bg, [0,0])
gamedisplay.blit(bow,[lead_x, lead_y])
while balloonR_y >= 50:
gamedisplay.blit(red_balloon, [balloonR_x, balloonR_y])
pygame.display.update()
pygame.event.clear(balloonR_y)
clock.tick(1)
balloonR_y -= balloonR_move
#gamedisplay.blit(red_balloon, [balloonR_x, balloonR_y])
gamedisplay.blit(purple_balloon, [balloonP_x, balloonP_y])
#gamedisplay.blit(blue_balloon, [balloonB_x, balloonB_y])
pygame.display.update()
clock.tick(20)
and also if i run the program first the balloon loop gets executed first in that time i cannot able to control the arrow.
You can't use while loop (and any long-running functions or sleep()).
You have to only change baloon position and let main while blits background and other elements (and does other things like handle events, make other animations, etc.)
More or less:
while not gameExit:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
lead_y_change -= 10
elif event.key == pygame.K_DOWN:
lead_y_change += 10
if event.type == pygame.KEYUP:
lead_y_change = 0
# --- updates (without draws) ---
lead_y += lead_y_change
if balloonR_y >= 50:
balloonR_y -= balloonR_move
# --- draws (without updates) ---
gamedisplay.blit(bg, [0,0])
gamedisplay.blit(bow,[lead_x, lead_y])
gamedisplay.blit(red_balloon, [balloonR_x, balloonR_y])
gamedisplay.blit(purple_balloon, [balloonP_x, balloonP_y])
#gamedisplay.blit(blue_balloon, [balloonB_x, balloonB_y])
pygame.display.update()
clock.tick(20)
Related
I'm currently trying to build a game through vscode using pygame lib.
My code to move character around with keyboard arrow keys won't apply to my module.
My module won't close even though I click exit button or esc.
Any thoughts why its not working?
import pygame
import os
pygame.init()
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("June's Game")
background = pygame.image.load("D:/Python/pygame_basic/background.png")
character = pygame.image.load("D:/Python/pygame_basic/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_position = (screen_width / 2) - (character_width / 2)
character_y_position = screen_height - character_height
to_x = 0
to_y = 0
running = True #게임이 진행중인가
while running:
for event in pygame.event.get():
if event == pygame.QUIT:
running = False
if event == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
pygame.quit()
i coudln't get it to work
event is an object. You have to get the type of the event, e.g.:
if event == pygame.KEYDOWN
if event.type == pygame.KEYDOWN:
You have to limit the frames per second to limit CPU usage with pygame.time.Clock.tick and to control the speed of the game. Otherwise, the player moves much too fast and immediately disappears from the screen. The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
However, there is a better method to move an object when a key is held down (See How can I make a sprite move when key is held down):
to_x = 0
to_y = 0
speed = 5
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
to_x = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
to_y = (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
character_x_position += to_x
character_y_position += to_y
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
This question already has answers here:
How can I make a sprite move when key is held down
(6 answers)
Closed 1 year ago.
right now it just moves in the direction i tell it to put it just stops. How do i go about making it KEEP going in the direction I inputted by? And make it constantly go in the direction, but be able to control how fast it moves, right now i want it to move every 4 minutes
import pygame
from pygame.locals import *
pygame.init()
surface = pygame.display.set_mode((600, 600))
background = pygame.image.load('back.png')
surface.blit(background, (0, 0))
block = pygame.image.load('block.png').convert()
block_y = 0
block_x = 0
surface.blit(block, (block_x, block_y))
def draw():
surface.blit(background, (0, 0))
surface.blit(block, (block_x, block_y))
pygame.display.flip()
direction = ''
pygame.display.flip()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
if event.key == K_UP:
block_y -= 10
draw()
if event.key == K_DOWN:
block_y += 10
draw()
if event.key == K_LEFT:
block_x -= 10
draw()
if event.key == K_RIGHT:
block_x += 10
draw()
elif event.type == QUIT:
running = False
```
Here's an option with minimal changes to your program. I changed the event handlers to update speed variables, which update the position in an added update() function. The speeds are zeroed when the key is released. I've also removed the duplicated draw() functions. Note this code is untested.
import pygame
from pygame.locals import *
pygame.init()
surface = pygame.display.set_mode((600, 600))
background = pygame.image.load('back.png')
surface.blit(background, (0, 0))
block = pygame.image.load('block.png').convert()
block_y = 0
block_x = 0
speed_x = 0
speed_y = 0
surface.blit(block, (block_x, block_y))
def draw():
surface.blit(background, (0, 0))
surface.blit(block, (block_x, block_y))
pygame.display.flip()
def update():
"""Update game state"""
block_x += speed_x
block_y += speed_y
direction = ''
pygame.display.flip()
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_UP:
speed_y -= 10
elif event.key == K_DOWN:
speed_y += 10
elif event.key == K_LEFT:
speed_x -= 10
elif event.key == K_RIGHT:
speed_x += 10
elif event.type == KEYUP:
if event.key in (K_DOWN, K_UP):
speed_y = 0
elif event.key in (K_LEFT, K_RIGHT):
speed_x = 0
elif event.type == QUIT:
running = False
update()
draw()
clock.tick(60) # limit frame rate to 60 FPS
EDIT: Added frame rate limiting
Use pygame.key.get_pressed() instead of the KEYDOWN event.
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.
pygame.key.get_pressed() returns a sequence 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
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
block_y -= 10
if keys[pygame.K_DOWN]:
block_y += 10
if keys[pygame.K_LEFT]:
block_x -= 10
if keys[pygame.K_RIGHT]:
block_x += 10
draw()
The code can be further simplified:
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
keys = pygame.key.get_pressed()
block_x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 10
block_y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 10
draw()
I can't seem to the error in this code, the game simply quits right after launching it. If anybody could read through my code and answer me what I'm doing wrong, and I'd be very grateful. I've already read through all of it and couldn't figure it out. I don't know why the game quits right after launching it. (Meaning I can't even move my block).
import pygame
import time
pygame.init()
width = 800
height = 600
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
gameDisplay = pygame.display.set_mode((width, height))
pygame.display.set_caption("First snake game.")
clock = pygame.time.Clock()
block_size = 1
FPS = 100
def gameloop():
gameExit = False
lead_x = width/2
lead_y = height/2
lead_x_change = 0
lead_y_change = 0
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:
lead_y_change = -block_size
lead_x_change = 0
if event.key == pygame.K_s:
lead_y_change = block_size
lead_x_change = 0
if event.key == pygame.K_d:
lead_x_change = block_size
lead_y_change = 0
if event.key == pygame.K_a:
lead_x_change = -block_size
lead_y_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_a or event.key == pygame.K_d:
lead_x_change = 0
if event.key == pygame.K_w or event.key == pygame.K_s:
lead_y_change = 0
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, black, [lead_x, lead_y, block_size, block_size])
pygame.display.update()
time.sleep(2)
pygame.quit()
quit()
clock.tick(FPS)
gameloop()
`
Not sure if I'm understanding the code correctly or not, but at the end of the gameloop() function you have pygame.quit() and quit() so comment that out and see what happens.
I'm stuck trying to change the sprite blitted to the screen (when moving upwards) to a back view of the sprite.
Currently the sprite is just blitted to the white background on each key press at the most recent x and y coordinates and not fluidly moving along the screen (i want to move the sprite continuously on set trajectories, based on arrow key press, like in snake).
This is my first stab at programming anything on python so Leyman's terms if possible!
lead_x_change = 0
lead_y_change = 0
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_LEFT:
lead_x_change = -5
if event.key == pygame.K_RIGHT:
lead_x_change = 5
#above are two snips of code to show the method i'm using to move the sprite
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_DOWN:
gameDisplay.fill(white)
gameDisplay.blit(spriteX,(lead_x,lead_y))
pygame.display.update()
if event.key == pygame.K_UP:
gameDisplay.fill(white)
gameDisplay.blit(spriteY,(lead_x,lead_y))
pygame.display.update()
lead_y += lead_y_change
lead_x += lead_x_change
clock.tick(60)
pygame.quit()
quit()
I think there are two plausible ways you can change your sprite depending on the direction you're moving.
First off, lets fix your current drawing logic, so that you draw the sprite regardless of keypresses:
while not gameExit:
for event in pygame.event.get(): # event loop handles setting player speed
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -5
if event.key == pygame.K_RIGHT:
lead_x_change = 5
lead_y += lead_y_change # update logic moves the position
lead_x += lead_x_change
gameDisplay.fill(white) # draw logic draws the background and the sprite
gameDisplay.blit(spriteX,(lead_x,lead_y))
pygame.display.update()
clock.tick(60)
The approach to the sprite is to change it at the same place you change your speed (in the event code), then use the changed sprite later when you actually draw the scene.
player_sprite = spriteX
while not gameExit:
for event in pygame.event.get(): # event loop handles setting speed and the sprite
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -5
player_sprite = spriteX
if event.key == pygame.K_UP:
lead_y_change = -5
player_sprite = spriteY
lead_y += lead_y_change # update logic moves the position
lead_x += lead_x_change
gameDisplay.fill(white) # draw logic draws the background and the sprite
gameDisplay.blit(player_sprite,(lead_x,lead_y))
pygame.display.update()
clock.tick(60)
The second approach is to limit the event code to just setting the speed, and then later examining the speed that has been set to pick a sprite to draw.
player_sprite = spriteX
while not gameExit:
for event in pygame.event.get(): # event loop handles setting speed only
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change = -5
if event.key == pygame.K_UP:
lead_y_change = -5
lead_y += lead_y_change # update logic moves the position
lead_x += lead_x_change
if lead_y_change < 0: # set sprite based on speed
player_sprite = spriteY
else:
player_sprite = spriteX
gameDisplay.fill(white) # draw logic draws the background and the sprite
gameDisplay.blit(player_sprite,(lead_x,lead_y))
pygame.display.update()
clock.tick(60)
For very simple logic with only a few different sprites, the event driven sprite changes may be easiest. If you want animations or other more complicated sprite changing behavior, the second approach may be better, since you will be able to handle all the sprite logic in one place.
I am trying to make a snake game using TheNewBoston's tutorials, since I am a Middle School student and dont have much experience in python. The code is:
__author__ = 'Ded'
import pygame
import time
pygame.init()
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Dipshit')
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
clock = pygame.time.Clock()
block_size = 10
FPS = 30
font = pygame.font.SysFont(None, 25)
def message_to_screen(msg,color):
screen_text = font.render(msg, True, color)
gameDisplay.blit(screen_text, [display_width/2, display_height/2])
def gameLoop():
gameExit = False
gameOver = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
while not gameExit:
while gameOver == True:
gameDisplay.fill(white)
message_to_screen("Game over, press C to play again or Q to quit", red)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x_change -= block_size
lead_y_change = 0
if event.key == pygame.K_RIGHT:
lead_x_change += block_size
lead_y_change = 0
if event.key == pygame.K_DOWN:
lead_y_change += block_size
lead_x_change = 0
if event.key == pygame.K_UP:
lead_y_change -= block_size
lead_x_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
lead_x_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
lead_y_change = 0
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, black, [lead_x,lead_y,block_size,block_size])
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
gameLoop()
However, I get this error when I execute, play, lose and press C to retry. Q works fine when I want to quit but C just quits, and prints this error:
C:\Python34\python.exe "C:/Users/Ded/PycharmProjects/PyGame/PyGame
Tutorial.py" Traceback (most recent call last): File
"C:/Users/Ded/PycharmProjects/PyGame/PyGame Tutorial.py", line 100, in
gameLoop() File "C:/Users/Ded/PycharmProjects/PyGame/PyGame Tutorial.py", line 56, in gameLoop
gameLoop() File "C:/Users/Ded/PycharmProjects/PyGame/PyGame Tutorial.py", line 76, in gameLoop
if event.type == pygame.KEYUP: UnboundLocalError: local variable 'event' referenced before assignment
Process finished with exit code 1
You need to indent these parts of the code:
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
lead_x_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
lead_y_change = 0
so that they are part of the for loop. Otherwise if there are no events to get and no iterations of the loop occur, the variable event won't be defined.