Rectangle won't stop moving - python

I'm using pygame.key.get_pressed() in my code in order to make a rectangle move up and down but when I let go of the key the rectangle continues moving. I'm wondering how to make the rectangle stop moving when the key is released.
import pygame, random, sys
from pygame.locals import *
fpsClock=pygame.time.Clock()
pygame.init()
WINDOWWIDTH = 600
WINDOWHEIGHT = 600
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 255)
FPS = 40
BLACK = (0,0,0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
rectY1 = 300
rectY2 = 300
Y1change = 0
Y2change = 0
def moveup():
rectY1 -= 10
pygame.display.set_caption('Pong')
def drawshapes():
pygame.init()
DISPLAY=pygame.display.set_mode((600,600),0,32)
DISPLAY.fill(BLACK)
pygame.draw.rect(DISPLAY,RED,(18,rectY1,10,120))
pygame.draw.rect(DISPLAY,RED,(580,rectY2,10,120))
pygame.draw.ellipse(DISPLAY,BLUE,(300,300,30,30))
drawshapes()
while True:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed()
if keys[K_UP]:
Y1change -= 10
if keys[K_DOWN]:
Y1change += 10
rectY1 += Y1change
rectY2 += Y2change
drawshapes()
pygame.display.update()
fpsClock.tick(FPS)
pygame.display.update()

You have to reset it before every test
Y1change = 0
if keys[K_UP]:
Y1change -= 10
if keys[K_DOWN]:
Y1change += 10
import random
import sys
import pygame
# --- constants (UPPERCASE_NAMES) ---
WINDOWWIDTH = 600
WINDOWHEIGHT = 600
TEXTCOLOR = (255, 255, 255)
BACKGROUNDCOLOR = (0, 0, 255)
FPS = 40
BLACK = (0,0,0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# --- classes (CamelCaseNames)---
# empty
# --- functions (lower_case_names)---
def move_up():
global rectY1
rectY1 -= 10
def draw_shapes():
pygame.draw.rect(DISPLAY, RED, (18, rectY1, 10, 120)) # spaces
pygame.draw.rect(DISPLAY, RED, (580, rectY2, 10, 120)) # spaces
pygame.draw.ellipse(DISPLAY, BLUE, (300, 300, 30, 30)) # spaces
# --- main ---
rectY1 = 300
rectY2 = 300
Y1change = 0
Y2change = 0
# - init -
pygame.init()
DISPLAY = pygame.display.set_mode((600, 600), 0, 32) # spaces
pygame.display.set_caption('Pong')
#TODO: use pygame.Rect() to keep size and position of paddles and ball
# - mainloop -
fpsClock = pygame.time.Clock()
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# - changes -
keys = pygame.key.get_pressed()
Y1change = 0
if keys[pygame.K_UP]:
Y1change -= 10
if keys[pygame.K_DOWN]:
Y1change += 10
# - updates -
rectY1 += Y1change
rectY2 += Y2change
# - draws -
DISPLAY.fill(BLACK)
draw_shapes()
pygame.display.update() # only once in loop
# - FPS -
fpsClock.tick(FPS)

Related

How do I make the square and circles show up at the same time in pygame?

I am trying to make a game where there are a bunch of falling circles and the player(the square) needs to avoid them. I have managed to get the controls of the player and all of the falling circles but when I press play all I see are the falling circles and no square. The only time the square shows is when I press the arrow keys. How can I make the square and circles show up at the same time?
import pygame
from pygame.locals import *
import os
import random
import math
import sys
import time
white = (255,255,255)
blue = (0,0,255)
gravity = 10
size =10
height = 500
width =600
varHeigth = height
ballNum = 5
eBall = []
apGame = pygame.display.set_mode((width, height))
pygame.display.set_caption("AP Project")
clock = pygame.time.Clock()
class Player(object):
def __init__(self):
red = (255, 0, 0)
move_x = 300
move_y = 400
self.rect = pygame.draw.rect(apGame,red, (move_x, move_y, 10, 10))
self.dist = 10
def handle_keys(self):
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit();
exit()
elif e.type == pygame.KEYDOWN:
key = e.key
if key == pygame.K_LEFT:
self.draw_rect(-1, 0)
elif key == pygame.K_RIGHT:
self.draw_rect(1, 0)
elif key == pygame.K_ESCAPE:
pygame.quit();
exit()
def draw_rect(self, x, y):
red = (255, 0, 0)
black = (0, 0, 0)
'''apGame.fill(black)'''
self.rect = self.rect.move(x * self.dist, y * self.dist);
pygame.draw.rect(apGame, red , self.rect)
pygame.display.update()
def draw(self,surface):
red = (255, 0, 0)
move_x = 300
move_y = 400
pygame.draw.rect(apGame, red, (move_x, move_y, 10, 10))
move_x = 300
move_y = 400
red = (255, 0, 0)
black = (0, 0, 0)
player = Player()
clock = pygame.time.Clock()
'''apGame.fill(black)'''
player.draw(apGame)
pygame.display.update()
for q in range(ballNum):
x = random.randrange(0, width)
y = random.randrange(0, varHeigth)
eBall.append([x, y])
while True:
#I think this is where my problem is
apGame.fill(black)
player.handle_keys()
for i in range(len(eBall)):
pygame.draw.circle(apGame, blue, eBall[i], size)
eBall[i][1] += 5
if eBall[i][1] > height:
y = random.randrange(-50, -10)
eBall[i][1] = y
x = random.randrange(0, width)
eBall[i][0] = x
pygame.display.flip()
clock.tick(30)
If you insert a line :
player.draw_rect (0, 0)
just above
pygame.display.flip ()
then your square will show up.
I would recommend using :
pygame.key.get_pressed ()
instead of :
pygame.KEYDOWN
so that your player will keep moving as long as the key is being held down instead of having to press and release the left or right keys over and over.
Edit :
In response to OPs question in comments, here is working code :
import pygame
from pygame.locals import *
import random
white = (255,255,255)
blue = (0,0,255)
gravity = 10
size =10
height = 500
width =600
varHeigth = height
ballNum = 5
eBall = []
apGame = pygame.display.set_mode((width, height))
pygame.display.set_caption("AP Project")
clock = pygame.time.Clock()
class Player(object):
def __init__(self):
red = (255, 0, 0)
move_x = 300
move_y = 400
self.rect = pygame.draw.rect(apGame,red, (move_x, move_y, 10, 10))
self.dist = 10
def handle_keys(self):
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit();
exit()
key = pygame.key.get_pressed ()
if key [pygame.K_LEFT]:
self.draw_rect(-1, 0)
elif key [pygame.K_RIGHT]:
self.draw_rect(1, 0)
elif key [pygame.K_ESCAPE]:
pygame.quit();
exit()
else :
self.draw_rect (0, 0)
def draw_rect(self, x, y):
red = (255, 0, 0)
black = (0, 0, 0)
self.rect = self.rect.move(x * self.dist, y * self.dist);
pygame.draw.rect(apGame, red , self.rect)
def draw(self,surface):
red = (255, 0, 0)
move_x = 300
move_y = 400
pygame.draw.rect(apGame, red, (move_x, move_y, 10, 10))
move_x = 300
move_y = 400
red = (255, 0, 0)
black = (0, 0, 0)
player = Player()
clock = pygame.time.Clock()
'''apGame.fill(black)'''
player.draw(apGame)
pygame.display.update()
for q in range(ballNum):
x = random.randrange(0, width)
y = random.randrange(0, varHeigth)
eBall.append([x, y])
while True:
apGame.fill(black)
for i in range(len(eBall)):
pygame.draw.circle(apGame, blue, eBall[i], size)
eBall[i][1] += 5
if eBall[i][1] > height:
y = random.randrange(-50, -10)
eBall[i][1] = y
x = random.randrange(0, width)
eBall[i][0] = x
player.handle_keys ()
pygame.display.flip()
clock.tick(30)

How to make my 'game over' text stay on when collision is activated?

I making a small game with multiple falling cubes and the player(the square) has to avoid it. I manage to get the collision to work but the problem is when every time the circle and square collide it displays the text every time they collide. But I want the text to stay on when the circle and square first collide. Is there any way to do that?
import pygame
from pygame.locals import *
import os
import random
import math
import sys
import time
white = (255,255,255)
blue = (0,0,255)
gravity = 10
size =10
height = 500
width =600
varHeigth = height
ballNum = 5
eBall = []
apGame = pygame.display.set_mode((width, height))
pygame.display.set_caption("AP Project")
clock = pygame.time.Clock()
class Player(object):
def __init__(self):
red = (255, 0, 0)
move_x = 300
move_y = 400
self.rect = pygame.draw.rect(apGame,red, (move_x, move_y, 10, 10))
self.dist = 10
def handle_keys(self):
for e in pygame.event.get():
if e.type == pygame.QUIT:
pygame.quit();
exit()
key = pygame.key.get_pressed()
if key[pygame.K_LEFT]:
self.draw_rect(-1, 0)
elif key[pygame.K_RIGHT]:
self.draw_rect(1, 0)
elif key[pygame.K_ESCAPE]:
pygame.quit();
exit()
else:
self.draw_rect(0, 0)
def draw_rect(self, x, y):
red = (255, 0, 0)
black = (0, 0, 0)
'''apGame.fill(black)'''
self.rect = self.rect.move(x * self.dist, y * self.dist);
pygame.draw.rect(apGame, red , self.rect)
pygame.display.update()
def draw(self,surface):
red = (255, 0, 0)
move_x = 300
move_y = 400
pygame.draw.rect(apGame, red, (move_x, move_y, 10, 10))
#The game over text here
def show_go_screen():
pygame.font.init()
myfont = pygame.font.SysFont("Comic Sans MS", 30)
label = myfont.render("Game Over", 1, red)
apGame.blit(label, (300,100))
def instuct():
pygame.font.init()
myfont = pygame.font.SysFont("Comic Sans MS", 15)
label = myfont.render("Avoid The Circles", 1, red)
apGame.blit(label, (250,450))
'''game_over = False'''
move_x = 300
move_y = 400
red = (255, 0, 0)
black = (0, 0, 0)
player = Player()
clock = pygame.time.Clock()
'''apGame.fill(black)'''
player.draw(apGame)
pygame.display.update()
for q in range(ballNum):
x = random.randrange(0, width)
y = random.randrange(0, varHeigth)
eBall.append([x, y])
while True:
apGame.fill(black)
for i in range(len(eBall)):
ball_rect = pygame.draw.circle(apGame, blue, eBall[i], size)
#where the code is supposed to work
if player.rect.colliderect(ball_rect):
'''game_over = True'''
show_go_screen()
eBall[i][1] += 5
if eBall[i][1] > height:
y = random.randrange(-50, -10)
eBall[i][1] = y
x = random.randrange(0, width)
eBall[i][0] = x
instuct()
player.handle_keys()
pygame.display.flip()
clock.tick(30)
Whenever you want functionality to only run once, you should add a check outside of that function to make sure the code within that function only runs once. Here's an example of that using your code.
collidedOnce = False
if player.rect.colliderect(ball_rect):
if(collidedOnce == False):
collidedOnce = True #This makes the code only run once since it's setting this variable to be true within the condition
#game_over = True
show_go_screen()
eBall[i][1] += 5
if eBall[i][1] > height:
y = random.randrange(-50, -10)
eBall[i][1] = y
x = random.randrange(0, width)
eBall[i][0] = x
instuct()
player.handle_keys()
pygame.display.flip()
clock.tick(30)
Hope this helps

Pygame changing movement speed of a blit [duplicate]

This question already has an answer here:
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
Closed 2 years ago.
Alright so I am trying to just code a simple pong game in python using pygame module and I keep running into an attribute error. I know similar questions have been asked before but I can't figure out the answer from those questions. I'd appreciate any help at all :).
so, the error i am getting in my code is
File "D:/Dev/Documents/Projects/Pong/pong.py", line 81, in <module>
ball.x += ball_speed_x
AttributeError: 'pygame.Surface' object has no attribute 'x'
my code is
import pygame, sys
pygame.init()
clock = pygame.time.Clock()
screen_width = 1280
screen_height = 960
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption('game')
background = pygame.image.load('bg.png')
white = (255, 255, 255)
green = (51, 255, 51)
ball = pygame.image.load('ball.png')
paddle1 = pygame.Rect(screen_width - int(20), screen_height/int(2) - int(70), int(10), int(140))
paddle2 = pygame.Rect(int(10), screen_height/int(2) - int(70), int(10), int(140))
basicfont = pygame.font.SysFont(None, 48)
text = basicfont.render('Pong Game', True, green)
textrect = text.get_rect()
textrect.centerx = screen.get_rect().centerx
ball_speed_x = 7
ball_speed_y = 7
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(white)
screen.blit(background, (0, 0))
screen.blit(text, textrect)
pygame.draw.rect(screen, white, paddle1)
pygame.draw.rect(screen, white, paddle2)
pygame.draw.aaline(screen, green, (screen_width/2, 0), (screen_width/2, screen_height))
pygame.display.flip()
ball.x += ball_speed_x
ball.y += ball_speed_y
if ball.top <= 0 or ball.bottom >= screen_height:
ball_speed_y *= -1
if ball.left <= 0 or ball.right >= screen_width:
ball_speed_x *= -1
clock.tick(60)
Again, any help would be greatly appreciated and I am aware of other similar questions, I'm just new to this language and can't seem to figure this out. Thanks.
A pygame.Surface has no position. A Surface just contains the image.
If you want to draw the ball surface in the window, then you have to blit() the ball at a certain position.
You have to create a pygame.Surface and a pygame.Rect objecct:
ball = pygame.image.load('ball.png')
ball_rect = ball.get_rect(center = (screen_width // 2, screen_height // 2))
Then you can change the location of ball_rect and blit the ball to the screen Surface:
screen.blit(ball, ball_rect)
See the example:
import pygame, sys
pygame.init()
clock = pygame.time.Clock()
screen_width = 1280
screen_height = 960
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption('game')
background = pygame.image.load('bg.png')
white = (255, 255, 255)
green = (51, 255, 51)
ball = pygame.image.load('ball.png')
ball_rect = ball.get_rect(center = (screen_width // 2, screen_height // 2))
paddle1 = pygame.Rect(screen_width - int(20), screen_height/int(2) - int(70), int(10), int(140))
paddle2 = pygame.Rect(int(10), screen_height/int(2) - int(70), int(10), int(140))
basicfont = pygame.font.SysFont(None, 48)
text = basicfont.render('Pong Game', True, green)
textrect = text.get_rect()
textrect.centerx = screen.get_rect().centerx
ball_speed_x = 7
ball_speed_y = 7
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(white)
screen.blit(background, (0, 0))
screen.blit(text, textrect)
pygame.draw.rect(screen, white, paddle1)
pygame.draw.rect(screen, white, paddle2)
pygame.draw.aaline(screen, green, (screen_width/2, 0), (screen_width/2, screen_height))
screen.blit(ball, ball_rect)
pygame.display.flip()
ball_rect.x += ball_speed_x
ball_rect.y += ball_speed_y
if ball_rect.top <= 0 or ball_rect.bottom >= screen_height:
ball_speed_y *= -1
if ball_rect.left <= 0 or ball_rect.right >= screen_width:
ball_speed_x *= -1
clock.tick(60)

Multiple balls moving in a box(2D)

I was working on a code to simulate multiple balls moving inside a box using pygame. I wrote the code for a single ball that collides with the walls of the container. I want to increase the number of balls as I want. I looked for help here and got a tutorial here: https://github.com/petercollingridge/code-for-blog/blob/master/pygame%20physics%20simulation/particle_tutorial_3.py
Here he uses class. But for now, I don't want to use a class to simulate this. Is there any other way? Please help me. I am new to python. This is my code:
import pygame
import time
import random
pygame.init()
display_width = 860
display_height = 540
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
display_surface = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("Simulation")
clock = pygame.time.Clock()
def draw_ball(ball_color, ballx, bally, ballr):
pygame.draw.ellipse(display_surface, ball_color, [int(ballx), int(bally), int(2 *ballr),int(2 * ballr)])
ball_radius = 7
ball_x_vel = 5
ball_y_vel = 5
ball_x_position=0.0
ball_y_position=0.0
number_of_balls=5
ball_x_position =ball_x_position+ random.randrange(0,display_width-2*ball_radius)
ball_y_position = ball_y_position+random.randrange(0,display_height-2*ball_radius)
display_exit = False
while not display_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if ball_x_position > display_width - 2 * ball_radius or ball_x_position < 0:
ball_x_vel *= -1
if ball_y_position > display_height - 2 * ball_radius or ball_y_position < 0:
ball_y_vel *= -1
ball_x_position += ball_x_vel
ball_y_position += ball_y_vel
display_surface.fill(white)
draw_ball(red, ball_x_position, ball_y_position, ball_radius)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()
I think I should use some kind of for loop to create multiple balls for random initial positions and then follow the same boundary conditions.
Edit: After the suggestions:
import pygame
import random
pygame.init()
display_width = 860
display_height = 540
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
display_surface = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption("Simulation")
clock = pygame.time.Clock()
def draw_ball(ball_color, ball_specs):
pygame.draw.ellipse(display_surface, ball_color, ball_specs)
ball_x_position = 0
ball_y_position = 0
ball_diameter = 10
number_of_balls = 10
def ball_show(number_of_balls):
for n in range(number_of_balls):
ball_x_position = random.randrange(0, display_width)
ball_y_position = random.randrange(0, display_height)
ball = [ball_x_position, ball_y_position, ball_diameter, ball_diameter]
draw_ball(red, ball)
display_exit = False
while not display_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
display_surface.fill(white)
ball_show(number_of_balls)
pygame.display.update()
clock.tick(100)
pygame.quit()
quit()

How can I make a ball bounce off a drawn rectangle with the code i am using?

I have an if statement constantly checking if the x and y values of the ball and the pong are the same. However, its not changing the direction. Why is this happening? The if statement is the first one after "bally += directiony"
import pygame
import random
pygame.init()
screenL = 1000
screenW = 600
screen = pygame.display.set_mode([screenL, screenW])
playerpoints = 0
aipoints = 0
run = True
playery = 50
playerx = 10
aiy = screenW/2
ballx = screenL//2
bally = screenW//2
directiony = 2
directionx = 2
while run:
pygame.time.delay(5)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.fill((0,0,0))
pygame.draw.rect(screen, (255, 255, 255), (playerx, playery, 10, 100))
keys = pygame.key.get_pressed()
if playery > 0 and keys[pygame.K_UP]:
playery -= 2
if playery < screenW - 100 and keys[pygame.K_DOWN]:
playery += 2
pygame.draw.line(screen, [255, 255, 255], [screenL/2, 0], [screenL/2, screenW])
pygame.draw.rect(screen, (255, 255, 255), (screenL - 60, aiy, 10, 100))
keys = pygame.key.get_pressed()
pygame.draw.circle(screen, [255, 255, 255], [ballx, bally], 8)
ballx += directionx
bally += directiony
if ballx == playerx + 10 and bally == playery + 100:
directionx = 2
if bally == 0:
directiony = 2
if bally == screenW:
directiony = -2
if ballx == 0:
directionx = 2
if ballx == screenL:
directionx = -2
pygame.display.flip()
You should use pygame.Rect to keep x,y,width,height. It has function to check collision between two rectangles (or rectangle and point - ie when you click button in menu) so it will check collision in different places of pong.
ball_rect.colliderect(player_rect)
ball_rect.colliderect(AI_rect)
This code check collisions with both pongs
import pygame
import random
# --- constants --- (UPPER_CASE_NAMES)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 600
SCREEN_WIDTH_HALF = SCREEN_WIDTH//2
SCREEN_HEIGHT_HALF = SCREEN_HEIGHT//2
#--- game ---
# - init -
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
# - objects -
player_rect = pygame.Rect(10, 50, 10, 100)
ai_rect = pygame.Rect(SCREEN_WIDTH-60, SCREEN_HEIGHT_HALF, 10, 100)
ball_rect = pygame.Rect(0, 0, 16, 16)
ball_rect.center = (SCREEN_WIDTH_HALF, SCREEN_HEIGHT_HALF)
directiony = 2
directionx = 2
playerpoints = 0
aipoints = 0
# --- mainloop ---
clock = pygame.time.Clock()
run = True
while run:
clock.tick(120) # 120 FPS
#pygame.time.delay(5)
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# --- changes ---
keys = pygame.key.get_pressed()
if player_rect.top > 0 and keys[pygame.K_UP]:
player_rect.y -= 2
if player_rect.bottom < SCREEN_HEIGHT and keys[pygame.K_DOWN]:
player_rect.y += 2
ball_rect.x += directionx
ball_rect.y += directiony
# collision with player
if ball_rect.colliderect(player_rect):
directionx = -directionx
# collision with AI
if ball_rect.colliderect(ai_rect):
directionx = -directionx
# collision with border
if ball_rect.top <= 0:
directiony = -directiony
if ball_rect.bottom >= SCREEN_HEIGHT:
directiony = -directiony
if ball_rect.left <= 0:
directionx = -directionx
if ball_rect.right >= SCREEN_WIDTH:
directionx = -directionx
# -- draws ---
screen.fill(BLACK)
pygame.draw.rect(screen, WHITE, player_rect)
pygame.draw.rect(screen, WHITE, ai_rect)
pygame.draw.circle(screen, WHITE, ball_rect.center, 8)
pygame.draw.line(screen, WHITE, (SCREEN_WIDTH_HALF, 0), (SCREEN_WIDTH_HALF, SCREEN_HEIGHT))
pygame.display.flip()
# --- end ---
pygame.quit()

Categories