How can I make the character moving when I press a key? - python-3.x

I know it has been asked before but I couldn't get it to work, I'm using idle 3.6 and PyGame.
Here is the code.(I just started I have been watching some tutorials but apart from that I'm new to PyGame)
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
location += 1

You can use a boolean flag to keep track of which key was pressed and released. Something like:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
pressedRight = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
pressedRight = False
# Now in your game loop
if pressedRight:
location += 1
Basically, this code emulates a way to check if the key is pressed at the current time or not, allowing you to use continuous movement.

Related

How do you break out of while loop by pressing a gamepad button (User Input)

I am using pygame just so that I can use the xbox controller on my script. My goal is to press a button to start a repeating task, and then be able to press another button to break out of the repeating task. I should then be able to press the original button to resume the task.
Before I even post the code, I know the crux of my problem is this part here: (something wrong with my indentation but the code works).
while True:
schedule.run_pending()
time.sleep(1)
How do I break out of this while loop so that I can use the next button JOYHATMOTION: Basically I would be using JOYHATMOTION to pause the job function.
Here is the code. It prints "Hello World" every five seconds for 200 seconds.
import schedule
from datetime import datetime, timedelta, time
import time
import sys
import pygame
from pygame.locals import *
pygame.init()
def job():
print('Hello World')
pygame.joystick.init()
joysticks = [pygame.joystick.Joystick(i) for i in range(pygame.joystick.get_count())]
for joystick in joysticks:
print(joystick.get_name())
while True:
for event in pygame.event.get():
if event.type == JOYBUTTONDOWN:
print(event)
if event.button == 8:
schedule.every(5).seconds.until(timedelta(seconds=200)).do(job)
while True:
schedule.run_pending()
time.sleep(1)
if event.type == JOYHATMOTION:
if event.value[0] == 1:
print(event)
if event.value[0] == -1:
print(event)
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
I have tried:
while True:
if event.type == JOYHATMOTION:
if event.value[0] == 1:
break
else:
schedule.run_pending()
time.sleep(1)
but this dosent seem to work. Thank You in advance.
Never try to control the application with a loop inside the application loop. Use the application loop. The application loop is continuously executed. Use a game_state variable that indicates the current state of the application. Execute the code in the application depending on the state of the variable.
With this approach, you can easily change the state back when another key is pressed.
game_state = ""
run = True
while run:
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
run = False
if event.type == JOYBUTTONDOWN:
print(event)
if event.button == 8:
if game_state == "schedule":
game_state = "" # schedule off
else:
game_state = "schedule" # schedule on
schedule.every(5).seconds.until(timedelta(seconds=200)).do(job)
if event.type == JOYHATMOTION:
if event.value[0] == 1:
print(event)
if event.value[0] == -1:
print(event)
if game_state == "schedule":
schedule.run_pending()
# [...]
pygame.quit()
sys.exit()

My space ship won't move towards right in pygame

import pygame
#initialize the screen
pygame.init()
#create the screen
screen = pygame.display.set_mode((800, 700))
#tile and icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load("spaceship.png")
pygame.display.set_icon(icon)
#Player
playerImg = pygame.image.load("player.png")
playerx = 370
playery = 600
playerx_change = 0.1
def player(x,y):
screen.blit(playerImg, (x,y))
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#keystroke
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerx_change = -0.1
if event.type == pygame.K_RIGHT:
playerx_change = 0.1
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerx_change = 0
playerx += playerx_change
player(playerx,playery)
pygame.display.update()
my spaceship won't move towards right side when i press the riht key. but it will move towards the left side if i press the left key and no error is displayed in the terminal. i use the community version of visual studio 2019.
You need to change this:
if event.type == pygame.K_RIGHT:
to this ("type" --> "key"):
if event.key == pygame.K_RIGHT:

pipes spawning too fast in flappy bird pygame

Im working on this flappy bird pygame tutorial and when I tested the code the pipes spawned in too fast. I'm using a tutorial since I'm fairly new to python and would appreciate any help. Thanks. Here is the link to the tutorial website: https://github.com/clear-code- projects/FlappyBird_Python/blob/master/flappy.py
Here is the code I have so far.
import pygame
import sys
import os
from random import randint
def draw_floor():
screen.blit(floor_surface,(floor_x_pos,750))
screen.blit(floor_surface,(floor_x_pos + 576,750))
def create_pipe():
new_pipe = pipe_surface.get_rect(midtop = (288,375))
return new_pipe
def move_pipes(pipes):
for pipe in pipes:
pipe.centerx -= 5
return pipes
def draw_pipes(pipes):
for pipe in pipes:
if pipe.bottom >= 750:
screen.blit(pipe_surface,pipe)
pygame.init()
screen = pygame.display.set_mode((576,855))
clock = pygame.time.Clock()
# Game variables
gravity = 0.25
bird_movement = 0
bg_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','bg.png')).convert_alpha())
floor_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','base.png')).convert_alpha())
floor_x_pos = 0
bird_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','bird2.png')).convert_alpha())
bird_rect = bird_surface.get_rect(center = (100,427))
pipe_surface = pygame.transform.scale2x(pygame.image.load(os.path.join('imgs','pipe.png')))
pipe_list = []
SPAWNPIPE = pygame.USEREVENT
pygame.time.set_timer(SPAWNPIPE,5000)
pipe_height = [300,500,700]
while True:
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_SPACE:
bird_movement = 0
bird_movement -= 12
if event.type == SPAWNPIPE:
pipe_list.extend(create_pipe())
# bird
screen.blit(bg_surface,(0,0))
bird_movement += gravity
bird_rect.centery += int(bird_movement)
screen.blit(bird_surface,bird_rect)
# pipes
pipe_list = move_pipes(pipe_list)
draw_pipes(pipe_list)
floor_x_pos -= 1
draw_floor()
if floor_x_pos <= -576:
floor_x_pos = 0
pygame.display.update()
clock.tick(120)`
Indent the SPAWNPIPE check:
while True:
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_SPACE:
bird_movement = 0
bird_movement -= 12
if event.type == SPAWNPIPE: # indent this
pipe_list.extend(create_pipe())
The issue is that once you get the first SPAWNPIPE event, the event.type condition for adding a new pipe becomes True.
However, due to improper indentation, that condition is repeatedly checked every frame until the next event is received. This means the code is continually spawning pipes every frame during this time.
Fix the indentation, to bring the pipe-event check back inside the event for-loop:
while True:
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_SPACE:
bird_movement = 0
bird_movement -= 12
if event.type == SPAWNPIPE: # <<-- HERE
pipe_list.extend(create_pipe()) # <<-- AND HERE
Which makes the SPAWNPIPE check be performed only when the event is actually received.

Why does pygame.time.wait kick in before display update?

I have written a code for a game where you slide 15 tiles to set them in order. At the end of the game, I want the screen to just wait for 5 seconds before closing (also want to give a message but that later).
When the game ends, it first pauses and then shows the last move and then closes out. Is there a lag in the display. How do I make it complete the display, and then wait. I tried reading similar posts, but couldn't quite understand.
Here is the relevant code.
> def run_game(self):
"""Start the main loop for the game"""
self._shuffle_grid()
self._show_board()
game_over = False
while True:
change = self._check_events()
if change:
self._show_board()
game_over = self.end_of_game()
if game_over:
pygame.time.wait(5000)
sys.exit()
def _check_events(self):
# Watch for keyboard and mouse events
change = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
key = "U"
elif event.key == pygame.K_DOWN:
key = "D"
elif event.key == pygame.K_LEFT:
key = "L"
elif event.key == pygame.K_RIGHT:
key = "R"
if key == "U" or "D" or "L" or "R":
change = self.key_check(key)
return(change)
I actually tried this and it worked. I still don't know how to show a message and then wait 5 seconds. Working on it.
def celebrate(self):
""" does end of game thing"""
game_clock = pygame.time.Clock()
time_passed = pygame.time.get_ticks()
self._show_board()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
sys.exit()
if pygame.time.get_ticks() > time_passed + 5000:
sys.exit()
def run_game(self):
"""Start the main loop for the game"""
self._shuffle_grid()
self._show_board()
game_over = False
while True:
change = self._check_events()
if change:
game_over = self.end_of_game()
if not game_over:
self._show_board()
else:
self.celebrate()

PYGAME: Continous K_DOWN doesn't really work

This code should make it so the black rectangle does continous movement while the K_LEFT or K_RIGHT are being pressed, but what happens instead is it just moves once it is pressed, and then once that happens, while the mouse is in motion over the window, it moves (when it shouldnt, it should only move when a key is being pressed).
So here's the code, hopefully you can help:
import pygame
pygame.init()
red = (255,0,0)
white = (255,255,255)
black = (0,0,0)
gameDisplay = pygame.display.set_mode((800,600))
pygame.display.set_caption('Slither')
gameExit = False
lead_x = 300
lead_y = 300
lead_x_change = 0
clock = pygame.time.Clock()
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 = -10
if event.key == pygame.K_RIGHT:
lead_x_change = 10
lead_x += lead_x_change
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, black, [lead_x, lead_y,10,10])
pygame.display.update()
clock.tick(30)
pygame.quit()
quit()
The reason is because you have indented all your code inside the event loop, meaning that you're only updating the screen and position of the rect when there are events in the event loop (such as moving the mouse, pressing a button, etc.).
Make sure you have your indention correct, like this:
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 = -10
if event.key == pygame.K_RIGHT:
lead_x_change = 10
# All code below was indented to much.
lead_x += lead_x_change
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, black, [lead_x, lead_y, 10, 10])
pygame.display.update()
clock.tick(30)
Also, it is usually good practice to be consistent when you're naming your variables. Preferably, gameDisplayand gameExit could be named game_display and game_exit for more continuity.

Resources