GPIO pins and pygame - python-2.7

I am planning on making a game with pygame using gpio buttons. Here is the code:
from gpiozero import Button
import pygame
from time import sleep
from sys import exit
up = Button(2)
left = Button(3)
right = Button(4)
down = Button(14)
fps = pygame.time.Clock()
pygame.init()
surface = pygame.display.set_mode((1300, 700))
x = 50
y = 50
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if up.is_pressed:
y -= 5
if down.is_pressed:
y += 5
if left.is_pressed:
x -= 5
if right.is_pressed:
x += 5
surface.fill((0, 0, 0))
pygame.draw.circle(surface, (255, 255, 255), (x, y), 20, 0)
pygame.display.update()
fps.tick(30)
However, when I press on the X button on the top of the window, it doesn't close. Is there a possible solution for this?
EDIT: Everyone is giving the same answer, that I am not adding a for loop to check events and quit. I did put that, here in my code:
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
I have also tried sys.exit().
EDIT 2: #Shahrukhkhan asked me to put a print statement inside the for event in pygame.event.get(): loop, which made the loop like this:
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print "X pressed"
break
root#raspberrypi:~/Desktop# python game.py
X pressed
X pressed

There are two possible ways to close the pygame window .
after the end of while loop simply write
import sys
while 1:
.......
pygame.quit()
sys.exit()
2.instead of putting a break statement ,replace break in for loop immediately after while as
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
......

You need to make a event and within it you need to quit the pygame
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()

Related

Pygame, my sprite looks wierd

I'm working on this project for Literature class and I'm planning on making a game with pygame based of this book we were reading.
Here's the code:
import pygame, sys
from pygame.locals import *
pygame.init()
FPS = 30
fpsClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((400, 300), 0, 32)
pygame.display.set_caption('Animation')
WHITE = (255, 255, 255)
romeo = pygame.image.load('rome.png.png')
romeo = pygame.transform.scale(romeo, (50, 50))
romeox = 10
romeoy = 10
while True: # the main game loop
keys = pygame.key.get_pressed()
if keys[K_RIGHT]:
romeox += 5
if keys[K_LEFT]:
romeox -= 5
if keys[K_UP]:
romeoy -=5
if keys[K_DOWN]:
romeoy += 5
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
DISPLAYSURF.blit(romeo, (romeox, romeoy))
pygame.display.update()
fpsClock.tick(FPS)
Unfortunately, the sprite seems to leave a trail of it's own copies while it moves.
Here
Please help!
Seems like you forgot to clear the screen every iteration
# Fill surface with black color
DISPLAYSURF.fill((0, 0, 0))
Insert it above the line that blits the sprite onto the screen.

circle inside a rect with a button click

