problems with pygame.event and pygame.draw - pygame

I am trying to make two 8*8 screens. In one i want pygame to draw circles and in the other one three rectangles.
import pygame,sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1063,501))
pygame.draw.line(screen,(255,255,255),(0,0),(0,500))
pygame.draw.line(screen, (255,255,255), (0,0),(500,0))
pygame.draw.line(screen, (255,255,255), (500,0),(500,500))
pygame.draw.line(screen, (255,255,255), (500,500),(0,500))
for i in range(8):
pygame.draw.line(screen, (255,255,255), (0,i*62.5+62.5),(500,i*62.5+62.5))
for i in range(8):
pygame.draw.line(screen, (255,255,255), (i*62.5+62.5,0),(i*62.5+62.5,500))
pygame.draw.line(screen,(255,255,255),(562,0),(562,500))
pygame.draw.line(screen, (255,255,255), (562,0),(1062,0))
pygame.draw.line(screen, (255,255,255), (1062,0),(1062,500))
pygame.draw.line(screen, (255,255,255), (1062,500),(500,500))
for i in range(8):
pygame.draw.line(screen, (255,255,255), (562,i*62.5+62.5),(1062,i*62.5+62.5))
for i in range(8):
pygame.draw.line(screen, (255,255,255), (562 + i*62.5+62.5,0),(562+i*62.5+62.5,500))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
x = int(pos[0])
y = int(pos[1])
x1 = int(pos[0]//62.5)
y1 = int(pos[1]//62.5)
x2 = int(x1*62.5+62.5/2)
y2 = int(y1*62.5+62.5/2)
print(x2,' ',y2)
if x >563:
pygame.draw.circle(screen, (255,0,0), (x2, y2), 10, 0)
print(x1-8,' ',y1+1)
while True:
if event.type == KEYDOWN :
if x < 531 and event. key == pygame.K_1:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.display.update()
if x < 531 and event. key == pygame.K_2:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2+35, y2-27, 55, 55))
pygame.display.update()
if x < 531 and event. key == pygame.K_3:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2+35, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2-(27+62.5), y2-27, 55, 55))
pygame.display.update()
pygame.display.update()
I have no idea whats the problem with this I am trying to make two 8*8 screens. In one i want pygame to draw circles and in the other one three rectangles.

You've got 2 while loops, changing it to this works:
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
x = int(pos[0])
y = int(pos[1])
x1 = int(pos[0]//62.5)
y1 = int(pos[1]//62.5)
x2 = int(x1*62.5+62.5/2)
y2 = int(y1*62.5+62.5/2)
print(x2,' ',y2)
if x >563:
pygame.draw.circle(screen, (255,0,0), (x2, y2), 10, 0)
print(x1-8,' ',y1+1)
if event.type == KEYDOWN :
if x < 531 and event. key == pygame.K_1:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
if x < 531 and event. key == pygame.K_2:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2+35, y2-27, 55, 55))
if x < 531 and event. key == pygame.K_3:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2+35, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2-(27+62.5), y2-27, 55, 55))
pygame.display.update()
However, unless you click somewhere in the window before you press 1, 2 or 3, you'll get an error as x is defined inside the MOUSEBUTTONDOWN event. To fix this and draw 1, 2 or 3 squares under the mouse pointer without clicking inside the window move the pos declaration out of the event loop:
while True:
pos = pygame.mouse.get_pos()
x = int(pos[0])
y = int(pos[1])
x1 = int(pos[0]//62.5)
y1 = int(pos[1]//62.5)
x2 = int(x1*62.5+62.5/2)
y2 = int(y1*62.5+62.5/2)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
print(x2,' ',y2)
if x >563:
pygame.draw.circle(screen, (255,0,0), (x2, y2), 10, 0)
print(x1-8,' ',y1+1)
if event.type == KEYDOWN :
if x < 531 and event. key == pygame.K_1:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
if x < 531 and event. key == pygame.K_2:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2+35, y2-27, 55, 55))
if x < 531 and event. key == pygame.K_3:
pygame.draw.rect(screen, (0,255,0), (x2-27, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2+35, y2-27, 55, 55))
pygame.draw.rect(screen, (0,255,0), (x2-(27+62.5), y2-27, 55, 55))
pygame.display.update()

