I’m trying to make a square character sprite in pygame. Can you please look at my code and tell me what I did wrong? Link to video about it - pygame

a youtube video told me to put what I've already put.
https://www.youtube.com/watch?v=bVx2nhB0t1o&feature=youtu.be
My window opens, but just stays at a black screen. When I close the window, then I get the error message:
Traceback (most recent call last):
File "./invaders.py", line 23, in <module>
keys = pygame.key.get_pressed()
pygame.error: video system not initialized
I don't really understand why this is happening and any help would be much appreciated.
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Space Invaders")
x = 50
y = 50
width = 30
height = 30
vel = 5
run = True
while run:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
win.fill(0)
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
pygame.display.update()

Your code is mixed-up. Generally PyGame applications have a "main loop" which handles the event loop, processes any user input, and then re-draws the screen.
Your code has all of these elements, but a whole block of code is not inside the main loop, it's only executed after the window has been closed. You need to be careful of the placement and indentation.
This code below is basically your exact code, re-arranged with some tweaks.
import pygame
BLACK = ( 0, 0, 0 ) # colours
RED = (255, 0, 0 )
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Space Invaders")
x = 50
y = 50
width = 30
height = 30
vel = 5
clock = pygame.time.Clock()
run = True
# Main loop
while run:
#pygame.time.delay(100) # <-- don't use delays like this
# handle the PyGame event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# handle user movement
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= vel
if keys[pygame.K_RIGHT]:
x += vel
if keys[pygame.K_UP]:
y -= vel
if keys[pygame.K_DOWN]:
y += vel
# repaint the window
win.fill( BLACK )
pygame.draw.rect( win, RED, ( x, y, width, height ) )
pygame.display.update()
clock.tick( 10 ) # limit the FPS here
# main loop has ended, quit
pygame.quit()
Now the window painting, and user-input handling is now moved inside the scope of the main loop.
Also it's best not to add fixed time delays into PyGame code. Adjust the frame rate using a PyGame clock.

Related

How do I use keyboard inputs in pygame?

so I am making a game where this character(a circle) has to pop balloons falling from the sky to get points. But I am having trouble making my character move in the first place.
Code:
import pygame
from pygame.locals import *
pygame.init()
#Variables
white = (255, 255, 255)
blue = (70,130,180)
black = (0,0,0)
x = 400
y = 450
#screen stuff
screenwidth = 800
screenheight = 600
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption("Balloon Game!")
#end of screen stuff
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
exit()
# Draw Character
character = pygame.draw.circle(screen, (blue), (x, y), 50, 50)
#End of Drawing Character
# Making Arrow Keys
keyPressed = pygame.key.get_pressed()
if keyPressed[pygame.K_LEFT]:
character.x -= 1
if keyPressed[pygame.K_RIGHT]:
character.x += 1
pygame.display.update()
I would appreciate it if someone could tell me why it wasn't
working with a fixed code. Thanks!
pygame.draw.circle returns the bounding rectangle (pygame.Rect object) of the circle. However the center of the circle is always (x, y). Therefore you need to change x instead of character.x:
while True:
# [...]
pygame.draw.circle(screen, (blue), (x, y), 50, 50)
keyPressed = pygame.key.get_pressed()
if keyPressed[pygame.K_LEFT]:
x -= 1
if keyPressed[pygame.K_RIGHT]:
x += 1
This code can even be simplified:
while True:
# [...]
pygame.draw.circle(screen, (blue), (x, y), 50, 50)
keyPressed = pygame.key.get_pressed()
x += (keyPressed[pygame.K_RIGHT] - keyPressed[pygame.K_LEFT])

NameError: name 'event' is not defined [duplicate]

