Pressing a button to have constant movement - python-3.x

I followed an online tutorial to make a snake game and want some help to make some changes. As of now, holding the left or right arrow keys will cause the snake to move. Would it be able to make the snake move to the left or right with only a tap of the button so the user doesn't have to hold down the arrow keys?
question = True
while not gameExit:
#Movement
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
direction = "left"
start_x_change = -block_size_mov
start_y_change = 0
elif event.key == pygame.K_RIGHT:
leftMov = False
direction = "right"
start_x_change = block_size_mov
start_y_change = 0

The solution is to start off by storing the x,y coordinates of the sprite, set a modifier (increase or decrease amount) on keypress, and then add the modifier to the coordinates while looping. I've written a quick demo of such a system:
import pygame
from pygame.locals import *
pygame.init()
# Set up the screen
screen = pygame.display.set_mode((500,500), 0, 32)
# Make a simple white square sprite
player = pygame.Surface([20,20])
player.fill((255,255,255))
# Sprite coordinates start at the centre
x = y = 250
# Set movement factors to 0
movement_x = movement_y = 0
while True:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
movement_x = -0.05
movement_y = 0
elif event.key == K_RIGHT:
movement_x = 0.05
movement_y = 0
elif event.key == K_UP:
movement_y = -0.05
movement_x = 0
elif event.key == K_DOWN:
movement_y = 0.05
movement_x = 0
# Modify the x and y coordinates
x += movement_x
y += movement_y
screen.blit(player, (x, y))
pygame.display.update()
Note that you need to reset the x movement modifier to 0 when changing y, and vice-versa - otherwise you end up with interesting diagonal movements!
For a snake game, you might want to modify the snake size as well as/instead of position - but you should be able to achieve something similar using the same structure.

Related

in my incomplete version of space invaders, the 1 bullet is not being fired.. but no error message is shown. can somebody review it suggest a solution [duplicate]

This question already has answers here:
How can i shoot a bullet with space bar?
(1 answer)
How do I stop more than 1 bullet firing at once?
(1 answer)
Closed 6 days ago.
import pygame
import random
# get the window
pygame.init
# window var declarataion and parameters
window = pygame.display.set_mode((800, 600))
background = pygame.image.load("space bg.png")
# characters
# spaceship
playerImg = pygame.image.load("spaceship-2.png")
playerX = 360
playerY = 535
playerX_change = 0
#enemy
enemyImg = pygame.image.load("space-invaders.png")
enemyX = random.randint(0, 536)
enemyY = random.randint(0, 120)
enemyX_change = 1
enemyY_change = 30
#bullet
bulletImg = pygame.image.load("space-invaders.png")
bulletX = playerX
bulletY = 535
bulletX_change = 0
bulletY_change = -100
bullet_state = "ready"
# character functions
#spaceship
def player(x, y):
window.blit(playerImg, (playerX, playerY))
def enemy(x, y):
window.blit(enemyImg, (enemyX, enemyY))
def fire_bullet(x, y):
global bullet_state
if bullet_state == "fire":
window.blit(bulletImg, (playerX + 16, playerY + 10))
# full loop
running = True
while running:
# to change the color of window
window.fill((255, 255, 255))
window.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# check if key pressed is right or left and executes events accordingly
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -1
if event.key == pygame.K_RIGHT:
playerX_change = 1
if event.key == pygame.K_SPACE:
fire_bullet(playerX, bulletY)
bulletY -= bulletY_change
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# enemy movement
# loops the enemy movement
enemyX += enemyX_change
# to change the enemy direction when border of window hit
if enemyX <= 0:
enemyY += enemyY_change
enemyX_change = 1
elif enemyX >= 736:
enemyY += enemyY_change
enemyX_change = -1
# calling function
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
i tried to make the bullet move along the y axis of the spaceship by adding the code shown below into the keystroke code section:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -1
if event.key == pygame.K_RIGHT:
playerX_change = 1
if event.key == pygame.K_SPACE:
fire_bullet(playerX, bulletY)
bulletY -= bulletY_change
but no error message is shown, the bullet is not being shown, but everything else works perfectly.. like the invader moving along the x axis infinitely, and the spaceship can still be controlled by my arrow key.. only thing that doesn't work is the bullet not firing from the spaceship.. and I can't seem to make it work with this code.. if someone could tell me where I went wrong, it would be of tons of help, and I've been on this problem for days now.. so
it would save me a lot of time in the future. thanks

