key event triggers and moving objects on screen - python

So I am making a game with the pygame module in python. The game is Breakout. One of the mechanics of the game is move the player left and right. How am I doing this is when the user presses the left or right arrow key, the player brick moves the left or right depending on what key is pressed, but the catch is that it if the player presses and holds the left or right button; the player brick will not continue to move... My question is how do I make the player brick continue to move instead of moving once when the key button is held down?!
here is my code
import pygame
pygame.init()
#colors
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
#the Brick
class goodbrick:
def __init__ (self, color):
self.color_scheme=color
##################X, Y L F
self.cordinates= [20, 450, 100, 0]
def move (self, x):
self.cordinates[0]+=x
def draw (self):
pygame.draw.rect(screen, self.color_scheme, self.cordinates, 0)
#class enemyBrick:
#the ball
#pygame stuff
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("BREAKOUT")
done= False
clock = pygame.time.Clock()
#init stuff
player1= goodbrick(GREEN)
#main loop
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT:
done=True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player1.move(-1)
if event.key == pygame.K_RIGHT:
player1.move(1)
elif event.type ==pygame.KEYUP:
if event.key == pygame.K_LEFT:
player1.move(-1)
print("yup")
if event.key == pygame.K_RIGHT:
player1.move(1)
#art
screen.fill(BLACK)
player1.draw()
#screent
pygame.display.flip()
clock.tick(60)
pygame.quit()

import pygame
pygame.init()
#colors
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
#the Brick
class goodbrick:
def __init__ (self, color):
self.color_scheme=color
##################X, Y L F
self.cordinates= [20, 450, 100, 0]
def move (self, x):
self.cordinates[0]+=x
def draw (self):
pygame.draw.rect(screen, self.color_scheme, self.cordinates, 0)
#class enemyBrick:
#the ball
#pygame stuff
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("BREAKOUT")
done= False
clock = pygame.time.Clock()
#init stuff
player1= goodbrick(GREEN)
#main loop
change = 0
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT:
done=True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
change = -1
if event.key == pygame.K_RIGHT:
change = 1
elif event.type ==pygame.KEYUP:
if event.key == pygame.K_LEFT:
change = 0
print("yup")
if event.key == pygame.K_RIGHT:
change = 0
player1.move(change)
#art
screen.fill(BLACK)
player1.draw()
#screent
pygame.display.flip()
clock.tick(60)
pygame.quit()

Related

After the screen is blitted how to make a rectangle when there is already an existing moving rectangle?

I am making this game in PyGame and I have a moving rectangle, So I want to make another rectangle which is drawn to the screen when I press the Space Bar. So I have tried adding the if statement but it doesn't work as the screen fills as soon as the Rectangle is drawn. Can anyone tell me how to draw the rectangle after the screen is filled with a color?
Here is my code
import pygame
from pygame.locals import *
pygame.init()
screenwidth = 1200
screenheight = 500
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption('Bullepacito')
def _rect():
run = False
while not run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_SPACE:
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(400, 400, 20, 20))
def gameloop():
run = False
shooterx = 350
shootery = 350
while not run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
shooterx -= 5
if event.key == pygame.K_RIGHT:
shooterx += 5
screen.fill((30, 30, 30))
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(shooterx, shootery, 50, 50))
# Code to draw the rectangle on key press
pygame.display.update()
gameloop()
Set a boolean state (draw_rect) when SPACE is pressed and draw the rectangle depending on the state:
import pygame
from pygame.locals import *
pygame.init()
screenwidth = 1200
screenheight = 500
screen = pygame.display.set_mode((screenwidth, screenheight))
pygame.display.set_caption('Bullepacito')
def gameloop():
run = False
shooterx = 350
shootery = 350
draw_rect = False
while not run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
shooterx -= 5
if event.key == pygame.K_RIGHT:
shooterx += 5
if event.key == pygame.K_SPACE:
draw_rect = True
screen.fill((30, 30, 30))
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(shooterx, shootery, 50, 50))
if draw_rect:
pygame.draw.rect(screen, (255, 0, 255), pygame.Rect(400, 400, 20, 20))
pygame.display.update()
gameloop()

