I want to make a Pong-like game, but I don't know how to make the ball go in a random angle and bounce off the walls. What I have so far is this. This just has an enemy player that follows the y axis of the ball and it will bounce off the player and enemy.
import pygame,time,pygame.mixer
from pygame.locals import *
from random import randint
pygame.init()
#set screen to be the window
screen=pygame.display.set_mode((640,480))
#fills screen with white
screen.fill((255,255,255))
#set starting gravity
gravity=0.5
#limits fps
FPS=60
fpstime=pygame.time.Clock()
timer=0
#sets colour codes
red=(255,0,0)
green=(0,255,0)
blue=(0,0,255)
white=(255,255,255)
#set player starting location
playerpos1=10
playerpos2=240
direction=20
#ball starting location
ballpos1=320
ballpos2=240
ballspeed=3
#enemypos
enemypos=ballpos2
#makes the game loop start
FLYING=True
#game loop
while FLYING:
mx,my = pygame.mouse.get_pos()
screen.fill((255,255,255))
#draws the player and ball
pygame.draw.rect(screen,blue,(playerpos1,my,10,50))
pygame.draw.rect(screen,red,(ballpos1,ballpos2,20,20))
pygame.draw.rect(screen,green,(630,ballpos2,10,50))
#ball speed and random direction
ballpos1-=ballspeed
balldirection=randint(60,90)
#draws collision boxes
rightside=pygame.Rect(630,0,10,480)
leftside=pygame.Rect(10,0,10,480)
top=pygame.Rect(0,0,640,10)
ball=pygame.Rect(ballpos1,ballpos2,20,20)
enemy=pygame.Rect((630,ballpos2,10,50))
player=pygame.Rect(playerpos1,my,20,20)
#checks for collisions
if ball.colliderect(player):
ballspeed=-3
if ball.colliderect(enemy):
ballspeed=3
#checks if you exit
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
break
if event.type == KEYDOWN:
if event.key == K_w:
playerpos2-=2
pygame.display.update()
fpstime.tick(FPS)
since pong doesn't require major angle bouncing it can be done easy with a possible eight directions.
side = 'left'
vert = 'up'
if ballX == 'insert collision points with paddles':
if side == 'left':
side = 'right'
else:
side = 'left'
if vert == 'up':
vert = 'down'
else:
vert = 'up'
if vert == 'up':
ballY -=10
else:
ballY +=10
if side == 'left':
ballX-=10
else:
ballx+=10
this will have the ball moving diagonally always, which i found worked fine for pong. If you want picture perfect bouncing i refer you to this tutorial
(http://www.petercollingridge.co.uk/pygame-physics-simulation)
Related
I have an image in pygame. I want to apply antialiasing to it. How can I do this? Ideally, I would be able to do this just with pygame and built-in modules but I'm open to other options if necessary.
More specifically, I've got an image of a square split into 4. Each of the quadrants has a different colour. I want to blur it so it looks more like a gradient, so instead of the colours switching instantly where the quadrants meet, it would fade slowly. I believe anti-aliasing is the best way to accomplish this? Here's an image of what I mean:left: what I've got, right: what I need to have
It's not clear what specific image smoothing algorithm you want to use. SciPy provides some relevant functions, so I've constructed an example using ndimage.gaussian_filter().
Clicking a mouse button will apply the filter, or you can scroll the wheel.
import pygame
from scipy.ndimage import gaussian_filter
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.gaussian_filter.html
def smooooooth(screen):
"""Apply a gaussian filter to each colour plane"""
# Get reference pixels for each colour plane and then apply filter
r = pygame.surfarray.pixels_red(screen)
gaussian_filter(r, sigma=72, mode="nearest", output=r)
g = pygame.surfarray.pixels_green(screen)
gaussian_filter(g, sigma=72, mode="nearest", output=g)
b = pygame.surfarray.pixels_blue(screen)
gaussian_filter(b, sigma=72, mode="nearest", output=b)
height = 300
width = 300
pygame.init()
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
pygame.display.set_caption("Smooth Image")
clock = pygame.time.Clock()
# draw initial pattern
screen.fill((194, 198, 199)) # fill with gray
# fill top left quadrant with white
screen.fill(pygame.Color("white"), pygame.Rect(0, 0, width // 2, height // 2))
# fill bottom left quadrant with black
screen.fill(pygame.Color("black"), pygame.Rect(width // 2, height // 2, width, height))
count = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONUP:
smooooooth(screen)
count += 1
pygame.display.set_caption(f"Smooth Image {count}")
pygame.display.update()
# limit framerate
clock.tick(30)
pygame.quit()
If you play with the sigma argument to the gaussian_filter function, you might be able to get closer to what you're after. E.g. with sigma 72, two passes looks like this:
I've modified the example code to properly support screen resizing, which will redraw the base pattern and using the + and - keys to increment the sigma value so you can do it interactively. Hold Shift to adjust by ten instead of one.
import pygame
from scipy.ndimage import gaussian_filter
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.gaussian_filter.html
def smooooooth(screen, sisgma):
"""Apply a gaussian filter to each colour plane"""
# Get reference pixels for each colour plane and then apply filter
r = pygame.surfarray.pixels_red(screen)
gaussian_filter(r, sigma=sigma, mode="nearest", output=r)
g = pygame.surfarray.pixels_green(screen)
gaussian_filter(g, sigma=sigma, mode="nearest", output=g)
b = pygame.surfarray.pixels_blue(screen)
gaussian_filter(b, sigma=sigma, mode="nearest", output=b)
def draw_grey_squares(screen):
"""Draw the base pattern"""
screen.fill((194, 198, 199)) # fill with grey
# fill top left quadrant with white
screen.fill(pygame.Color("white"), (0, 0, width // 2, height // 2))
# fill bottom left quadrant with black
screen.fill(pygame.Color("black"), (width // 2, height // 2, width, height))
height = 300
width = 300
pygame.init()
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
draw_grey_squares(screen)
pygame.display.set_caption("Smooth Image")
clock = pygame.time.Clock()
sigma = 72
count = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.VIDEORESIZE:
# redraw on window resize
width, height = event.w, event.h
draw_grey_squares(screen)
count = 0
elif event.type == pygame.KEYUP:
# support + and - to modify sigma
if event.key in (pygame.K_PLUS, pygame.K_KP_PLUS):
if event.mod & pygame.KMOD_SHIFT:
sigma += 10
else:
sigma += 1
elif event.key in (pygame.K_MINUS, pygame.K_KP_MINUS):
if event.mod & pygame.KMOD_SHIFT:
sigma -= 10
else:
sigma -= 1
sigma = max(sigma, 1) # sigma below one doesn't make sense
elif event.type == pygame.MOUSEBUTTONUP:
smooooooth(screen, sigma)
count += 1
pygame.display.set_caption(f"Smooth Image {count} σ {sigma}")
pygame.display.update()
clock.tick(30) # limit framerate
pygame.quit()
Here's an example with sigma 200:
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 1 year ago.
I read an article about how a mouse cursor can detect a rect, and it includes the line ".get_rect()" but somehow it doesnt work
heres the articles code ->
import pygame
pygame.init()
width=350;
height=400
screen = pygame.display.set_mode( (width, height ) )
pygame.display.set_caption('clicked on image')
redSquare = pygame.image.load("images/red-square.png").convert()
x = 20; # x coordnate of image
y = 30; # y coordinate of image
screen.blit(redSquare , ( x,y)) # paint to screen
pygame.display.flip() # paint screen one time
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if redSquare.get_rect().collidepoint(x, y):
print('clicked on image')
#loop over, quite pygame
pygame.quit()
heres my code ->
import pygame
import os
import sys
pygame.init()
width,height = (1100,800)
WIN = pygame.display.set_mode((width,height))
global bcard
bg_filename = os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','background.jpg')
bg = pygame.image.load(bg_filename)
bg = pygame.transform.scale(bg, (width, height)).convert()
card_width=130
card_height=160
blue_card=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','blue_card.png'))
red_card=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','red_card.png'))
bcard=pygame.transform.scale(blue_card,(card_width,card_height)).convert()
rcard=pygame.transform.scale(red_card,(card_width,card_height)).convert()
text=pygame.image.load(os.path.join('C:\\Users\\USER\\Desktop\\Python\\picture match','text.png'))
global clicking
clicking = False
def pictures():
global card1
card1=WIN.blit(bcard,(30,200))
card2=WIN.blit(rcard,(200,200))
card3=WIN.blit(bcard,(370,200))
card4=WIN.blit(rcard,(550,200))
card5=WIN.blit(bcard,(730,200))
card6=WIN.blit(rcard,(900,200))
card7=WIN.blit(rcard,(30,400))
card8=WIN.blit(bcard,(200,400))
card9=WIN.blit(rcard,(370,400))
card10=WIN.blit(bcard,(550,400))
card11=WIN.blit(rcard,(730,400))
card12=WIN.blit(bcard,(900,400))
card13=WIN.blit(bcard,(30,600))
card14=WIN.blit(rcard,(200,600))
card15=WIN.blit(bcard,(370,600))
card16=WIN.blit(rcard,(550,600))
card17=WIN.blit(bcard,(730,600))
card18=WIN.blit(rcard,(900,600))
card1_rect=pygame.Rect(30,200,130,160)
card1_rect=pygame.Rect(200,200,130,160)
card1_rect=pygame.Rect(370,200,130,160)
card1_rect=pygame.Rect(550,200,130,160)
card1_rect=pygame.Rect(730,200,130,160)
card1_rect=pygame.Rect(900,200,130,160)
WIN.blit(text,(25,0))
def draw():
WIN.blit(bg,(0,0))
pictures()
def main():
global clicking
global card1
global bcard
run = True
mx , my = pygame.mouse.get_pos()
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if bcard.get_rect().collidepoint(mx, my):
print('clicked on image')
draw()
pygame.display.flip()
main()
its suppose to be a picture match game btw, heres the error code "AttributeError: 'pygame.Surface' object has no attribute 'get_rect'"
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. A Surface is blit at a position on the screen. The position of the rectangle can be specified by a keyword argument. For example, the top left of the rectangle can be specified with the keyword argument topleft:
if bcard.get_rect().collidepoint(mx, my):
if bcard.get_rect(topleft = (30, 200)).collidepoint(mx, my):
print('clicked on image')
import sys
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
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):
if (event.key == pygame.K_LEFT):
print('LEFT')
if (event.key == pygame.K_DOWN):
print('DOWN')
if (event.key == pygame.K_RIGHT):
print('RIGHT')
if (event.key == pygame.K_UP):
print('UP')
print('FRAME')
pygame.display.update()
clock.tick(1)
If you press arrow key just after 'FRAME' is printed, sometimes 'FRAME' is printed for second time before keypressed arrow is printed. Is as if pygame.event.get() is delayed. Example:
FRAME
FRAME
<---- UP pressed here
FRAME
UP
FRAME
FRAME
<---- UP pressed here
FRAME
UP
How could I correct this behaviour?
You are using clock.tick(1), so this is telling pygame that you want 1 fps. This will make everything slower, and pretty much pause your code for a tiny bit. Try changing the 1 to something like 60 or 30.
I'm trying to create a brush on pygame. It should draw rectangles while the left mouse button is down.
Below is what I tried:
while not game_exit:
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
while pygame.mouse.get_pressed()[0]:
pygame.draw.rect(gameDisplay, red, [pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1], 10, 10])
But it is now working. Where is the problem?
If you need to draw rectangle when mouse button is pressed (and mouse is moving) then use
import pygame
RED = (255,0,0)
BLACK = (0,0,0)
gameDisplay = pygame.display.set_mode((600,400))
brush = None
game_exit = False
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left button pressed
brush = event.pos
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # left button released
brush = None
elif event.type == pygame.MOUSEMOTION:
if brush: # left button still pressed
brush = event.pos
# clear bufor
gameDisplay.fill(BLACK)
# draw brush in bufor
if brush:
pygame.draw.rect(gameDisplay, RED, [brush[0], brush[1], 10, 10])
# send bufor on the screen
pygame.display.flip()
Here is a stable loop that fills, flips and receives events:
while True:
for event in pregame.event.get():
if event.type == pregame.QUIT:
pregame.quit()
window.fill((0,0,0))
#####Render here
pygame.display.flip()
pygame.time.Clock().tick(30)
Hope it helps :D
I'm relatively new to PyGame. I'm trying to make a simple program to show a string denoting the mouse position on the screen.
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((400,400),0,32)
myFont = pygame.font.SysFont('arial', 14)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
x,y = pygame.mouse.get_pos()
label = myFont.render('mouse coords: ' + str(x) + ', ' + str(y), 1, (0,128,255))
screen.blit(label, (10,10))
pygame.display.update()
When I move the mouse around, the label becomes blurry until the text is unreadable. I'm sure I'm calling screen.blit() and pygame.display.update() correctly, but yet the label doesn't seem to update! Any help would be great.
what you need to do is blit a background in the loop becuase what oure doing is blitting the mousecoords one on top of eachother
do something like this:
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((400,400),0,32)
myFont = pygame.font.SysFont('arial', 14)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
x,y = pygame.mouse.get_pos()
label = myFont.render('mouse coords: ' + str(x) + ', ' + str(y), 1, (0,128,255))
screen.fill((0,0,0))
screen.blit(label, (10,10))
pygame.display.update()
this way you are filling the screen with black in between each update so the mouse pos is being blitted then its cleared by the fill then the new pos is being blitted and so on