Snake Game cannot add length to the snake [duplicate] - pygame

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()

Related

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

Problem creating new enemies when player levels up

i'm working on a simple clone of Space Invaders for an University project. The idea is that when the players levels up, the amount of enemies increase, but when i try to do it, the enemies creates infinitly while the stablished condition is true. I can't dettect the problem, so if one of you can help me, i'll apreciate it.
import random
import csv
import operator
import pygame
import time
from pygame import mixer
# Intialize the pygame
pygame.init()
# create the screen
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('background.png')
# Sound
mixer.music.load("background.wav")
mixer.music.play(-1)
#Reloj
clock = pygame.time.Clock()
# Caption and Icon
pygame.display.set_caption("Space Invader")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
# Score
score_value = 0
level_value = 1
level_up_value = ""
font = pygame.font.Font('freesansbold.ttf', 20)
game_over = False
high_scores = []
names = []
with open('high_scores.csv') as csvfile:
reader = csv.reader(csvfile)
sortedlist = sorted(reader, key=operator.itemgetter(1), reverse=True)
for i in sortedlist:
names.append(i[0])
high_scores.append(i[1])
scoreX = 10
scoreY = 10
level_textX = 10
level_textY = 80
levelX = 10
levelY = 40
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
menu_font = pygame.font.Font('freesansbold.ttf', 48)
scores_font = pygame.font.Font('freesansbold.ttf', 45)
#Número de vidas
num_vidas = 3
font = pygame.font.Font('freesansbold.ttf', 32)
vidasX = 650
vidasY = 10
# Player
playerImg = pygame.image.load('player.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemy
enemyImg = []
bichoImg = []
meteoroImg = []
enemyX = []
enemyY = []
enemyY_change = []
bichoX = []
bichoY = []
bichoY_change = []
meteoroX = []
meteoroY = []
meteoroY_change = []
num_of_enemies_10 = 5
num_of_enemies_20 = 4
num_of_enemies_30 = 3
for i in range(num_of_enemies_10):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyY_change.append(0.5)
for i in range(num_of_enemies_20):
bichoImg.append(pygame.image.load('bicho.png'))
bichoX.append(random.randint(0, 736))
bichoY.append(random.randint(10, 120))
bichoY_change.append(0.5)
for i in range(num_of_enemies_30):
meteoroImg.append(pygame.image.load('meteoro.png'))
meteoroX.append(random.randint(0, 736))
meteoroY.append(random.randint(0, 150))
meteoroY_change.append(0.5)
# Bullet
# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bulletImg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 10
bullet_state = "ready"
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def show_level(x, y):
level = font.render("Level: " + str(level_value), True, (255, 255, 255))
screen.blit(level, (x, y))
def level_up_text(x, y):
level_text = font.render(level_up_value, True, (255, 255, 0))
screen.blit(level_text, (level_textX, level_textY))
def show_vidas(x, y):
vidas = font.render("Vidas : " + str(num_vidas), True, (255, 255, 255))
screen.blit(vidas, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def bicho(x, y, i):
screen.blit(bichoImg[i], (x, y))
def meteoro(x, y, i):
screen.blit(meteoroImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletImg, (x + 16, y + 10))
#Colisiones para cada tipo de enemigo
def isCollision1(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt(math.pow(enemyX - bulletX, 2) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def isCollision2(bichoX, bichoY, bulletX, bulletY):
distance = math.sqrt(math.pow(bichoX - bulletX, 2) + (math.pow(bichoY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def isCollision3(meteoroX, meteoroY, bulletX, bulletY):
distance = math.sqrt(math.pow(meteoroX - bulletX, 2) + (math.pow(meteoroY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Pause Loop
def show_pause():
paused = True
while paused:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
pause_title = menu_font.render("PAUSED", True, (255, 255, 0))
pauseRect = pause_title.get_rect()
pauseRect.centerx = screen.get_rect().centerx
pauseRect.centery = screen.get_rect().centery - 50
screen.blit(pause_title, pauseRect)
high_title = menu_font.render("HIGH SCORES", True, (255, 255, 255))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = screen.get_rect().centery + 50
screen.blit(high_title, highRect)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = False
break
if event.type == pygame.MOUSEBUTTONDOWN:
mpos = pygame.mouse.get_pos()
if highRect.collidepoint(mpos):
show_high_scores_menu()
break
pygame.display.update()
# High Scores Loop
def show_high_scores_menu():
high_scores_menu = True
global high_scores, names
high_scores.clear()
names.clear()
with open('high_scores.csv') as csvfile:
reader = csv.reader(csvfile)
sortedlist = sorted(reader, key=operator.itemgetter(1), reverse=True)
for i in sortedlist:
names.append(i[0])
high_scores.append(i[1])
while high_scores_menu:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
high_title = menu_font.render("HIGH SCORES", True, (255, 255, 0))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = 100
screen.blit(high_title, highRect)
score1 = scores_font.render(names[0] + " : " + str(high_scores[0]), True, (255, 255, 255))
score1Rect = score1.get_rect()
score1Rect.centerx = screen.get_rect().centerx
score1Rect.centery = 250
screen.blit(score1, score1Rect)
score2 = scores_font.render(names[1] + " : " + str(high_scores[1]), True, (255, 255, 255))
score2Rect = score1.get_rect()
score2Rect.centerx = screen.get_rect().centerx
score2Rect.centery = 300
screen.blit(score2, score2Rect)
score3 = scores_font.render(names[2] + " : " + str(high_scores[2]), True, (255, 255, 255))
score3Rect = score3.get_rect()
score3Rect.centerx = screen.get_rect().centerx
score3Rect.centery = 350
screen.blit(score3, score3Rect)
score4 = scores_font.render(names[3] + " : " + str(high_scores[3]), True, (255, 255, 255))
score4Rect = score4.get_rect()
score4Rect.centerx = screen.get_rect().centerx
score4Rect.centery = 400
screen.blit(score4, score4Rect)
score5 = scores_font.render(names[4] + " : " + str(high_scores[4]), True, (255, 255, 255))
score5Rect = score1.get_rect()
score5Rect.centerx = screen.get_rect().centerx
score5Rect.centery = 450
screen.blit(score5, score5Rect)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
high_scores_menu = False
show_pause()
break
pygame.display.update()
def save_high_scores():
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
name = ""
while len(name) < 3:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.unicode.isalpha():
name += event.unicode
elif event.key == pygame.K_BACKSPACE:
name = name[:-1]
name = name.upper()
screen.fill((0, 0, 0))
screen.blit(background, (0, 0))
high_title = menu_font.render("High Score!", True, (255, 255, 0))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = 100
screen.blit(high_title, highRect)
inpt = font.render("Enter a 3-letter name", True, (255, 255, 255))
inptRect = inpt.get_rect()
inptRect.centerx = screen.get_rect().centerx
inptRect.centery = 200
screen.blit(inpt, inptRect)
namedisplay = menu_font.render(name, True, (255, 255, 255))
namedisplayRect = namedisplay.get_rect()
namedisplayRect.center = screen.get_rect().center
screen.blit(namedisplay, namedisplayRect)
pygame.display.update()
#replace lowest
lowest = high_scores[0]
lowest_index = 0
for i in range(len(high_scores)):
if high_scores[i] <= lowest:
lowest = high_scores[i]
lowest_index = i
high_scores[lowest_index] = score_value
names[lowest_index] = name
with open('high_scores.csv', 'w',newline='') as csvfile:
writer = csv.writer(csvfile)
for i in range(len(names)):
writer.writerow([str(names[i]), str(high_scores[i])])
show_high_scores_menu()
BLACK = (0, 0, 0)
#Agregar imágenes para explosión
explosión_anim = []
for i in range(9):
file = "Explosión/Explosión 0{}.png".format(i)
img = pygame.image.load(file).convert()
img.set_colorkey(BLACK)
img_scale = pygame.transform.scale(img, (70, 70))
explosión_anim.append (img_scale)
def explosión1():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (enemyX[i], enemyY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
def explosión2():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (bichoX[i], bichoY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
def explosión3():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (meteoroX[i], meteoroY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
# Game Loop
en_partida = True
while en_partida:
clock.tick(60)
en_final = False
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
# if player levels up
if score_value < 40:
level_value = 1
elif score_value <= 80:
level_value = 2
elif score_value <= 120:
level_value = 3
elif score_value <= 160:
level_value = 4
if (score_value >= 40 and score_value <= 42):
level_up_value = "LEVEL UP!"
elif (score_value >= 80 and score_value <= 82):
level_up_value = "LEVEL UP!"
elif (score_value >= 120 and score_value <= 122):
level_up_value = "LEVEL UP!"
else:
level_up_value = ""
for event in pygame.event.get():
if event.type == pygame.QUIT:
en_partida = False
# if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletSound = mixer.Sound("laser.wav")
bulletSound.play()
# Get the current x cordinate of the spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemy Movement
for i in range(num_of_enemies_10):
# Game Over
enemyY[i] += enemyY_change[i]
if enemyY[i] > 440:
for j in range(num_of_enemies_10):
enemyY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies_20):
# Game Over
bichoY[i] += bichoY_change[i]
if bichoY[i] > 440:
for j in range(num_of_enemies_20):
bichoY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies_30):
# Game Over
meteoroY[i] += meteoroY_change[i]
if meteoroY[i] > 440:
for j in range(num_of_enemies_30):
meteoroY[j] = 2000
game_over_text()
break
# Collision
collision1 = isCollision1(enemyX[i], enemyY[i], bulletX, bulletY)
collision2 = isCollision2(bichoX[i], bichoY[i], bulletX, bulletY)
collision3 = isCollision3(meteoroX[i], meteoroY[i], bulletX, bulletY)
enemy(enemyX[i], enemyY[i], i)
bicho(bichoX[i], bichoY[i], i)
meteoro(meteoroX[i], meteoroY[i], i)
if collision1:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión1()
bulletY = 480
bullet_state = "ready"
score_value += 10
num_of_enemies_10 -= 1
if collision2:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión2()
bulletY = 480
bullet_state = "ready"
score_value += 20
num_of_enemies_20 -= 1
if collision3:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión3()
bulletY = 480
bullet_state = "ready"
score_value += 30
num_of_enemies_30 -= 1
#Aumento de enemigos por nivel
enemy_created = False
flag = False
if(level_value == 2 and flag == True):
flag = True
enemyX[i] = random.randint(0,736)
enemyY[i] = random.randint(50,150)
enemy(enemyX[i], enemyY[i], i)
enemy_created = True
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(scoreX, scoreY)
show_level(levelX, levelY)
level_up_text(levelX + 100, levelY)
show_vidas(vidasX, vidasY)
pygame.display.update()
pygame.quit()
Set the flag before the game loop:
# Game Loop
flag = True # set flag here
en_partida = True
while en_partida:
clock.tick(60)
....................
#Aumento de enemigos por nivel
enemy_created = False
if(level_value == 2 and flag == True): # check flag
flag = False # reset flag
enemyX[i] = random.randint(0,736)
enemyY[i] = random.randint(50,150)
enemy(enemyX[i], enemyY[i], i)
enemy_created = True

Pygame error 'pow expected 2 arguments, got 1'

They pygame game i made has run into an error i cannot figure out how to fix. I am new to pygame. I am using pycharm and python version 3.
The error is stopping me from doing anything and it won't even let me run it
Here is the error
TypeError: pow expected 2 arguments, got 1
Here is the code:
import math
import random
import pygame
pygame.init()
# Screen (Pixels by Pixels (X and Y (X = right and left Y = up and down)))
screen = pygame.display.set_mode((800, 600))
running = True
# Title and Icon
pygame.display.set_caption("Space Invaders")
icon = pygame.image.load('Icon.png')
pygame.display.set_icon(icon)
# Player Icon/Image
playerimg = pygame.image.load('Player.png')
playerX = 370
playerY = 480
playerX_change = 0
def player(x, y):
# Blit means Draw
screen.blit(playerimg, (x, y))
def enemy(x, y):
# Blit means Draw
screen.blit(enemyimg, (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletimg, (x + 16, y + 10))
def isCollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt(math.pow(enemyX - bulletX, 2) + math.pow(math.pow(enemyY - bulletY,2)))
if distance < 27:
return True
else:
return False
background = pygame.image.load('247.jpg')
enemyimg = pygame.image.load('space-invaders.png')
enemyX = random.randint(0, 800)
enemyY = random.randint(50, 150)
enemyX_change = 4
enemyY_change = 40
bulletimg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 450
bulletX_change = 480
bulletY_change = 10
bullet_state = "ready"
score = 0
# Game loop (Put most of code for game in this loop)
while running:
screen.fill((255, 0, 0))
# BAckground
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# if keystroke is pressed check whether is right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletX = playerX
fire_bullet(playerX, bulletY)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# RGB (screen.fill) = red green blue
# 5 = 5 + - 0.1 -> 5 = 5 - 0.1
# making so nothing can go out of bounds
enemyX += enemyX_change
if enemyX <= 0:
enemyX_change = 4
enemyY += enemyY_change
elif enemyX >= 736:
enemyX_change = -4
enemyY += enemyY_change
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Bullet movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
# Collison
collision = isCollision(enemyX,enemyY,bulletX,bulletY)
if collision:
bulletY = 480
bullet_state = "ready"
score +=1
player(playerX, playerY)
enemy(enemyX, enemyY)
pygame.display.update()
I believe you are trying to do this:
c = sqrt(pow(a,2) + pow(b,2))
But your code has one pow() too many. Happens to me too, when I make I make game sounds in my head, while coding (pew pew pew)
Try to remove one pow()
from
math.pow(math.pow(enemyY - bulletY,2))
to
math.pow(enemyY - bulletY,2)

I want to create multiple enemies but keep getting same error code

Blockquote I just started coding in this coronatime and I am running into a problem.
The error code is
enemy_icon = [i]
NameError: name 'i' is not defined
And i'm not sure why. I having been looking online but couldn't find any answers.
Hopefully this has given enough resources to be a good enough question.
import pygame
import random
import math
pygame.init()
# game over logo
game_over = pygame.image.load("game-over.png")
# create screen
screen = pygame.display.set_mode((1000, 600))
background = pygame.image.load("8717.jpg")
# Title + Logo
pygame.display.set_caption("Space Invader")
icon = pygame.image.load("chicken.png")
pygame.display.set_icon(icon)
# Player icon
player_icon = pygame.image.load("spaceship.png")
playerX = 400
playerY = 500
player_changeX = 0
player_changeY = 0
# multiple enemy players
enemy_icon = [i]
enemyX = [i]
enemyY = [i]
enemy_changeX = [i]
enemy_changeY = [i]
num_of_enemies = 2
for i in range(num_of_enemies):
enemy_icon.append(pygame.image.load("space-invaders.png"))
enemyX.append(random.randint(0, 936))
enemyY.append(random.randint(-100, -50))
enemy_changeX.append(random.randint(-2, 2))
enemy_changeY.append(random.randint(1, 2))
# bullet #ready you can't see bullet. fire you can
bullet = pygame.image.load("bullet.png")
bulletX = 0
bulletY = 0
bulletY_change = 2
bulletX_change = 0
bullet_state = "ready"
# score
score = 0
def player(x, y):
screen.blit(player_icon, (x, y))
def enemy(x, y, i):
screen.blit(enemy_icon[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bullet, (x + 16, y + 10))
def has_collided(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def collided(enemyX, enemyY, playerX, playerY):
distance2 = math.sqrt((math.pow(enemyX - playerX, 2)) + (math.pow(enemyY - playerY, 2)))
if distance2 < 27:
return True
else:
return False
# game loop
running = True
while running:
# background round colour RGB
screen.fill((0, 0, 0))
# background image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# If key pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player_changeX = -5
if event.key == pygame.K_RIGHT:
player_changeX = 5
if event.key == pygame.K_UP:
player_changeY = -5
if event.key == pygame.K_DOWN:
player_changeY = 5
# bullet shot
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletX = playerX
bulletY = playerY
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
player_changeX = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
player_changeY = 0
# If player reaches boarder
if playerX >= 936:
playerX = 20
if playerX <= 0:
playerX = 936
if playerY <= 0:
playerY = 0
if playerY >= 550:
playerY = 550
# enemy control
for i in range(num_of_enemies):
if enemyX[i] >= 936:
enemyX[i] = 20
if enemyX[i] <= 0:
enemyX[i] = 936
if enemyY[i] <= 0:
enemyY[i] = 0
if enemyY[i] >= 550:
enemyY[i] = random.randint(-100, -50)
# collision bullet and enemy
collision = has_collided(enemyX[i], enemyY[i], bulletX, bulletY)
if collision:
bulletY = playerY
bulletX = playerX
bullet_state = "ready"
score += 1
print(score)
enemyX[i] = random.randint(0, 936)
enemyY[i] = random.randint(-100, -50)
enemy_changeX[i] = random.randint(-2, 2)
enemy_changeY[i] = random.randint(1, 2)
collision2 = collided(enemyX[i], enemyY[i], playerX, playerY)
if collision2:
screen.blit(game_over, (400, 100))
score = 0
playerY = 400
playerX = 500
enemy(enemyX[i], enemyY[i], i)
# bullet movement
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
if bulletY <= 0:
bullet_state = "ready"
# collision enemy and player
# Player coordinates
playerX += player_changeX
playerY += player_changeY
# enemy change in coordinates
enemyX += enemy_changeX
enemyY += enemy_changeY
# bullet change in y
bulletY -= bulletY_change
# Results
player(playerX, playerY)
pygame.display.update()
The error seems pretty clear. You have this line in you code:
# multiple enemy players
enemy_icon = [i]
This line says that you are trying to create a variable enemy_icon and initialize it to a list with one element in it. That element is the variable i which has not been previously defined. I suspect that the i is a typo and that you are really trying to initialize with an empty list, in which case just remove the i like this:
# multiple enemy players
enemy_icon = []
The same is true for the 4 variables right after that.

How do I get the percentage of a colour in a screen in pygame?

I am new to pygame and trying to create a 'splatoon' like game, I got the basic elements ready but I don't know how to calculate the percentage of the screen. Do I individually scan each pixel using get_at or is there an easier method to calculate it?
Here is my code:
import pygame
import sys
black = (0,0,0)
white = (255, 255, 255)
silver = (192, 192, 192)
aqua = (0, 255,255)
x = 10
y =490
a = 490
b = 10
vel = 1
pygame.init()
FPS = 60
fpsClock = pygame.time.Clock()
win = pygame.display.set_mode((500,500))
time = pygame.time.get_ticks()
while True:
seconds = (pygame.time.get_ticks())/1000
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if seconds <= 10:
keys = pygame.key.get_pressed()
color = black
if keys[pygame.K_d] and x < 490:
x += vel
if keys[pygame.K_RIGHT] and a < 490:
a += vel
if keys[pygame.K_a] and x > 0:
x -= vel
if keys[pygame.K_LEFT] and a > 0:
a -= vel
if keys[pygame.K_w] and y > 0:
y -= vel
if keys[pygame.K_UP] and b > 0:
b -= vel
if keys[pygame.K_s] and y < 490:
y += vel
if keys[pygame.K_DOWN] and b < 490:
b += vel
if keys[pygame.K_e]:
pygame.draw.rect(win, aqua, (x-20,y-20,50,50))
if keys[pygame.K_SPACE]:
pygame.draw.rect(win, silver, (a-20,b-20,50,50))
if keys[pygame.K_p]:
win.fill((0,0,0))
pygame.draw.rect(win, aqua, (x,y,10,10))
pygame.draw.rect(win, silver, (a,b,10,10))
pygame.display.update()
fpsClock.tick(FPS)
else:
break
I think you can use a function like this, using pygame.Surface.get_at():
def get_percentage(color, step=1):
width, height = screen_size
total_number_of_pixels = width * height
number_of_pixels = 0
for x in range(0, width, step):
for y in range(0, height, step):
if screen.get_at((x, y)) == color:
number_of_pixels += 1
percentage = number_of_pixels / total_number_of_pixels * 00
return percentage
But because it can considerably slow down the code, you may store the percentage and call this function only when the percentage is updated (for example if a player attacks).
And you can change the step var in the code above to get the percentage more roughly (and quicker).