Making a drawn rectangle disappear for pygame - python

I am only quite new to Python only been working on the Introduction Netacad course for about 4 weeks now and I am having trouble with an lab exercise given to me by my lecturer.
Using a prebuilt pygame file it asks to add in lines of code to add left and right movement upon left and right keydown evens, up and down, and increase speed and decrease for which ive already completed. I am having trouble with the final task which asks:
Add a feature to make player1 sprite visible/invisible when the space bar is pressed.
So i figure this must just be another keydown event/listener but what exactly is the if statement outcome to make my already drawn rectangle sprite disappear and reappear.
This is my code below and sorry if i havent been clear with this im quite new to this language and only ever done C# intro before.
import pygame # accesses pygame files
import sys # to communicate with windows
# game setup ################ only runs once
pygame.init() # starts the game engine
clock = pygame.time.Clock() # creates clock to limit frames per second
FPS = 60 # sets max speed of main loop
SCREENSIZE = SCREENWIDTH, SCREENHEIGHT = 1000, 800 # sets size of screen/window
screen = pygame.display.set_mode(SCREENSIZE) # creates window and game screen
# set variables for colors RGB (0-255)
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
yellow = (255, 255, 0)
green = (0, 255, 0)
gameState = "running" # controls which state the games is in
player1XPos = 100 #Variable for x axes position of player 1
player1YPos = 100 #Variable for Y axis position
player1Direction = ""
player1Speed = 5
player1Visible
# game loop #################### runs 60 times a second!
# your code starts here ##############################
while gameState != "exit": # game loop - note: everything in the mainloop is indented one tab
for event in pygame.event.get(): # get user interaction events
if event.type == pygame.QUIT: # tests if window's X (close) has been clicked
gameState = "exit" # causes exit of game loop
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
#Decreases playerYPos -5 on the X axis
player1Direction = "left"
elif event.key == pygame.K_RIGHT:
#Inrceases playerYPos +5 on the Y Axis
player1Direction = "right"
elif event.key == pygame.K_UP:
#player1XPos Decreases playerxPos -5 on the X axis
player1Direction = "up"
elif event.key == pygame.K_DOWN:
#player1YPos Inrceases playeryPos +5 on the Y axis
player1Direction = "down"
elif event.key == pygame.K_w:
player1Speed= player1Speed / 2
#Decrease movement speed player1Speed of movement
elif event.key == pygame.K_q:
player1Speed= player1Speed * 2
#Increase movement speed player1Speed
elif event.key == pygame.K_SPACE:
# Player 1 Event handler code now...
if player1Direction =="up":
player1YPos = player1YPos - player1Speed
#Increases the player1 rectangle up on the Y axis
elif player1Direction =="down":
player1YPos = player1YPos + player1Speed
#Decreases the player1 rectangle on Y Axis
if player1Direction =="left":
player1XPos = player1XPos - player1Speed
#Moves the player1Pos to the left by decreasing X Pos by the value of player1Speed
#which is 5
elif player1Direction =="right":
player1XPos = player1XPos + player1Speed
#Moves player1Pos rectangle to the right by increasing player1XPos X axis position
#by the value of player1Speed
screen.fill(black)
player1 = pygame.draw.rect(screen, red, (player1XPos, player1YPos, 80, 80))
# your code ends here ###############################
pygame.display.flip() # transfers build screen to human visable screen
clock.tick(FPS) # limits game to frame per second, FPS value
# out of game loop ###############
print("The game has closed") # notifies user the game has ended
pygame.quit() # stops the game engine
sys.exit() # close operating system window