I am making a game in pygame 1.9.2.
It's a faily simple game in which a ship moves between five columns of bad guys who attack by moving slowly downward. I am attempting to make it so that the ship moves left and right with the left and right arrow keys. Here is my code:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location-=1
if location==-1:
location=0
if keys[K_RIGHT]:
location+=1
if location==5:
location=4
It works too well. The ship moves too fast. It is near impossible to have it move only one location, left or right. How can i make it so the ship only moves once every time the key is pressed?
You can get the events from pygame and then watch out for the KEYDOWN event, instead of looking at the keys returned by get_pressed()(which gives you keys that are currently pressed down, whereas the KEYDOWN event shows you which keys were pressed down on that frame).
What's happening with your code right now is that if your game is rendering at 30fps, and you hold down the left arrow key for half a second, you're updating the location 15 times.
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
location -= 1
if event.key == pygame.K_RIGHT:
location += 1
To support continuous movement while a key is being held down, you would have to establish some sort of limitation, either based on a forced maximum frame rate of the game loop or by a counter which only allows you to move every so many ticks of the loop.
move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if move_ticker == 0:
move_ticker = 10
location -= 1
if location == -1:
location = 0
if keys[K_RIGHT]:
if move_ticker == 0:
move_ticker = 10
location+=1
if location == 5:
location = 4
Then somewhere during the game loop you would do something like this:
if move_ticker > 0:
move_ticker -= 1
This would only let you move once every 10 frames (so if you move, the ticker gets set to 10, and after 10 frames it will allow you to move again)
pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is 1, otherwise 0. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
This code can be simplified by subtracting "left" from "right" and "up" from "down":
while True:
keys = pygame.key.get_pressed()
x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
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 movement:
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x -= speed
if event.key == pygame.K_RIGHT:
x += speed
if event.key == pygame.K_UP:
y -= speed
if event.key == pygame.K_DOWN:
y += speed
See also Key and Keyboard event
Minimal example of continuous movement: replit.com/#Rabbid76/PyGame-ContinuousMovement
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
keys = pygame.key.get_pressed()
rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
rect.centerx = rect.centerx % window.get_width()
rect.centery = rect.centery % window.get_height()
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), rect)
pygame.display.flip()
pygame.quit()
exit()
Minimal example for a single action: replit.com/#Rabbid76/PyGame-ShootBullet
import pygame
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))
bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
bullet_list.insert(0, tank_rect.midright)
for i, bullet_pos in enumerate(bullet_list):
bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
del bullet_list[i:]
break
window.fill((224, 192, 160))
window.blit(tank_surf, tank_rect)
for bullet_pos in bullet_list:
window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
pygame.display.flip()
pygame.quit()
exit()
import pygame
pygame.init()
pygame.display.set_mode()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); #sys.exit() if sys is imported
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_0:
print("Hey, you pressed the key, '0'!")
if event.key == pygame.K_1:
print("Doing whatever")
In note that K_0 and K_1 aren't the only keys, to see all of them, see pygame documentation, otherwise, hit tab after typing in
pygame.
(note the . after pygame) into an idle program. Note that the K must be capital. Also note that if you don't give pygame a display size (pass no args), then it will auto-use the size of the computer screen/monitor. Happy coding!
I think you can use:
pygame.time.delay(delayTime)
in which delayTime is in milliseconds.
Put it before events.
Try this:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if count == 10:
location-=1
count=0
else:
count +=1
if location==-1:
location=0
if keys[K_RIGHT]:
if count == 10:
location+=1
count=0
else:
count +=1
if location==5:
location=4
This will mean you only move 1/10 of the time. If it still moves to fast you could try increasing the value you set "count" too.
The reason behind this is that the pygame window operates at 60 fps (frames per second) and when you press the key for just like 1 sec it updates 60 frames as per the loop of the event block.
clock = pygame.time.Clock()
flag = true
while flag :
clock.tick(60)
Note that if you have animation in your project then the number of images will define the number of values in tick(). Let's say you have a character and it requires 20 sets images for walking and jumping then you have to make tick(20) to move the character the right way.
Just fyi, if you're trying to ensure the ship doesn't go off of the screen with
location-=1
if location==-1:
location=0
you can probably better use
location -= 1
location = max(0, location)
This way if it skips -1 your program doesn't break
make something like this, but based on time delay. i call my function first time immediately and then lunch timer, and while button is pressed i call it every button_press_delta seconds
from time import time
before main loop:
button_press_delta = 0.2
right_button_pressed = 0
while not done:
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
if not right_button_pressed:
call_my_function()
right_button_pressed = 1
right_button_pressed_time_start = time()
if right_button_pressed:
right_button_pressed_time = (
time() - right_button_pressed_time_start)
if right_button_pressed_time > button_press_delta:
call_my_function()
right_button_pressed_time_start = time()
else:
right_button_pressed = 0
You should use clock.tick(10) as stated in the docs.
all of the answers above are too complexicated i would just change the variables by 0.1 instead of 1
this makes the ship 10 times slower
if that is still too fast change the variables by 0.01
this makes the ship 100 times slower
try this
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location -= 0.1 #or 0.01
if location==-1:
location=0
if keys[K_RIGHT]:
location += 0.1 #or 0.01
if location==5:
location=4
To slow down your game, use pygame.clock.tick(10)

Why is the sprite not moving? [duplicate]