I am trying to create a game and i have to make this plexus made of buttons. Every time the player clicks the button, it should appear a small circle inside the pressed button. I tried to make a draw_circle function but when i place it on the action variable inside the buttons, I get this errror. Global name x is not defined.
import pygame
pygame.init()
display_width = 900
display_height = 600
black = (0,0,0)
white = (255,255,255)
red = (250,0,0)
green = (0,250,0)
bright_red =(200,0,0)
bright_green = (0,200,0)
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("A MATH'S GAME")
def draw_circle():
pygame.draw.circle(gameDisplay,black,(x,y),100)
def button(msg,x,y,w,h,ic,ac,action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x+w > mouse[0] > x and y+h > mouse[1] > y:
pygame.draw.rect(gameDisplay, ac,(x,y,w,h))
if click[0] == 1 and action != None:
action()
else:
pygame.draw.rect(gameDisplay, ic,(x,y,w,h))
smallText = pygame.font.SysFont("comicsansms",20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def messgae_display(text):
largeText = pygame.font.Font("Arial",60)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
def quitgame():
pygame.quit()
quit()
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.SysFont("comicsansms",115)
TextSurf, TextRect = text_objects("A math's game", largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
button("GO!",150,450,100,50,green,bright_green,draw_circle)
button("Quit",550,450,100,50,red,bright_red,quitgame)
pygame.display.update()
def game_loop():
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.SysFont("comicsansms",50)
TextSurf, TextRect = text_objects("A math's game", largeText)
TextRect.center = ((display_width/2),100)
gameDisplay.blit(TextSurf, TextRect)
button(None,200,250,50,50,bright_red,red,None)
button(None,200,300,50,50,bright_red,red,None)
button(None,200,350,50,50,bright_red,red,None)
button(None,200,400,50,50,bright_red,red,None)
button(None,200,450,50,50,bright_red,red,None)
button(None,200,500,50,50,bright_red,red,None)
button(None,250,250,50,50,bright_red,red,None)
button(None,250,300,50,50,bright_red,red,None)
button(None,250,350,50,50,bright_red,red,None)
button(None,250,400,50,50,bright_red,red,None)
button(None,250,450,50,50,bright_red,red,None)
button(None,250,500,50,50,bright_red,red,None)
button(None,300,250,50,50,bright_red,red,None)
button(None,300,300,50,50,bright_red,red,None)
button(None,300,350,50,50,bright_red,red,None)
button(None,300,400,50,50,bright_red,red,None)
button(None,300,450,50,50,bright_red,red,None)
button(None,300,500,50,50,bright_red,red,None)
button(None,350,250,50,50,bright_red,red,None)
button(None,350,300,50,50,bright_red,red,None)
button(None,350,350,50,50,bright_red,red,None)
button(None,350,400,50,50,bright_red,red,None)
button(None,350,450,50,50,bright_red,red,None)
button(None,350,500,50,50,bright_red,red,None)
button(None,400,250,50,50,bright_red,red,None)
button(None,400,300,50,50,bright_red,red,None)
button(None,400,350,50,50,bright_red,red,None)
button(None,400,400,50,50,bright_red,red,None)
button(None,400,450,50,50,bright_red,red,None)
button(None,400,500,50,50,bright_red,red,None)
button(None,450,250,50,50,bright_red,red,None)
button(None,450,300,50,50,bright_red,red,None)
button(None,450,350,50,50,bright_red,red,None)
button(None,450,400,50,50,bright_red,red,None)
button(None,450,450,50,50,bright_red,red,None)
button(None,450,500,50,50,bright_red,red,None)
button(None,500,250,50,50,bright_red,red,None)
button(None,500,300,50,50,bright_red,red,None)
button(None,500,350,50,50,bright_red,red,None)
button(None,500,400,50,50,bright_red,red,None)
button(None,500,450,50,50,bright_red,red,None)
button(None,500,500,50,50,bright_red,red,None)
button(None,550,250,50,50,bright_red,red,None)
button(None,550,300,50,50,bright_red,red,None)
button(None,550,350,50,50,bright_red,red,None)
button(None,550,400,50,50,bright_red,red,None)
button(None,550,450,50,50,bright_red,red,None)
button(None,550,500,50,50,bright_red,red,None)
button(None,600,250,50,50,bright_red,red,None)
button(None,600,300,50,50,bright_red,red,None)
button(None,600,350,50,50,bright_red,red,None)
button(None,600,400,50,50,bright_red,red,None)
button(None,600,450,50,50,bright_red,red,None)
button(None,600,500,50,50,bright_red,red,None)
button(None,650,250,50,50,bright_red,red,None)
button(None,650,300,50,50,bright_red,red,None)
button(None,650,350,50,50,bright_red,red,None)
button(None,650,400,50,50,bright_red,red,None)
button(None,650,450,50,50,bright_red,red,None)
button(None,650,500,50,50,bright_red,red,None)
pygame.display.update()
pygame.init()
game_intro()
In the line button("GO!",150,450,100,50,green,bright_green,draw_circle) you aren't giving draw_circle a value for x or y, so they are, in fact, not defined. You need to pass these down to to the draw_circle function.
Inside of your button function, pass the arguments down to draw_circle like:
if click[0] == 1 and action != None:
action(x, y)

Optimizing Keyboard Input in Pygame

I am creating a very simple game using the pygame library in which the player moves a square around the screen with the arrow keys. Unfortunately, the response of the controls are proving to be a problem.
The controls work fine until you switch direction e.g. left to right. When the player switches direction, the square the player is controlling jars to a halt.
The code for the controls looks like this in my game:
def move(self, event):
speed = 6
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.rect.x -= speed
if event.key == pygame.K_RIGHT:
self.rect.x += speed
if event.key == pygame.K_DOWN:
self.rect.y += speed
if event.key == pygame.K_UP:
self.rect.y -= speed
This method is located in a class called Block (I stole Block from the pygame docs) that just makes a sprite for the player alongside providing movement.
The function move() is actually called inside the main.py file like this:
while going:
clock.tick(60)
# event handling
for event in pygame.event.get():
if event.type == QUIT:
going = False
# controller input
player.move(event)
Where player is an instance of the Block class and event is just an item from the event queue of my game.
I tried using the pygame.key.get_pressed function (which did work better) but I would rather use the pygame.KEYDOWN locals alternatively because it returns the key presses as events in the event queue rather than booleans returned from a list.
If you are more investigative than your average joe you can take a look at the "full" game here: https://github.com/catmes/Project_React
You will need pygame 1.9.2 and python 2.7. Keep in my mind that the game itself is more a learning exercise so don't surprised when you see bad code (that will be fixed later of course ;) ).
Thanks for stopping by and giving this question a peek, I do appreciate your time.
I've tried out a smooth way to move around a player that works pretty well. It basically keeps track of the key presses in a list and moves the player based on the last key pressed. When you press a key it'll add a speed variable at the first position in the list, and when you release the key it'll remove that variable. In the update method you'll add the first speed variable of the list to corresponding x and y value.
import pygame
pygame.init()
screen = pygame.display.set_mode((720, 480))
class Player(pygame.sprite.Sprite):
def __init__(self):
super(Player, self).__init__()
self.rect = pygame.Rect((0, 0), (32, 32))
self.image = pygame.Surface((32, 32))
self.image.fill((255, 255, 255))
self.velocity = [0, 0] # It's current velocity.
self.speed = 4 # The speed the player will move.
self.dx = [] # Keeps track of the horizontal movement.
self.dy = [] # Keeps track of the vertical movement.
def update(self):
try:
self.rect.x += self.dx[0] # Index error if the list is empty.
except IndexError:
self.rect.x += 0
try:
self.rect.y += self.dy[0] # Index error if the list is empty.
except IndexError:
self.rect.y += 0
player = Player()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
raise SystemExit
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
player.dx.insert(0, -player.speed)
elif event.key == pygame.K_d:
player.dx.insert(0, player.speed)
elif event.key == pygame.K_w:
player.dy.insert(0, -player.speed)
elif event.key == pygame.K_s:
player.dy.insert(0, player.speed)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.dx.remove(-player.speed)
elif event.key == pygame.K_d:
player.dx.remove(player.speed)
elif event.key == pygame.K_w:
player.dy.remove(-player.speed)
elif event.key == pygame.K_s:
player.dy.remove(player.speed)
player.update()
screen.fill((0, 0, 0))
screen.blit(player.image, player.rect)
pygame.display.update()
# print player.dx, player.dy # Uncomment to see what's happening in action!

How to reset time back to 0 in pygame?

I am trying to make a game in pygame where you need to click the image to gain a score.My program works but i still need to fix 2 bugs:
Bug 1
When the user presses 'c' that is play again,the **time does not reset back to 0. I want it back to 0 , so that every 10 seconds the game gets over and you cant play it anymore.
Bug 2
The time starts even if the user does not press 'c' , i.e to play game.So by the time user reads the rules (assuming they took 5 seconds to read rules) , and then they press 'c' they only have 5 more seconds to play.I want it to do it so that only when the user presses 'c' the game time starts.
This is my game run up source code:
def runGame():
#Initial score is 0
score=0
gameExit = False
gameOver = False
while not gameExit:
while gameOver == True:
#Game Over message
gameDisplay.fill(black)
message_to_screen("Game over",
red,
y_displace=-50,
size="large")
message_to_screen("Press C to play again or Q to quit.",
white,
y_displace=50,
size="medium")
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c: #If user press 'c' , game starts
gameLoop()
gameDisplay.fill((white))
#Possible Error from here
# ~~~~~~~~~~~~~~~
#My time function
time=pygame.time.get_ticks()/1000
if time==11: #Checks if time hit 10 (i took as 11 as it should complete the 10th second)
global time
global score
score=0
time=0
gameOver=True
#~~~~~~~~~~~~~ Till here
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == LEFT:
# Set the x, y postions of the mouse click
x, y = event.pos
if foodrect.collidepoint(x, y):
foodrect.center=(random.randint(5,1060),random.randint(5,700))
print "New Position: ",foodrect.center
score+=1
continue
gameDisplay.blit(foodimg,foodrect)
showtime=font.render("Time: "+str(time),0,(0,0,0))
gameDisplay.blit(showtime,(950,10))
scoredisplay(score)
pygame.display.update()
My Game Loop
def gameLoop():
clock.tick(FPS)
runGame()
pygame.quit()
quit()
gameLoop()
Full Code
As requested by Herman Yanush.
import pygame
import time
import random
pygame.init()
foodimg=pygame.image.load("food.png")
foodrect=foodimg.get_rect()
#Colours
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
LEFT =1
#Game Display
display_width = 1080
display_height = 720
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Click It! ~ Snapnel Productions')
gameDisplay.fill((white))
font=pygame.font.SysFont("Arial",30)
#Clock
clock = pygame.time.Clock()
FPS = 30
cellSize=10
#Font Size
exsmallfont = pygame.font.SysFont("comicsansms", 17)
smallfont = pygame.font.SysFont("comicsansms", 25)
medfont = pygame.font.SysFont("comicsansms", 50)
largefont = pygame.font.SysFont("comicsansms", 80)
#The score function - displays the score on top right
def scoredisplay(scoredef=0):
text=smallfont.render("Score :%s" %(scoredef) ,True ,white)
gameDisplay.blit(text,[0,0])
def scoredisplay1(musicname):
text=exsmallfont.render("Now Playing :%s" %(musicname) ,True ,white)
gameDisplay.blit(text,[690,5])
#Starting Of the game
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key ==pygame.K_c:
intro = False
if event.key ==pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(black)
#Game Initial display message
message_to_screen("Click It!",
red,
-200,
size="large")
message_to_screen("This Game is created by Shrapnel",
white,
-30,
size="small")
message_to_screen(" the food to gain a point!",
white,
10,
size="small")
message_to_screen("Press 'C' to play the game or 'Q' to quit.",
white,
150,
size="small")
pygame.display.update()
clock.tick(15)
#Text Size
def text_objects(text,color, size):
if size=="small":
textSurface=smallfont.render(text, True ,color)
elif size=="medium":
textSurface=medfont.render(text, True ,color)
elif size=="large":
textSurface=largefont.render(text, True ,color)
return textSurface,textSurface.get_rect()
#Message to screen
def message_to_screen(msg,color,y_displace=0,size="small"):
textSurf,textRect=text_objects(msg,color,size)
textRect.center = (display_width / 2),(display_height / 2)+y_displace
gameDisplay.blit(textSurf,textRect)
#Score Display
def scoredisplay(scoredef=0):
text=smallfont.render("Score :%s" %(scoredef) ,True ,black)
gameDisplay.blit(text,[0,0])
score=0
global a
a=10
#print score
def runGame():
score=0
gameExit = False
gameOver = False
thing_startx = random.randrange(0,display_width)
thing_starty = -600
thing_speed = 7
thing_width = 100
thing_height = 100
while not gameExit:
deadZones=[]
while gameOver == True:
#Game Over message
gameDisplay.fill(black)
message_to_screen("Game over",
red,
y_displace=-50,
size="large")
message_to_screen("Press C to play again or Q to quit.",
white,
y_displace=50,
size="medium")
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
gameDisplay.fill((white))
time=pygame.time.get_ticks()/1000
if time==11:
global time
global score
score=0
time=0
gameOver=True
#print score
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN and event.button == LEFT:
# Set the x, y postions of the mouse click
x, y = event.pos
if foodrect.collidepoint(x, y):
foodrect.center=(random.randint(5,1060),random.randint(5,700))
print "New Position: ",foodrect.center
score+=1
continue
gameDisplay.blit(foodimg,foodrect)
showtime=font.render("Time: "+str(time),0,(0,0,0))
gameDisplay.blit(showtime,(950,10))
#scoredisplay(score)
pygame.display.update()
def gameLoop():
clock.tick(FPS)
runGame()
pygame.quit()
quit()
game_intro()
gameLoop()
Thanks in advance to help.
I think I might have a solution that at least I use. While sometimes it is nice to use pygame.time.get_ticks, there is an easier solution. Before your while loop set a variable called frame to 0. Then at the end of your while loop type:
if gameEnd == True:
frame=0
score=0
else:
frame+=1
Then all you have to do is only draw the picture when frame>0. You can also easily manipulate frame. Message me if you need any more help.

Pygame assiging to rect.attributes doesn't change the anything

From the documentation:
"Assigning to size, width or height changes the dimensions of the rectangle".
I have the following circle, assign a new attribute but no changes can be seen in circle. What am i doing wrong?
import pygame
from pygame.locals import *
pygame.init()
TV=pygame.display.set_mode((400,400))
pygame.display.set_caption("Rect")
c=pygame.draw.circle(TV,(0,100,0),(150,150),100,1)
pygame.draw.rect(TV,(100,0,0),c,1)
print c.size
c.size=(100,100)
print c.size
pygame.display.flip()
while True:
for e in pygame.event.get():
if e.type==QUIT:
pygame.quit()
You draw the circle on the screen surface. Every drawing function then returns a Rect, but:
The functions return a rectangle representing the bounding area of changed pixels.
To actually change the circle on the screen, you have to erase it first (draw something above it), then draw a new circle in the size you want.
Here's a simple example:
import pygame
from pygame.locals import *
pygame.init()
pygame.display.set_caption("Rect")
TV = pygame.display.set_mode((400,400))
c = pygame.draw.circle(TV, (0, 100, 0), TV.get_rect().center, 100, 1)
clock = pygame.time.Clock()
pygame.time.set_timer(USEREVENT, 250)
value = 10
run = True
while run:
for e in pygame.event.get():
if e.type == QUIT:
run = False
if e.type == USEREVENT:
c.inflate_ip(value, value)
if c.width > 260 or c.width < 200:
value *= -1
TV.fill(pygame.color.Color('Black'))
pygame.draw.circle(TV, (0, 100, 0), c.center, c.width/2, 1)
pygame.display.flip()
clock.tick(60)
pygame.quit()