The solution is to conditionally draw the player 1 sprite only if player 1 is visible. Every time when the space is pressed, the value of player1Visible changes to the opposite value.
import pygame # accesses pygame files
import sys # to communicate with windows
# game setup ################ only runs once
pygame.init() # starts the game engine
clock = pygame.time.Clock() # creates clock to limit frames per second
FPS = 60 # sets max speed of main loop
SCREENSIZE = SCREENWIDTH, SCREENHEIGHT = 1000, 800 # sets size of screen/window
screen = pygame.display.set_mode(SCREENSIZE) # creates window and game screen
# set variables for colors RGB (0-255)
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
yellow = (255, 255, 0)
green = (0, 255, 0)
gameState = "running" # controls which state the games is in
player1XPos = 100 #Variable for x axes position of player 1
player1YPos = 100 #Variable for Y axis position
player1Direction = ""
player1Speed = 5
player1Visible = True
# game loop #################### runs 60 times a second!
# your code starts here ##############################
while gameState != "exit": # game loop - note: everything in the mainloop is indented one tab
for event in pygame.event.get(): # get user interaction events
if event.type == pygame.QUIT: # tests if window's X (close) has been clicked
gameState = "exit" # causes exit of game loop
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
#Decreases playerYPos -5 on the X axis
player1Direction = "left"
elif event.key == pygame.K_RIGHT:
#Inrceases playerYPos +5 on the Y Axis
player1Direction = "right"
elif event.key == pygame.K_UP:
#player1XPos Decreases playerxPos -5 on the X axis
player1Direction = "up"
elif event.key == pygame.K_DOWN:
#player1YPos Inrceases playeryPos +5 on the Y axis
player1Direction = "down"
elif event.key == pygame.K_w:
player1Speed= player1Speed / 2
#Decrease movement speed player1Speed of movement
elif event.key == pygame.K_q:
player1Speed= player1Speed * 2
#Increase movement speed player1Speed
elif event.key == pygame.K_SPACE:
player1Visible = not player1Visible
# Player 1 Event handler code now...
if player1Direction =="up":
player1YPos = player1YPos - player1Speed
#Increases the player1 rectangle up on the Y axis
elif player1Direction =="down":
player1YPos = player1YPos + player1Speed
#Decreases the player1 rectangle on Y Axis
if player1Direction =="left":
player1XPos = player1XPos - player1Speed
#Moves the player1Pos to the left by decreasing X Pos by the value of player1Speed
#which is 5
elif player1Direction =="right":
player1XPos = player1XPos + player1Speed
#Moves player1Pos rectangle to the right by increasing player1XPos X axis position
#by the value of player1Speed
screen.fill(black)
if player1Visible:
player1 = pygame.draw.rect(screen, red, (player1XPos, player1YPos, 80, 80))
# your code ends here ###############################
pygame.display.flip() # transfers build screen to human visable screen
clock.tick(FPS) # limits game to frame per second, FPS value
# out of game loop ###############
print("The game has closed") # notifies user the game has ended
pygame.quit() # stops the game engine
sys.exit() # close operating system window

Related

How do I create a border in Pygame so my character doesn't walk over an image? [duplicate]