why this code is not letting me draw using the rectangle but just moving the rectangle?

import pygame
pygame.init()
win = pygame.display.set_mode((800, 600))
Listing all pixels in pygame window in an array
pts = pygame.PixelArray(win)
Creating some color constants
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREY = (128, 128, 128)
clicked = False
clock = pygame.time.Clock()
# GAME LOOP
while True:
win.fill(BLACK)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
Checking if left mousebutton if clicked and held
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
clicked = True
Checking if mousebutton released
elif event.type == pygame.MOUSEBUTTONUP:
clicked = False
I don't know if something is wrong down here.
if clicked:
mouse_X, mouse_Y = pygame.mouse.get_pos()
for a in range(mouse_X, mouse_X + 79):
pts[a][mouse_Y:mouse_Y + 60] = GREEN
pygame.display.update()
clock.tick(250)
This is a problem of your logic. The rectangle is not drawn permanently.
pts[a][mouse_Y:mouse_Y + 60] = GREEN changes a pixel in the win Surface.
However win.fill(BLACK) turns all the pixel in win into BLACK.
Copy the "win" surface as soon as a rectangle has been placed on a permanant_win Surface. blit the Surface as the background of the window at the beginning of the application loop:
import pygame
pygame.init()
win = pygame.display.set_mode((800, 600))
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
clicked = False
clock = pygame.time.Clock()
permanant_win = win.copy()
while True:
win.blit(permanant_win, (0, 0))
make_permanent = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
clicked = True
elif event.type == pygame.MOUSEBUTTONUP:
make_permanent = True
if clicked:
mouse_X, mouse_Y = pygame.mouse.get_pos()
pts = pygame.PixelArray(win)
for a in range(mouse_X, mouse_X + 79):
pts[a][mouse_Y:mouse_Y + 60] = GREEN
pts = None
if make_permanent:
permanant_win = win.copy()
pygame.display.update()
clock.tick(250)

How to draw a continuous line in Pygame?

I want to draw a line when mouse clicked and moving in Pygame framework, it will be a line if I move the mouse very slowly. However, if I move the mouse quickly, it's just incontinuous dots. The question is how to draw a continuous line when mouse move? Thanks in advance.
import pygame, sys
from pygame.locals import *
def main():
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
mouse_position = (0, 0)
drawing = False
screen = pygame.display.set_mode((600, 800), 0, 32)
screen.fill(WHITE)
pygame.display.set_caption("ScratchBoard")
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
if (drawing):
mouse_position = pygame.mouse.get_pos()
pygame.draw.line(screen, BLACK, mouse_position, mouse_position, 1)
elif event.type == MOUSEBUTTONUP:
mouse_position = (0, 0)
drawing = False
elif event.type == MOUSEBUTTONDOWN:
drawing = True
pygame.display.update()
if __name__ == "__main__":
main()
By calling pygame.draw.line with the same argument (mouse_position) twice, you're not drawing a line, you're drawing a single pixel, because start_pos and end_pos are the same.
To get a contiguous line, you need to save the last position and draw a line between it and the next position, like this (changes are the lines with last_pos):
import pygame, sys
from pygame.locals import *
def main():
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
mouse_position = (0, 0)
drawing = False
screen = pygame.display.set_mode((600, 800), 0, 32)
screen.fill(WHITE)
pygame.display.set_caption("ScratchBoard")
last_pos = None
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
if (drawing):
mouse_position = pygame.mouse.get_pos()
if last_pos is not None:
pygame.draw.line(screen, BLACK, last_pos, mouse_position, 1)
last_pos = mouse_position
elif event.type == MOUSEBUTTONUP:
mouse_position = (0, 0)
drawing = False
elif event.type == MOUSEBUTTONDOWN:
drawing = True
pygame.display.update()
if __name__ == "__main__":
main()
vgel is right, you need to pass the previous position and the current position to pygame.draw.line. You can also calculate the previous position by subtracting the event.rel attribute of the event from the event.pos attribute.
It's also possible get rid of the drawing variable by using the event.buttons attribute. If event.buttons[0] is True then the left mouse button is being pressed.
import pygame
def main():
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
screen = pygame.display.set_mode((600, 800), 0, 32)
screen.fill(WHITE)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0]: # Left mouse button down.
last = (event.pos[0]-event.rel[0], event.pos[1]-event.rel[1])
pygame.draw.line(screen, BLACK, last, event.pos, 1)
pygame.display.update()
clock.tick(30) # Limit the frame rate to 30 FPS.
if __name__ == "__main__":
main()

