I am trying to program a ping pong game in python, and I am able to make the ball bounce off the side of the pad. However, I am unable to make the ball bounce off the top and bottom of the pad. I am currently only doing the left pad (pad1). Here is my code:
import sys, pygame, random, math
pygame.init()
width, height = 1200, 675
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
clock = pygame.time.Clock()
FPS = 120
xmb1 = False
xmf1 = False
ymb1 = False
ymf1 = False
xmb2 = False
xmf2 = False
ymb2 = False
ymf2 = False
squareh = 275
squarew = 35
squares = 3
x1 = 100
y1 = (height / 2) - (squareh / 2)
x2 = width - 100 - squarew
y2 = (height / 2) - (squareh / 2)
BLACK = (0,0,0)
WHITE = (255,255,255)
font = pygame.font.SysFont("arial", 30)
text = font.render("Press Space to start", True, WHITE)
text3 = font.render("3", True, WHITE)
text2 = font.render("2", True, WHITE)
text1 = font.render("1", True, WHITE)
startt = font.render("Start!", True, WHITE)
text3b = False
text2b = False
text1b = False
starttb = False
start = False
startballmove = False
bx = width / 2
by = height / 2
br = 40
bms = 6
bxm = random.randint(-bms, bms)
bym = random.randint(-bms, bms)
btc = by
blc = bx
bbc = by + br + br
brc = bx + br + br
circle=pygame.Surface((br * 2, br * 2))
circle.fill((0, 0, 0))
pygame.draw.circle(circle, WHITE , (br, br), br, 0)
circle.set_colorkey((0, 0, 0))
pad1 = pygame.Rect(x1, y1, squarew, squareh)
pad2 = pygame.Rect(x2, y2, squarew, squareh)
while 1:
if start and not text1b and not text2b and not text3b and not starttb and not startballmove:
text3b = True
pygame.time.set_timer(pygame.USEREVENT, 1000)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
# pad 2 check if key is down
if event.key == pygame.K_UP:
ymb2 = True
if event.key == pygame.K_DOWN:
ymf2 = True
# pad 1 check if key is down
if event.key == pygame.K_w:
ymb1 = True
if event.key == pygame.K_s:
ymf1 = True
if event.key == pygame.K_SPACE:
start = True
elif event.type == pygame.KEYUP:
#pad 2 check if key goes up
if event.key == pygame.K_UP:
ymb2 = False
if event.key == pygame.K_DOWN:
ymf2 = False
# pad 1 check if key goes up
if event.key == pygame.K_w:
ymb1 = False
if event.key == pygame.K_s:
ymf1 = False
# check if window has been resized
if event.type == pygame.VIDEORESIZE:
width = event.dict['size'][0]
height = event.dict['size'][1]
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
if event.type == pygame.USEREVENT:
# check if start should be hidden
if starttb:
starttb = False
startballmove = True
# check if start should be showed
if text1b and not text2b and not text3b:
text1b = False
text2b = False
text3b = False
starttb = True
# check if 1 should be showed
if text2b and not text3b and not text1b:
text3b = False
text2b = False
text1b = True
# check if 2 should be showed
if text3b and not text2b and not text1b:
text3b = False
text2b = True
text1b = False
# check if pad 1 is out of bounds and move it
if ymb1 and not (y1 <= 0): y1 -= squares
if ymf1 and not (y1 + squareh >= height): y1 += squares
if y1 > (height - squareh) + 1: y1 -= squares
# check if pad 2 is out of bounds and move it
if ymb2 and not (y2 <= 0): y2 -= squares
if ymf2 and not (y2 + squareh >= height): y2 += squares
if y2 > (height - squareh) + 1: y2 -= squares
# put pads in center if game has not started
if not start:
# pad 1
x1 = 75
y1 = (height / 2) - (squareh / 2)
# pad 2
x2 = width - 75 - squarew
y2 = (height / 2) - (squareh / 2)
#ball
bx = width / 2 - br
by = height / 2 - br
# put pads in center in x if game has started
else:
# pad 1
x1 = 75
# pad 2
x2 = width - 75 - squarew
# if ball has not started moving center it
if not startballmove:
bx = width / 2 - br
by = height / 2 - br
# check if movement variables are 0
while bxm == 0 or bym == 0:
if bxm == 0:
bxm = random.randint(-6, 6)
if bym == 0:
bym = random.randint(-6, 6)
screen.fill(BLACK)
# draw starting text if game has not started
if not start:
screen.blit(text,((width / 2) - text.get_width() // 2, (height / 4) - text.get_height() // 2))
# put 3 on screen
if start and text3b:
screen.blit(text3,((width / 2) - 15, (height / 4) - (text.get_height() / 2)))
# put 2 on screen
if start and text2b:
screen.blit(text2,((width / 2) - 15, (height / 4) - (text.get_height() / 2)))
# put 1 on screen
if start and text1b:
screen.blit(text1,((width / 2) - 15, (height / 4) - (text.get_height() / 2)))
# put start on screen
if start and starttb:
screen.blit(startt,((width / 2) - (text.get_width() / 8), (height / 4) - (text.get_height() / 2)))
# check if ball is out of bounds
btc = by
blc = bx
bbc = by + br + br
brc = bx + br + br
if start and startballmove:
# screen
if btc <= 0:
bym = bym * -1
print("top side")
if bbc >= height:
bym = bym * -1
print("bottom side")
if blc <= 0:
bxm = bxm * -1
print("left side")
if brc >= width:
bxm = bxm * -1
print("right side")
# left pad
pad1 = pygame.Rect(x1, y1, squarew, squareh)
if pad1.collidepoint(int(bx), int(by)):
bxm = bxm * -1
bx += abs(bxm)
print("Collision")
# move ball
if start and startballmove:
bx += bxm
by += bym
# draw circle if game start
if start:
screen.blit(circle, (int(bx), int(by)))
# draw pad 1
pad1 = pygame.Rect(x1, y1, squarew, squareh)
pygame.draw.rect(screen, WHITE, pad1, 0)
# draw pad 2
pad2 = pygame.Rect(x2, y2, squarew, squareh)
pygame.draw.rect(screen, WHITE, pad2, 0)
pygame.display.flip()
clock.tick(FPS)
Does anyone know how to do this? I have only recently learned to program in python and pygame.
You have to split move and cheking collision on two steps. First move only in X and then you can recognize front collision. Later move in Y and you can recogize side collision.
Your code is big mess so it may need a lot changes. You should organize code and use better names for variables to make it more readable.
And you could use elif and nested if so it will be cleaner.
import sys
import pygame
import random
import math
# --- constants --- (UPPER_CASE_NAMES)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
FPS = 60
SQUARE_HEIGHT = 275
SQUARE_WIDTH = 35
SQUARE_SPEED = 3
BALL_R = 40
# --- main ---
window_width = 1200
window_height = 675
# - init -
pygame.init()
screen = pygame.display.set_mode((window_width, window_height), pygame.RESIZABLE)
screen_rect = screen.get_rect()
# - text -
font = pygame.font.SysFont("arial", 30)
# - text - press space -
text_press_space = font.render("Press Space to start", True, WHITE)
text_press_space_rect = text_press_space.get_rect()
text_press_space_rect.centerx = screen_rect.centerx
text_press_space_rect.centery = screen_rect.height // 4
# - text - count down -
text_1 = font.render("1", True, WHITE)
text_1_rect = text_1.get_rect()
text_1_rect.centerx = screen_rect.centerx
text_1_rect.centery = screen_rect.height // 4
text_2 = font.render("2", True, WHITE)
text_2_rect = text_2.get_rect()
text_2_rect.centerx = screen_rect.centerx
text_2_rect.centery = screen_rect.height // 4
text_3 = font.render("3", True, WHITE)
text_3_rect = text_3.get_rect()
text_3_rect.centerx = screen_rect.centerx
text_3_rect.centery = screen_rect.height // 4
text_start = font.render("Start!", True, WHITE)
text_start_rect = text_start.get_rect()
text_start_rect.centerx = screen_rect.centerx
text_start_rect.centery = screen_rect.height // 4
display_text_3 = False
display_text_2 = False
display_text_1 = False
display_text_start = False
# - ball -
ball = pygame.Surface((BALL_R * 2, BALL_R * 2))
# circle.fill(BLACK) # not need it because surface is black as default
ball.set_colorkey(BLACK)
pygame.draw.circle(ball, WHITE , (BALL_R, BALL_R), BALL_R, 0)
ball_rect = ball.get_rect()
ball_rect.center = screen_rect.center
ball_speed = 6
ball_speed_x = ball_speed * random.choice([1, -1])
ball_speed_y = ball_speed * random.choice([1, -1])
ball_move = False
# - pads -
pad1_rect = pygame.Rect(0, 0, SQUARE_WIDTH, SQUARE_HEIGHT)
pad1_rect.left = 100
pad1_rect.centery = screen_rect.centery
pad1_move_up = False
pad1_move_down = False
pad2_rect = pygame.Rect(0, 0, SQUARE_WIDTH, SQUARE_HEIGHT)
pad2_rect.right = screen_rect.right - 100
pad2_rect.centery = screen_rect.centery
pad2_move_up = False
pad2_move_down = False
# --- mainloop ---
play_start = False
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
# pad 2 check if key is down
if event.key == pygame.K_UP:
pad2_move_up = True
elif event.key == pygame.K_DOWN:
pad2_move_down = True
# pad 1 check if key is down
elif event.key == pygame.K_w:
pad1_move_up = True
elif event.key == pygame.K_s:
pad1_move_down = True
elif event.key == pygame.K_SPACE:
if not play_start:
play_start = True
pygame.time.set_timer(pygame.USEREVENT, 1000)
display_text_3 = True
elif event.type == pygame.KEYUP:
#pad 2 check if key goes up
if event.key == pygame.K_UP:
pad2_move_up = False
elif event.key == pygame.K_DOWN:
pad2_move_down = False
# pad 1 check if key goes up
elif event.key == pygame.K_w:
pad1_move_up = False
elif event.key == pygame.K_s:
pad1_move_down = False
# check if window has been resized
if event.type == pygame.VIDEORESIZE:
window_width = event.dict['size'][0]
window_height = event.dict['size'][1]
screen = pygame.display.set_mode((window_width, window_height), pygame.RESIZABLE)
screen_rect = screen.get_rect()
if event.type == pygame.USEREVENT:
if display_text_3:
display_text_3 = False
display_text_2 = True
elif display_text_2:
display_text_2 = False
display_text_1 = True
elif display_text_1:
display_text_1 = False
display_text_start = True
elif display_text_start:
display_text_start = False
ball_move = True
# - moves (without draws) -
# move paddle 1
if pad1_move_up and pad1_rect.top > 0: # > screen_rect.top:
pad1_rect.y -= SQUARE_SPEED
if pad1_rect.top < 0:
pad1_rect.top = 0
if pad1_move_down and pad1_rect.bottom < screen_rect.bottom:
pad1_rect.y += SQUARE_SPEED
if pad1_rect.bottom > screen_rect.bottom:
pad1_rect.bottom = screen_rect.bottom
# move paddle 2
if pad2_move_up and pad2_rect.top > 0: # > screen_rect.top:
pad2_rect.y -= SQUARE_SPEED
if pad2_rect.top < 0:
pad2_rect.top = 0
if pad2_move_down and pad2_rect.bottom < screen_rect.bottom:
pad2_rect.y += SQUARE_SPEED
if pad2_rect.bottom > screen_rect.bottom:
pad2_rect.bottom = screen_rect.bottom
# check if ball is out of bounds
if play_start:
# move ball
if ball_move:
ball_rect.x += ball_speed_x
# check FRONT collision with pads
if pad1_rect.colliderect(ball_rect):
#if
ball_rect.left = pad1_rect.right
ball_speed_x = -ball_speed_x
print("Front collision right pad")
if pad2_rect.colliderect(ball_rect):
ball_rect.right = pad2_rect.left
ball_speed_x = -ball_speed_x
print("Front collision left pad")
ball_rect.y += ball_speed_y
# check SIDE collision with pads
if pad1_rect.colliderect(ball_rect):
# move from top
if ball_speed_y > 0:
ball_rect.bottom = pad1_rect.top
print("Top collision right pad")
# move from bottom
else: # elif ball_speed_y < 0:
ball_rect.top = pad1_rect.bottom
print("Bottom collision right pad")
# change both or only Y (depends on what effect you need)
ball_speed_x = -ball_speed_x
ball_speed_y = -ball_speed_y
if pad2_rect.colliderect(ball_rect):
# move from top
if ball_speed_y > 0:
ball_rect.bottom = pad2_rect.top
print("Top collision left pad")
# move from bottom
else: # if ball_speed_y < 0:
ball_rect.top = pad2_rect.bottom
print("Bottom collision left pad")
# change both or only Y (depends on what effect you need)
ball_speed_x = -ball_speed_x
ball_speed_y = -ball_speed_y
# check collision with border
if ball_rect.left <= 0: # <= screen_rect.left:
ball_speed_x = -ball_speed_x
print("left side")
print("point for left player")
# move ball to center
ball_rect.center = screen_rect.center
ball_speed_x = ball_speed * random.choice([1, -1])
ball_speed_y = ball_speed * random.choice([1, -1])
if ball_rect.right >= screen_rect.right:
ball_speed_x = -ball_speed_x
print("right side")
print("point for right player")
# move ball to center
ball_rect.center = screen_rect.center
ball_speed_x = ball_speed * random.choice([1, -1])
ball_speed_y = ball_speed * random.choice([1, -1])
if ball_rect.top <= 0: # <= screen_rect.top:
ball_speed_y = -ball_speed_y
print("top side")
if ball_rect.bottom >= screen_rect.bottom:
ball_speed_y = -ball_speed_y
print("bottom side")
# - draws (without moves) -
screen.fill(BLACK)
if not play_start:
screen.blit(text_press_space, text_press_space_rect)
else: # if play_start:
if display_text_3:
screen.blit(text_3, text_3_rect)
if display_text_2:
screen.blit(text_2, text_2_rect)
if display_text_1:
screen.blit(text_1, text_1_rect)
if display_text_start:
screen.blit(text_start, text_start_rect)
screen.blit(ball, ball_rect)
# draw pads
pygame.draw.rect(screen, WHITE, pad1_rect, 0)
pygame.draw.rect(screen, WHITE, pad2_rect, 0)
pygame.display.flip()
clock.tick(FPS)
# --- end ---
pygame.quit()
Related
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.
I want to make a Snake game in Python but when I want to detect collision with rects, it seems the game detects collisions even though they are not happening:
if snake_rect.colliderect(jablko_rect):
print("Mniam!")
This collision check prints out text infinitely. How can it print out text when obviously these 2 separate objects are not touching each other. It's not a while loop problem I think. The collision check is for the images which are 49 x 49 px
The whole code:
import random
import pygame
from time import sleep
pygame.init()
SZEROKOSC = 800
WYSOKOSC = 600
plansza = pygame.display.set_mode((SZEROKOSC, WYSOKOSC)) # rozmiar okna gry
pygame.display.update()
pygame.display.set_caption("Snake") # tytuł okna gry
KROK = 25 # o ile "kroków" ma się przemieszczać snake
snake = pygame.image.load("snake_element.png").convert() # nasz snake
jablko = pygame.image.load("apple.png").convert() # nasze jabłko
snake_rect = snake.get_rect()
jablko_rect = jablko.get_rect()
clock = pygame.time.Clock()
czcionka = pygame.font.SysFont(None, 50)
def wiadomosc(msg, color):
wiad = czcionka.render(msg, True, color)
plansza.blit(wiad, [SZEROKOSC / 2 - 100, WYSOKOSC / 2 - 25])
def petla_gry():
przegrana = False
zamkniecie = False
x1 = SZEROKOSC / 2 # koordynaty
y1 = WYSOKOSC / 2 # koordynaty
x1_zmiana = 0
y1_zmiana = 0
jablko_x = round(random.randrange(0, SZEROKOSC - 25) / 25.0) * 25.0 # 25 to połowa rozmiaru naszych obrazków
jablko_y = round(random.randrange(0, WYSOKOSC - 25) / 25.0) * 25.0 # 25 to połowa rozmiaru naszych obrazków
print(jablko_x)
print(jablko_y)
while not przegrana:
while zamkniecie:
plansza.fill(white)
wiadomosc("Przegrałeś! Q - wyjście z gry, C - restart gry", (255, 0, 0))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
przegrana = True
zamkniecie = False
if event.key == pygame.K_c:
petla_gry()
for event in pygame.event.get():
if event.type == pygame.QUIT:
przegrana = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
x1_zmiana = -KROK
y1_zmiana = 0
elif event.key == pygame.K_d:
x1_zmiana = KROK
y1_zmiana = 0
elif event.key == pygame.K_w:
x1_zmiana = 0
y1_zmiana = -KROK
elif event.key == pygame.K_s:
x1_zmiana = 0
y1_zmiana = KROK
if x1 >= SZEROKOSC or x1 <= 0 or y1 >= WYSOKOSC or y1 <= 0:
przegrana = True
wiadomosc("Przegrałeś!", (255, 0, 0))
pygame.display.update()
sleep(2)
x1 += x1_zmiana
y1 += y1_zmiana
plansza.fill((255, 255, 255))
plansza.blit(snake, (x1 - 25, y1 - 25)) # 25 to połowa rozmiaru naszych obrazków
plansza.blit(jablko, (jablko_x, jablko_y))
pygame.display.update()
if snake_rect.colliderect(jablko_rect):
print("Mniam!")
'''if x1 == jablko_x and y1 == jablko_y:
print("Mniam!")'''
clock.tick(8) # czas odświeżania - ruch snake'a
pygame.quit()
quit()
petla_gry()
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, but it returns a rectangle that always starts at (0, 0) since a Surface object has no position.
The Surface is placed at a position on the display with the blit function.
You've to set the location of the rectangle,, e.g:
snake_rect.topleft = (x1 - 25, y1 - 25)
jablko_rect.topleft = (jablko_x, jablko_y)
if snake_rect.colliderect(jablko_rect):
print("Mniam!")
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
ok so i'm creating the game pong and i'm currently setting up the score.There is a small bug I'm unable to fix. The code I tried was R2Score = R2Score + 1 for it to add a point every time it gets out of the screen. It is telling me there's an error with this code and i'm under how to fix it. Also as it is going to get out of the screen the ball slows down which I'm confused on why that could also be happening.
ERROR:
Traceback (most recent call last):
File "/Users/name/Documents/PongGame.py", line 130, in <module>
R2Score = R2Score + 1
TypeError: unsupported operand type(s) for +: 'pygame.Surface' and 'int'
# import the necessary modules
import pygame
import sys
import time
#initialize pygame
pygame.init()
screenSize=(700,500)
screen=pygame.display.set_mode((screenSize), 0)
# set the caption for the screen
pygame.display.set_caption("Pong Game")
# define colours you will be using
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0,0,0)
YELLOW = (255,255,0)
# set the size for the surface (screen)
screen_h = screen.get_height()
screen_w = screen.get_width()
cx = int(screen_w/2)
cy = int(screen_h/2)
#initialize variables for player
#variables for first rectangle
R1x = 660
R1y = 300
R1w = 10
R1h = 132
R1dx = 0
R1dy = 0
R1_score = 0
#variables for second rectangle
R2x = 10
R2y = 2
R2w = 10
R2h = 132
R2dx = 0
R2dy = 0
R2_score = 0
#ball variables
bx = cx
by = cy
dby = 3
dbx = 3
br = 5
cy = screen.get_height()/2
cx = screen.get_width()/2
# variable for scores
R1_score = 0
R2_score = 0
playerRect = pygame.Rect(R1x, R1y, R1w, R1h)
playerRect2 = pygame.Rect(R2x, R2y, R2w, R2h)
ballRect = pygame.Rect (cx,cy,30,30)
#speed
speed = 3
fontsize = 50
fontScore = pygame.font.SysFont('arial', 50)
fontScore = pygame.font.SysFont('arial', 50)
R1Score = fontScore.render(str(R1_score), True, (WHITE))
R2Score = fontScore.render(str(R2_score), True, (WHITE))
# speed of object "clock"
clock = pygame.time.Clock()
# set main loop to True so it will run
main = True
# main loop
while main:
for event in pygame.event.get(): # check for any events (i.e key press, mouse click etc.)
if event.type ==pygame.QUIT: # check to see if it was "x" at top right of screen
main = False # set the "main" variable to False to exit while loop
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_UP:
R1dx = 0
R1dy = -speed
elif event.key == pygame.K_DOWN:
R1dx = 0
R1dy = speed
if event.key == pygame.K_w:
R2dx = 0
R2dy = -speed
elif event.key == pygame.K_s:
R2dx = 0
R2dy = speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
R1dx = 0
R1dy = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
R2dx = 0
R2dy = 0
playerRect.y = playerRect.y + R1dy
playerRect2.y = playerRect2.y + R2dy
ballRect.move_ip(dbx,dby)
R1y = R1dy + R1y
R2y = R2dy + R2y
bx = dbx + bx
by = dby + by
if R1y >= screen_h - 80 or R1y < 0:
R1dy = 0
if R2y >= screen_h - 80 or R2y < 0:
R2dy = 0
if by >= screen_h - br:
dby = -1
if by <= 15:
dby = 1
if bx >= R2x - br and by - R2y > 0 and by - R2y <100:
dbx = -1
if bx >= R1x - br and by - R1y > 0 and by - R1y <100:
dbx = 1
if bx == 1:
R2Score = R2Score + 1
pause = True
if bx == 699:
R2Score = R2Score + 1
pause = True
#collision of ball
if ballRect.top <= 0:
dby = -dby
if ballRect.bottom >= screen_h:
dby = -dby
if ballRect.colliderect(playerRect2):
dbx = -dbx
if ballRect.colliderect(playerRect):
dbx = -dbx
screen.fill(BLACK)
# draw the shapes
pygame.draw.rect(screen, WHITE,(playerRect),0)
pygame.draw.rect(screen, WHITE,(playerRect2),0)
pygame.draw.circle(screen, RED,ballRect.center,br,0)
screen.blit(R1Score, (280,10))
screen.blit(R2Score, (400,10))
# we are using .flip() here, it basically works the same as .update()
time.sleep(0.005)
pygame.display.flip()
# quit pygame and exit the program (i.e. close everything down)
pygame.quit()
sys.exit()
R2Score is a pygame.Surface object, so what do you expect by R2Score = R2Score + 1?
You can't add 1 to a Surface.
If you wan to increment the score, then you have to (re-)render the Surface. e.g.:
if bx == 1:
R1_score += 1
R1Score = fontScore.render(str(R1_score), True, (WHITE))
Trying to add text into a rectangle and move the rectangle around the screen using the arrow keys. I want to make it so the text doesn't go off the edge. So far I had it working without putting it into a Rect but I want to make the Rect function work. Right now the text just bounces back and I don't know how big to make the original rectangle that corresponds with the font size.
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((800,600),0)
pygame.display.set_caption("Basic Pygame Text With Rects")
width = screen.get_width()
height = screen.get_height()
x = int(width/2)
y = int(height/2)
dx = 0
dy = 0
speed = 10
oldx = x
oldy = y
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
colour = BLACK
textRect = pygame.Rect(x, y, 30, 10)
screen.fill(WHITE)
pygame.display.update()
# first set up your font (typeface and size)
# I have created two different ones here that can be used later in the program
fontTitle = pygame.font.SysFont("arial",10)
main = True
while main:
for event in pygame.event.get():
if event.type ==pygame.QUIT:
main = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_UP:
dx = 0
dy = -speed
colour = RED
elif event.key == pygame.K_DOWN:
dx = 0
dy = speed
colour = BLUE
elif event.key == pygame.K_LEFT: # note: this section of code
dx = -speed # doesn't have to change from
dy = 0
colour = GREEN
elif event.key == pygame.K_RIGHT:
dx = speed
dy = 0
colour = YELLOW
elif event.key == pygame.K_c:
x = screen.get_width() / 2
y = screen.get_height() / 2
colour = BLACK
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
dx = 0
dy = 0
elif event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
dx = 0
dy = 0
screen.fill(WHITE)
oldx = x
oldy = y
textRect.move_ip(dx,dy)
if (textRect.y <= 0) or (textRect.y >= height):
dy = 0
textRect.y = int(oldy)
if (textRect.x <= 20) or (textRect.x >= width - 20):
dx = 0
textRect.x = int(oldx)
# render the text into an image of the text, colour is red
# create a rect with it's centre placed at centre of screen
# blit the image to memory, it will display upon next update
textTitle = fontTitle.render("Go Huskies", True, colour)
drawText = textTitle.get_rect(center=(textRect.x, textRect.y))
screen.blit(textTitle, textRect)
pygame.display.update()
pygame.quit()
sys.exit()
You could generate text at start to get its size
fontTitle = pygame.font.SysFont("arial", 10)
textTitle = fontTitle.render("Go Huskies", True, colour)
rectTitle = textTitle.get_rect(center=screen.get_rect().center)
and later use only this rectTitle to move it and check collision with borders - and don't create new textTitle.get_rect()
screen.blit(textTitle, rectTitle)
Rect has .top, .bottom, .left, .right, .centerx, .centery which you can use to check collision
oldx, oldy = rectTitle.center
rectTitle.move_ip(dx, dy)
if (rectTitle.top <= 0) or (rectTitle.bottom >= height):
dy = 0
rectTitle.centery = oldy
if (rectTitle.left <= 0) or (rectTitle.right >= width):
dx = 0
rectTitle.centerx = oldx
import pygame
import sys
# --- constants --- (UPPER_CASE_NAMES)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
# --- classes --- (CamelCaseNames)
# empty
# --- functions --- (lower_case_names)
# empty
# --- main --- (lower_case_names)
pygame.init()
screen = pygame.display.set_mode((800,600),0)
screen_rect = screen.get_rect()
pygame.display.set_caption("Basic Pygame Text With Rects")
x, y = screen_rect.center
width, height = screen_rect.size
dx = 0
dy = 0
speed = 10
oldx = x
oldy = y
colour = BLACK
fontTitle = pygame.font.SysFont("arial", 10)
textTitle = fontTitle.render("Go Huskies", True, colour)
rectTitle = textTitle.get_rect(center=screen_rect.center)
# - mainloop -
clock = pygame.time.Clock()
main = True
while main:
# - events -
for event in pygame.event.get():
if event.type ==pygame.QUIT:
main = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_UP:
dx = 0
dy = -speed
colour = RED
elif event.key == pygame.K_DOWN:
dx = 0
dy = speed
colour = BLUE
elif event.key == pygame.K_LEFT: # note: this section of code
dx = -speed # doesn't have to change from
dy = 0
colour = GREEN
elif event.key == pygame.K_RIGHT:
dx = speed
dy = 0
colour = YELLOW
elif event.key == pygame.K_c:
x, y = screen_rect.center
colour = BLACK
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
dx = 0
dy = 0
elif event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
dx = 0
dy = 0
# - moves/updates -
oldx, oldy = rectTitle.center
rectTitle.move_ip(dx,dy)
if (rectTitle.top <= 0) or (rectTitle.bottom >= height):
dy = 0
rectTitle.centery = oldy
if (rectTitle.left <= 0) or (rectTitle.right >= width):
dx = 0
rectTitle.centerx = oldx
textTitle = fontTitle.render("Go Huskies", True, colour)
# - draws -
screen.fill(WHITE)
screen.blit(textTitle, rectTitle)
pygame.display.update()
clock.tick(25) # slow down to 25 FPS (frames per seconds)
# - end -
pygame.quit()
sys.exit()
If you want to move text with background rectangle then you can create Surface(), fill it with some color and then blit text on it
at start:
rectRect = pygame.surface.Surface
fontTitle = pygame.font.SysFont("arial", 10)
textTitle = fontTitle.render("Go Huskies", True, colour)
rectTitle = textTitle.get_rect(center=screen_rect.center)
item_surface = pygame.surface.Surface(rectTitle.size)
item_surface.fill(RED)
item_surface.blit(textTitle, (0,0))
textTitle = item_surface
in loop:
textTitle = fontTitle.render("Go Huskies", True, colour)
item_surface = pygame.surface.Surface(rectTitle.size)
item_surface.fill(RED)
item_surface.blit(textTitle, (0,0))
textTitle = item_surface
Full code:
import pygame
import sys
# --- constants --- (UPPER_CASE_NAMES)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0, 0, 0)
YELLOW = (255, 255, 0)
# --- classes --- (CamelCaseNames)
# empty
# --- functions --- (lower_case_names)
# empty
# --- main --- (lower_case_names)
pygame.init()
screen = pygame.display.set_mode((800,600),0)
screen_rect = screen.get_rect()
pygame.display.set_caption("Basic Pygame Text With Rects")
x, y = screen_rect.center
width, height = screen_rect.size
dx = 0
dy = 0
speed = 10
oldx = x
oldy = y
colour = BLACK
rectRect = pygame.surface.Surface
fontTitle = pygame.font.SysFont("arial", 10)
textTitle = fontTitle.render("Go Huskies", True, colour)
rectTitle = textTitle.get_rect(center=screen_rect.center)
item_surface = pygame.surface.Surface(rectTitle.size)
item_surface.fill(RED)
item_surface.blit(textTitle, (0,0))
textTitle = item_surface
# - mainloop -
clock = pygame.time.Clock()
main = True
while main:
# - events -
for event in pygame.event.get():
if event.type ==pygame.QUIT:
main = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_UP:
dx = 0
dy = -speed
colour = RED
elif event.key == pygame.K_DOWN:
dx = 0
dy = speed
colour = BLUE
elif event.key == pygame.K_LEFT: # note: this section of code
dx = -speed # doesn't have to change from
dy = 0
colour = GREEN
elif event.key == pygame.K_RIGHT:
dx = speed
dy = 0
colour = YELLOW
elif event.key == pygame.K_c:
x, y = screen_rect.center
colour = BLACK
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
dx = 0
dy = 0
elif event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
dx = 0
dy = 0
# - moves -
oldx, oldy = rectTitle.center
rectTitle.move_ip(dx,dy)
if (rectTitle.top <= 0) or (rectTitle.bottom >= height):
dy = 0
rectTitle.centery = oldy
if (rectTitle.left <= 0) or (rectTitle.right >= width):
dx = 0
rectTitle.centerx = oldx
textTitle = fontTitle.render("Go Huskies", True, colour)
item_surface = pygame.surface.Surface(rectTitle.size)
item_surface.fill(RED)
item_surface.blit(textTitle, (0,0))
textTitle = item_surface
# - draws -
screen.fill(WHITE)
screen.blit(textTitle, rectTitle)
pygame.display.update()
clock.tick(25) # slow down to 25 FPS (frames per seconds)
# - end -
pygame.quit()
sys.exit()
I'm using pygame for my game, but when I start it, I can see a black window. When you click on the close button, you can see all the objects of the game for a short while.
import pygame
pygame.init()
win = pygame.display.set_mode((800, 600))
pygame.display.set_caption('World of Fighters')
walkRight = [pygame.image.load('g_right1.png'),
pygame.image.load('g_right2.png'), pygame.image.load('g_right3.png'),
pygame.image.load('g_right4.png')]
walkLeft = [pygame.image.load('g_left1.png'),
pygame.image.load('g_left2.png'), pygame.image.load('g_left3.png'),
pygame.image.load('g_left4.png')]
bg = pygame.image.load('bg.jpg')
playerStand = pygame.image.load('g_stand.png')
clock = pygame.time.Clock()
#player 2
x2 = 720
y2 = 500
width2 = 35
height2 = 50
speed2 = 15
left2 = False
right2 = False
animCount2 = 0
isJump2 = False
jumpCount2 = 10
#player 1
x = 50
y = 500
width = 35
height = 50
speed = 15
left = False
right = False
animCount = 0
isJump = False
jumpCount = 10
#blue
color = (0, 0, 255)
run = True
def drawWindow():
global animCount
win.blit(bg, (0, 0))
if animCount + 1 >= 30:
animCount = 0
if left:
win.blit(walkLeft[animCount // 5], (x, y))
animCount += 1
elif right:
win.blit(walkRight[animCount // 5], (x, y))
animCount += 1
else:
win.blit(playerStand, (x, y))
pygame.display.update()
while run:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
#p1
if keys[pygame.K_a] and x > 5:
x -= speed
left = True
right = False
elif keys[pygame.K_d] and x < 800 - width - 5:
x += speed
left = False
right = True
else:
right = False
left = False
animCount = 0
if not(isJump):
if keys[pygame.K_SPACE]:
isJump = True
else:
if jumpCount >= -10:
if jumpCount < 0:
y += (jumpCount ** 2) / 2
else:
y -= (jumpCount ** 2) / 2
jumpCount -= 1
else:
isJump = False
jumpCount = 10
#p2
if keys[pygame.K_LEFT] and x2 > 5:
x2 -= speed2
left2 = True
right2 = False
elif keys[pygame.K_RIGHT] and x2 < 800 - width2 - 5:
x2 += speed2
left2 = False
right2 = True
if not(isJump2):
if keys[pygame.K_RCTRL]:
isJump2 = True
else:
right2 = False
left2 = False
animCount2 = 0
if jumpCount2 >= -10:
if jumpCount2 < 0:
y2 += (jumpCount2 ** 2) / 2
else:
y2 -= (jumpCount2 ** 2) / 2
jumpCount2 -= 1
else:
isJump2 = False
jumpCount2 = 10
drawWindow()
pygame.quit()
Also, this game will be a dynamic fighter for 2 players in pixel art style, but I can't find the answer for this bug, because I watched a tutorial and I have the same code like on video.
It is a matter Indentation.
drawWindow() has to be called in the main application loop rather than after the loop.
What you do is:
while run:
clock.tick(30)
# [...]
drawWindow()
pygame.quit()
What you have to do is
while run:
clock.tick(30)
# [...]
drawWindow()
pygame.quit()
I am making a platformer type game but I have run into two problems.
My Sprite is confined to a small box in the centered in the window. How do I make it so he can cover the entire window?
When I move the old sprite is not removed. It make it appear that there is a tail following the sprite.
Help for either would be appreciated!
import random, sys, copy, os, pygame, time, math
from pygame.locals import *
TILESIZE = 20
WINDOWWIDTH = 1280
WINDOWHEIGHT = 720
FPS = 30
floorx = (WINDOWHEIGHT - (TILESIZE))
floory = (WINDOWWIDTH / TILESIZE)
TileOffset = 20
tilesNeeded = (WINDOWWIDTH / TILESIZE)
floorSize = TILESIZE * 2
OUTSIDE_DECORATION_PCT = 20
HALF_WINDOWHEIGHT = (WINDOWHEIGHT / 2)
HALF_WINDOWWIDTH = (WINDOWWIDTH / 2)
CAMERASLACK = 25
MOVERATE = 9
BOUNCERATE = 6
BOUNCEHEIGHT = 30
INVULTIME = 2
GAMEOVERTIME = 4
MAXHEALTH = 3
STARTSIZE = 30
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
LIGHTGRAY = (174, 174, 174)
DARKGRAY = ( 41, 41, 41)
MEDGRAY = (101, 101, 101)
SKYBLUE = (200, 210, 255)
DARKTURQUOISE = ( 3, 54, 73)
GREEN = ( 0, 92, 7)
LIGHTGREEN = ( 0, 135, 15)
BGCOLOR = LIGHTGRAY
TEXTCOLOR = BLACK
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
def main():
global FPSCLOCK, DISPLAYSURF, BASICFONT, TILESIZE, floorx, floory, floorCovered, tilesNeeded, OUTSIDEDECOMAPPING, L_Monster, R_Monster, BGIMAGE
pygame.init()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
FPSCLOCK = pygame.time.Clock()
pygame.display.set_caption('Alpha One')
# Set up the background image.
boardImage = pygame.image.load('bg.png')
# Use smoothscale() to stretch the board image to fit the entire board:
boardImageRect = boardImage.get_rect()
boardImageRect.topleft = (0, 0)
BGIMAGE = pygame.image.load('bg.png')
# Use smoothscale() to stretch the background image to fit the entire window:
BGIMAGE = pygame.transform.smoothscale(BGIMAGE, (WINDOWWIDTH, WINDOWHEIGHT))
BGIMAGE.blit(boardImage, boardImageRect)
#Draw the background
DISPLAYSURF.blit(BGIMAGE, BGIMAGE.get_rect())
#Draw the Floor
drawFloor()
L_Monster = pygame.image.load('monster.png')
L_Monster = pygame.transform.scale(L_Monster, (1000, 600))
R_Monster = pygame.transform.flip(L_Monster, True, False)
pygame.display.flip()
#Main Game Loop
while True:
runGame()
#pygame.display.update()
def runGame():
invulnerableMode = False
invulnerableStartTime = 0
gameOverMode = False
gameOverStartTime = 0
winMode = False
camerax = 0
cameray = 0
playerObj = {'surface': pygame.transform.scale(L_Monster,(STARTSIZE, STARTSIZE)),
'facing': LEFT,
'size': STARTSIZE,
'x': HALF_WINDOWWIDTH,
'y': HALF_WINDOWHEIGHT,
'bounce':0,
'health': MAXHEALTH}
moveLeft = False
moveRight = False
moveUp = False
moveDown = False
while True:
DISPLAYSURF.blit(BGIMAGE, BGIMAGE.get_rect())
drawFloor()
#DISPLAYSURF.fill(WHITE)
if invulnerableMode and time.time() - invulnerableStartTime > INVULNTIME:
invulnerableMode = False
playerCenterx = playerObj['x'] + int(playerObj['size'] / 2)
playerCentery = playerObj['y'] + int(playerObj['size'] / 2)
if (camerax + HALF_WINDOWWIDTH) - playerCenterx > CAMERASLACK:
camerax = playerCenterx + CAMERASLACK - HALF_WINDOWWIDTH
elif playerCenterx - (camerax +HALF_WINDOWWIDTH) > CAMERASLACK:
camerax = playerCenterx - CAMERASLACK - HALF_WINDOWWIDTH
if (cameray + HALF_WINDOWHEIGHT) - playerCentery > CAMERASLACK:
cameray = playerCentery + CAMERASLACK - HALF_WINDOWHEIGHT
elif playerCentery - (cameray +HALF_WINDOWHEIGHT) > CAMERASLACK:
cameray = playerCentery - CAMERASLACK - HALF_WINDOWHEIGHT
flashIsOn = round(time.time(), 1) * 10 % 2 == 1
if not gameOverMode and not (invulnerableMode and flashIsOn):
playerObj['rect'] = pygame.Rect((playerObj['x'] - camerax,
playerObj['y'] - cameray - getBounceAmount(playerObj['bounce'], BOUNCERATE, BOUNCEHEIGHT),
playerObj['size'],
playerObj['size']))
DISPLAYSURF.blit(playerObj['surface'], playerObj['rect'])
for event in pygame.event.get():
if event.type == QUIT:
terminate()
elif event.type == KEYDOWN:
if event.key in (K_UP, K_w):
moveDown = False
moveUp = True
elif event.key in (K_DOWN, K_s):
moveUp = False
moveDown = True
elif event.key in (K_LEFT, K_a):
moveRight = False
moveLeft = True
if playerObj['facing'] == RIGHT:
playerObj['surface'] = pygame.transform.scale(L_Monster, (playerObj['size'], playerObj['size']))
playerObj['facing'] == LEFT
elif event.key in (K_RIGHT, K_d):
moveLeft = False
moveRight = True
if playerObj['facing'] == LEFT:
playerObj['surface'] = pygame.transform.scale(R_Monster, (playerObj['size'], playerObj['size']))
playerObj['facing'] = RIGHT
elif winMode and event.key == K_r:
return
elif event.type == KEYUP:
if event.key in (K_LEFT, K_a):
moveLeft = False
elif event.key in (K_RIGHT, K_d):
moveRight = False
elif event.key in (K_UP, K_w):
moveUp = False
elif event.key in (K_DOWN, K_s):
moveDown = False
elif event.key == K_ESCAPE:
terminate()
if not gameOverMode:
if moveLeft:
playerObj['x'] -= MOVERATE
if moveRight:
playerObj['x'] += MOVERATE
if moveUp:
playerObj['y'] -= MOVERATE
if moveDown:
playerObj['y'] += MOVERATE
if (moveLeft or moveRight or moveUp or moveDown) or playerObj['bounce'] != 0:
playerObj['bounce'] += 1
if playerObj['bounce'] > BOUNCERATE:
playerObj['bounce'] = 0
else:
# game is over, show "game over" text
DISPLAYSURF.blit(gameOverSurf, gameOverRect)
if time.time() - gameOverStartTime > GAMEOVERTIME:
return
if winMode:
DISPLAYSURF.blit(winSurf, winRect)
DISPLAYSURF.blit(winSurf2, winRect2)
pygame.display.update()
FPSCLOCK.tick(FPS)
def getBounceAmount(currentBounce, bounceRate, bounceHeight):
return int(math.sin( (math.pi / float(bounceRate)) * currentBounce ) * bounceHeight)
def getRandomOffCameraPos(camerax, cameray, objWidth, objHeight):
# create a Rect of the camera view
cameraRect = pygame.Rect(camerax, cameray, WINDOWWIDTH, WINDOWHEIGHT)
while True:
x = random.randint(camerax - WINDOWWIDTH, camerax + (2 * WINDOWWIDTH))
y = random.randint(cameray - WINDOWHEIGHT, cameray + (2 * WINDOWHEIGHT))
# create a Rect object with the random coordinates and use colliderect()
# to make sure the right edge isn't in the camera view.
objRect = pygame.Rect(x, y, objWidth, objHeight)
if not objRect.colliderect(cameraRect):
return x, y
def isOutsideActiveArea(camerax, cameray, obj):
boundsLeftEdge = camerax - WINDOWWIDTH
boundsTopEdge = cameray - WINDOWHEIGHT
boundsRect = pygame.Rect(boundsLeftEdge, boundsTopEdge, WINDOWWIDTH * 3, WINDOWHEIGHT * 3)
objRect = pygame.Rect(obj['x'], obj['y'], obj['width'], obj['height'])
return not boundsRect.colliderect(objRect)
def checkForQuit():
for event in pygame.event.get(QUIT): # get all the QUIT events
terminate() # terminate if any QUIT events are present
for event in pygame.event.get(KEYUP): # get all the KEYUP events
if event.key == K_ESCAPE:
terminate() # terminate if the KEYUP event was for the Esc key
pygame.event.post(event)
def drawFloor():
#Open the image used for tiles and initialize N
floorTile = pygame.image.load('tile.png')
N = 0
while (N < tilesNeeded):
DISPLAYSURF.blit(floorTile,((20 * N, (floorx + (TILESIZE/4)) - TILESIZE)), )
DISPLAYSURF.blit(floorTile,(20 * N, (floorx + (TILESIZE/4))))
N = N + 1
#Updates the display
pygame.display.flip()
def checkCollide():
FLOOR_SURF = pygame.Rect( 0, (WINDOWHEIGHT - (TILESIZE * 2)), WINDOWWIDTH, WINDOWHEIGHT)
def terminate():
pygame.quit()
sys.exit()
if __name__ == '__main__':
main()
The reason you're getting the "tail" of your sprite is because you're not clearing the screen before you begin drawing a new frame. One way to handle this would be to enter something like the following at the beginning of runGame():
DISPLAYSURF.fill(white)
This will "clear" the surface by covering everything in white. When you begin drawing images for that frame, they will be drawn over a blank white surface. The caveat to this is that you will need to redraw every sprite on the screen, not just the ones that have moved in the last frame.
For the first question, if you're asking how to scale the size of the image, you would use the scale function from pygame.transform
L_monster = pygame.transform.scale(L_monster, (500, 500))
This creates a new surface by transforming the given surface to the new size given by the tuple.
http://www.pygame.org/docs/ref/transform.html#pygame.transform.scale