So I made a Nibbles/Snake remake by following the pygame tutorials on thenewboston youtube channel by sentdex. I made a lot of minor aesthetic changes, but overall, it's the same game. Here's the code for that:
import pygame
import time
import random
pygame.init()
# A few extra colors just for testing purposes.
WHITE = (pygame.Color("white"))
BLACK = ( 0, 0, 0)
RED = (245, 0, 0)
TURQ = (pygame.Color("turquoise"))
GREEN = ( 0, 155, 0)
GREY = ( 90, 90, 90)
SCREEN = (800, 600)
gameDisplay = pygame.display.set_mode(SCREEN)
#Set the window title and picture
pygame.display.set_caption('Slither')
ICON = pygame.image.load("apple10pix.png")
pygame.display.set_icon(ICON)
CLOCK = pygame.time.Clock()
FPS = 20
FONT = pygame.font.SysFont("arial", 25)
SNAKE_SIZE = 10 # The width of the snake in pixels, not the length. Start length is defined in the game loop.
APPLE_SIZE = 10
TINY_FONT = pygame.font.SysFont("candara", 15)
SMALL_FONT = pygame.font.SysFont("candara", 25)
MED_FONT = pygame.font.SysFont("candara", 50)
LARGE_FONT = pygame.font.SysFont("krabbypatty", 75)
HUGE_FONT = pygame.font.SysFont("krabbypatty", 150)
IMG = pygame.image.load("snakehead.png")
APPLE_IMG = pygame.image.load("apple10pix.png")
DIRECTION = "up"
def pause():
paused = True
message_to_screen("Paused",
BLACK,
Y_DISPLACE = -100,
size = "huge")
message_to_screen("Press C to continue or Q to quit.",
BLACK,
Y_DISPLACE = 25)
pygame.display.update()
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_c, pygame.K_p):
paused = False
elif event.key in(pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
CLOCK.tick(5)
def score(score):
text = SMALL_FONT.render("Score: " + str(score), True, BLACK)
gameDisplay.blit(text, [0, 0])
pygame.display.update
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 in (pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
gameDisplay.fill(WHITE)
message_to_screen("Welcome to",
GREEN,
Y_DISPLACE = -170,
size = "large")
message_to_screen("Block Worm",
GREEN,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("The objective of the game is to eat apples.",
BLACK,
Y_DISPLACE = 36,
size = "tiny")
message_to_screen("The more apples you eat the longer you get.",
BLACK,
Y_DISPLACE = 68,
size = "tiny")
message_to_screen("If you run into yourself or the edges, you die.",
BLACK,
Y_DISPLACE = 100,
size = "tiny")
message_to_screen("Press C to play or Q to quit.",
GREY,
Y_DISPLACE = 210,)
pygame.display.update()
CLOCK.tick(FPS)
def snake(SNAKE_SIZE, SNAKE_LIST):
if DIRECTION == "right":
HEAD = pygame.transform.rotate(IMG, 270)
elif DIRECTION == "left":
HEAD = pygame.transform.rotate(IMG, 90)
elif DIRECTION == "down":
HEAD = pygame.transform.rotate(IMG, 180)
else:
DIRECTION == "up"
HEAD = IMG
gameDisplay.blit(HEAD, (SNAKE_LIST[-1][0], SNAKE_LIST[-1][1]))
for XnY in SNAKE_LIST[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], SNAKE_SIZE, SNAKE_SIZE])
pygame.display.update
def text_objects(text, color, size):
if size == "tiny":
TEXT_SURFACE = TINY_FONT.render(text, True, color)
elif size == "small":
TEXT_SURFACE = SMALL_FONT.render(text, True, color)
elif size == "medium":
TEXT_SURFACE = MED_FONT.render(text, True, color)
elif size == "large":
TEXT_SURFACE = LARGE_FONT.render(text, True, color)
elif size == "huge":
TEXT_SURFACE = HUGE_FONT.render(text, True, color)
return TEXT_SURFACE, TEXT_SURFACE.get_rect()
def message_to_screen(msg, color, Y_DISPLACE = 0, size = "small"):
TEXT_SURF, TEXT_RECT = text_objects(msg, color, size)
TEXT_RECT.center = (SCREEN[0] / 2), (SCREEN[1] / 2) + Y_DISPLACE
gameDisplay.blit(TEXT_SURF, TEXT_RECT)
def randAppleGen():
randAppleX = random.randrange(0, (SCREEN[0] - APPLE_SIZE), APPLE_SIZE)
randAppleY = random.randrange(0, (SCREEN[1]- APPLE_SIZE), APPLE_SIZE)
return randAppleX, randAppleY
def gameLoop():
global DIRECTION
gameExit = False
gameOver = False
SNAKE_LIST = [] # Where the snake head has been.
SNAKE_LENGTH = 1 #Length that the snake starts.
lead_x = (SCREEN[0] / 2)
lead_y = (SCREEN[1] - (SCREEN[1] / 5))
move_speed = 10
move_speed_neg = move_speed * -1
lead_x_change = 0
lead_y_change = -move_speed
randAppleX, randAppleY = randAppleGen()
while not gameExit:
if gameOver == True:
message_to_screen("Game over",
RED,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("Press C to play again or Q to quit.",
BLACK,
Y_DISPLACE = 50,
size = "small")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
elif event.key == pygame.K_c:
gameLoop()
# Handles arrow key and WASD events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
lead_x_change = move_speed_neg
lead_y_change = 0
DIRECTION = "left"
elif event.key in (pygame.K_RIGHT, pygame.K_d):
lead_x_change = move_speed
lead_y_change = 0
DIRECTION = "right"
elif event.key in (pygame.K_UP, pygame.K_w):
lead_y_change = move_speed_neg
lead_x_change = 0
DIRECTION = "up"
elif event.key in (pygame.K_DOWN, pygame.K_s):
lead_y_change = move_speed
lead_x_change = 0
DIRECTION = "down"
elif event.key in (pygame.K_p, pygame.K_ESCAPE):
pause()
# If the snake goes beyond the screen borders the game will end.
if lead_x >= SCREEN[0] or lead_x < 0 or lead_y >= SCREEN[1] or lead_y <0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(WHITE)
# Draw the apple on screen
APPLE_RECT = pygame.draw.rect(gameDisplay, RED, [randAppleX, randAppleY, APPLE_SIZE, APPLE_SIZE])
if APPLE_RECT in SNAKE_LIST:
APPLE_RECT #If the apple appears anywhere "under" the snake, it will immediately respawn elsewhere.
# Draw the snake on screen
SNAKE_HEAD = []
SNAKE_HEAD.append(lead_x)
SNAKE_HEAD.append(lead_y)
SNAKE_LIST.append(SNAKE_HEAD)
# If you hit yourself, game over.
if SNAKE_HEAD in SNAKE_LIST[:-1]:
gameOver = True
if len(SNAKE_LIST) > SNAKE_LENGTH:
del SNAKE_LIST[0]
snake(SNAKE_SIZE, SNAKE_LIST)
score(SNAKE_LENGTH - 1)
# If the snake eats the apple
if APPLE_RECT.collidepoint(lead_x, lead_y) == True:
randAppleX, randAppleY = randAppleGen()
SNAKE_LENGTH += 1
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
It's a pretty solid little game. But I want to make the snake and apple into classes so that I can later spawn other types of snakes (perhaps basic AI?) and other types of apples (maybe ones that are green that grow your snake 3+). I made an attempt at doing this myself with a snake class:
import pygame
import time
import random
pygame.init()
WHITE = (pygame.Color("white"))
BLACK = ( 0, 0, 0)
RED = (245, 0, 0)
TURQ = (pygame.Color("turquoise"))
GREEN = ( 0, 155, 0)
GREY = ( 90, 90, 90)
SCREEN = (800, 600)
gameDisplay = pygame.display.set_mode(SCREEN)
#Set the window title and picture
pygame.display.set_caption('Block Worm')
ICON = pygame.image.load("apple10pix.png")
pygame.display.set_icon(ICON)
CLOCK = pygame.time.Clock()
FPS = 20
FONT = pygame.font.SysFont("arial", 25)
APPLE_SIZE = 10
TINY_FONT = pygame.font.SysFont("candara", 15)
SMALL_FONT = pygame.font.SysFont("candara", 25)
MED_FONT = pygame.font.SysFont("candara", 50)
LARGE_FONT = pygame.font.SysFont("krabbypatty", 75)
HUGE_FONT = pygame.font.SysFont("krabbypatty", 150)
IMG = pygame.image.load("snakehead.png")
APPLE_IMG = pygame.image.load("apple10pix.png")
def pause():
paused = True
message_to_screen("Paused",
BLACK,
Y_DISPLACE = -100,
size = "huge")
message_to_screen("Press C to continue or Q to quit.",
BLACK,
Y_DISPLACE = 25)
pygame.display.update()
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_c, pygame.K_p):
paused = False
elif event.key in(pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
CLOCK.tick(5)
def score(score):
text = SMALL_FONT.render("Score: " + str(score), True, BLACK)
gameDisplay.blit(text, [5, 5])
pygame.display.update
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 in (pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
gameDisplay.fill(WHITE)
message_to_screen("Welcome to",
GREEN,
Y_DISPLACE = -170,
size = "large")
message_to_screen("Block Worm",
GREEN,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("The objective of the game is to eat apples.",
BLACK,
Y_DISPLACE = 36,
size = "tiny")
message_to_screen("The more apples you eat the longer you get.",
BLACK,
Y_DISPLACE = 68,
size = "tiny")
message_to_screen("If you run into yourself or the edges, you die.",
BLACK,
Y_DISPLACE = 100,
size = "tiny")
message_to_screen("Press C to play or Q to quit.",
GREY,
Y_DISPLACE = 210,)
pygame.display.update()
CLOCK.tick(FPS)
def text_objects(text, color, size):
if size == "tiny":
TEXT_SURFACE = TINY_FONT.render(text, True, color)
elif size == "small":
TEXT_SURFACE = SMALL_FONT.render(text, True, color)
elif size == "medium":
TEXT_SURFACE = MED_FONT.render(text, True, color)
elif size == "large":
TEXT_SURFACE = LARGE_FONT.render(text, True, color)
elif size == "huge":
TEXT_SURFACE = HUGE_FONT.render(text, True, color)
return TEXT_SURFACE, TEXT_SURFACE.get_rect()
def message_to_screen(msg, color, Y_DISPLACE = 0, size = "small"):
TEXT_SURF, TEXT_RECT = text_objects(msg, color, size)
TEXT_RECT.center = (SCREEN[0] / 2), (SCREEN[1] / 2) + Y_DISPLACE
gameDisplay.blit(TEXT_SURF, TEXT_RECT)
def randAppleGen():
randAppleX = random.randrange(0, (SCREEN[0] - APPLE_SIZE), APPLE_SIZE)
randAppleY = random.randrange(0, (SCREEN[1]- APPLE_SIZE), APPLE_SIZE)
return randAppleX, randAppleY
class Snake:
def __init__(self, image, x, y, direction, speed):
self.image = image
self.rect = self.image.get_rect()
self.width = self.rect.width
self.rect.x = x
self.rect.y = y
self.direction = direction
self.speed = speed
self.trail = [] # Where the snake head has been.
self.length = 1 # Length that the snake starts.
def snake_direction_change(direction):
if direction == "right":
self.image = pygame.transform.rotate(self.image, 270)
elif direction == "left":
self.image = pygame.transform.rotate(self.image, 90)
elif direction == "down":
self.image = pygame.transform.rotate(self.image, 180)
else:
direction == "up"
pygame.display.update
def snake_grow(x, y, z):
gameDisplay.blit(self.image, (self.trail[-1][0], self.trail[-1][1]))
for XnY in snake.trail[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], self.width, self.width])
pygame.display.update
def gameLoop():
gameExit = False
gameOver = False
lead_x_change = 0
lead_y_change = -snake.speed
randAppleX, randAppleY = randAppleGen()
gameDisplay.fill(WHITE)
snake = Snake(IMG,
x = (SCREEN[0] / 2),
y =(SCREEN[1] - (SCREEN[1] / 5)),
direction = "up",
speed = 10,)
while not gameExit:
if gameOver == True:
message_to_screen("Game over",
RED,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("Press C to play again or Q to quit.",
BLACK,
Y_DISPLACE = 50,
size = "small")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
elif event.key == pygame.K_c:
gameLoop()
# Handles arrow key and WASD events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
lead_x_change = snake.speed * -1
lead_y_change = 0
snake.snake_direction_change("left")
elif event.key in (pygame.K_RIGHT, pygame.K_d):
lead_x_change = snake.speed
lead_y_change = 0
snake.snake_direction_change("right")
elif event.key in (pygame.K_UP, pygame.K_w):
lead_y_change = snake.speed * -1
lead_x_change = 0
snake.snake_direction_change("up")
elif event.key in (pygame.K_DOWN, pygame.K_s):
lead_y_change = snake.speed
lead_x_change = 0
snake.snake_direction_change("down")
elif event.key in (pygame.K_p, pygame.K_ESCAPE):
pause()
# If the snake goes beyond the screen borders the game will end.
if snake.rect.x >= SCREEN[0] or snake.rect.x < 0 or snake.rect.y >= SCREEN[1] or snake.rect.y <0:
gameOver = True
snake.rect.x += lead_x_change
snake.rect.y += lead_y_change
gameDisplay.fill(WHITE)
# Draw the apple on screen
APPLE_RECT = pygame.draw.rect(gameDisplay, RED, [randAppleX, randAppleY, APPLE_SIZE, APPLE_SIZE])
if APPLE_RECT in snake.trail:
APPLE_RECT #If the apple appears anywhere "under" the snake, it will immediately respawn elsewhere.
# Draw the snake on screen
SNAKE_HEAD = []
SNAKE_HEAD.append(snake.rect.x)
SNAKE_HEAD.append(snake.rect.y)
snake.trail.append(SNAKE_HEAD)
# If you hit yourself, game over.
if SNAKE_HEAD in snake.trail[:-1]:
gameOver = True
if len(snake.trail) > snake.length:
del snake.trail[0]
snake.snake_grow(snake.width, snake.trail)
score(snake.length - 1)
# If the snake eats the apple
if APPLE_RECT.collidepoint(snake.rect.x, snake.rect.y) == True:
randAppleX, randAppleY = randAppleGen()
snake.length += 1
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
This version isn't nearly as cute. In fact, it doesn't work at all. My understanding off classes and functions is elementary at best. A lot of code from the original was changed or completely deleted in my trial and error processes. I spent several hours trying to make this work to no avail. My main goal was to produce a Snake and Apple class that can be reused for later variations of both of them.
So, I've come to you fine folks to assist me! I have two main questions:
1) What do I have to do to make this work properly?
2) How can I clean up my code to make it easier to read and more efficient overall?
"A lot of code from the original was changed or completely deleted in my trial and error processes"
Bingo. You just found the crux of your issue. Software development should be a controlled, thought out process - not trial and error. You need to proceed thoughtfully, and purposefully.
What you are trying to do (or should be trying to do) when introducing classes is refactoring your code.
You should start again with the original, working copy, and proceed to change as little as possible when you introduce a Snake class. The first step would be to simply convert your snake function into a class, and substitute that in. Below is where you might start: replace your snake method with this Snake class, and change the line where you use it
class Snake:
def __init__(self, SNAKE_SIZE, SNAKE_LIST):
if DIRECTION == "right":
HEAD = pygame.transform.rotate(IMG, 270)
elif DIRECTION == "left":
HEAD = pygame.transform.rotate(IMG, 90)
elif DIRECTION == "down":
HEAD = pygame.transform.rotate(IMG, 180)
else:
DIRECTION == "up" # note: this line does nothing
HEAD = IMG
gameDisplay.blit(HEAD, (SNAKE_LIST[-1][0], SNAKE_LIST[-1][1]))
for XnY in SNAKE_LIST[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], SNAKE_SIZE, SNAKE_SIZE])
pygame.display.update # note: this likely does nothing - I think you want to call it (pygame.display.update())
and change this:
snake(SNAKE_SIZE, SNAKE_LIST)
into:
snake = Snake(SNAKE_SIZE, SNAKE_LIST)
Now at this point, if your code worked before, it should still work (assuming I haven't done anything silly). Is this a good example of a class? No. My Snake class is terrible. Your attempt at a snake class is far, far better. Doing things this way gives you a starting point though. You can then proceed to do things like:
assign the parameters to instance variables
move pretty much all the code into another method
start removing the module-level variables it has access to, and pass in additional arguments
etc.
An alternate way to refactor this module might be to change each of your functions so that none of them rely on module level variables. Pass every variable that each function needs into that function.
The main point I'd like to leave you with is that it is far easier to make working software by writing/changing just a little at a time. Make sure it still works before changing something else. Work on small bits of code & test each change so you'll know exactly where and how your program broke.
Related
i'm learning how to make a snake game in pygame from the thenewboston tutorials on youtube and make it my own.
There's a problem in the game where the 'apple' spawns behind the snake's position which is something that i don't want.
I'm sure i have to state that apple position can't be the same as the snake but can't figure it out how:
# Snake eating the apple
if snake_x_pos == apple_x and snake_y_pos == apple_y:
pygame.mixer.Sound.play(eat_apple_sound)
snakelength += 1
apple_x = random.randrange(box_size, field_x, box_size)
apple_y = random.randrange(box_size, field_y, box_size)
Full code:
import pygame
import random
pygame.init()
# Game Title
pygame.display.set_caption("Original Snake")
# Game display 4:3
screen_w = 640
screen_h = 480
surface = pygame.display.set_mode((screen_w, screen_h))
bg_color = (170, 204, 102)
box_color = (43, 51, 26)
box_size = screen_h / 24
# PLAYING FIELD
field_x = screen_w - (box_size*2)
field_y = screen_h - (box_size*2)
# Frames per Second
clock = pygame.time.Clock()
FPS = 8
# Font settings
kongtext = "C:\Windows\Fonts\kongtext.ttf"
verysmall = pygame.font.Font(kongtext, 12)
small = pygame.font.Font(kongtext, 15)
medium = pygame.font.Font(kongtext, 30)
large = pygame.font.Font(kongtext, 60)
verylarge = pygame.font.Font(kongtext, 80)
# sound settings
game_over_sound = pygame.mixer.Sound("sounds/game_over.wav")
eat_apple_sound = pygame.mixer.Sound("sounds/eat_apple.wav")
def snake(box_size, snakelist):
for XnY in snakelist:
pygame.draw.rect(surface, box_color, [XnY[0], XnY[1], box_size, box_size])
# Text Object
def text_objects(text, color, size):
if size == "small":
text_surface = small.render(text, True, color)
elif size == "verysmall":
text_surface = verysmall.render(text, True, color)
elif size == "medium":
text_surface = medium.render(text, True, color)
elif size == "large":
text_surface = large.render(text, True, color)
elif size == "verylarge":
text_surface = large.render(text, True, color)
return text_surface, text_surface.get_rect()
# Start screen
def start_screen():
intro = True
while intro:
# IF USER CLICKS ON THE X
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
# Start Game
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
intro = False
surface.fill(bg_color)
# SCREEN FIELD WITH BORDER 3
pygame.draw.rect(surface, box_color, [16, 16, screen_w-33, screen_h-33-box_size], 3)
# START SCREEN
message_to_screen("SNAKE", box_color, -25, size="verylarge")
message_to_screen("PRESS SPACE TO PLAY", box_color, 35, size="verysmall")
pygame.display.update()
clock.tick(15)
# Message to screen
def message_to_screen(msg, color, text_y_pos=0, size="small"):
text_surf, text_rect = text_objects(msg, color, size)
text_rect.center = (screen_w / 2), (screen_h / 2)+text_y_pos
surface.blit(text_surf, text_rect)
def score(score):
text = small.render("Score: "+str((score*10)-20), True, box_color)
surface.blit(text, [box_size, screen_h-box_size-7])
def game_loop():
direction = "right"
quit_game = False
game_over = False
# Box settings
box_color = (43, 51, 26)
# Defining snake position
snakelist = []
snakelength = 3
snake_x_pos = screen_w / 2
snake_y_pos= screen_h / 2
snake_x_chg = box_size
snake_y_chg = 0
# Randomizing the apple position
apple_x = random.randrange(box_size, field_x, box_size)
apple_y = random.randrange(box_size, field_y, box_size)
while not quit_game:
# Game Over
while game_over:
surface.fill(bg_color)
message_to_screen("GAME OVER", box_color, -10, size="large")
message_to_screen("PRESS SPACE TO PLAY AGAIN OR Q TO QUIT", box_color, 50, size="small")
# PLAYING FIELD
pygame.draw.rect(surface, box_color,
[16, 16, screen_w - 33, screen_h - 33 - box_size], 3)
# SCORE
score(snakelength - 1)
pygame.display.update()
# Closing Game Over screen with X
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_game = True
game_over = False
# Closing Game Over screen with Q or Restart with space
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
quit_game = True
game_over = False
if event.key == pygame.K_SPACE:
direction = "right"
game_loop()
for event in pygame.event.get():
# Closing the game
if event.type == pygame.QUIT:
quit_game = True
game_over = False
# Controlling the snake
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_LEFT) and direction != "right":
snake_x_chg = -box_size
snake_y_chg = 0
direction = "left"
elif (event.key == pygame.K_RIGHT) and direction != "left":
snake_x_chg = box_size
snake_y_chg = 0
direction = "right"
elif (event.key == pygame.K_UP) and direction != "down":
snake_y_chg = -box_size
snake_x_chg = 0
direction = "up"
elif (event.key == pygame.K_DOWN) and direction != "up":
snake_y_chg = box_size
snake_x_chg = 0
direction = "down"
# Screen boundaries
if snake_x_pos > (field_x) or snake_x_pos < box_size or snake_y_pos > (field_y) or snake_y_pos < box_size:
pygame.mixer.Sound.play(game_over_sound)
game_over = True
# Snake new position
snake_x_pos += snake_x_chg
snake_y_pos += snake_y_chg
# Clear screen
surface.fill(bg_color)
# Draw and update
pygame.draw.rect(surface, box_color, [apple_x, apple_y, box_size, box_size])
snakehead = []
snakehead.append(snake_x_pos)
snakehead.append(snake_y_pos)
snakelist.append(snakehead)
if len(snakelist) > snakelength:
del snakelist[0]
for snaketail in snakelist[:-1]:
if snaketail == snakehead:
pygame.mixer.Sound.play(game_over_sound)
game_over = True
snake(box_size, snakelist)
# PLAYING FIELD
pygame.draw.rect(surface, box_color, [16, 16, screen_w-33, screen_h-33-box_size], 3)
# SCORE
score(snakelength-1)
pygame.display.update()
# Snake eating the apple
if snake_x_pos == apple_x and snake_y_pos == apple_y:
pygame.mixer.Sound.play(eat_apple_sound)
snakelength += 1
apple_x = random.randrange(box_size, field_x, box_size)
apple_y = random.randrange(box_size, field_y, box_size)
clock.tick(FPS)
pygame.quit()
quit()
start_screen()
game_loop()
Create a rectangle at the new random "apple" position:
apple_rect = pygame.Rect(apple_x, apple_y, box_size, box_size)
Check for each position (pos) in snakelist if the "apple" rectangle collides with the part of the snake by pygame.Rect.collidepoint:
apple_rect.collidepoint(*pos)
Use any() to check if the apple "collides" with any part of the snake:
any(apple_rect.collidepoint(*pos) for pos in snakelist)
If the apple "collides" with the snake the create a new random point and repeat the process:
# Snake eating the apple
if snake_x_pos == apple_x and snake_y_pos == apple_y:
pygame.mixer.Sound.play(eat_apple_sound)
snakelength += 1
while True:
apple_x, apple_y = (random.randrange(box_size, fs, box_size) for fs in (field_x, field_y))
apple_rect = pygame.Rect(apple_x, apple_y, box_size, box_size)
if not any(apple_rect.collidepoint(*pos) for pos in snakelist):
break
The snake seems to be a list of "boxes", held in the list snakelist. So to ensure the apple does not appear inside the parts of the snake, the generated random point needs to be created outside the snake's boxes.
A simple (but inefficient) way to do this is to keep generating random points, and testing them for collision.
collision = True
while collision == True:
# Randomizing the apple position
apple_x = random.randrange(box_size, field_x, box_size)
apple_y = random.randrange(box_size, field_y, box_size)
# Check apple not within snake
collision = False
for XnY in snakelist:
part = pygame.Rect( XnY[0], XnY[1], box_size, box_size )
# is the apple-point within the snake part?
if part.collidepoint( apple_x, apple_y ) == True:
collision = True
break # any collision is final, stop checking
It would be worth thinking of a more efficient way to move the point away from the snake instead of looping over-and-over. Picking a random point may simply pick the same point, or a near-by bad point again. Also the longer the snake gets, the worse this looping will be as there are less "non-snake" points on the screen. I guess there's some known safe-spots, like the space the snake just moved out of, but these are obviously not random.
this is my first game I have created using pygame, it's basically snake.
Please do not mind my hideous comments.
## William's Snake Game
import pygame
import time
import random
pygame.init()
##Global variables
# Colours
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 155, 0)
bground = (204, 204, 0)
# Display vars.
display_width = 800
display_height = 600
# Variables
gameDisplay = pygame.display.set_mode((display_width, display_height)) ##resolution, note that this is a tuple.
pygame.display.set_caption("Snake VS Apple") # Title at the top of the screen
icon = pygame.image.load('logoapple32x32.png') # Loads the icon for the top left
pygame.display.set_icon(icon) # Sets the icon for the top left
snakeHeadImg = pygame.image.load("snakeHead.png") # Loads the image for the snake head
appleImg = pygame.image.load("apple20x20.png") # Loads the image for the apple
appleThickness = 20 # Defines how thick apple will be. Note to self: This is changable
clock = pygame.time.Clock() # Starts clocking the game, used later for FPS
blockSize = 20 # Defines how big the snake will be. Changing this will mess up collision detection.
FPS = 15 # Frames per second. Called at the bottom of script
smallfont = pygame.font.SysFont("arial", 25) ## format: ("font", fontsize)
medfont = pygame.font.SysFont("arial", 40) ##
largefont = pygame.font.SysFont("arial", 80) ##
direction = "right" # Starting direction of snake, used in main gameLoop
##
def pauseGame():
gameisPaused = True
while gameisPaused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
gameisPaused = False
elif event.key == pygame.K_q:
pygame.quit()
quit()
gameDisplay.fill(white)
message_to_screen("Paused",
black,
-100,
size="large")
message_to_screen("Press ESC to continue or Q to quit.",
black,
25,
size="small")
pygame.display.update()
clock.tick(5)
def text_objects(text, color, size): # Function to render text
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()
def message_to_screen(msg, color, y_displace=0, size="medium"): # Function to blit (draw) text to surface
textSurf, textRect = text_objects(msg, color, size)
textRect.center = (display_width / 2), (display_height / 2) + y_displace
gameDisplay.blit(textSurf, textRect)
##
def score(score):
text = smallfont.render("Score: " + str(score), True, black)
gameDisplay.blit(text, [0, 0])
def randAppleGen(): # Function to generate random apples
randAppleX = round(
random.randrange(0, display_width - appleThickness)) # /10.0)*10.0 ##Create another rand X value for new apple
randAppleY = round(
random.randrange(0, display_height - appleThickness)) # /10.0)*10.0 ##Create another rand Y value for new apple
return randAppleX, randAppleY
def gameIntro(): # Function for game menu.
intro = True
while intro: # Event handling during menu
for eachEvent in pygame.event.get():
if eachEvent.type == pygame.QUIT:
pygame.quit()
quit()
if eachEvent.type == pygame.KEYDOWN:
if eachEvent.key == pygame.K_c:
gameLoop()
if eachEvent.key == pygame.K_q:
pygame.quit()
quit()
# Text displayed in menu
gameDisplay.fill(white)
message_to_screen("Welcome to Slither",
green,
-90,
"large")
message_to_screen("The more apples you eat, the longer you are",
black,
100)
message_to_screen("The objective of the game is to eat red apples",
black,
0,
"small")
message_to_screen("If you run into yourself, or the edges, you die!",
black,
30,
"small")
message_to_screen("Press C to play or Q to quit.",
black,
180)
pygame.display.update()
clock.tick(500)
def snake(blockSize, snakeList): # Function to draw snake
if direction == "right":
head = pygame.transform.rotate(snakeHeadImg,
270) # In gameLoop, right,left,up,down are used to change direction of snakeHead
elif direction == "left":
head = pygame.transform.rotate(snakeHeadImg, 90)
elif direction == "up":
head = snakeHeadImg
elif direction == "down":
head = pygame.transform.rotate(snakeHeadImg, 180)
gameDisplay.blit(head, (snakeList[-1][0], snakeList[-1][1])) ##???
for XandY in snakeList[:-1]:
pygame.draw.rect(gameDisplay, green,
[XandY[0], XandY[1], blockSize, blockSize]) ##width height, width height, drawing
##Main Game Loop
def gameLoop():
global direction ## Make direction a global var. Important
# Local variables
gameExit = False
gameOver = False
lead_x = display_width / 2
lead_y = display_height / 2
lead_x_change = 10
lead_y_change = 0
snakeList = []
snakeLength = 3
randAppleX, randAppleY = randAppleGen() # Generate apples. Calls randAppleGen()
# Main Game Loop ##eventHandler
while not gameExit:
snakeHead = [] # Creates list snakeHead
snakeHead.append(lead_x) # Appends snakeHead x value to list
snakeHead.append(lead_y) # Appends snakeHead y value to list
snakeList.append(snakeHead) # Appends coordinates of snakeHead x,y to list
while gameOver == True: # Handles game over
gameDisplay.fill(white)
message_to_screen("Game over",
red,
-50,
size="large")
message_to_screen("Press C to play again or Q to quit",
black,
50,
size="medium")
pygame.display.update()
for event in pygame.event.get(): # eventHandler for loss screen
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
direction = "right"
gameLoop()
for event in pygame.event.get(): # eventHandler for keyboard events during game
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a: # Each of these handles either arrow keys or WASD key events.
lead_x_change = -blockSize
lead_y_change = 0
direction = "left"
elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
lead_x_change = blockSize
lead_y_change = 0
direction = "right"
elif event.key == pygame.K_UP or event.key == pygame.K_w:
lead_y_change = -blockSize
lead_x_change = 0
direction = "up"
elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
lead_y_change = blockSize
lead_x_change = 0
direction = "down"
elif event.key == pygame.K_ESCAPE:
pauseGame()
# Checks if user has hit screen boundaries.
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0: # If user hits display boundaries
gameOver = True # They lose
lead_x += lead_x_change # Ensures continous movement of the snake
lead_y += lead_y_change
# Drawing
gameDisplay.fill(bground) # Fills the display background with predefined bground colour (defined at the top)
gameDisplay.blit(appleImg,
(randAppleX, randAppleY)) ##Draws the apple using the appleImg, at random coordinates.
if len(
snakeList) > snakeLength: # If the length of the list of snake body coordinates is greater than the length
del snakeList[0] # Delete the oldest value in the list (as the snake is constantly moving)
for eachSegment in snakeList[:-1]: # For each coordinate in snakeList
if eachSegment == snakeHead: # If the segment touches the snakeHead
## gameDisplay.fill(bground)
## snake(blockSize, snakeList)
##
## pygame.display.update
time.sleep(0.3)
gameOver = True # Game over
snake(blockSize, snakeList) ##Creates snake using function snake
score(snakeLength - 3) # Displays score (it minuses 3 because the snake starts at 3)
pygame.display.update() ##Updates to screen
## COLLISION DETECTION
if lead_x + blockSize > randAppleX and lead_x < randAppleX + appleThickness:
if lead_y + blockSize > randAppleY and lead_y < randAppleY + appleThickness:
randAppleX, randAppleY = randAppleGen()
snakeLength += 1
clock.tick(FPS)
pygame.quit()
quit()
##update screen
##
gameIntro()
gameLoop()
##Code goes above.
I have a problem where if my snake is going right, and then it turns left, my snake will crash onto itself and the game will end.
I want to design this so when my snake is going right, it cannot simply turn left, crash into itself and end the game. So when it turns right, it can only turn up, down, or keep going right. So simply, I want to make it so it cannot run backwards into itself.
I have tried coding this in myself, and I have tried many methods but nothing has worked.
Please help!!
Without altering your code too much (and without testing), an easy way to get what you want is to add another condition to your key checks. If you alter the relevant code section as follows, all should be fine:
for event in pygame.event.get(): # eventHandler for keyboard events during game
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if (event.key == pygame.K_LEFT or event.key == pygame.K_a) and direction != "right": # Each of these handles either arrow keys or WASD key events.
lead_x_change = -blockSize
lead_y_change = 0
direction = "left"
elif (event.key == pygame.K_RIGHT or event.key == pygame.K_d) and direction != "left":
lead_x_change = blockSize
lead_y_change = 0
direction = "right"
elif (event.key == pygame.K_UP or event.key == pygame.K_w) and direction != "down":
lead_y_change = -blockSize
lead_x_change = 0
direction = "up"
elif (event.key == pygame.K_DOWN or event.key == pygame.K_s) and direction != "up":
lead_y_change = blockSize
lead_x_change = 0
direction = "down"
elif event.key == pygame.K_ESCAPE:
pauseGame()
Mind the parentheses around the or'd key checks!
This is a snake remake. My goal here was to make the apple respawn randomly after the snake collided with it. For some reason the collide_rect function seems to think they are continuously colliding at all times after I start the game.
Any other tips to help clean this mess up are also welcome:
import pygame
import time
import random
pygame.init()
WHITE = (pygame.Color("white"))
BLACK = ( 0, 0, 0)
RED = (245, 0, 0)
TURQ = (pygame.Color("turquoise"))
GREEN = ( 0, 155, 0)
GREY = ( 90, 90, 90)
SCREEN = (800, 600)
gameDisplay = pygame.display.set_mode(SCREEN)
#Set the window title and picture
pygame.display.set_caption('Block Worm')
ICON = pygame.image.load("apple10pix.png")
pygame.display.set_icon(ICON)
CLOCK = pygame.time.Clock()
FPS = 20
FONT = pygame.font.SysFont("arial", 25)
APPLE_SIZE = 10
TINY_FONT = pygame.font.SysFont("candara", 15)
SMALL_FONT = pygame.font.SysFont("candara", 25)
MED_FONT = pygame.font.SysFont("candara", 50)
LARGE_FONT = pygame.font.SysFont("krabbypatty", 75)
HUGE_FONT = pygame.font.SysFont("krabbypatty", 150)
IMG = pygame.image.load("snakehead.png")
APPLE_IMG = pygame.image.load("apple10pix.png")
DIRECTION = "up"
def pause():
paused = True
message_to_screen("Paused",
BLACK,
Y_DISPLACE = -100,
size = "huge")
message_to_screen("Press C to continue or Q to quit.",
BLACK,
Y_DISPLACE = 25)
pygame.display.update()
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_c, pygame.K_p):
paused = False
elif event.key in(pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
CLOCK.tick(5)
def score(score):
text = SMALL_FONT.render("Score: " + str(score), True, BLACK)
gameDisplay.blit(text, [0, 0])
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 in (pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
gameDisplay.fill(WHITE)
message_to_screen("Welcome to",
GREEN,
Y_DISPLACE = -170,
size = "large")
message_to_screen("Block Worm",
GREEN,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("The objective of the game is to eat apples.",
BLACK,
Y_DISPLACE = 36,
size = "tiny")
message_to_screen("The more apples you eat the longer you get.",
BLACK,
Y_DISPLACE = 68,
size = "tiny")
message_to_screen("If you run into yourself or the edges, you die.",
BLACK,
Y_DISPLACE = 100,
size = "tiny")
message_to_screen("Press C to play or Q to quit.",
GREY,
Y_DISPLACE = 210,)
pygame.display.update()
CLOCK.tick(FPS)
def text_objects(text, color, size):
if size == "tiny":
TEXT_SURFACE = TINY_FONT.render(text, True, color)
elif size == "small":
TEXT_SURFACE = SMALL_FONT.render(text, True, color)
elif size == "medium":
TEXT_SURFACE = MED_FONT.render(text, True, color)
elif size == "large":
TEXT_SURFACE = LARGE_FONT.render(text, True, color)
elif size == "huge":
TEXT_SURFACE = HUGE_FONT.render(text, True, color)
return TEXT_SURFACE, TEXT_SURFACE.get_rect()
def message_to_screen(msg, color, Y_DISPLACE = 0, size = "small"):
TEXT_SURF, TEXT_RECT = text_objects(msg, color, size)
TEXT_RECT.center = (SCREEN[0] / 2), (SCREEN[1] / 2) + Y_DISPLACE
gameDisplay.blit(TEXT_SURF, TEXT_RECT)
class Snake(pygame.sprite.Sprite):
def __init__(self, image, size, trail, start_size):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.size = size
self.trail = trail
self.start_size = start_size
self.rect = self.image.get_rect()
if DIRECTION == "right":
HEAD = pygame.transform.rotate(self.image, 270)
elif DIRECTION == "left":
HEAD = pygame.transform.rotate(self.image, 90)
elif DIRECTION == "down":
HEAD = pygame.transform.rotate(self.image, 180)
else:
HEAD = image
gameDisplay.blit(HEAD, (self.trail[-1][0], self.trail[-1][1]))
for XnY in self.trail[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], self.size, self.size])
class Apple(pygame.sprite.Sprite):
def __init__(self, image):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.size = self.rect.width
gameDisplay.blit(self.image, (100, 100))
def random_location(self):
self.rect.x = random.randrange(0, (SCREEN[0] - 10), 10)
self.rect.y = random.randrange(0, (SCREEN[1]- 10), 10)
gameDisplay.blit(self.image, (self.rect.x, self.rect.y))
def gameLoop():
global DIRECTION
DIRECTION = "up"
gameExit = False
gameOver = False
SCORE = 0
player_snake_trail = [] # Where the snake head has been.
enemy_snake_trail = [] # If I create an AI snake.
start_length = 1
lead_x = (SCREEN[0] / 2)
lead_y = (SCREEN[1] - (SCREEN[1] / 5))
move_speed = 10
move_speed_neg = move_speed * -1
lead_x_change = 0
lead_y_change = -move_speed
while not gameExit:
if gameOver == True:
message_to_screen("Game over",
RED,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("Press C to play again or Q to quit.",
BLACK,
Y_DISPLACE = 50,
size = "small")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
elif event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
lead_x_change = move_speed_neg
lead_y_change = 0
DIRECTION = "left"
elif event.key in (pygame.K_RIGHT, pygame.K_d):
lead_x_change = move_speed
lead_y_change = 0
DIRECTION = "right"
elif event.key in (pygame.K_UP, pygame.K_w):
lead_y_change = move_speed_neg
lead_x_change = 0
DIRECTION = "up"
elif event.key in (pygame.K_DOWN, pygame.K_s):
lead_y_change = move_speed
lead_x_change = 0
DIRECTION = "down"
elif event.key in (pygame.K_p, pygame.K_ESCAPE):
pause()
# If the snake goes beyond the screen borders the game will end.
if lead_x >= SCREEN[0] or lead_x < 0 or lead_y >= SCREEN[1] or lead_y <0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(WHITE)
# Draw the apple on screen
red_apple = Apple(APPLE_IMG)
# Draw the snake on screen
SNAKE_HEAD = []
SNAKE_HEAD.append(lead_x)
SNAKE_HEAD.append(lead_y)
player_snake_trail.append(SNAKE_HEAD)
# If you hit yourself, game over.
if SNAKE_HEAD in player_snake_trail[:-1]:
gameOver = True
if len(player_snake_trail) > start_length:
del player_snake_trail[0]
player_snake = Snake(IMG, 10, player_snake_trail, start_length)
if pygame.sprite.collide_rect(player_snake, red_apple) == True:
print("Collided!")
## start_length += 1
## SCORE += 1
## red_apple.random_location()
# If the snake eats the apple
# Old code below, needs to be rewritten. Disregard.
## if APPLE_RECT.collidepoint(lead_x, lead_y) == True:
## randAppleX, randAppleY = randAppleGen()
## start_length += 1
## SCORE += 1
score(SCORE)
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
When you set the rects in the constructors for the apple and snake head, they have x and y co-ordinates of 0. You need to set the rects and update them as the snake moves. I have added a set_rect method to them. I have also moved the draw from apple.random_location to its own method. Your code should look like this:
init()
run()
and in run:
check_events()
update_snake()
collision_check()
draw_things()
clock.tick(FPS)
Here is the altered code, try to break it up into sections as above.
import pygame
import time
import random
pygame.init()
WHITE = (pygame.Color("white"))
BLACK = ( 0, 0, 0)
RED = (245, 0, 0)
TURQ = (pygame.Color("turquoise"))
GREEN = ( 0, 155, 0)
GREY = ( 90, 90, 90)
SCREEN = (800, 600)
gameDisplay = pygame.display.set_mode(SCREEN)
#Set the window title and picture
pygame.display.set_caption('Block Worm')
ICON = pygame.Surface((10,10)) #pygame.image.load("apple10pix.png")
pygame.display.set_icon(ICON)
CLOCK = pygame.time.Clock()
FPS = 20
FONT = pygame.font.SysFont("arial", 25)
APPLE_SIZE = 10
TINY_FONT = pygame.font.SysFont("candara", 15)
SMALL_FONT = pygame.font.SysFont("candara", 25)
MED_FONT = pygame.font.SysFont("candara", 50)
LARGE_FONT = pygame.font.SysFont("krabbypatty", 75)
HUGE_FONT = pygame.font.SysFont("krabbypatty", 150)
IMG = pygame.Surface((10,10)) #pygame.image.load("snakehead.png")
APPLE_IMG = pygame.Surface((10,10)) #pygame.image.load("apple10pix.png")
DIRECTION = "up"
def pause():
paused = True
message_to_screen("Paused",
BLACK,
Y_DISPLACE = -100,
size = "huge")
message_to_screen("Press C to continue or Q to quit.",
BLACK,
Y_DISPLACE = 25)
pygame.display.update()
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_c, pygame.K_p):
paused = False
elif event.key in(pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
CLOCK.tick(5)
def score(score):
text = SMALL_FONT.render("Score: " + str(score), True, BLACK)
gameDisplay.blit(text, [0, 0])
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 in (pygame.K_q, pygame.K_ESCAPE):
pygame.quit()
quit()
gameDisplay.fill(WHITE)
message_to_screen("Welcome to",
GREEN,
Y_DISPLACE = -170,
size = "large")
message_to_screen("Block Worm",
GREEN,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("The objective of the game is to eat apples.",
BLACK,
Y_DISPLACE = 36,
size = "tiny")
message_to_screen("The more apples you eat the longer you get.",
BLACK,
Y_DISPLACE = 68,
size = "tiny")
message_to_screen("If you run into yourself or the edges, you die.",
BLACK,
Y_DISPLACE = 100,
size = "tiny")
message_to_screen("Press C to play or Q to quit.",
GREY,
Y_DISPLACE = 210,)
pygame.display.update()
CLOCK.tick(FPS)
def text_objects(text, color, size):
if size == "tiny":
TEXT_SURFACE = TINY_FONT.render(text, True, color)
elif size == "small":
TEXT_SURFACE = SMALL_FONT.render(text, True, color)
elif size == "medium":
TEXT_SURFACE = MED_FONT.render(text, True, color)
elif size == "large":
TEXT_SURFACE = LARGE_FONT.render(text, True, color)
elif size == "huge":
TEXT_SURFACE = HUGE_FONT.render(text, True, color)
return TEXT_SURFACE, TEXT_SURFACE.get_rect()
def message_to_screen(msg, color, Y_DISPLACE = 0, size = "small"):
TEXT_SURF, TEXT_RECT = text_objects(msg, color, size)
TEXT_RECT.center = (SCREEN[0] / 2), (SCREEN[1] / 2) + Y_DISPLACE
gameDisplay.blit(TEXT_SURF, TEXT_RECT)
class Snake(pygame.sprite.Sprite):
def __init__(self, image, size, trail, start_size):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.size = size
self.trail = trail
self.start_size = start_size
self.rect = self.image.get_rect()
if DIRECTION == "right":
HEAD = pygame.transform.rotate(self.image, 270)
elif DIRECTION == "left":
HEAD = pygame.transform.rotate(self.image, 90)
elif DIRECTION == "down":
HEAD = pygame.transform.rotate(self.image, 180)
else:
HEAD = image
gameDisplay.blit(HEAD, (self.trail[-1][0], self.trail[-1][1]))
for XnY in self.trail[:-1]:
pygame.draw.rect(gameDisplay, GREEN, [XnY[0], XnY[1], self.size, self.size])
def set_rect(self, rect):
self.rect = rect
class Apple(pygame.sprite.Sprite):
def __init__(self, image):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.random_location()
self.size = self.rect.width
gameDisplay.blit(self.image, (100, 100))
def random_location(self):
x = random.randrange(0, (SCREEN[0] - 10), 10)
y = random.randrange(0, (SCREEN[1]- 10), 10)
self.rect = pygame.Rect(x,y, 10, 10)
print "apple rect =",
print self.rect
def draw(self):
gameDisplay.blit(self.image, (self.rect.x, self.rect.y))
def gameLoop():
global DIRECTION
DIRECTION = "up"
gameExit = False
gameOver = False
SCORE = 0
player_snake_trail = [] # Where the snake head has been.
enemy_snake_trail = [] # If I create an AI snake.
start_length = 1
lead_x = (SCREEN[0] / 2)
lead_y = (SCREEN[1] - (SCREEN[1] / 5))
move_speed = 10
move_speed_neg = move_speed * -1
lead_x_change = 0
lead_y_change = -move_speed
red_apple = Apple(APPLE_IMG)
while not gameExit:
if gameOver == True:
message_to_screen("Game over",
RED,
Y_DISPLACE = -50,
size = "huge")
message_to_screen("Press C to play again or Q to quit.",
BLACK,
Y_DISPLACE = 50,
size = "small")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameOver = False
gameExit = True
elif event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
elif event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
lead_x_change = move_speed_neg
lead_y_change = 0
DIRECTION = "left"
elif event.key in (pygame.K_RIGHT, pygame.K_d):
lead_x_change = move_speed
lead_y_change = 0
DIRECTION = "right"
elif event.key in (pygame.K_UP, pygame.K_w):
lead_y_change = move_speed_neg
lead_x_change = 0
DIRECTION = "up"
elif event.key in (pygame.K_DOWN, pygame.K_s):
lead_y_change = move_speed
lead_x_change = 0
DIRECTION = "down"
elif event.key in (pygame.K_p, pygame.K_ESCAPE):
pause()
# If the snake goes beyond the screen borders the game will end.
if lead_x >= SCREEN[0] or lead_x < 0 or lead_y >= SCREEN[1] or lead_y <0:
gameOver = True
lead_x += lead_x_change
lead_y += lead_y_change
gameDisplay.fill(WHITE)
# Draw the snake on screen
SNAKE_HEAD = []
SNAKE_HEAD.append(lead_x)
SNAKE_HEAD.append(lead_y)
player_snake_trail.append(SNAKE_HEAD)
# draw the apple on the screen
red_apple.draw()
# If you hit yourself, game over.
if SNAKE_HEAD in player_snake_trail[:-1]:
gameOver = True
if len(player_snake_trail) > start_length:
del player_snake_trail[0]
player_snake = Snake(IMG, 10, player_snake_trail, start_length)
player_snake.set_rect(pygame.Rect(lead_x, lead_y, 10, 10))
if pygame.sprite.collide_rect(player_snake, red_apple) == True:
print("Collided!")
start_length += 1
SCORE += 1
red_apple.random_location()
# If the snake eats the apple
# Old code below, needs to be rewritten. Disregard.
## if APPLE_RECT.collidepoint(lead_x, lead_y) == True:
## randAppleX, randAppleY = randAppleGen()
## start_length += 1
## SCORE += 1
score(SCORE)
pygame.display.update()
CLOCK.tick(FPS)
pygame.quit()
quit()
game_intro()
gameLoop()
i have a snake game i made in python and i want to add him boulders that will appear every 10 "apples" he gets, so can you help me please? this is the code right now
import pygame
import random
__author__ = 'Kfir_Kahanov'
init = pygame.init()
def quit_game():
"""
this function will quit the game
:return:
"""
pygame.quit()
quit()
# this will set a nice sound when the player gets an apple
BLOP = pygame.mixer.Sound("Blop.wav")
pygame.mixer.Sound.set_volume(BLOP, 1.0)
volume = pygame.mixer.Sound.get_volume(BLOP)
# making colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 155, 0)
BLUE = (0, 0, 255)
YELLOW = (217, 217, 0)
SNAKE_RED = (152, 2, 2)
def display_fill():
"""
this will fill the screen with a color of my choice
:return:
"""
game_display.fill(GREEN)
def mute():
"""
this will mute the game or unmute it
:return:
"""
if volume == 1.0:
pygame.mixer.Sound.set_volume(BLOP, 0.0)
else:
pygame.mixer.Sound.set_volume(BLOP, 10.0)
# all the pygame stuff for the display
DISPLAY_WIDTH = 800
DISPLAY_HEIGHT = 600
game_display = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
pygame.display.set_caption("The hungry Cobra")
ICON = pygame.image.load("apple_icon.png")
pygame.display.set_icon(ICON)
pygame.display.update()
# deciding on FPS, the size of the snake, apples, and making the fonts for the text
CLOCK = pygame.time.Clock()
BLOCK_SIZE = 20
APPLE_THICKNESS = 30
fps = 15
# BOULDER_THICKNESS = 30
direction = "right" # deciding the starting direction
tiny_font = pygame.font.SysFont("comicsansms", 10)
small_font = pygame.font.SysFont("comicsansms", 25)
med_font = pygame.font.SysFont("comicsansms", 50)
large_font = pygame.font.SysFont("comicsansms", 80)
def text_objects(text, color, size):
"""
defining the text
:param text:
:param color:
:param size:
:return:
"""
global text_surface
if size == "tiny":
text_surface = tiny_font.render(text, True, color)
if size == "small":
text_surface = small_font.render(text, True, color)
if size == "medium":
text_surface = med_font.render(text, True, color)
if size == "large":
text_surface = large_font.render(text, True, color)
return text_surface, text_surface.get_rect()
# loading apple and snake img
IMG = pygame.image.load("snake_head.png")
APPLE_IMG = pygame.image.load("apple_icon.png")
# BOULDER_IMG = pygame.image.load("boulder.png")
def rand_apple_gen():
"""
making apple function
:return:
"""
rand_apple_x = round(random.randrange(10, DISPLAY_WIDTH - APPLE_THICKNESS)) # / 10.0 * 10.0
rand_apple_y = round(random.randrange(10, DISPLAY_HEIGHT - APPLE_THICKNESS)) # / 10.0 * 10.0
return rand_apple_x, rand_apple_y
"""
def rand_boulder_gen():
making the boulder parameters
:return:
rand_boulder_x = round(random.randrange(10, DISPLAY_WIDTH - BOULDER_THICKNESS))
rand_boulder_y = round(random.randrange(10, DISPLAY_WIDTH - BOULDER_THICKNESS))
return rand_boulder_x, rand_boulder_y
"""
def message(msg, color, y_displace=0, size="small"):
"""
making a function for the making of the text
:param msg:
:param color:
:param y_displace:
:param size:
:return:
"""
text_surf, text_rect = text_objects(msg, color, size)
text_rect.center = ((DISPLAY_WIDTH / 2), (DISPLAY_HEIGHT / 2) + y_displace)
game_display.blit(text_surf, text_rect)
def intro_message():
"""
making the intro
:return:
"""
intro = True
while intro:
display_fill()
message("Welcome to ", BLACK, -200, "large")
message("The hungry Cobra!", BLACK, -100, "large")
message("Eat apples to grow, but be care full", BLACK)
message("if you run into yourself or outside the screen", BLACK, 30)
message("you gonna have a bad time", BLACK, 60)
message("Press S to start or E to exit", BLACK, 90)
message("Created by Kfir Kahanov", BLACK, 200, "tiny")
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
display_fill()
pygame.display.update()
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_m:
mute()
if event.key == pygame.K_s:
intro = False
if event.key == pygame.K_e:
display_fill()
pygame.display.update()
quit_game()
score_edit = 0
def score_f(score):
"""
making a score_f on the top left
:param score:
:return:
"""
text = small_font.render("Score:" + str(score + score_edit), True, YELLOW)
game_display.blit(text, [0, 0])
def pause_f():
"""
making a pause_f screen
:return:
"""
pause = True
if pause:
message("Paused", RED, -50, "large")
message("Press R to start over, E to exit or C to continue", BLACK)
pygame.display.update()
while pause:
for event in pygame.event.get():
if event.type == pygame.QUIT:
display_fill()
pygame.display.update()
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_m:
mute()
if event.key == pygame.K_c or pygame.K_ESCAPE or pygame.K_p:
pause = False
if event.key == pygame.K_r:
global score_edit, direction, cheat1, cheat4, cheat3, cheat2
direction = "right"
score_edit = 0
cheat1 = 16
cheat2 = 16
cheat3 = 16
cheat4 = 16
game_loop()
if event.key == pygame.K_e:
display_fill()
pygame.display.update()
quit_game()
CLOCK.tick(5)
# making cheats
cheat1 = 16
cheat2 = 16
cheat3 = 16
cheat4 = 16
def snake(snake_list):
"""
defining the snake head
:param snake_list:
:return:
"""
global head
if direction == "right":
head = pygame.transform.rotate(IMG, 270)
elif direction == "left":
head = pygame.transform.rotate(IMG, 90)
elif direction == "down":
head = pygame.transform.rotate(IMG, 180)
elif direction == "up":
head = IMG
game_display.blit(head, (snake_list[-1][0], snake_list[-1][1]))
for x_n_y in snake_list[:-1]:
pygame.draw.rect(game_display, SNAKE_RED, [x_n_y[0], x_n_y[1], BLOCK_SIZE, BLOCK_SIZE])
def game_loop():
"""
this will be the game itself
:return:
"""
global cheat1
global cheat2
global cheat3
global cheat4
global direction
global fps
game_exit = False
game_over = False
global score_edit
lead_x = DISPLAY_WIDTH / 2
lead_y = DISPLAY_HEIGHT / 2
# rand_boulder_x, rand_boulder_y = -50, -50
lead_x_change = 10
lead_y_change = 0
snake_list = []
snake_length = 1
rand_apple_x, rand_apple_y = rand_apple_gen()
while not game_exit:
if game_over:
message("Game over!", RED, -50, "large")
message("Press E to exit or R to retry.", BLACK, 20, "medium")
pygame.display.update()
while game_over:
fps = 15
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
game_over = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_m:
mute()
if event.key == pygame.K_e:
game_exit = True
game_over = False
if event.key == pygame.K_r:
direction = "right"
score_edit = 0
cheat1 = 16
cheat2 = 16
cheat3 = 16
cheat4 = 16
game_loop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_m:
mute()
if event.key == pygame.K_LEFT and lead_x_change is not BLOCK_SIZE and direction is not "right":
lead_x_change = -BLOCK_SIZE
lead_y_change = 0
direction = "left"
elif event.key == pygame.K_RIGHT and lead_x_change is not -BLOCK_SIZE and direction is not "left":
lead_x_change = BLOCK_SIZE
lead_y_change = 0
direction = "right"
elif event.key == pygame.K_UP and lead_y_change is not BLOCK_SIZE and direction is not "down":
lead_y_change = -BLOCK_SIZE
lead_x_change = 0
direction = "up"
elif event.key == pygame.K_DOWN and lead_y_change is not -BLOCK_SIZE and direction is not "up":
lead_y_change = BLOCK_SIZE
lead_x_change = 0
direction = "down"
elif event.key == pygame.K_p:
pause_f()
elif event.key == pygame.K_ESCAPE:
pause_f()
elif event.key == pygame.K_k: # the cheat
cheat1 = 0
elif event.key == pygame.K_f:
cheat2 = 4
elif event.key == pygame.K_i:
cheat3 = 0
elif event.key == pygame.K_r:
cheat4 = 3
elif cheat1 == 0 and cheat2 == 4 and cheat3 == 0 and cheat4 == 3:
score_edit = 10000
if lead_x >= DISPLAY_WIDTH or lead_x < 0 or lead_y >= DISPLAY_HEIGHT or lead_y < 0:
game_over = True
lead_x += lead_x_change
lead_y += lead_y_change
display_fill()
game_display.blit(APPLE_IMG, (rand_apple_x, rand_apple_y))
snake_head = [lead_x, lead_y]
snake_list.append(snake_head)
if len(snake_list) > snake_length:
del snake_list[0]
for eachSegment in snake_list[:-1]:
if eachSegment == snake_head:
game_over = True
snake(snake_list)
score_f(snake_length * 10 - 10)
pygame.display.update()
if rand_apple_x < lead_x < rand_apple_x + APPLE_THICKNESS or rand_apple_x < lead_x + BLOCK_SIZE < rand_apple_x \
+ APPLE_THICKNESS:
if rand_apple_y < lead_y < rand_apple_y + APPLE_THICKNESS or rand_apple_y < lead_y + BLOCK_SIZE < \
rand_apple_y + APPLE_THICKNESS:
pygame.mixer.Sound.play(BLOP)
rand_apple_x, rand_apple_y = rand_apple_gen()
snake_length += 1
fps += 0.15
"""
if snake_length * 10 - 10 == 20:
rand_boulder_x, rand_boulder_y = rand_boulder_gen()
game_display.blit(BOULDER_IMG, (rand_boulder_x, rand_boulder_y))
elif rand_boulder_x < lead_x < rand_boulder_y + BOULDER_THICKNESS or rand_boulder_x < lead_x + BLOCK_SIZE < \
rand_boulder_x + BOULDER_THICKNESS:
if rand_boulder_x < lead_y < rand_boulder_y + BOULDER_THICKNESS or rand_boulder_y < lead_y + BLOCK_SIZE < \
rand_boulder_y + BOULDER_THICKNESS:
game_over = True
"""
CLOCK.tick(fps)
display_fill()
pygame.display.update()
quit_game()
intro_message()
game_loop()
Maybe try explaining what you have tried and why it isn't working. You would get better help that way.
From what I can see from your code though....
You seem to be on the right track in your commented out code. Evaluating the snake length or score variable during your game loop, then generating a random boulder to the screen. The next step is just handling the collision logic for all the boulders, which I see two ways of doing. First way is creating a lists of the boulder attributes like the x,y positions, similar to how you did the snake list. The second way would be to create a class for boulders, then when the score, or snake length, reaches 10, create a new boulder object. Using a class may make the collision logic much easier to handle.
I am building an asteroids-like game with python, but I'm running into trouble with keeping within the range of my possibleTurrets array. All I'm doing is iterating through the array, and when the edge cases outside of the array occur, I deal with them through:
if currentTurPos > 8:
currentTurPos = 8
elif currentTurPos < 0:
currenTurPos = 0
This is in reference to this array:
possibleTurrets = [ (x-27,y-2),
(x-26,y-5),
(x-25,y-8),
(x-23,y-12),
(x-20,y-14),
(x-18,y-15),
(x-15,y-17),
(x-13,y-19),
(x-11,y-21)
]
For some reason this code works fine on pygame.K_UP but not on pygame.K_DOWN and I have no idea why.
This seems like it should be really obvious, but I've spent an hour trying to fix it, and am drawing a blank. The issue is with my ufo function, and the currentTurPos variable.
# Libraries
import pygame
import time
import random
import os
# Initialize Pygame
pygame.init()
# Colors
white = (255,255,255)
black = (0,0,0)
red = (200,0,0)
blue = (0,0,255)
green = (34,177,76)
light_green = (0,255,0)
yellow = (200,200,0)
light_yellow = (255,255,0)
light_red = (255,0,0)
# Display
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
#pygame.display.set_caption('Slither')
#icon = pygame.image.load('apple.bmp')
#pygame.display.set_icon(icon)
clock = pygame.time.Clock()
# Sprites
ufoWidth = 40
ufoHeight = 20
turretWidth = 5
turretHeight = 10
fps = 15 # Speed
# Fonts
smallFont = pygame.font.SysFont("comicsansms", 25)
medFont = pygame.font.SysFont("comicsansms", 50)
largeFont = pygame.font.SysFont("comicsansms", 80)
def ufo(x,y,turPos):
x = int(x)
y = int(y)
possibleTurrets = [ (x-27,y-2),
(x-26,y-5),
(x-25,y-8),
(x-23,y-12),
(x-20,y-14),
(x-18,y-15),
(x-15,y-17),
(x-13,y-19),
(x-11,y-21)
]
pygame.draw.circle(gameDisplay, blue, (x,y),int(ufoHeight/2))
pygame.draw.ellipse(gameDisplay, black, (x-ufoHeight, y, ufoWidth, ufoHeight))
pygame.draw.line(gameDisplay,blue,(x,y),possibleTurrets[turPos],turretWidth)
# Font sizes
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()
# Displays a message: Requires message, color, y-displacement, and size arguments
def message_to_screen(msg, color, y_displace=0, size="small"):
textSurf, textRect = text_objects(msg, color, size)
textRect.center = (int(display_width/2), (int(display_height/2) + y_displace))
gameDisplay.blit(textSurf, textRect)
# Show button text
def text_to_button(msg,color, buttonx,buttony,buttonwidth,buttonheight,size="small"):
textSurf, textRect = text_objects(msg,color,size)
textRect.center = ((buttonx+(buttonwidth/2)), buttony+(buttonheight/2))
gameDisplay.blit(textSurf, textRect)
# On button hover
def button(text,x,y,width,height,inactive_color,active_color,action):
cursor = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + width > cursor[0] > x and y + height > cursor[1] > y:
pygame.draw.rect(gameDisplay,active_color,(x,y,width,height))
if click[0] == 1 and action != None:
if action == "play":
gameLoop()
if action == "controls":
game_controls()
if action == "quit":
pygame.quit()
quit()
else:
pygame.draw.rect(gameDisplay,inactive_color,(x,y,width,height))
text_to_button(text,black,x,y,width,height)
def game_controls():
gcont = True
while gcont:
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(white)
message_to_screen("Controls", green, -100, size="large")
message_to_screen("Fire: Spacebar", black, -30, size="small")
message_to_screen("Move turret: Up and Down arrows", black, 10, size="small")
message_to_screen("Move UFO: Left and Right arrows", black, 50, size="small")
message_to_screen("Pause: P", black, 90, size="small")
button("Play",150,450,100,50, green, light_green, action="play")
button("Quit",550,450,100,50, red, light_red, action="quit")
pygame.display.update()
clock.tick(fps)
# Pauses game and gives continue and quit options
def pause():
paused = True
message_to_screen("Paused", black, -100, size="large")
message_to_screen("Press P to play, or Q to quit.", black, 25, size="small")
while paused:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
paused = False
elif event.key == pygame.K_q:
pygame.quit()
quit()
pygame.display.update()
clock.tick(fps)
# Keeps track of, and displays the score
def score(score):
text = smallFont.render(" Score: " + str(score), True, black)
gameDisplay.blit(text, [0,0])
# Barrier
def barrier():
xlocation = (display_width/2) + random.randint(-0.2*displayWidth,0.2*displayWidth)
# Intro screen - Title and directions
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(white)
message_to_screen("Welcome to UFO!", green, -100, size="large")
message_to_screen("The objective of the game is to search and destroy.", black, -30, size="small")
message_to_screen("Destroy your opponent before they destroy you.", black, 10, size="small")
message_to_screen("The more enemies you destroy, the harder they get.", black, 50, size="small")
button("Play",150,450,100,50, green, light_green, action="play")
button("Controls",350,450,100,50, yellow, light_yellow, action="controls")
button("Quit",550,450,100,50, red, light_red, action="quit")
pygame.display.update()
clock.tick(fps)
# Main game loop
def gameLoop():
gameExit = False
gameOver = False
mainUfoX = display_width * 0.9
mainUfoY = display_height * 0.9
ufoMove = 0
currentTurPos = 0
changeTur = 0
# Game over screen and changes for key inputs
while not gameExit:
if gameOver == True:
message_to_screen("Game over!", red, -50, size="large")
message_to_screen("Press C to play again, Q to quit.", black, 50, size="medium")
pygame.display.update()
while gameOver == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
gameOver = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
gameExit = True
gameOver = False
if event.key == pygame.K_c:
gameLoop()
# Make changes for specific key inputs
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
ufoMove = -5
elif event.key == pygame.K_RIGHT:
ufoMove = 5
elif event.key == pygame.K_UP:
changeTur = 1
elif event.key == pygame.K_DOWN:
changeTur = -1
elif event.key == pygame.K_p:
pause()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
ufoMove = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
changeTur = 0
gameDisplay.fill(white)
mainUfoX += ufoMove
currentTurPos += changeTur
if currentTurPos > 8:
currentTurPos = 8
elif currentTurPos < 0:
currenTurPos = 0
ufo(mainUfoX,mainUfoY,currentTurPos)
pygame.display.update()
clock.tick(fps)
# Quits
pygame.quit()
quit()
# Loads game intro screen
game_intro()
# gameLoop calls itself to begin game
gameLoop()
It was a typo (I'm an idiot).
currentTurPos was currenTurPos.
Lesson learned: complex variable names with repeating letters are dangerous.