Space Invaders bug pygame

After finally beeing able to make multiple enemies in the game I confronted myself with the most annoying bug ever. I have multiple enemies, a space ship and I can even shoot bullets, but right after I added the enemies to the game and followed the exact same steps as show in this video, the background is gone for some reason, what made the speed of the player character, of the enemies and the bullet went like crazy. Plus, the sprites are duplicating themselves and wont go away, and the only think that I can think is "What the hell am I doing wrong??" because I feel like I can't even follow the steps and copy the code from a video (btw I'm not receiving any error messages). Anyways, here's the full game code.
import pygame
import random
import math
# Initiate pygame
pygame.init()
# Display the game window
screen = pygame.display.set_mode((800, 600))
# Title and Icon
pygame.display.set_caption('Space Invaders')
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)
# Background
background = pygame.image.load('background.png')
# Player
playerSprite = pygame.image.load('player.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemies
enemySprite = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemySprite.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyX_change.append(4)
enemyY_change.append(40)
# Bullet
bulletSprite = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletY_change = 10
# When bullet_state = 'ready', you can't see the bullet on the screen
# When bullet_state = 'fire', the bullet is currently moving
bullet_state = 'ready'
score = 0
def player(x, y):
screen.blit(playerSprite, (x, y))
def enemy(x, y, i):
screen.blit(enemySprite[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = 'fire'
screen.blit(bulletSprite, (x + 16, y + 10))
def isCollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# If a key is pressed, check if it's the right or left arrow key
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 == 'ready':
bulletX = playerX
fire_bullet(playerX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# Player movement
playerX += playerX_change
# Prevents the player from going off the border
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemies movement
for i in range(num_of_enemies):
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 4
enemyY[i] += enemyX_change[i]
elif enemyX[i] >= 736:
enemyX_change[i] = -4
enemyY[i] += enemyY_change[i]
# Collision
collision = isCollision(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
bulletY = 480
bullet_state = 'ready'
score += 1
print(score)
enemyX[i] = random.randint(0, 736)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
# Bullet movement
if bulletY <= 0:
bulletY = 480
bullet_state = 'ready'
if bullet_state == 'fire':
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
pygame.display.update()
the background is gone for some reason
Of course, because the background is never blit to screen.
the sprites are duplicating themselves and wont go away,
That's because you don't draw the background.
blit the background in the main application loop, before the objects of the scene are drawn:
while running:
# [...]
screen.blit(background, (0, 0))
# Enemies movement
for i in range(num_of_enemies):
# [...]
the speed of the player character, of the enemies and the bullet went like crazy.
Use pygame.time.Clock() to control the frames per second.
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
# [...]
Another (less sophisticated) possibility, which is probably use in the tutorial is to use pygame.time.delay():
running = True
while running:
pygame.time.delay(10)
# [...]

Powerbar decrease script, pygame

I'm trying to create a "powerbar."
In the following code I can press left & right key to increase the bar, and the prg terminates when the bar_start_width > 400 px.
I would like the "powerbar" to decrease while bar_start_width > 0. So, if you stop to press the buttons, the bar will slowly decrease until bar_start_width > 0.
With my code it is slowly decreasing bar_start_width, but not updating the display. The while loop also continues running.
Here is full code:
import time
import random
import pygame
import time
import pygame
pygame.init()
display_width = 800
display_height = 600
black = (0, 0, 0)
white = (255, 255, 255)
gameDisplay = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
def powerbar(thingx, thingy, thingw, thingh, color):
pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
def game_quit():
pygame.quit()
quit()
def game_loop():
decrease_speed = -1
bar_start_width = 0
bar_x = 100
bar_y = 100
bar_height = 50
bar_color = black
x_change = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white) # the background color before img
# Should change so you can ONLY press right after left (or opposite)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = 5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
bar_start_width += x_change
# Draw powerbar
powerbar(bar_x, bar_y, bar_start_width, bar_height, bar_color)
if bar_start_width > 10:
while True:
bar_start_width += decrease_speed
time.sleep(0.5)
print(bar_start_width) #See output in terminal
if bar_start_width == 0:
break
if bar_start_width > 400:
game_quit()
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
I have tried also to think in terms of a for loop to solve my problems but after long time of trying out different things this is the best I can come up with.
Can anyone help, or link me to a similar discussion?
Thanks!
I'm not sure why you have a nested while loop in the main while loop. If I understand you correctly, you want to decrease the width every frame if (not while) the width is greater than 0. Just remove the while loop and the time.sleep call and decrease the width if bar_start_width > 0:.
import pygame
pygame.init()
black = (0, 0, 0)
white = (255, 255, 255)
gameDisplay = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
def game_loop():
decrease_speed = -1
bar_start_width = 0
bar_x = 100
bar_y = 100
bar_height = 50
x_change = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = 5
elif event.key == pygame.K_RIGHT:
x_change = 5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
bar_start_width += x_change
if bar_start_width > 0:
bar_start_width += decrease_speed
if bar_start_width <= 0: # Set it to the minimum width of 1.
bar_start_width = 1
if bar_start_width > 400:
print('> 400')
gameDisplay.fill(white)
# Draw powerbar
pygame.draw.rect(gameDisplay, black, (bar_x, bar_y, bar_start_width, bar_height))
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
I've rearranged a few things, because the game logic and the event loop were mixed. You should generally try to separate the event handling, game logic and the rendering.

pygame event keys are not responding even though idle is not showing an error?

import pygame
from pygame import *
pygame.init
pygame.display.init
pygame.display.set_caption("Test")
bg = pygame.image.load("bg.jpg")
human = pygame.image.load("human1.bmp")
display_screen = pygame.display.set_mode((1000,500))
keyboard_input = 0
clock = pygame.time.Clock()
def screen_Quit():
running = False
while not running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
keyboard_input = (90)
print("Left arrow key has been pressed.")
if event.key == pygame.K_RIGHT:
keyboard_input = (-90)
print("Right arrow key has been pressed.")
if event.key == pygame.K_UP:
keyboard_input = (20)
print("Up arrow key has been pressed.")
if event.key == pygame.K_DOWN:
keyboard_input = (-20)
print("Down arrow key has been pressed.")
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
keyboard_input = (0)
print("Left arrow key has been released.")
if event.key == pygame.K_RIGHT:
keyboard_input = (0)
print("Right arrow key has been released.")
if event.key == pygame.K_UP:
keyboard_input = (0)
print("Up arrow key has been released.")
if event.key == pygame.K_DOWN:
keyboard_input = (0)
print("Down arrow key has been released.")
# this code here has been left for later --> print(event)
display_screen.blit(bg, [0,0])
display_screen.blit(human, [50,87])
pygame.display.update()
clock.tick(60)
screen_Quit()
pygame.quit
quit()
I don't understand the problem, I have posted my full code as the problem might be something else. The problem I've been having with the program is the event keys in python it's not responding to the input which is the keyboard I'm using pygame to create a game but cannot understand why the event keys are not working. I have checked everywhere and cannot understand. The code seems fine to me, python idle is not giving any errors I'm even getting input in the idle but the character doesn't move there should be no reason for it not to move.
Here is a picture and a link to a video that goes more in depth into the problem (I created the video myself):
an image of the problem
Link to video:
https://www.youtube.com/watch?v=QVFaiuF9KY8&feature=youtu.be
Video will most likely be more useful than image.
Short Answer
Your code doesn't have any commands that tell the image to move. I fixed this and posted the full working code at the bottom. If you want a more in depth explanation, read on.
Explanation
If that is your full code, then the problem is that first of all you don't even have any code in the first place that tells the character to move. And second of all your pygame.display.update() is outside the while loop, so any changes made to the screen don't show.
For every event you just told python to print a message:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
keyboard_input = (90)
print("Left arrow key has been pressed.")
What you want to do is add another line there to actually move the character.
This can be done by changing it's x and y position. I recommend using sprites for this, but for now since you are using an image, we'll just stick to that.
To change the position of an image you have to run a new window.blit() with the desired (x,y). This means that you will have to constantly iterate this if you're going to need to move it around a lot, so it's better to put it INSIDE the running while loop. So bring this part of your code on indentation forward:
display_screen.blit(bg, [0,0])
display_screen.blit(human, [50,87])
pygame.display.update()
clock.tick(60)
screen_Quit()
pygame.quit
quit()
So now the screen get's regularly updated. The second thing you want to do is create 2 new variables x and yand change
display_screen.blit(human, [50,87])
to
display_screen.blit(human, [x,y])
This basically means that you character now gets blitted to the screen at the position YOU choose, not at a fixed position that doesn't change. So now you can add + to the x position whenever the left key is clicked, or - from the x position whenever the right key is clicked!
Here is the full working code:
import pygame
from pygame import *
pygame.init
pygame.display.init
pygame.display.set_caption("Test")
bg = pygame.image.load("bg.jpg")
human = pygame.image.load("human1.bmp")
display_screen = pygame.display.set_mode((1000,500))
keyboard_input = 0
clock = pygame.time.Clock()
running = False
x=0
y=0
moving = "none"
white = (255,255,255)
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_LEFT:
moving = "left"
print("Left arrow key has been pressed.")
elif event.key == pygame.K_RIGHT:
moving = "right"
print("Right arrow key has been pressed.")
elif event.key == pygame.K_UP:
moving = "up"
print("Up arrow key has been pressed.")
elif event.key == pygame.K_DOWN:
moving = "down"
print("Down arrow key has been pressed.")
else:
moving = "hello"
if moving == "left":
x -= 5
if moving == "right":
x += 5
if moving == "up":
y -= 5
if moving == "down":
y += 5
# this code here has been left for later --> print(event)
display_screen.blit(bg,[0,0])
display_screen.blit(human, [x,y])
clock.tick(60)
pygame.display.update()
You never update the position of your player and just blit it at [50,87]. If you want it to move, you first have to store the position, e.g. player_pos = [50, 87] and define variables for the velocity velocity_x = 0, then set the velocity in the event loop if a key gets pressed:
if event.key == pygame.K_RIGHT:
velocity_x = 5
and update the position in the while loop:
player_pos[0] += velocity_x
player_pos[1] += velocity_y

make sprite crouch in current position python

Hi i'm making a fighting game to get some practice with pygame but I have run into a problem with crouching/ducking. When I press the down button it goes back to its original location then ducks. If you need more info to help i will provide.
import pygame
import random
display_height = 600
display_width = 1000
dis_screen = pygame.display.set_mode((display_width, display_height))
FPS = 30
clock = pygame.time.Clock()
img = pygame.image.load('foo.png')
crouchimg = pygame.image.load('crouchimg.png')
# Simple player object
class Player(object):
def __init__(self, x, y, image):
self.x = x
self.y = y
self.image = image
# Method to draw object
def draw(self):
dis_screen.blit(self.image, (self.x, self.y))
# Method to move object
def move(self, speedx, speedy):
self.x += speedx
self.y += speedy
class MainRun(object):
def __init__(self, displayw, displayh):
self.dw = displayw
self.dh = displayh
self.Main()
def Main(self):
# Put all variables up here
stopped = False
x_move = 0
y_move = 0
p1_y_loc = 200
p1_x_loc = 200
x = pygame.Rect().x
greg = Player(p1_x_loc, p1_y_loc, img)
# Main Loop
while not stopped:
print(x)
dis_screen.fill((255, 255, 255)) # Tuple for filling display... Current is white
# Event Tasking
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:
y_move = 0
x_move = 5
elif event.key == pygame.K_LEFT:
y_move = 0
x_move = -5
elif event.key == pygame.K_UP:
y_move = -5
x_move = 0
elif event.key == pygame.K_DOWN:
p1_y_loc = 300
p1_x_loc = 0
greg = Player(p1_x_loc, p1_y_loc, crouchimg)
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN:
p1_y_loc = 200
greg = Player(p1_x_loc, p1_y_loc, img)
if event.key == pygame.K_UP:
y_move = 0
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
x_move = 0
greg.move(x_move, y_move)
greg.draw()
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
run = MainRun(display_width, display_height)
run.Main()
That's because when you're pressing the down key you're creating a new player at the x-position p1_x_loc (which you've set to 0) and y-position p1_y_loc (which you've set to 300). So when the player crouches it also moves it to (0, 300) no matter the position the player currently is.
A way to solve this would be to just change the player's image, and not create a completely new player. You can do it this way, player.image = crouchimg instead of greg = Player(p1_x_loc, p1_y_loc, crouchimg). And when the player gets up you just change the image again: player.image = img
And if you have to change the players' y-position when crouching you could do it the same way: player.y = 200 and player.y = 300.

Resources