This question already has answers here:
Why is my PyGame application not running at all?
(2 answers)
Closed 1 year ago.
I am currently programming a pygame game where you move a spaceship around the screen. Currently, I have got to the part where I made the spaceship and tried to make it move. However, when I try to move the spaceship around, the spaceship doesn't move!
Here is my current code:
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 500))
screen.fill((255, 255, 255))
class Spaceship(pygame.sprite.Sprite):
def __init__(self, s, x, y):
pygame.sprite.Sprite.__init__(self)
self.screen = s
self.x, self.y = x, y
self.image = pygame.image.load("C:/eqodqfe/spaceship.png")
self.image = pygame.transform.scale(self.image, (175, 175))
self.rect = self.image.get_rect()
self.rect.center = (self.x, self.y)
def update(self):
self.rect.center = (self.x, self.y)
spaceship = Spaceship(screen, 400, 400)
screen.blit(spaceship.image, spaceship.rect)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
if key[pygame.K_a]:
spaceship.x -= 5
elif key[pygame.K_d]:
spaceship.x += 5
elif key[pygame.K_w]:
spaceship.y += 5
elif key[pygame.K_s]:
spaceship.y -= 5
spaceship.update()
pygame.display.update()
What is wrong with my current code?
You have to draw the Sprties in the application loop:
clock = pygame.time.Clock()
running = True
while running:
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
if key[pygame.K_a]:
spaceship.x -= 5
elif key[pygame.K_d]:
spaceship.x += 5
elif key[pygame.K_w]:
spaceship.y -= 5
elif key[pygame.K_s]:
spaceship.y += 5
# update the position of the object
spaceship.update()
# clear the display
screen.fill((255, 255, 255))
# draw the object
screen.blit(spaceship.image, spaceship.rect)
# update the display
pygame.display.update()
# limit frames per second
clock.tick(60)
The typical PyGame application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage
Furthermore I suggest to use a pygame.sprite.Group:
pygame.sprite.Group.draw() and pygame.sprite.Group.update() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update mehtod of the contained pygame.sprite.Sprites - you have to implement the method. See pygame.sprite.Group.update():
Calls the update() method on all Sprites in the Group [...]
The later uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects - you have to ensure that the pygame.sprite.Sprites have the required attributes. See pygame.sprite.Group.draw():
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]
spaceship = Spaceship(screen, 400, 400)
all_sprites = pygame.sprite.Group()
all_sprites.add(spaceship)
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
if key[pygame.K_a]:
spaceship.x -= 5
elif key[pygame.K_d]:
spaceship.x += 5
elif key[pygame.K_w]:
spaceship.y += 5
elif key[pygame.K_s]:
spaceship.y -= 5
all_sprites.update()
screen.fill((255, 255, 255))
all_sprites.draw(screen)
pygame.display.update()

Pygame Reset game

I need some help with reseting a game I made. I've got the main loop going and the collision detection working. I'm trying to get an instant restart on the game, one that just resets the score and gets going again - I don't want it to have any user input before it restarts the game again.
MoveAsteroids() simply moves asteroids across the screen which the player has to avoid. It's also the function where score is incremented by 1 each time an asteroid is dodged.
def game_loop():
global score
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
spaceship.change = -5
elif event.key == pygame.K_DOWN:
spaceship.change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
spaceship.change = 0
spaceship.y += spaceship.change
if spaceship.y > window_height - spaceship.height: # Creating borders on the window
spaceship.y = window_height - spaceship.height
elif spaceship.y < 0:
spaceship.y = 0
window.blit(bg_img, (0, 0))
MoveAsteroids()
CollisionDetection()
Score_display("Score: " + str(score * 100), white)
pygame.display.update()
def CollisionDetection():
global score
spaceship_rect = pygame.Rect(spaceship.x, spaceship.y, spaceship.width, spaceship.height)
for x in range(1, 5):
rect = pygame.Rect(asteroids[x].x, asteroids[x].y, asteroids[x].width, asteroids[x].height)
if spaceship_rect.colliderect(rect):
pass
# The part I need help with is this line of code just above^. .colliderect() returns true when a collision happens.
If I get you right you just want to reset the game. Just do
def CollisionDetection():
global score
spaceship_rect = pygame.Rect(spaceship.x, spaceship.y, spaceship.width, spaceship.height)
for x in range(1, 5):
rect = pygame.Rect(asteroids[x].x, asteroids[x].y, asteroids[x].width, asteroids[x].height)
if spaceship_rect.colliderect(rect):
score = 0
// here you reset your spaceship.x and y to the normal state
you could also have a look at sprites. It makes collision detection easier and is nice for larger games with it's groups.

A blank black window opens in pygame

When I run this code it shows a blank black window and it says x is not defined.
import pygame,sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((800,500))
screen.fill((255,255,255))
#basic stuff
pygame.draw.line(screen,(0,0,0),(500,0),(500,500))
pygame.draw.rect(screen, (0,255,0), (20,50,460,420))
#pygame.draw.line(screen, (0,0,0), (500,0),(500,500))
#pygame.draw.line(screen, (0,0,0), (500,500),(0,500))
#draw
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
x = int(pos[0]//20)
y = int(pos[1]//20)
j = int(x*20+20)
l = int(y*20+20)
print(x+1,' ',y+1)
if x > 2 and y > 3 and x < 24 and y < 24:
pygame.quit()
its not the color. it dose not draw any lines tough i gave the command
myfont = pygame.font.SysFont("monospace", 20)
label = myfont.render("Allameh helli 3 stock exchange group",1,0,0,0))
screen.blit(label, (30, 10))
What are my error(s) here that prevent me from making the screen white and raising that error?
You need to add this line in your while loop but not in your for loop :
screen.fill([255, 255, 255])
and this line of code outside and after the while loop:
pygame.quit()
You have not defined x nor y yet. You will need to redefine those variables, including pos to prevent the error. The error is that your if statement:
if x > 2 and y > 3 and x < 24 and y < 24:
pygame.quit()
was not in line with the one above it. The program then could not see what x or y was, raising the error. Your while loop is fine by the way. I hope this helps you!