I am struggling with moving a drawn rectangle on the screen in pygame, I am trying to create a Snake game. I am very new to Python and object oriented programming in general so it is probably a stupid mistake. Code below.
#X coordinate of snake
lead_x = 300
#sets window position on screen
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (320,240)
#imports pygame module
import sys, pygame
#initialises pygame module
pygame.init()
#changes background colour to green
background_colour = 155, 188, 15
blue =(0,0,255)
red = (100,40,20)
#sets screen size
screen = pygame.display.set_mode((640, 480))
#changes the background colour
screen.fill(background_colour)
#creates rectangle on the screen
pygame.draw.rect(screen, blue, [lead_x,lead_x,10,10])
#updates display to show new background colour
pygame.display.update()
#Sets the window title to 'Python'
pygame.display.set_caption('Python')
#closes the window when user presses X
running = True
#if cross is clicked set running = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#Controls
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
lead_x -= 10
if event.key == pygame.K_RIGHT:
lead_x += 10
#if running = False close pygame window
if running == False:
pygame.quit()
You need to put pygame.draw.rect(screen, blue, [lead_x, lead_y, 10, 10]) in your game loop. As of right now you're drawing the rect on the screen only once, and that's in the beginning of the program. You want to continuously draw the rect at different lead_x and lead_y positions in order for a rect to move on the screen.
You should also put a screen.fill(background_colour) (to clear the previous drawing) and pygame.display.update() (to update the changes) in your loop as well.
EDIT: I noticed something: you probably want to create a variable lead_y and use pygame.draw.rect(screen, blue, [lead_x, lead_y, 10, 10]) so you don't move diagonally every time.
Related
So I run the code and it just starts glitching out. I am new to pygame.
Here is the code:
import pygame
pygame.init()
# Screen (Pixels by Pixels (X and Y (X = right and left Y = up and down)))
screen = pygame.display.set_mode((1000, 1000))
running = True
# Title and Icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('Icon.png')
pygame.display.set_icon(icon)
# Player Icon/Image
playerimg = pygame.image.load('Player.png')
playerX = 370
playerY = 480
def player(x, y):
# Blit means Draw
screen.blit(playerimg, (x, y))
# Game loop (Put all code for pygame in this loop)
while running:
screen.fill((225, 0, 0))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether is right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("Left arrow is pressed")
if event.key == pygame.K_RIGHT:
print("Right key has been pressed")
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
print("kEYSTROKE RELEASED")
# RGB (screen.fill) = red green blue
player(playerX, playerY)
pygame.display.update()
The image is not the glitching one as I was not able to post a video but it is what my code does
The problem is caused by multiple calls to pygame.display.update(). An update of the display at the end of the application loop is sufficient. Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering.
Remove all calls to pygame.display.update() from your code, but call it once at the end of the application loop:
while running:
screen.fill((225, 0, 0))
# pygame.display.update() <---- DELETE
# [...]
player(playerX, playerY)
pygame.display.update()
If you update the display after screen.fill(), the display will be shown filled with the background color for a short moment. Then the player is drawn (blit) and the display is shown with the player on top of the background.
I've got an issue where pygame is only rendering ablack screen with a strange glitchy green line on it.
I'm following a tutorial on RealPython.com and everything went smoothly with the first attempt. Once I did the second attempt this is what renders, which is clearly wrong.
#sidescrolling air-shooter
import pygame
#import pygame locals
from pygame.locals import(
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
)
#constants for screen width/height
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.surf = pygame.Surface((75,25))
self.surf.fill((255, 255,255))
self.rect = self.surf.get_rect()
pygame.init()
#create screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
# Instantiate player
player = Player()
#keep the game running!
running = True
#loop time!
while running:
#look at all the events
for event in pygame.event.get():
#did the user hit a key?
if event.type == KEYDOWN:
#Was it escape? uh oh we gotta stop
if event.key == K_ESCAPE:
running = False
elif event.type ==QUIT:
running = False
#fill screen with white
screen.fill((255, 255, 255))
# Create a surface and pass in a tuple containing legth and width
surf = pygame.Surface((50, 50))
# Give the surface a color to separate it from the Background
surf.fill((0, 0, 0))
rect = surf.get_rect()
#This line says "Draw surf onto the screen at the center"
screen.blit(surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
#Draw the player on the screen
screen.blit(player.surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
pygame.display.flip()
pygame.quit()
I've even checked the source code for their project and it seems to match up.
It is a matter of Indentation. You need to draw the scene and update the display in the application loop instead of after the application loop:
#loop time!
while running:
#look at all the events
for event in pygame.event.get():
#did the user hit a key?
if event.type == KEYDOWN:
#Was it escape? uh oh we gotta stop
if event.key == K_ESCAPE:
running = False
elif event.type ==QUIT:
running = False
#-->| INDENTATION
#fill screen with white
screen.fill((255, 255, 255))
# Create a surface and pass in a tuple containing legth and width
surf = pygame.Surface((50, 50))
# Give the surface a color to separate it from the Background
surf.fill((0, 0, 0))
rect = surf.get_rect()
#This line says "Draw surf onto the screen at the center"
screen.blit(surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
#Draw the player on the screen
screen.blit(player.surf, (SCREEN_WIDTH/2, SCREEN_HEIGHT/2))
pygame.display.flip()
pygame.quit()
This is my first post in StackOverflow, hope you guys can help a newbie programmer. It's Pygame Python simple ask.
I am trying to move a square on the screen, but can not erase the previous movements.
import pygame
pygame.init()
screen = pygame.display.set_mode((400,300))
pygame.display.set_caption("shield hacking")
JogoAtivo = True
GAME_BEGIN = False
# Speed in pixels per frame
x_speed = 0
y_speed = 0
cordX = 10
cordY = 100
def desenha():
quadrado = pygame.Rect(cordX, cordY ,50, 52)
pygame.draw.rect(screen, (255, 0, 0), quadrado)
pygame.display.flip()
while JogoAtivo:
for evento in pygame.event.get():
print(evento);
#verifica se o evento que veio eh para fechar a janela
if evento.type == pygame.QUIT:
JogoAtivo = False
pygame.quit();
if evento.type == pygame.KEYDOWN:
if evento.key == pygame.K_SPACE:
print('GAME BEGIN')
desenha()
GAME_BEGIN = True;
if evento.key == pygame.K_LEFT and GAME_BEGIN:
speedX=-3
cordX+=speedX
desenha()
if evento.key == pygame.K_RIGHT and GAME_BEGIN:
speedX=3
cordX+=speedX
desenha()
You have to draw over the previous image. Easiest is to fill the screen with a background color in the beginning of the game loop, like so:
screen.fill((0, 0, 0))
I am doing something similar and I hope this helps
import pygame
clock=pygame.time.Clock() #the frames per second BIF in pygame
pygame.init()
FPS=30
display_width=800
display_height=600
white=(255,255,255)
black=(0,0,0)
block_size=10
gameExit=False
lead_x = display_width / 2
lead_y = display_height / 2
lead_x_change = 0 # 0 beacuse we will not be changing the position in the beginning
lead_y_change = 0
gameDisplay=pygame.display.set_mode((display_width,display_height))
while not gameExit: #game loop
for event in pygame.event.get(): #event handling BIF in pygame EVENT LOOP
#print(event) # prints out the position of the mouse and the buttons pressed when in game window
if event.type== pygame.QUIT: #if the user presses the [x] in game window, it quits the window
gameExit=True
if event.key == pygame.K_LEFT:
lead_x_change = -block_size #block size is number of pixels moved in one loop
lead_y_change=0
elif event.key==pygame.K_RIGHT:
lead_x_change= block_size
lead_y_change=0
elif event.key==pygame.K_UP:
lead_y_change= -block_size
lead_x_change=0
elif event.key==pygame.K_DOWN:
lead_y_change= block_size
lead_x_change=0
lead_y+=lead_y_change
lead_x+=lead_x_change
gameDisplay.fill(white) #fills the display surface object, backgroud color is the parameter filled in
pygame.draw.rect(gameDisplay,black,[lead_x,lead_y,block_size,block_size])
pygame.display.update() #after done with all the action,update the surface
clock.tick(FPS) #runs the game at 30FPS
pygame.quit()
quit()
You also can draw everything from a previous surface, before the square was in place, then draw the square on it always in a different place.
Then draw the new surface to screen each time.
But not really good strategy, it can be slow and/or induce flickering.
For instance:
# Draw anything to the display surface named screen, then do:
# By display surface I mean the surface returned by pygame.display.set_mode()
orig = screen.copy()
# Sometimes it will not be filled with a image from screen that you have drawn before, so you draw
# all to orig surface
# Then you make a surface that will be shown on the screen and do:
s = pygame.surface.Surface()
s.blit(orig, 0, 0)
# Then you draw the rectangle or whatever on s, and then:
screen.blit(s, 0, 0)
pygame.display.flip()
# and you keep orig as a starting point for every move
If you have many movable objects on the screen simultaneously this is good, or if you are refreshing restricted areas only, else redraw over the last image as suggested in other answer.
If you go about drawing directly to the display surface flicker will be bigger and sometimes, especially when display is hardware accelerated you will have problems. On non desktop devices like mobile phones especially. Drawing over and adding new usually works fine directly on display surface and would be the correct approach to your problem.
I know I sound contradictive, but some stuff you simply must see for yourself. Get experience by experimenting.
I'm trying to make a Space Invaders game using Pygame. However, I'm having trouble figuring out how to make the spaceship continuously shoot multiple bullets and have the bullets move along with it. The only way I have actually made the program shoot multiple bullets is through a for loop, although the bullets stop shooting once the for loop hits its end. Should I create a list to store all the bullets? Any help is appreciated :D.
Below is my Python code so far (It only has the spaceship that fires one bullet).
from __future__ import print_function
import pygame
import os, sys
from pygame.locals import *
x_location = 357
y_location = 520
bullet_location_x = x_location + 35
bullet_location_y = y_location - 5
def load_image(path, colorkey): # loads an image given the file path
try:
image = pygame.image.load(path)
except pygame.error, message:
print("Cannot load image: {0}".format(path)) # print out error message
image = image.convert() # convert image so that it can be displayed properly
if colorkey is not None:
if colorkey is -1:
colorkey = image.get_at((0, 0))
image.set_colorkey(colorkey, RLEACCEL)
return image, image.get_rect() # Return the image and the image's rectangular area
def main():
global x_location, y_location, bullet_location_x, bullet_location_y
pygame.init()
background_color = (0, 0, 0) # green background
width, height = (800, 600) # width and height of screen
screen = pygame.display.set_mode((width, height)) # set width and height
pygame.display.set_caption('space invaders') # set title of game
clock = pygame.time.Clock() # create the clock
spaceship_img, spaceship_rect = load_image("spaceship.png", (0, 0, 0))
bullet_img, bullet_rect = load_image("bullet.png", (0, 0, 0))
while True:
screen.fill(background_color) # make the background green
##############################################################
# DISPLAY BULLET #
##############################################################
screen.blit(bullet_img, (bullet_location_x, bullet_location_y))
# Render the images
screen.blit(spaceship_img, (x_location, y_location))
keys = pygame.key.get_pressed() # get the keysnpressed
for event in pygame.event.get(): # check the events
if event.type == pygame.QUIT: # if the user presses quit
pygame.quit() # quit pygame
sys.exit() # terminate the process
if event.type == KEYDOWN:
if event.key == K_LEFT:
screen.fill(background_color)
x_location -= 5
screen.blit(spaceship_img, (x_location, y_location))
if event.key == K_RIGHT:
screen.fill(background_color)
x_location += 5
screen.blit(spaceship_img, (x_location, y_location))
if event.key == K_UP:
screen.blit(bullet_img, (bullet_location_x, bullet_location_y))
display_bullets = True
pygame.display.flip() # refresh the pygame window
clock.tick(60) # Makes the game run at around 60 FPS
bullet_location_y -= 5
pass
if __name__ == '__main__':
main()
You should separate your game into a loop that contains 3 different functions:
LOOP
UPDATE_LOGIC
INPUT_HANDLING
DRAW_ELEMENTS
END-LOOP
In the input_handling, put a bullet into a list of bullets if the player is not in cool-down.
In the update_logic, iterate of the bullet list calculating the positions through time, and cool-down time of the player.
In the draw_elements, simply draw every thing on your scene. (iterate over the bullet list)
and you can use different timers for the draw and update_logic. That way will help you to add new elements to your game easily
I'm new to python/pygame and I'm trying to make a game. Basically it is a space ship floating around in space(it will be a scrolling background) pointing towards the mouse/crosshair. on clicking it will shoot bullets. there will be flying enemies which need AI and clinging enemies which need AI. Also liquids need to "flow." Collision detection for running into walls/bullets,enemies/floor. And lastly I will need a menu GUI (if i used gui in the right context.)
But right now, i would like to move the background (or for now the sprite) with keyboard controls. also how do I do a stretched image for the background?
This is what i've got:
import pygame, random, sys, time
pygame.init()
SIZE = [1000, 1000]
screen = pygame.display.set_mode(SIZE)
crosshair = pygame.image.load('crosshair.jpg')
player = pygame.image.load('spaceship.jpg')
pygame.display.set_caption("Solar Warfare")
WHITE = [255, 255, 255]
mouse_pos = []
spaceshipX = 0
spaceshipY = 0
done = False
pygame.mouse.set_visible(False)
while not done:
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
mouse_pos = pygame.mouse.get_pos([])
screen.blit(crosshair, (mouse_pos[0], mouse_pos[1]))
pygame.display.flip()#What is the other way to
#update the screen?
if event.type == pygame.QUIT:
done = True
if event.type == pygame.K_RIGHT:
spaceshipX += 1
screen.fill(WHITE)
screen.blit(player, (spaceshipX, spaceshipY))
screen.blit(crosshair, (mouse_pos))
pygame.display.flip()
pygame.quit()
I would like to add a scrolling background.
I also need AI for the enemies, but thats later. Same with the Main Menu and levels and bosses/features etc...
I talk alot XD