What is the simplest way to rotate a pygame sprite on holding a button?

I currently have a racecar game in development, using Pygame. I understand that in order to get the sprite to move the way a real car does, trigonometry is required. However, for now, I am simply trying to get the racecar image to rotate as the user holds a button. What is the simplest way to do so?
import pygame
pygame.init()
#DEFING COLOURS
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
BLUE = (0, 0, 255)
GREEN = ( 0, 255, 0)
RED = (255, 0, 0)
size = (800,600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("My First Game")
class Car(pygame.sprite.Sprite):
#BASE CAR CLASS
def __init__(self, filename):
#INITIALISE OBJECT PROPERTIES
super().__init__()
#LOAD IMAGE
self.image = pygame.image.load(filename).convert_alpha()
#SET BACKGROUND COLOUR
#self.image.set_colorkey(WHITE)
#SET RECTANGLE COLLISION BOX
self.rect = self.image.get_rect()
self.angle = 0
self.angle_change = 0
#Create sprites list
all_sprites_list = pygame.sprite.Group()
#Create F1car object
F1car = Car("car.png")
car_rotation = 0.0
surface = pygame.Surface((15, 15))
#Add F1car to sprites list
all_sprites_list.add(F1car)
#LOOP UNTIL USER EXITS THE GAME
carryOn = True
#CLOCK TO CONTROL FRAME RATE
clock = pygame.time.Clock()
##MAIN LOOP##
while carryOn:
#MAIN EVENT LOOP
for event in pygame.event.get(): #USER DID SOMETHING
if event.type == pygame.QUIT: #IF USER CLICKED CLOSE
carryOn = False #END THE LOOP
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
car_rotation += 0.1
pygame.transform.rotate(surface, car_rotation)
#GAME LOGIC
#DRAWING CODE
#CLEARING SCREEN
screen.fill(WHITE)
#DRAWING SHAPES
pygame.draw.rect(screen, RED, [55, 200, 100, 70], 0)
pygame.draw.rect(screen, BLUE, [78, 300, 60, 70], 0)
#LIST OF SPRITES TO COLLIDE WITH EACHOTHER
#blocks_hit_list = pygame.sprite.spritecollide(F1car, )
#DRAW SPRITES FROM all_sprites_list LIST
all_sprites_list.draw(screen)
#UPDATE THE SCREEN
pygame.display.flip()
#SET UPDATE RATE
clock.tick(60)
pygame.quit()
I'd give the Car class an update method and in this method rotate the car if self.angle_change is not 0. That allows you to call all_sprites.update() to call the update methods of all contained sprites.
Set the angle_change in the event loop to start the rotation. In the update method, increase the self.angle by the self.angle_change, then use pygame.transform.rotate or .rotozoom and pass the self.angle. Afterwards you need to get a new rect and pass the center of the old rect as the center argument.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
WHITE = (255, 255, 255)
CAR_IMAGE = pygame.Surface((45, 90), pygame.SRCALPHA)
CAR_IMAGE.fill((150, 20, 0))
class Car(pygame.sprite.Sprite):
def __init__(self, pos, image):
super().__init__()
self.image = image
# Store a reference to the original to preserve the image quality.
self.orig_image = self.image
self.rect = self.image.get_rect(center=pos)
self.angle = 0
self.angle_change = 0
def update(self):
if self.angle_change != 0:
self.angle += self.angle_change
# I prefer rotozoom because it looks smoother.
self.image = pygame.transform.rotozoom(self.orig_image, self.angle, 1)
self.rect = self.image.get_rect(center=self.rect.center)
all_sprites = pygame.sprite.Group()
f1_car = Car((300, 300), CAR_IMAGE)
all_sprites.add(f1_car)
carryOn = True
while carryOn:
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn = False
elif event.type == pygame.KEYDOWN:
# Set the rotation speed of the car sprite.
if event.key == pygame.K_RIGHT:
f1_car.angle_change = -3
elif event.key == pygame.K_LEFT:
f1_car.angle_change = 3
elif event.type == pygame.KEYUP:
# Stop rotating if the player releases the keys.
if event.key == pygame.K_RIGHT and f1_car.angle_change < 0:
f1_car.angle_change = 0
elif event.key == pygame.K_LEFT and f1_car.angle_change > 0:
f1_car.angle_change = 0
all_sprites.update()
screen.fill(WHITE)
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
This can be done rather simply. You need a game loop that checks for inputs. Then you must check that the desired input is present, and increase the rotation of your car each time the input is present.
import pygame
run = True
car_rotation = 0.0
surface = pygame.Surface((100, 60)) # 100 horizontal length. 60 is the vertical length.
while run:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
car_rotation += 0.1
surface = pygame.transform.rotate(surface, car_rotation)
For the case of your code
You have done some wrong checks in the loop. Change your code from pygame.K_RIGHT to pygame.K_r, to use your R key to rotate your sprite. In order to use the mouse, change the pygame.event.type to .MOUSEBUTTONDOWN or .MOUSEBUTTONUP, and keep pygame.K_RIGHT.
Change the if statement, if event.key == pygame.K_r, to
if event.key == pygame.K_r
car_rotation += 1.0
for car in all_sprites_list:
car.image = pygame.transform.rotate(car.image, car_rotation)
and then remove surface = pygame.Surface((15, 15)).

Why is my ship not shooting bullets?

I have made a game using Python and Pygame. My ship moves around but I am having trouble making it shoot bullets. I have defined a function called shootBullets() but it is not working. And now, if I press the space bar, my ship moves. It is only supposed to move when I press the left or right arrow keys. I want my ship to shoot bullets towards the bottom of the screen when I press the space bar. here is my code:
import pygame,sys
from pygame.locals import *
pygame.init()
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
bright_blue = (0, 135, 255)
yellow = (255,242,0)
ship_body = (33, 117, 243)
screen = pygame.display.set_mode((500,500))
pygame.display.set_caption("Battleship")
gameExit = False
background = pygame.image.load("Sky Background.png")
bulletImg = pygame.image.load("Bullet.png")
bulletY = 80
def shootBullets():
for event in pygame.event.get():
if event.type == KEYDOWN and event.key == K_SPACE:
bulletY += 5
screen.blit(bulletImg,(247,bulletY))
pygame.key.set_repeat(50,50)
ship_points = [ [100, 50], [180, 95], [320, 95], [400, 50], [250, 35] ]
x = 0
y = 0
while not gameExit:
for event in pygame.event.get():
if event.type == QUIT:
gameExit = True
if event.type == KEYDOWN:
if event.key == pygame.K_LEFT: x = -5
if event.key == pygame.K_RIGHT: x = 5
for point in ship_points:
point[0] += x
for point in ship_points:
if point[0] <= 0 or point[0] >= 500:
gameExit = True
shootBullets()
screen.fill(black)
screen.blit(background, (0,0))
ship = [
pygame.draw.polygon(screen, ship_body, ship_points),
pygame.draw.polygon(screen, black, ship_points, 1)]
pygame.display.update()
pygame.quit()
quit()
In your main loop you are only checking for left and right, not for space. You check in the function shootBullets whether space is pressed, but that is too late, shootBullets will never be executes (actually it will get executed if the for event in get() loop is somehow exited but that is not what you want).
Instead do something like:
while not gameExit:
for event in pygame.event.get():
if event.type == QUIT:
gameExit = True
if event.type == KEYDOWN:
if event.key == pygame.K_LEFT:
move_left()
if event.key == pygame.K_RIGHT:
move_right()
if event.key == pygame.SPACE:
shootBullet()
[...]

Categories