This question already has answers here:
Not letting the character move out of the window
(2 answers)
Closed 2 years ago.
I need a rectangular border around an image so my character stops walking through it. It would be nice if my character stopped at certain coordinates instead of walking over the image.
I've tried to create a border with my 'x' and 'y' coordinates, but the border seems to stretch across the screen.
import pygame
from pygame.locals import *
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT,))
pygame.display.set_caption("Zombie Hunters")
background = pygame.image.load("background.jpg").convert()
background = pygame.transform.scale(background, (SCREEN_WIDTH,SCREEN_HEIGHT))
player = pygame.image.load("character no gun.png").convert_alpha()
player = pygame.transform.scale(player, (270, 270))
# these are the coordinates to move the player
x, y = 0, 0
MOVE_RIGHT = 1
MOVE_LEFT = 2
MOVE_UP = 3
MOVE_DOWN = 4
direction = 0
speed = 1
#House barrier
barrier_xlocation = 345
barrier_ylocation = 80
barrier_width = 190
barrier_height = 260
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == ord('q'):
pygame.quit()
exit()
if event.key == K_LEFT:
direction = MOVE_LEFT
if event.key == K_RIGHT:
direction = MOVE_RIGHT
if event.key == K_UP:
direction = MOVE_UP
if event.key == K_DOWN:
direction = MOVE_DOWN
elif event.type == KEYUP:
if event.key == K_LEFT:
direction = 0
if event.key == K_RIGHT:
direction = 0
if event.key == K_UP:
direction = 0
if event.key == K_DOWN:
direction = 0
if(direction == MOVE_LEFT):
x-= speed
if(direction == MOVE_RIGHT):
x+= speed
if(direction == MOVE_UP):
y-= speed
if(direction == MOVE_DOWN):
y += speed
#Background
screen.blit(background, (0, 0))
#House border
pygame.draw.rect(screen, (255,0,0), (barrier_xlocation,barrier_ylocation,barrier_width,barrier_height), 2)
#Player hitbox
pygame.draw.rect(screen, (255,0,0), (x + 117,y + 105, 50,50),2)
screen.blit(player, (x,y))
pygame.display.update()
I don't get any error messages, but I need to create a border around the house.
Use pygame.Rect objects and .colliderect() to check for the collision of two rectangles.
Store the current position of the player. After the player position has change, check for a collision with the barrier. When the player and the barrier are colliding, then reset the position of the player.
The size of as [pygame.Surface] object can be get by .get_size():
# store current position
px, py = x, y
# change position
if(direction == MOVE_LEFT):
x-= speed
if(direction == MOVE_RIGHT):
x+= speed
if(direction == MOVE_UP):
y-= speed
if(direction == MOVE_DOWN):
y += speed
# set player and barrier rectangle
playerRect = pygame.Rect(x, y, *player.get_size())
barrierRect = pygame.Rect(
barrier_xlocation, barrier_ylocation, barrier_width, barrier_height)
# check for collision
if playerRect.colliderect(barrierRect):
# reset position
x, y = px, py

Pygame running super slow (~2 fps)

My pygame game runs super slowly, about 2 fps. You are supposed to be able to move around with WASD and always be centered in the screen. I know it has something to do with my tilemap and the way I do my math, but I can't pin it down. Also, if there is a better way to keep the player in the center while moving the map behind it, I would love to know how to do that.
import pygame, sys, numpy
#create fps clock
clock = pygame.time.Clock()
#
MAPHEIGHT = 80
MAPWIDTH = 80
TILESIZE = 40
TILESONSCREENW = 13
TILESONSCREENH = 13
#set screen size
SCREENH = TILESONSCREENH*TILESIZE
SCREENW = TILESONSCREENW*TILESIZE
#create character vars
circleRad = 40
circleSpeed = 4
#create circle pos vars
circleX = 250
circleY = 250
#create keyboard button vars
rightP = False
leftP = False
upP = False
downP = False
#
playerOnTileS = pygame.Surface((MAPWIDTH*TILESIZE, MAPHEIGHT*TILESIZE))
#constants for the tilemap
GRASS = pygame.image.load("grass.png")
#tilemap
tilemap = [[GRASS for i in range(MAPHEIGHT)] for j in range(MAPWIDTH)]
#create window
DISPLAYSURF = pygame.display.set_mode((SCREENW, SCREENH))
#set window name
pygame.display.set_caption("Snowball Fight!")
#---------------------------------------------------
class Player:
def __init__(self, playX, playY, size):
self.playerX = playX
self.playerY = playY
self.size = size
self.playerSurface = pygame.Surface((size, size))
pygame.draw.rect(self.playerSurface, (19,135,67), (0,0,size, size))
#------------------------------------------------
def update(self):
playerOnTileS.blit(self.playerSurface, (self.playerX, self.playerY))
DISPLAYSURF.blit(playerOnTileS, (SCREENW/2-self.playerX-self.size ,SCREENH/2-self.playerY-self.size))
#game loop
myPlayer = Player(0,0,circleRad)
while True:
DISPLAYSURF.fill((0,0,0))
for event in pygame.event.get():
#if the user closed the window
if event.type == pygame.QUIT:
#close pygame
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
leftP = True
if event.key == pygame.K_d:
rightP = True
if event.key == pygame.K_w:
upP = True
if event.key == pygame.K_s:
downP = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
leftP = False
if event.key == pygame.K_d:
rightP = False
if event.key == pygame.K_w:
upP = False
if event.key == pygame.K_s:
downP = False
if leftP:
myPlayer.move(-circleSpeed,0,True)
if rightP:
myPlayer.move(circleSpeed,0,True)
if downP:
myPlayer.move(0,circleSpeed,True)
if upP:
myPlayer.move(0,-circleSpeed,True)
for row in range(len(tilemap)):
for column in range(len(tilemap[row])):
playerOnTileS.blit(tilemap[row][column],(column*TILESIZE,row*TILESIZE))
myPlayer.update()
pygame.display.update()
clock.tick(30)
Images/pygame.Surfaces should usually be converted with the pygame.Surface.convert or convert_alpha methods. The performance of unconverted surfaces is abysmal. When I convert the grass image, I get nearly 30 FPS.
The next problem is the nested for loop. Python's function call overhead is rather big, so it would be a good idea to blit all the tiles onto one large background surface before the main loop starts and then blit this background surface onto the DISPLAYSURF once per frame to clear it. With that change I get pygame's apparent maximum FPS, that means clock.get_fps() jumps between 2000 and 1666.666 FPS.
# Ahead of the while loop.
playerOnTileS = pygame.Surface((MAPWIDTH*TILESIZE, MAPHEIGHT*TILESIZE))
for row in range(len(tilemap)):
for column in range(len(tilemap[row])):
playerOnTileS.blit(tilemap[row][column],(column*TILESIZE,row*TILESIZE))
You have to change the update method (by the way, better call it draw) and blit the player surface onto the DISPLAYSURF instead.