Related

Snake Game cannot add length to the snake [duplicate]

I want to implement a snake game. The snake meanders through the playground. Every time when the snake eats some food, the length of the snake increase by one element.
The elements of the snakes body follow its head like a chain.
snake_x, snake_y = WIDTH//2, HEIGHT//2
body = []
move_x, move_y = (1, 0)
food_x, food_y = new_food(body)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: move_x, move_y = (-1, 0)
elif event.key == pygame.K_RIGHT: move_x, move_y = (1, 0)
elif event.key == pygame.K_UP: move_x, move_y = (0, -1)
elif event.key == pygame.K_DOWN: move_x, move_y = (0, 1)
snake_x = (snake_x + move_x) % WIDTH
snake_y = (snake_y + move_y) % HEIGHT
if snake_x == food_x and snake_y == food_y:
food_x, food_y = new_food(body)
body.append((snake_x, snake_x))
# [...]
How do I accomplish, that the body parts follow the snake's head on its path, when the snake's head moves ahead?
In general you have to distinguish between 2 different types of snake. In the first case, the snake moves in a grid and every time when the snake moves, it strides ahead one field in the grid. In the other type, the snakes position is not in a raster and not snapped on the fields of the grid, the position is free and the snake slides smoothly through the fields.
In former each element of the body is snapped to the fields of the grid, as the head is. The other is more trick, because the position of a body element depends on the size of the element and the dynamic, previous positions of the snakes head.
First the snake, which is snapped to a grid.
The elements of the snake can be stored in a list of tuples. Each tuple contains the column and row of the snakes element in the grid. The changes to the items in the list directly follow the movement of the snake. If the snake moves, a the new position is add to the head of the list and the tail of the list is removed.
For instance we have a snake with the following elements:
body = [(3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]
When the snakes head moves form (3, 3) to (3, 2), then the new head position is add to the head of the list (body.insert(0, (3, 2)):
body = [(3, 2), (3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]
Finally the tail of the ist is removed (del body[-1]):
body = [(3, 2), (3, 3), (3, 4), (4, 4), (5, 4)]
Minimal example: repl.it/#Rabbid76/PyGame-SnakeMoveInGrid
import pygame
import random
pygame.init()
COLUMNS, ROWS, SIZE = 10, 10, 20
screen = pygame.display.set_mode((COLUMNS*SIZE, ROWS*SIZE))
clock = pygame.time.Clock()
background = pygame.Surface((COLUMNS*SIZE, ROWS*SIZE))
background.fill((255, 255, 255))
for i in range(1, COLUMNS):
pygame.draw.line(background, (128, 128, 128), (i*SIZE-1, 0), (i*SIZE-1, ROWS*SIZE), 2)
for i in range(1, ROWS):
pygame.draw.line(background, (128, 128, 128), (0, i*SIZE-1), (COLUMNS*SIZE, i*SIZE-1), 2)
def random_pos(body):
while True:
pos = random.randrange(COLUMNS), random.randrange(ROWS)
if pos not in body:
break
return pos
length = 1
body = [(COLUMNS//2, ROWS//2)]
dir = (1, 0)
food = random_pos(body)
run = True
while run:
clock.tick(5)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dir = (-1, 0)
elif event.key == pygame.K_RIGHT: dir = (1, 0)
elif event.key == pygame.K_UP: dir = (0, -1)
elif event.key == pygame.K_DOWN: dir = (0, 1)
body.insert(0, body[0][:])
body[0] = (body[0][0] + dir[0]) % COLUMNS, (body[0][1] + dir[1]) % ROWS
if body[0] == food:
food = random_pos(body)
length += 1
while len(body) > length:
del body[-1]
screen.blit(background, (0, 0))
pygame.draw.rect(screen, (255, 0, 255), (food[0]*SIZE, food[1]*SIZE, SIZE, SIZE))
for i, pos in enumerate(body):
color = (255, 0, 0) if i==0 else (0, 192, 0) if (i%2)==0 else (255, 128, 0)
pygame.draw.rect(screen, color, (pos[0]*SIZE, pos[1]*SIZE, SIZE, SIZE))
pygame.display.flip()
Now the snake with completely free positioning.
We have to track all the positions which the snake's head has visited in a list. We have to place the elements of the snakes body on the positions in the list like the pearls of a chain.
The key is, to compute the Euclidean distance between the last element of the body in the chain and the following positions on the track.
When an new point with a distance that is large enough is found, then an new pearl (element) is add to the chain (body).
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
The following function has 3 arguments. track is the list of the head positions. no_pearls is then number of elements of the shakes body and distance is the Euclidean distance between the elements. The function creates and returns a list of the snakes body positions.
def create_body(track, no_pearls, distance):
body = [(track[0])]
track_i = 1
for i in range(1, no_pearls):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
break
while len(body) < no_pearls:
body.append(track[-1])
del track[track_i:]
return body
Minimal example: repl.it/#Rabbid76/PyGame-SnakeMoveFree
import pygame
import random
import math
pygame.init()
COLUMNS, ROWS, SIZE = 10, 10, 20
WIDTH, HEIGHT = COLUMNS*SIZE, ROWS*SIZE
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
background = pygame.Surface((WIDTH, HEIGHT))
background.fill((255, 255, 255))
for i in range(1, COLUMNS):
pygame.draw.line(background, (128, 128, 128), (i*SIZE-1, 0), (i*SIZE-1, ROWS*SIZE), 2)
for i in range(1, ROWS):
pygame.draw.line(background, (128, 128, 128), (0, i*SIZE-1), (COLUMNS*SIZE, i*SIZE-1), 2)
def hit(pos_a, pos_b, distance):
dx, dy = pos_a[0]-pos_b[0], pos_a[1]-pos_b[1]
return math.sqrt(dx*dx + dy*dy) < distance
def random_pos(body):
pos = None
while True:
pos = random.randint(SIZE//2, WIDTH-SIZE//2), random.randint(SIZE//2, HEIGHT-SIZE//2)
if not any([hit(pos, bpos, 20) for bpos in body]):
break
return pos
def create_body(track, no_pearls, distance):
body = [(track[0])]
track_i = 1
for i in range(1, no_pearls):
while track_i < len(track):
pos = track[track_i]
track_i += 1
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1]
if math.sqrt(dx*dx + dy*dy) >= distance:
body.append(pos)
break
while len(body) < no_pearls:
body.append(track[-1])
del track[track_i:]
return body
length = 1
track = [(WIDTH//2, HEIGHT//2)]
dir = (1, 0)
food = random_pos(track)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: dir = (-1, 0)
elif event.key == pygame.K_RIGHT: dir = (1, 0)
elif event.key == pygame.K_UP: dir = (0, -1)
elif event.key == pygame.K_DOWN: dir = (0, 1)
track.insert(0, track[0][:])
track[0] = (track[0][0] + dir[0]) % WIDTH, (track[0][1] + dir[1]) % HEIGHT
body = create_body(track, length, 20)
if hit(body[0], food, 20):
food = random_pos(body)
length += 1
screen.blit(background, (0, 0))
pygame.draw.circle(screen, (255, 0, 255), food, SIZE//2)
for i, pos in enumerate(body):
color = (255, 0, 0) if i==0 else (0, 192, 0) if (i%2)==0 else (255, 128, 0)
pygame.draw.circle(screen, color, pos, SIZE//2)
pygame.display.flip()

screen.blit() function executing even after pygame.quit() is used

I am making a basic pong game in pygame with a separate menu screen. I have figured out all the gameplay (physics of ball,score system etc.).However, when i quit the game no matter from the menu screen or from the main game loop, i get this error:pygame.error: display Surface quit. I have seen all the posts about this error on stackoverflow, as well as other websites. I understand that the error is occuring because even after the pygame.quit() function, the next screen.blit(player1,(player1x,player1y)) is being executed. Following is the my code :
import pygame
import random
pygame.init()
#screen
screenw = 1000
screenh = 600
screen = pygame.display.set_mode((screenw, screenh))
bg = pygame.image.load("bg.jpg")
dp = pygame.image.load("ping-pong.png")
pygame.display.set_caption("PONG")
pygame.display.set_icon(dp)
def main():
# score
font = pygame.font.Font('font.otf', 24)
winfont = pygame.font.Font('font.otf', 50)
score_value_p1 = 0
scorexp1 = 10
scoreyp1 = 0
score_value_p2 = 0
scorexp2 = screenw - 145
scoreyp2 = 0
#toss
toss = random.choice([-1,1])
#players
def initial_bars():
global player1,player1x,player1y,player1_change,player2,player2x,player2y,player2_change
player1 = pygame.image.load("danda.png")
player1 = pygame.transform.scale(player1,(25,128))
player1x = 10
player1y = 232
player1_change = 0
player2 = pygame.image.load("danda.png")
player2 = pygame.transform.scale(player1,(25,128))
player2x = 965
player2y = 232
player2_change = 0
#ball
def initial_ball():
global ball,ballx,bally,ballx_change,bally_change
ball = pygame.image.load("ball.png")
ballx = 484
bally = 284
ballx_change = 0.4*toss
bally_change = 0.0
initial_bars()
initial_ball()
global player1,player1x,player1y,player1_change,player2,player2x,player2y,player2_change,ball,ballx,bally,ballx_change,bally_change,running
#functions
def player1bar():
screen.blit(player1,(player1x,player1y))
def player2bar():
screen.blit(player2,(player2x,player2y))
def balll():
screen.blit(ball,(ballx,bally))
def show_score():
scorep1 = font.render("Score : " + str(score_value_p1), True, (255, 50, 50))
screen.blit(scorep1, (scorexp1 , scoreyp1))
scorep2 = font.render("Score : " + str(score_value_p2), True, (255, 50, 50))
screen.blit(scorep2, (scorexp2 , scoreyp2))
#game window
running = True
while running:
screen.fill((0, 0, 0))
pygame.draw.line(screen,(255,255,30),(499,0),(499,600), 10)
pygame.draw.circle(screen,(255,255,30),(500,300), 40, 10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
# player1 movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_s :
player1_change = 0.6
if event.key == pygame.K_w:
player1_change = -0.6
if event.type == pygame.KEYUP:
if event.key == pygame.K_s or event.key == pygame.K_w:
player1_change = 0
# player2 movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN :
player2_change = 0.6
if event.key == pygame.K_UP:
player2_change = -0.6
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
player2_change = 0
player1y += player1_change
player2y += player2_change
# player1 boundary
if player1y <= 0:
player1y = 0
elif player1y >= 472:
player1y = 472
# player2 boundary
if player2y <= 0:
player2y = 0
elif player2y >= 472:
player2y = 472
#ball move
ballx += ballx_change
bally += bally_change
toss = random.choice([-1,1])
if ballx < 35 and ballx > 30 and (player1y == bally or (player1y < bally and player1y > bally - 128) or (player1y > bally and player1y < bally + 32)):
ballx_change *= -1
if ballx_change < 1:
ballx_change += 0.05
bally_change = ballx_change*toss
if ballx > 933 and ballx < 938 and (player2y == bally or (player2y < bally and player2y > bally - 128) or (player2y > bally and player2y < bally + 32)):
ballx_change *= -1
if ballx_change > -1:
ballx_change -= 0.05
bally_change = ballx_change*toss
# ball boundary
if bally < 0 or bally > screenh - 32:
bally_change *= -1
#score
if ballx > screenw:
score_value_p1 += 1
if ballx < -32:
score_value_p2 += 1
#respawn
if ballx > screenw or ballx < -32:
initial_ball()
initial_bars()
player1bar()
player2bar()
balll()
show_score()
#winner
if score_value_p1 == 5:
winner = winfont.render("The Winner is Player 1", True, (50, 255, 50))
winner_rect = winner.get_rect(center=(screenw/2, screenh/2))
pygame.draw.rect(screen, (0,0,0), pygame.Rect(winner_rect))
screen.blit(winner, winner_rect)
if score_value_p2 == 5:
winner = winfont.render("The Winner is Player 2", True, (50, 255, 50))
winner_rect = winner.get_rect(center=(screenw/2, screenh/2))
pygame.draw.rect(screen, (0,0,0), pygame.Rect(winner_rect))
screen.blit(winner, winner_rect)
pygame.display.update()
if score_value_p1 == 5 or score_value_p2 == 5:
pygame.time.delay(2000)
menu_screen()
if ballx == 484 and bally == 284:
pygame.time.delay(1250)
ballx_change = 0.4*toss
def menu_screen():
menufont = pygame.font.Font('font.otf', 50)
tipfont = pygame.font.Font('font.otf', 30)
running = True
while running:
screen.blit(bg,(0,0))
title = menufont.render("Multiplayer Pong", True, (255, 255, 20))
screen.blit(title, (220,70))
tip = tipfont.render("Click Anywhere to Play", True, (50, 255, 50))
screen.blit(tip, (275,500))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
running = False
pygame.display.update()
main()
menu_screen()
I have tried methods like adding break,pygame.quit(),declaring running as a global variable. However, i have not been able to get rid of this problem. Can anyone please try o provide a solution for this problem. Following is the complete error i recieved :
Traceback (most recent call last):
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 208, in <module>
menu_screen()
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 206, in menu_screen
main()
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 158, in main
player1bar()
File "c:\Users\jaism\OneDrive\Desktop\Codes\Minor Project CSE\main.py", line 63, in player1bar
screen.blit(player1,(player1x,player1y))
pygame.error: display Surface quit
pygame.quit() uninitialize all pygame modules that have previously been initialized. So you can't call any pygame API function after pygame.quite(). pygame.quite() must be the very last pygame function called after the application loop:
def main():
# [...]
running = True
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# pygame.quit() <-- DELETE
# [...]
def menu_screen():
# [...]
run_main = True
running = True
while running:
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
run_main = False
# pygame.quit() <-- DELETE
# [...]
if run_main:
main()
menu_screen()
pygame.quit() # <-- INSERT

The continue button doesn't work when the game is paused

I have made a game where you have to dodge objects. You can also pause the game by pressing p. Once you pause the game you get an option if you want to continue or quit. For me, the quit button is working but the continue button isn't. Where it says define unpause() is where the code starts for the pause button.
import time
import random
pygame.init()
display_width = 800
display_height = 600
red = (200,0,0)
orange = (255, 165, 0)
yellow = (255, 242, 0)
green = (0,200,0)
blue = (0,0,255)
indigo = (75, 0, 130)
violet = (238, 130, 238)
black = (0,0,0)
white = (255,255,255)
bright_red = (255,0,0)
bright_green = (0,255,0)
car_width = 86
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Racing Game")
clock = pygame.time.Clock()
carImg = pygame.image.load("download.png")
carImg = pygame.transform.scale(carImg,(100,160))
pause = False
def things_dodged(count):
font = pygame.font.SysFont(None, 25)
text = font.render ("Dodged: "+str(count), True, black)
gameDisplay.blit(text,(0,0))
def things(thingx, thingy, thingw, thingh, color):
pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh])
def car(x,y):
gameDisplay.blit(carImg, (x,y))
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def message_display(text):
largeText = pygame.font.Font("freesansbold.ttf",100)
TextSurf, TextRect = text_objects(text, largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
pygame.display.update()
game_loop()
time.sleep(2000)
def crash():
message_display ("YOU CRASHED")
def button(msg,x,y,w,h,ic,ac,action = None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
print(click)
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:
if action == "play":
game_loop()
elif action == "quit":
pygame.quit()
quit()
else:
pygame.draw.rect(gameDisplay, ic, (x,y,w,h))
smallText = pygame.font.Font("freesansbold.ttf",20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ( (x+(w/2)), (y+(h/2)) )
gameDisplay.blit(textSurf, textRect)
def quitgame():
pygame.quit()
quit
def unpause():
global pause
pause = False
def paused():
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameDisplay.fill(white)
largeText = pygame.font.Font("freesansbold.ttf",100)
TextSurf, TextRect = text_objects("PAUSED", largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
button ("Continue!",150,450,100,50,green,bright_green,unpause)
button ("Quit!",550,450,100,50,red,bright_red,"quit")
pygame.display.update()
clock.tick(15)
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.Font("freesansbold.ttf",100)
TextSurf, TextRect = text_objects("Racing Game", largeText)
TextRect.center = ((display_width/2),(display_height/2))
gameDisplay.blit(TextSurf, TextRect)
button ("GO!",150,450,100,50,green,bright_green,"play")
button ("QUIT!",550,450,100,50,red,bright_red,"quit")
pygame.display.update()
clock.tick(15)
def game_loop():
global pause
x = (display_width * 0.45)
y = (display_height * 0.72)
x_change = 0
thing_startx = random.randrange(0, display_width)
thing_starty = -600
thing_speed = 7
thing_width = 100
thing_height = 100
thingCount = 1
dodged = 0
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.key == pygame.K_p:
pause = True
paused()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameDisplay.fill(white)
things(thing_startx, thing_starty, thing_width, thing_height, black)
thing_starty += thing_speed
car (x,y)
things_dodged(dodged)
if x > display_width - car_width or x < -10:
crash()
if thing_starty > display_height:
thing_starty = 0 - thing_height
thing_startx = random.randrange(0,display_width)
dodged += 1
thing_speed += 1
#thing_width += (dodged * 0.5)
if y < thing_starty + thing_height:
if x > thing_startx and x < thing_startx + thing_width or x + car_width > thing_startx and x + car_width < thing_startx + thing_width:
crash()
pygame.display.update()
clock.tick(100)
game_intro()
game_loop()
pygame.quit()
quit()
Please try to help. I am saying Thank You in advance for all your guy's help.
You have typo in while paused: in def paused()- it has to be while pause:
def paused():
while pause: # <- pause instead of paused

pygame creating multiple sprites

I am very new to pygame, and was trying to make a basic tower defence game. I have looked around, but cannot grasp how to create multiple sprites (towers) from the image I am using. Here is my code for the TD game. But I do not know how to create more then one sprite(tower).
import pygame
import time
import sys
import os
pygame.init()
WINDOWWIDTH = 1800
WINDOWHEIGHT = 1800
os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (0,30)
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
background_colour = (63,200,70)
GAMETITLE = "Tower Defence"
font = pygame.font.SysFont(None, 100)
def balanceText(balance):
screen_text = font.render(str(balance), True, (255,255,255))
screen.blit(screen_text, [1640,0])
def main():
balance = 100
pygame.display.set_caption(GAMETITLE)
clock = pygame.time.Clock()
spritegroup =pygame.sprite.Group()
sprite =pygame.sprite.Sprite()
tower = sprite.image = pygame.image.load("tower.png")
sprite.image = tower
sprite.rect = sprite.image.get_rect()
drawTower = False
towerPlaced = False
bulletX = 250
sprite.add(spritegroup)
while True:
screen.fill(background_colour)
pygame.draw.rect(screen, (255,255,255), ((0, 100), (1100, 90)))
pygame.draw.rect(screen, (255, 255,255), ((1010, 100), (100, 600)))
pygame.draw.rect(screen, (255,255,255), ((1010, 700), (2400, 90)))
pygame.draw.rect(screen, (139,69,19), ((1600, 0), (2400, 18000)))
pygame.draw.rect(screen, (128, 128,128), (( 300,250), (140,140)))
pygame.draw.rect(screen, (128, 128,128), (( 600,250), (140,140)))
pygame.draw.rect(screen, (128, 128,128), (( 800,700), (140,140)))
pygame.draw.rect(screen, (128, 128,128), (( 1150,500), (140,140)))
balanceText(balance)
if drawTower:
spritegroup.draw(screen)
pygame.display.update()
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if pygame.mouse.get_pressed()[0] and towerPlaced == False:
mousePos = pygame.mouse.get_pos()
if mousePos[0] > 300 and mousePos[0] < 450 and mousePos[1] > 250 and mousePos[1] < 400:
drawTower = True
sprite.rect.center = (370, 320)
towerPlaced = True
balance -= 50
elif mousePos[0] > 600 and mousePos[0] < 750 and mousePos[1] > 250 and mousePos[1] < 400:
drawTower = True
sprite.rect.center = (670, 320)
towerPlaced = True
balance-= 50
elif mousePos[0] > 800 and mousePos[0] < 950 and mousePos[1] > 700 and mousePos[1] < 850:
drawTower = True
sprite.rect.center = (870, 770)
towerPlaced = True
balance-= 50
elif mousePos[0] > 1150 and mousePos[0] < 1300 and mousePos[1] > 500 and mousePos[1] < 650:
drawTower = True
sprite.rect.center = (1220, 570)
towerPlaced = True
balance-= 50
elif event.type == pygame.QUIT:
pygame.display.quit()
main()
Thanks for looking! I know the code is a bit messy right now.
You need to use the Sprite class properly. To do this, you have to define your sprite as a subclass of pygame.sprite.Sprite, like this:
class Tower(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = tower_img
self.rect = self.image.get_rect()
self.rect.center = (x, y)
Then you can spawn a tower any time you like by creating another instance and adding it to the group:
new_tower = Tower(370, 320)
spritegroup.add(new_tower)
I highly recommend looking at the Sprite documentation:
http://www.pygame.org/docs/ref/sprite.html - there's lots of good info in there. There are also many good tutorials out there that go into how you use sprites in Pygame. Here is a link to one that I wrote:
http://kidscancode.org/blog/2016/08/pygame_1-2_working-with-sprites/

How to force the player to keyup?

In my program I have a square that jumps over cars. But the player can just hold down space and never touch the ground. This means this can't. I am wondering how o make it force the cube to go back down to the ground after a set time.
Here is my code:
import pygame
import time
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Traffic Jumper')
orange = (255, 100, 0)
black = (0,0,0)
grey = (128,128,128)
yellow = (255,255,0)
green = (0,128,0)
red=(255,0,0)
blue = (64,224,208)
brown = (139,69,19)
magenta = (255,0,255)
olive = (128,128,0)
clock = pygame.time.Clock()
def options():
op = True
while op:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.QUIT()
screen.fill(magenta)
largeText = pygame.font.Font('freesansbold.ttf',115)
Textsurf, TextRect = text_objects("Get Hit Bro!", largeText)
TextRect.center = ((400),(300))
screen.blit(Textsurf, TextRect)
smallText = pygame.font.Font('freesansbold.ttf',30)
Textsurf, TextRect1 = text_objects("Press Y to restart and N to\ leave", smallText)
TextRect1.center = (400,(400))
screen.blit(Textsurf, TextRect1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_y:
game_loop()
elif event.key == pygame.K_n:
pygame.quit()
def pause():
paused = True
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
paused=False
pygame.QUIT()
quit()
screen.fill(olive)
largeText = pygame.font.Font('freesansbold.ttf',115)
Textsurf, TextRect = text_objects("Paused", largeText)
TextRect.center = ((400),(300))
screen.blit(Textsurf, TextRect)
smallText = pygame.font.Font('freesansbold.ttf',30)
Textsurf, TextRect1 = text_objects("Press r To Resume", smallText)
TextRect1.center = (400,(400))
screen.blit(Textsurf, TextRect1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
paused = False
def text_objects(text, font):
textsurface = font.render(text,True,red)
return textsurface, textsurface.get_rect()
def message_display(text):
largeText = pygame.font.Font('freesansbold.ttf',115)
Textsurf, TextRect = text_objects(text, largeText)
TextRect.center = ((400),(300))
screen.blit(Textsurf, TextRect)
pygame.display.update()
time.sleep(2)
#game_loop()
def game_loop():
paused = False
score = 0
x = 20
y = 520
carx = 1000
cary = 490
carspeed = 7
done = False
while not done:
screen.fill((255, 255, 255))
sky=pygame.draw.rect(screen,blue,pygame.Rect(0,0,800,400))
grass=pygame.draw.rect(screen,green,pygame.Rect(0,400,800,100))
floor1=pygame.draw.rect(screen,black,pygame.Rect(0,500,800,10))
floor2=pygame.draw.rect(screen,black,pygame.Rect(0,590,800,10))
road=pygame.draw.rect(screen,grey,pygame.Rect(0,510,800,80))
paint1=pygame.draw.rect(screen,yellow,pygame.Rect(10,540,100,\ 20))
paint2=pygame.draw.rect(screen,yellow,pygame.Rect(200,540,100,\ 20))
paint3=pygame.draw.rect(screen,yellow,pygame.Rect(400,540,100,\ 20))
paint4=pygame.draw.rect(screen,yellow,pygame.Rect(600,540,100,\ 20))
paint5=pygame.draw.rect(screen,yellow,pygame.Rect(780,540,100,\ 20))
player=pygame.draw.rect(screen, orange, pygame.Rect(x, y, 60,\ 60))
car=pygame.draw.rect(screen,black,pygame.Rect(carx,cary,80,\ 95))
if x > 800 - 60:
x -= 3
elif x < 0:
x += 3
for event in pygame.event.get():
if event.type == pygame.QUIT:
#done = True
quit()
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
y -= 200
if event.type == pygame.KEYUP and event.key == pygame.K_SPACE:
y += 200
if event.type == pygame.KEYDOWN and event.key == pygame.K_p:
pause()
pressed = pygame.key.get_pressed()
#if pressed[pygame.K_UP]: y -= 3
#if pressed[pygame.K_DOWN]: y += 3
if pressed[pygame.K_LEFT]: x -= 3
if pressed[pygame.K_RIGHT]: x += 3
carx -= carspeed
if carx < -100:
score += 1
carspeed += 0.2
carx = 1000
if x > carx - 55 and x < carx + 55 and y > cary:
#message_display('Get Hit Bro!')
options()
font = pygame.font.SysFont(None,25)
text = font.render("Dodged: " + str(score) ,True,black)
screen.blit(text,(0,0))
pygame.display.flip()
clock.tick(60)
game_loop()
Add these variables to game_loop:
hasJumped = False
jumpCooldown = 0.0
In your loop, in the 'while not done' add
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
if hasJumped == False:
y -= 200
hasJumped = True
if hasJumped == True:
jumpCooldown += clock.get_time()
if jumpCooldown > [Jump Cooldown Limit]: # Set this number to the amount of time the car can jump at once. You'll have to experiment.
hasJumped = False
jumpCooldown = 0.0
PS : I don't understand why you use pygame.KEYDOWN/KEYUP to detect one set of keys and pygame.key.get_pressed() for another set. It seems messy
You could have a counter that was set each time the player presses space. This counter could count down each iteration, and when it reaches zero, the y position would be set back:
delta_y = 0
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
counter = 10
if event.type == pygame.KEYUP and event.key == pygame.K_SPACE:
counter = 0
if counter > 0:
delta_y = 200
counter -= 1
else:
delta_y = 0
You have to set counter = 0 outside the while loop. I've added a delta_y to the vertical position, because this is a little more cleaner way to do it. You have to update this line to:
player=pygame.draw.rect(screen, orange, pygame.Rect(x, y + delta_y, 60, 60))
The counter counts down from 10 - you'll just have to experiment with that.