How to execute two events in pygame at same time?

I'm trying to make a game where the player can move the main sprite (gran) left right in 3 columns avoiding falling thunderclouds from the sky. Both components work but won't at the same time, so I can either move the player or the thundercloud falls from the top. Please can someone help so both of these events can occur at the same time
Heres my code...
import pygame, sys
import random
import time
from pygame.locals import *
#sets colours for transparency
BLACK = ( 0, 0, 0)
#Sets gran sprite
class Sprite_maker(pygame.sprite.Sprite): # This class represents gran it derives from the "Sprite" class in Pygame
def __init__(self, filename):
super().__init__() # Call the parent class (Sprite) constructor
self.image = pygame.image.load(filename).convert()# Create an image loaded from the disk
self.image.set_colorkey(BLACK)#sets transparrency
self.rect = self.image.get_rect()# Fetchs the object that has the dimensions of the image
#Initilizes pygame game
pygame.init()
pygame.display.set_caption("2nd try")
#sets background
swidth = 360
sheight = 640
sky = pygame.image.load("sky.png")
screen = pygame.display.set_mode([swidth,sheight])
#This is a list of every sprite
all_sprites_list = pygame.sprite.Group()
#Sets thunder list and creates a new thunder cloud and postions it
tcloud_speed = 10
tc_repeat = 0
thunder_list = [0, 120, 240]
for i in range(1):
tx = random.choice(thunder_list)
tcloud = Sprite_maker("thundercloud.png")
tcloud.rect.x = tx
tcloud.rect.y = 0
all_sprites_list.add(tcloud)
#Creates the gran sprite
gran = Sprite_maker("gran.png")
all_sprites_list.add(gran)
gran.rect.x = 120
gran.rect.y = 430
#Movement of gran sprite when left/right pressed
def gran_movement(movex):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and gran.rect.x == 0:
gran.rect.x = 0
elif event.key == pygame.K_RIGHT and gran.rect.x == 240:
gran.rect.x = 240
elif event.key == pygame.K_LEFT:#left key pressed player moves left 1
gran.rect.x -= 120
elif event.key == pygame.K_RIGHT:#right key pressed player moves left 1
gran.rect.x += 120
return movex
#Main program loop
game_start = True
while game_start == True:
for event in pygame.event.get():
tcloud.rect.y += tcloud_speed
if event.type == pygame.QUIT: #If user clicked close
game_start = False #Exits loop
#Clear the screen and sets background
screen.blit(sky, [0, 0])
#Displays all the sprites
all_sprites_list.draw(screen)
pygame.display.flip()
#Moves gran by accessing gran
gran_movement(gran.rect.x)
#Moves cloud down screen
if tc_repeat == 0:
tcloud.rect.y = 0
time.sleep(0.25)
tc_repeat = 1
else:
tcloud.rect.y += tcloud_speed
pygame.quit()
I'd actually create some pygame.sprite.Sprite subclasses and sprite groups, but since you're not familiar with them, I'll just use pygame.Rects and pygame.Surfaces.
So, create a rect for the player and a list of rects for the clouds. The rects are used as the blit positions (images/surfaces get blitted at the rect.topleft coordinates) and also for the collision detection (colliderect).
To move the clouds, you have to iterate over the cloud_list with a for loop and increment the y coordinate of each rect. That will happen once per frame (iteration of the while loop) and the game will run with 30 frames per second (because of clock.tick(30)).
The player movement (in the event loop) will seemingly take place at the same time as the cloud movement.
import random
import pygame
pygame.init()
# Some replacement images/surfaces.
PLAYER_IMG = pygame.Surface((38, 68))
PLAYER_IMG.fill(pygame.Color('dodgerblue1'))
CLOUD_IMG = pygame.Surface((38, 38))
CLOUD_IMG.fill(pygame.Color('gray70'))
def main():
screen = pygame.display.set_mode((360, 640))
clock = pygame.time.Clock()
# You can create a rect with the `pygame.Surface.get_rect` method
# and pass the desired coordinates directly as an argument.
player_rect = PLAYER_IMG.get_rect(topleft=(120, 430))
# Alternatively create pygame.Rect instances in this way.
cloud_rect = pygame.Rect(120, 0, 38, 38)
# The clouds are just pygame.Rects in a list.
cloud_list = [cloud_rect]
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
player_rect.x += 120
elif event.key == pygame.K_a:
player_rect.x -= 120
remaining_clouds = []
for cloud_rect in cloud_list:
# Move the cloud downwards.
cloud_rect.y += 5
# Collision detection with the player.
if player_rect.colliderect(cloud_rect):
print('Collision!')
# To remove cloud rects that have left the
# game area, append only the rects above 600 px
# to the remaining_clouds list.
if cloud_rect.top < 600:
remaining_clouds.append(cloud_rect)
else:
# I append a new rect to the list when an old one
# disappears.
new_rect = pygame.Rect(random.choice((0, 120, 240)), 0, 38, 38)
remaining_clouds.append(new_rect)
# Assign the filtered list to the cloud_list variable.
cloud_list = remaining_clouds
screen.fill((30, 30, 30))
# Blit the cloud image at the cloud rects.
for cloud_rect in cloud_list:
screen.blit(CLOUD_IMG, cloud_rect)
screen.blit(PLAYER_IMG, player_rect)
pygame.display.flip()
clock.tick(30)
if __name__ == '__main__':
main()
pygame.quit()

Rotate/angle object towards mouse gets less accurate as it moves away from point of origin [duplicate]

This question already has answers here:
Pygame doesn't let me use float for rect.move, but I need it
(2 answers)
Problem with Pygame movement acceleration, platformer game
(1 answer)
Closed 2 years ago.
Im trying to set player controlled character in the game constantly face the mouse. I managed to get the angle working well except that towards the edges of the screen, as in the surface the object is blited onto, it seems to get progressively less and less accurate. it rotates allot less and seems to want to face the center of the screen. In the middle of the screen the object rotates almost perfectly.
Edit: It doesnt actually seem to want to face the center, it wants to face the original point that it blited into, rather then the place it is currently in.
# Imports
import pygame
import os
import math
import pyganim
# -- Initialize the Surface --
# Startup
pygame.init()
# Screen
size = (500, 500)
screen = pygame.display.set_mode(size)
pygame.mouse.set_visible(True)
clock = pygame.time.Clock()
# -- Assign Global Variables --
#Sets the color of pure white to a variable to be called
WHITE = (255, 255, 255)
#Sets the color of pure black to a variable to be called
BLACK = (0, 0, 0)
#Sets the background to an image
menu_Background = pygame.image.load("image-menu_background.png")
#Sets the possible players to images
player_bright_blue = pygame.image.load("player-bright_blue.png")
player_dark_blue = pygame.image.load("player-dark_blue.png")
player_bright_green = pygame.image.load("player-bright_green.png")
player_dark_green = pygame.image.load("player-dark_green.png")
player_bright_purple = pygame.image.load("player-bright_purple.png")
player_dark_purple = pygame.image.load("player-dark_purple.png")
player_bright_red = pygame.image.load("player-bright_red.png")
player_dark_red = pygame.image.load("player-dark_red.png")
#Sets the weapons for the player to images\
player_bright_green_shortsword = pygame.image.load("player-bright_green_shortsword.png")
#Sets the pointer to an image
pointer = pygame.image.load("pointer-cross_green.png")
#Sets the dark and bright menu go button to an image
menu_go_dark = pygame.image.load("button-go_dark.png")
menu_go_bright = pygame.image.load("button-go_bright.png")
#Sets the dark and bright menu exit button to an image
menu_exit_dark = pygame.image.load("button-exit_dark.png")
menu_exit_bright = pygame.image.load("button-exit_bright.png")
#sets the dark and bright menu options button to an image
menu_options_dark = pygame.image.load("button-options_dark.png")
menu_options_bright = pygame.image.load("button-options_bright.png")
#sets the arcflash text to an image and animation
anim_arcflash = pyganim.PygAnimation([("anim-arcflash_001.png", 100),
("anim-arcflash_002.png", 100),
("anim-arcflash_003.png", 100),
("anim-arcflash_004.png", 100),
("anim-arcflash_005.png", 100),
("anim-arcflash_006.png", 100)])
anim_arcflash.play
arcflash = pygame.image.load("image-arcflash.png")
#Sets a variable to know whether the script has run once or not
firstRun = 0
#sets up the Main loop of the game
# -- Main Loop --
def Main_Loop():
#Sets the bool for the loop to run on
loop = True
#Game variables --
#Sets the player center position
player_pos_x = 255
player_pos_y = 255
#Sets the players X and y speed
move_a_speed = 0
move_d_speed = 0
move_w_speed = 0
move_s_speed = 0
move_x_speed = 0
move_y_speed = 0
#Makes the mouse invisible
pygame.mouse.set_visible(False)
#Starts the loop
while loop == True:
# -- Event Loop --
for event in pygame.event.get():
if event.type == pygame.QUIT:
Game_Quit()
if event.type == pygame.KEYDOWN:
if event.type == pygame.QUIT:
done = True
elif event.key == pygame.K_a:
move_a_speed = -2
elif event.key == pygame.K_d:
move_d_speed = 2
elif event.key == pygame.K_w:
move_w_speed = -2
elif event.key == pygame.K_s:
move_s_speed = 2
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
move_a_speed = 0
elif event.key == pygame.K_d:
move_d_speed = 0
elif event.key == pygame.K_w:
move_w_speed = 0
elif event.key == pygame.K_s:
move_s_speed = 0
# -- Screen Clearing --
screen.fill(WHITE)
# -- Drawing Logic --
move_x_speed = move_a_speed + move_d_speed
move_y_speed = move_w_speed + move_s_speed
#Increments vertical and horizontal player position by horizontal
#and vertical speed
player_pos_x += move_x_speed
player_pos_y += move_y_speed
#Set the mouse X and Y to a variable
mouse_pos = pygame.mouse.get_pos()
#Set the angle needed to rotate
angle = 270-math.atan2(mouse_pos[1] - player_pos_x, mouse_pos[0] - player_pos_y) * 180 / math.pi
# should rotate the character to the mouse, but doesnt work properly towards the edge/while moving
#Transforms the image to the angle
player_rotate = pygame.transform.rotate(player_bright_green, angle)
rect = player_rotate.get_rect(center=(player_pos_x + 15, player_pos_y + 15))
# -- Drawing --
#blits the rotated player
screen.blit(player_rotate, rect)
#blits the weapon the player is currently using
Sword(player_bright_green_shortsword, player_pos_x, player_pos_y, 14, 25)
#blits the pointer at mouse - KEEP ABOVE ALL OTHER BLITS
screen.blit(pointer, [mouse_pos[0] - 50, mouse_pos[1] - 50])
#Screen Refresh
pygame.display.flip()
# -- Refresh Rate --
clock.tick(80)
fps = str(clock.get_fps())
pygame.display.set_caption(fps)
# -- Runs the game --
(i left out the whole menu script it seemed unnecessary.)
Ive tried adjusting the values in the angle calculation and this game isnt really going to be viable without a moving character.
My end goal is to have the character perfectly synced to the mouse, or atleast as perfect as possible.

Continuous movement of a box in pygame

I have written the following code that creates a simple game where when you click an arrow on the keyboard a box moves a unit over in the game.
I am trying to make it so that if i push any of the arrow buttons the box will continue to move in that direction until another arrow is pushed. So if i push the right arrow once instead of scooting +50 pixels it will move continuously across the screen untill a different arrow is clicked and then it will go that way
import pygame #importing the pygame library
# some initializations
pygame.init() # this line initializes pygame
window = pygame.display.set_mode( (800,600) ) # Create a window with width=800 and height=600
pygame.display.set_caption( 'Rectangle move' ) # Change the window's name we create to "Rectangle move"
clock = pygame.time.Clock() # Clocks are used to track and control the frame-rate of a game (how fast and how slow the pace of the game)
# This line creates and initializes a clock.
# color definitions, using RBG color model.
black = (0,0,0)
white = (255,255,255)
# initial center position for the square (bob)
x,y = 0,0
lastKey=0
game_loop=True
while game_loop:
for event in pygame.event.get(): # loop through all events
if event.type == pygame.QUIT:
game_loop = False # change the game_loop boolean to False to quit.
if event.type == pygame.KEYDOWN:
lastKey = event.key
#check last entered key
#lastKey equals "LEFT", "RIGHT", "UP", "DOWN" --> do the required stuff!
#set x coordinate minus 50 if left was pressed
if lastKey == pygame.K_LEFT:
x -= 50
if lastKey == pygame.K_RIGHT:
x += 50
if lastKey == pygame.K_UP:
y += 50
if lastKey == pygame.K_DOWN:
y -= 50
if event.key == pygame.K_LEFT:
x -= 50
if event.key == pygame.K_RIGHT:
x += 50
if event.key == pygame.K_UP:
y += 50
if event.key == pygame.K_DOWN:
y -= 50
# draw and update screen
window.fill( black ) # fill the screen with black overwriting even bob.
pygame.draw.rect( window, white, (x, y, 50, 50) ) # draw bob on the screen with new coordinates after its movement.
# the parameters are as follows: window: is the window object you want to draw on. white: the object color used to fill the rectangle
# (x,y,50,50) x is the x position of the left side of the rectangle. y is the y position of the upper side of the rectangle.
# In other words (x,y) is the coordinate of the top left point of the rectangle.
# 50 is the width, and 50 is the height
pygame.display.update() #updates the screen with the new drawing of the rectangle.
#fps stuff:
clock.tick(10) # this controls the speed of the game. low values makes the game slower, and large values makes the game faster.
pygame.quit()
any help would be much appreciated.
Try to save the entered key into a variable and check it after your Event-Loop.
Like this:
#...
lastKey = None
while game_loop:
for event in pygame.event.get(): # loop through all events
if event.type == pygame.QUIT:
game_loop = False # change the game_loop boolean to False to quit.
if event.type == pygame.KEYDOWN:
lastKey = event.key
#check last entered key
#lastKey equals "LEFT", "RIGHT", "UP", "DOWN" --> do the required stuff!
#set x coordinate minus 50 if left was pressed
if lastKey == pygame.K_LEFT
x -= 50
#<add the other statements here>
#(...)
I would recommend to not use that many if-statements. It could get a bit confusing after some time.
Check the following question out to keep your code brief:
Replacements for switch statement in Python?
You want to change the state of your application when you press a key. So you need a variable to keep track of that state (the state is: What direction should the box move?).
Here's a complete, minimal example that does what you're looking for. Note the comments.
import pygame, sys
pygame.init()
screen = pygame.display.set_mode((640, 480))
screen_r = screen.get_rect()
clock = pygame.time.Clock()
rect = pygame.rect.Rect(0, 0, 50, 50)
# let's start at the center of the screen
rect.center = screen_r.center
# a dict to map keys to a direction
movement = {pygame.K_UP: ( 0, -1),
pygame.K_DOWN: ( 0, 1),
pygame.K_LEFT: (-1, 0),
pygame.K_RIGHT: ( 1, 0)}
move = (0, 0)
# a simple helper function to apply some "speed" to your movement
def mul10(x):
return x * 10
while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
sys.exit()
# try getting a direction from our dict
# if the key is not found, we don't change 'move'
if e.type == pygame.KEYDOWN:
move = movement.get(e.key, move)
# move the rect by using the 'move_ip' function
# but first, we multiply each value in 'move' with 10
rect.move_ip(map(mul10, move))
# ensure that 'rect' is always inside the screen
rect.clamp_ip(screen_r)
screen.fill(pygame.color.Color('Black'))
pygame.draw.rect(screen, pygame.color.Color('White'), rect)
pygame.display.update()
clock.tick(60)
I use a Rect instead of keeping track of two coordinates x and y, since that allows to make use of the move_ip and clamp_ip functions to easily move the rect inside the screen.
Here are two versions, the first demonstrates how to utilize an event loop to get continuous movement (similar to Sloth's solution, but a bit simpler for beginners who don't know dictionaries yet), the second one shows how to achieve this with pygame.key.get_pressed().
Solution 1: Check which key was pressed in the event loop and change the x and y velocities to the desired values. Then add the velocities to the rect.x and rect.y positions in the while loop.
I'd actually recommend using vectors instead of the velocity_x and velocity_y variables and another one for the actual position of your sprite. pygame.Rects can't have floats as their coordinates and so a vector or separate variables for the position would be more accurate.
import pygame as pg
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
rect = pg.Rect(100, 200, 40, 60)
velocity_x = 0
velocity_y = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_d:
velocity_x = 4
elif event.key == pg.K_a:
velocity_x = -4
elif event.type == pg.KEYUP:
if event.key == pg.K_d and velocity_x > 0:
velocity_x = 0
elif event.key == pg.K_a and velocity_x < 0:
velocity_x = 0
rect.x += velocity_x
rect.y += velocity_y
screen.fill((40, 40, 40))
pg.draw.rect(screen, (150, 200, 20), rect)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
Solution 2: Call pygame.key.get_pressed to check which key is currently being held down. Check if the left, right, up or down keys are held and then adjust the position of the sprite each frame.
pygame.key.get_pressed has the disadvantage that you can't know the order of the key presses, but the code looks a bit simpler.
import pygame as pg
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
rect = pg.Rect(100, 200, 40, 60)
velocity = (0, 0)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
keys = pg.key.get_pressed()
if keys[pg.K_d]:
rect.x += 4
if keys[pg.K_a]:
rect.x -= 4
screen.fill((40, 40, 40))
pg.draw.rect(screen, (150, 200, 20), rect)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()

Categories