I'm doing a snake game and I got a bug I can't figure out how to solve, I want to make my snake teleport trough walls, when the snake colllides with a wall it teleports to another with the opposite speed and position, like the classic game, but with my code when the snake gets near the wall it duplicates to the opposite wall, but it was supposed to not even detect collision yet
important thing: in the grid the snake is on the side of the wall, like this
SSSS
WWWW
and not like this:
SSSS
NNNN
WWWW
when S represents the snake, W represents the wall and N represents nothing.
edit: whole code
import pygame, random, os, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1020, 585))
pygame.display.set_caption('2snakes!')
#files location
current_path = os.path.dirname(__file__)
data_path = os.path.join(current_path, 'data')
icon = pygame.image.load(os.path.join(data_path, 'icon.png'))
press_any = pygame.image.load(os.path.join(data_path, 'press_any.png'))
pygame.display.set_icon(icon)
#collission
def collision(c1,c2):
return (c1[0] == c2[0]) and (c1[1] == c2[1])
#game over
def gameOverBlue():
print("blue")
main()
def gameOverRed():
print("red")
main()
fps = 15
def main():
#variables
direction = 'RIGHT'
direction2 = 'RIGHT'
change_to = direction
change2_to = direction2
#snake
size = 15
s_posx = 60
s_posy = 60
snake = [(s_posx + size * 2, s_posy),(s_posx + size, s_posy),(s_posx, s_posy)]
s_skin = pygame.Surface((size, size))
s_skin.fill((82,128,208))
#snake2
size2 = 15
s2_posx = 390
s2_posy = 390
snake2 = [(s2_posx + size2 * 2, s2_posy),(s2_posx + size2, s2_posy),(s2_posx, s2_posy)]
s2_skin = pygame.Surface((size2, size2))
s2_skin.fill((208,128,82))
#apple
apple = pygame.Surface((size, size))
apple_pos = ((random.randint(0, 67)) * 15, (random.randint(0, 38)) * 15)
#endregion
while True:
pygame.time.Clock().tick(fps)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
#input
elif event.type == pygame.KEYDOWN:
#snake
if event.key == ord('w'):
change_to = 'UP'
if event.key == ord('s'):
change_to = 'DOWN'
if event.key == ord('a'):
change_to = 'LEFT'
if event.key == ord('d'):
change_to = 'RIGHT'
#snake2
if event.key == pygame.K_UP:
change2_to = 'UP'
if event.key == pygame.K_DOWN:
change2_to = 'DOWN'
if event.key == pygame.K_LEFT:
change2_to = 'LEFT'
if event.key == pygame.K_RIGHT:
change2_to = 'RIGHT'
#quit game
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.quit()
#smoot snake movement
#snake
if change_to == 'UP' and direction != 'DOWN':
direction = 'UP'
if change_to == 'DOWN' and direction != 'UP':
direction = 'DOWN'
if change_to == 'LEFT' and direction != 'RIGHT':
direction = 'LEFT'
if change_to == 'RIGHT' and direction != 'LEFT':
direction = 'RIGHT'
#snake2
if change2_to == 'UP' and direction2 != 'DOWN':
direction2 = 'UP'
if change2_to == 'DOWN' and direction2 != 'UP':
direction2 = 'DOWN'
if change2_to == 'LEFT' and direction2 != 'RIGHT':
direction2 = 'LEFT'
if change2_to == 'RIGHT' and direction2 != 'LEFT':
direction2 = 'RIGHT'
#movement
#snake
new_pos = None
if direction == 'DOWN':
new_pos = (snake[0][0], snake[0][1] + size)
if direction == 'UP':
new_pos = (snake[0][0], snake[0][1] - size)
if direction == 'LEFT':
new_pos = (snake[0][0] - size, snake[0][1])
if direction == 'RIGHT':
new_pos = (snake[0][0] + size, snake[0][1])
if new_pos:
snake = [new_pos] + snake
del snake[-1]
#snake2
new_pos2 = None
if direction2 == 'DOWN':
new_pos2 = (snake2[0][0], snake2[0][1] + size2)
if direction2 == 'UP':
new_pos2 = (snake2[0][0], snake2[0][1] - size2)
if direction2 == 'LEFT':
new_pos2 = (snake2[0][0] - size2, snake2[0][1])
if direction2 == 'RIGHT':
new_pos2 = (snake2[0][0] + size2, snake2[0][1])
if new_pos2:
snake2 = [new_pos2] + snake2
del snake2[-1]
#apple collision
#snake
if collision(snake[0], apple_pos):
snake.append((-20,-20))
size = 15
s_skin = pygame.Surface((size, size))
s_skin.fill((82,128,208))
apple_pos = ((random.randint(0, 32)) * 15, (random.randint(0, 19)) * 15)
#snake2
if collision(snake2[0], apple_pos):
snake2.append((-20,-20))
apple_pos = ((random.randint(0, 67)) * 15, (random.randint(0, 38)) * 15)
#wall collisison
#snake
_pos = None
if snake[0][0] == 15:
_pos = (990, snake[0][1])
elif snake[0][1] == 15:
_pos = (snake[0][0], 555)
elif snake[0][0] == 990:
_pos = (15, snake[0][1])
elif snake[0][1] == 555:
_pos = (snake[0][0], 15)
if _pos:
snake = [_pos] + snake
del snake[-1]
#snake2
_pos2 = None
if snake2[0][0] == 15:
_pos2 = (1005, snake2[0][1])
elif snake2[0][1] == 0:
_pos2 = (snake2[0][0], 570)
elif snake2[0][0] == 1005:
_pos2 = (0, snake2[0][1])
elif snake2[0][1] == 570:
_pos2 = (snake2[0][0], 0)
if _pos2:
snake2 = [_pos2] + snake2
del snake2[-1]
#self collisison
#snake
if snake[0] in snake[1:]:
print("self collision")
gameOverBlue()
#snake2
if snake2[0] in snake2[1:]:
print("self collision")
gameOverRed()
#snakes colliding with each other
if snake2[0] == snake[0]:
print("head to head collisions")
if snake[0] in snake2:
gameOverRed()
if snake2[0] in snake:
gameOverBlue()
#rendering
apple.fill((255,0,0))
screen.fill((10,10,10))
screen.blit(apple,apple_pos)
for pos in snake:
screen.blit(s_skin,pos)
for pos2 in snake2:
screen.blit(s2_skin,pos2)
pygame.display.update()
while True:
pygame.time.Clock().tick(fps)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
#input
elif event.type == pygame.KEYDOWN:
main()
screen.blit(press_any, (0,0))
pygame.display.update()
edit: the red dot is the food/apple
You want to implement a teleporter. Therefore, once the snake is over the edge of the window, you will have to teleport to the other side. The size of your window is 1020x585. The snake is out of the window if x == -15, y == -15, x == 1020 or y == 585 Hence you have to do the following teleportations:
if x = 1020 teleport to x = 0
if x = -15 teleport to x = 1005
if y = 585 teleport to y = 0
if y = -15 teleport to y = 570
_pos = None
if snake[0][0] == -15:
_pos = (1005, snake[0][1])
elif snake[0][1] == -15:
_pos = (snake[0][0], 570)
elif snake[0][0] == 1020:
_pos = (0, snake[0][1])
elif snake[0][1] == 585:
_pos = (snake[0][0], 0)
if _pos:
snake = [_pos] + snake
del snake[-1]
Related
I am doing a game where you control a snake and when he dies the game quits. I have tried adding a different function (on) so only while on is true the game will continue. However, this does not restart here is the code I have and could anyone put in a restart function?
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Happy Birthday Mum')
redColour = pygame.Color(255, 0, 0)
blackColour = pygame.Color(0, 0, 0)
whiteColour = pygame.Color(255, 255, 255)
greyColour = pygame.Color(150, 150, 150)
snakePosition = [100,100]
snakeSegments = [[100,100],[80,100],[60,100]]
raspberryPosition = [300,300]
raspberrySpawned = 1
direction = 'right'
changeDirection = direction
diff = 30
def gameOver():
gameOverFont = pygame.font.Font('freesansbold.ttf', 72)
gameOverSurf = gameOverFont.render('Game Over', True, greyColour)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (320, 10)
playSurface.blit(gameOverSurf, gameOverRect)
pygame.display.flip()
time.sleep(5)
pygame.quit()
sys.exit()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
changeDirection = 'right'
if event.key == K_LEFT or event.key == ord('a'):
changeDirection = 'left'
if event.key == K_UP or event.key == ord('w'):
changeDirection = 'up'
if event.key == K_DOWN or event.key == ord('s'):
changeDirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
if event.key == K_1:
diff = 10
if event.key == K_2:
diff = 20
if event.key == K_3:
diff = 30
if event.key == K_4:
diff = 40
if event.key == K_5:
diff = 50
if event.key == K_r:
restart()
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
if direction == 'right':
snakePosition[0] += 20
if direction == 'left':
snakePosition[0] -= 20
if direction == 'up':
snakePosition[1] -= 20
if direction == 'down':
snakePosition[1] += 20
snakeSegments.insert(0,list(snakePosition))
if snakePosition[0] == raspberryPosition[0] and snakePosition[1] == raspberryPosition[1]:
raspberrySpawned = 0
else:
snakeSegments.pop()
if raspberrySpawned == 0:
x = random.randrange(1,32)
y = random.randrange(1,24)
raspberryPosition = [int(x*20),int(y*20)]
raspberrySpawned = 1
playSurface.fill(blackColour)
for position in snakeSegments:
pygame.draw.rect(playSurface,whiteColour,Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface,redColour,Rect(raspberryPosition[0], raspberryPosition[1], 20, 20))
pygame.display.flip()
if snakePosition[0] > 620 or snakePosition[0] < 0:
gameOver()
if snakePosition[1] > 460 or snakePosition[1] < 0:
gameOver()
for snakeBody in snakeSegments[1:]:
if snakePosition[0] == snakeBody[0] and snakePosition[1] == snakeBody[1]:
gameOver()
fpsClock.tick(diff)
You essentially want two while loops - one for when the overall game is running, and a smaller one while the snake is alive.
start pygame and set global variables;
while the program is running:
set all of the initial variables for the game (snake position, etc)
while the snake is alive:
handle input;
check to see if the snake is dead;
I've taken your python code and structured it this way. Pay attention to where I set the variable snake_is_alive to false. See how it makes the inner loop end, but makes the outer loop start over.
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Happy Birthday Mum')
redColour = pygame.Color(255, 0, 0)
blackColour = pygame.Color(0, 0, 0)
whiteColour = pygame.Color(255, 255, 255)
greyColour = pygame.Color(150, 150, 150)
game_is_running = True
while game_is_running:
snakePosition = [100,100]
snakeSegments = [[100,100],[80,100],[60,100]]
raspberryPosition = [300,300]
raspberrySpawned = 1
direction = 'right'
changeDirection = direction
diff = 30
snake_is_alive = True
while snake_is_alive:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
changeDirection = 'right'
if event.key == K_LEFT or event.key == ord('a'):
changeDirection = 'left'
if event.key == K_UP or event.key == ord('w'):
changeDirection = 'up'
if event.key == K_DOWN or event.key == ord('s'):
changeDirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
if event.key == K_1:
diff = 10
if event.key == K_2:
diff = 20
if event.key == K_3:
diff = 30
if event.key == K_4:
diff = 40
if event.key == K_5:
diff = 50
if event.key == K_r:
snake_is_alive = False
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
if direction == 'right':
snakePosition[0] += 20
if direction == 'left':
snakePosition[0] -= 20
if direction == 'up':
snakePosition[1] -= 20
if direction == 'down':
snakePosition[1] += 20
snakeSegments.insert(0,list(snakePosition))
if snakePosition[0] == raspberryPosition[0] and snakePosition[1] == raspberryPosition[1]:
raspberrySpawned = 0
else:
snakeSegments.pop()
if raspberrySpawned == 0:
x = random.randrange(1,32)
y = random.randrange(1,24)
raspberryPosition = [int(x*20),int(y*20)]
raspberrySpawned = 1
playSurface.fill(blackColour)
for position in snakeSegments:
pygame.draw.rect(playSurface,whiteColour,Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface,redColour,Rect(raspberryPosition[0], raspberryPosition[1], 20, 20))
pygame.display.flip()
if snakePosition[0] > 620 or snakePosition[0] < 0:
snake_is_alive = False
if snakePosition[1] > 460 or snakePosition[1] < 0:
snake_is_alive = False
for snakeBody in snakeSegments[1:]:
if snakePosition[0] == snakeBody[0] and snakePosition[1] == snakeBody[1]:
snake_is_alive = False
fpsClock.tick(diff)
gameOverFont = pygame.font.Font('freesansbold.ttf', 72)
gameOverSurf = gameOverFont.render('Game Over', True, greyColour)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (320, 10)
playSurface.blit(gameOverSurf, gameOverRect)
pygame.display.flip()
time.sleep(5)
I got rid of the functions to make it easier to read, but even if you make functions, the overall structure (inner loop and outer loop) should remain the same.
You need to turn your game into a function just like you did with end game. Then in your end game loop instead of exiting just call playGame again. Make sure that you reset all your variables to there original state at the begging of the loop before the while. Something like this: (pseudo code)
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Happy Birthday Mum')
redColour = pygame.Color(255, 0, 0)
blackColour = pygame.Color(0, 0, 0)
whiteColour = pygame.Color(255, 255, 255)
greyColour = pygame.Color(150, 150, 150)
snakePosition = [100,100]
snakeSegments = [[100,100],[80,100],[60,100]]
raspberryPosition = [300,300]
raspberrySpawned = 1
direction = 'right'
changeDirection = direction
diff = 30
def gameOver():
gameOverFont = pygame.font.Font('freesansbold.ttf', 72)
gameOverSurf = gameOverFont.render('Game Over', True, greyColour)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (320, 10)
playSurface.blit(gameOverSurf, gameOverRect)
pygame.display.flip()
time.sleep(5)
playGame();
def playGame():
RESET ALL GAME VARIABLES HERE
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
changeDirection = 'right'
if event.key == K_LEFT or event.key == ord('a'):
changeDirection = 'left'
if event.key == K_UP or event.key == ord('w'):
changeDirection = 'up'
if event.key == K_DOWN or event.key == ord('s'):
changeDirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
if event.key == K_1:
diff = 10
if event.key == K_2:
diff = 20
if event.key == K_3:
diff = 30
if event.key == K_4:
diff = 40
if event.key == K_5:
diff = 50
if event.key == K_r:
restart()
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
if direction == 'right':
snakePosition[0] += 20
if direction == 'left':
snakePosition[0] -= 20
if direction == 'up':
snakePosition[1] -= 20
if direction == 'down':
snakePosition[1] += 20
snakeSegments.insert(0,list(snakePosition))
if snakePosition[0] == raspberryPosition[0] and snakePosition[1] == raspberryPosition[1]:
raspberrySpawned = 0
else:
snakeSegments.pop()
if raspberrySpawned == 0:
x = random.randrange(1,32)
y = random.randrange(1,24)
raspberryPosition = [int(x*20),int(y*20)]
raspberrySpawned = 1
playSurface.fill(blackColour)
for position in snakeSegments:
pygame.draw.rect(playSurface,whiteColour,Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface,redColour,Rect(raspberryPosition[0], raspberryPosition[1], 20, 20))
pygame.display.flip()
if snakePosition[0] > 620 or snakePosition[0] < 0:
gameOver()
if snakePosition[1] > 460 or snakePosition[1] < 0:
gameOver()
for snakeBody in snakeSegments[1:]:
if snakePosition[0] == snakeBody[0] and snakePosition[1] == snakeBody[1]:
gameOver()
fpsClock.tick(diff)
playGame();
This question already has an answer here:
How do I get the snake to grow and chain the movement of the snake's body?
(1 answer)
Closed 2 years ago.
I am creating a snake clone in pygame, and I am currently working on managing the turning mechanisms of the snake and its movement. I create a point at the time of turning in pygame, then store it in snake.pos_at_turn. After that I adjust each snake segments direction the should move until either their x or y coordinate equals that of snake.pos_at_turn then I change their direction again. The problem is that for some reason the snake segment doesn't move at all. Any help would be appreciated!
Code for snake object and event loop:
import pygame,sys,random
from pygame.locals import *
pygame.init()
WINDOW_HEIGHT = 500
WINDOW_WIDTH = 500
RECTANGLE_HEIGHT = 20
RECTANGLE_WIDTH = 20
GREEN = (0,255,0)
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
clock = pygame.time.Clock()
SCREEN = pygame.display.set_mode((WINDOW_WIDTH,WINDOW_HEIGHT))
pygame.display.set_caption("Snake")
class Snake(object):
def __init__(self, color, width, height):
self.body = []
self.image = pygame.Surface((width,height))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.speed = 20
self.direction = 'right'
self.living = True
self.move = (0,0)
self.pos_at_turn = [0,0]
def movement(self):
if self.direction == 'right':
self.move = (self.speed,0)
elif self.direction == 'left':
self.move = (-self.speed,0)
elif self.direction == 'up':
self.move = (0,-self.speed)
elif self.direction == 'down':
self.move = (0,self.speed)
self.rect.move_ip(self.move)
self.rect.clamp_ip(SCREEN.get_rect())
def blit(self):
SCREEN.blit(self.image,self.rect)
def update(self,food):
self.movement()
self.add_segment(food)
self.draw_snake()
for snake_segment in self.body:
print(snake_segment.rect)
def add_segment(self,food):
snake_segment = Snake(GREEN,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
if len(self.body) == 0:
self.body.append(snake_segment)
if self.rect.colliderect(food.rect):
self.body.append(snake_segment)
def draw_snake(self):
for snake_segment in self.body:
if self.body.index(snake_segment) == 0:
self.blit()
else:
# original movement code:
# if self.direction == 'right':
# snake_segment.rect.x = self.rect.x - RECTANGLE_WIDTH * self.body.index(snake_segment)
# snake_segment.rect.y = self.rect.y
# snake_segment.blit()
# elif self.direction == 'left':
# snake_segment.rect.x = self.rect.x + RECTANGLE_WIDTH * self.body.index(snake_segment)
# snake_segment.rect.y = self.rect.y
# snake_segment.blit()
# elif self.direction == 'up':
# snake_segment.rect.x = self.rect.x
# snake_segment.rect.y = self.rect.y + RECTANGLE_HEIGHT * self.body.index(snake_segment)
# snake_segment.blit()
# elif self.direction == 'down':
# snake_segment.rect.x = self.rect.x
# snake_segment.rect.y = self.rect.y - RECTANGLE_HEIGHT * self.body.index(snake_segment)
# snake_segment.blit()
if self.direction == 'right':
if snake_segment.rect.y >= self.pos_at_turn[1]:
snake_segment.direction = 'down'
elif snake_segment.rect.y <= self.pos_at_turn[1]:
snake_segment.direction = 'up'
if snake_segment.rect.y == self.pos_at_turn[1]:
if snake_segment.rect.x >= self.pos_at_turn[0]:
snake_segment.direction = 'left'
elif snake_segment.rect.x <= self.pos_at_turn[0]:
snake_segment.direction = 'right'
snake_segment.blit()
elif self.direction == 'left':
if snake_segment.rect.y >= self.pos_at_turn[1]:
snake_segment.direction = 'down'
elif snake_segment.rect.y <= self.pos_at_turn[1]:
snake_segment.direction = 'up'
if snake_segment.rect.y == self.pos_at_turn[1]:
if snake_segment.rect.x >= self.pos_at_turn[0]:
snake_segment.direction = 'left'
elif snake_segment.rect.x <= self.pos_at_turn[0]:
snake_segment.direction = 'right'
snake_segment.blit()
elif self.direction == 'up':
if snake_segment.rect.x >= self.pos_at_turn[0]:
snake_segment.direction = 'left'
elif snake_segment.rect.x <= self.pos_at_turn[0]:
snake_segment.direction = 'right'
if snake_segment.rect.x == self.pos_at_turn[0]:
if snake_segment.rect.y >= self.pos_at_turn[1]:
snake_segment.direction = 'down'
elif snake_segment.rect.y <= self.pos_at_turn[1]:
snake_segment.direction = 'up'
snake_segment.blit()
elif self.direction == 'down':
if snake_segment.rect.x >= self.pos_at_turn[0]:
snake_segment.direction = 'left'
elif snake_segment.rect.x <= self.pos_at_turn[0]:
snake_segment.direction = 'right'
if snake_segment.rect.x == self.pos_at_turn[0]:
if snake_segment.rect.y >= self.pos_at_turn[1]:
snake_segment.direction = 'down'
elif snake_segment.rect.y <= self.pos_at_turn[1]:
snake_segment.direction = 'up'
snake_segment.blit()
class Food(object):
def __init__(self,color,width,height):
self.image = pygame.Surface((width,height))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = random.randrange(20,500,20)
self.rect.y = random.randrange(20,500,20)
self.state = 'uneaten'
def check_eaten(self,snake):
if snake.rect.colliderect(self.rect):
self.state = 'eaten'
def blit(self):
SCREEN.blit(self.image,self.rect)
def update_state(self,snake):
self.check_eaten(snake)
if self.state == 'uneaten':
self.blit()
elif self.state == 'eaten':
self.rect.x = random.randrange(0,500,20)
self.rect.y = random.randrange(0,500,20)
if self.rect.x == snake.rect.x or self.rect.x == snake.rect.y:
self.rect.x = random.randrange(0,500,20)
self.rect.y = random.randrange(0,500,20)
self.blit()
self.state = 'uneaten'
def update(self,snake):
self.update_state(snake)
def event_loop(snake,food):
while True:
SCREEN.fill(BLACK)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
snake.pos_at_turn = [snake.rect.x, snake.rect.y]
if event.key == K_RIGHT:
snake.direction = 'right'
elif event.key == K_LEFT:
snake.direction = 'left'
elif event.key == K_UP:
snake.direction = 'up'
elif event.key == K_DOWN:
snake.direction = 'down'
snake.update(food)
food.update(snake)
pygame.display.update()
clock.tick(5)
SNAKE = Snake(GREEN,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
FOOD = Food(RED,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
event_loop(SNAKE,FOOD)
You've to traverse the snakes body in reverse order in the method movement. For each part of the body, copy the position of the previous part. The head part gets the current position of the snake:
class Snake(object):
# [...]
def movement(self):
if self.direction == 'right':
self.move = (self.speed,0)
elif self.direction == 'left':
self.move = (-self.speed,0)
elif self.direction == 'up':
self.move = (0,-self.speed)
elif self.direction == 'down':
self.move = (0,self.speed)
self.rect.move_ip(self.move)
self.rect.clamp_ip(SCREEN.get_rect())
for i in range(len(self.body)-1, 0, -1):
self.body[i].rect.center = self.body[i-1].rect.center
if self.body:
self.body[0].rect.center = self.rect.center
Init the position of a part, when a new part is add to the body in the method add_segment:
class Snake(object):
# [...]
def add_segment(self,food):
if len(self.body) == 0 or self.rect.colliderect(food.rect):
snake_segment = Snake(GREEN,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
snake_segment.rect.center = self.rect.center
self.body.append(snake_segment)
In the method draw_snake it is sufficient to traverse the parts of the body and to "blit" each part:
class Snake(object):
# [...]
def draw_snake(self):
for snake_segment in self.body:
snake_segment.blit()
I have used pygame for a while now, but now the player rect isn't updating or noticing collisions. It is still moving though. This just happened after I modified a bit of code. I have looked at the .draw functions and the walls and the border is being drawn, but the player isn't, and the screen is being updated. (The code snippet is in javascript because I still don't know how to use a code snippet in python.)
import pygame, sys, random
from pygame.locals import *
from time import sleep
pygame.init()
def render():
windowSurface.fill(black)
pygame.draw.rect(windowSurface,white,player1)
if level == 1:
pygame.draw.rect(windowSurface,white,wall_lvl_1_1)
pygame.draw.rect(windowSurface,white,wall_lvl_1_2)
pygame.draw.rect(windowSurface,white,border1_lvl_1)
elif level == 2:
filler = 'done'
pygame.display.update()
black = (0,0,0)
white = (255,255,255)
windowSurface = pygame.display.set_mode((500, 500),0,32)
windowSurface.fill(black)
level = 1
xmod = 0
ymod = 0
direction = 'none'
player1 = pygame.Rect(225 + xmod,450 - ymod,30,30)
wall_lvl_1_1 = pygame.Rect(0,225,250,50)
wall_lvl_1_2 = pygame.Rect(300,250,200,50)
border1_lvl_1 = pygame.Rect(0,0,25,500)
border2_lvl_1 = pygame.Rect(0,0,500,25)
border3_lvl_1 = pygame.Rect(0,0,1,1)
pygame.draw.rect(windowSurface,white,wall_lvl_1_1)
render()
while True:
render()
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_LEFT:
direction = 'left'
if event.key == K_RIGHT:
direction = 'right'
if event.key == K_UP:
direction = 'up'
if event.key == K_DOWN:
direction = 'down'
if event.type == QUIT:
pygame.quit()
sys.exit()
if player1.colliderect(wall_lvl_1_1) or player1.colliderect(wall_lvl_1_2):
xmod = 0
ymod = 0
player1 = pygame.Rect(225 + xmod,450 - ymod,30,30)
print('again')
if direction == 'left':
xmod -= 1
sleep(0.004)
if direction == 'right':
xmod += 1
sleep(0.004)
if direction == 'up':
ymod += 1
sleep(0.004)
if direction == 'down':
ymod -= 1
sleep(0.004)
if ymod == 450:
level = 2
render()
You need to update the position of the player1 rect each frame.
player1.topleft = (xmod, ymod)
While doing some test in python, one of the sprites in a Player class randomly started duplicating itself.. I can't figure it out.. (I realize it's probally something really simple)
Here's the code:
import pygame
from pygame.locals import *
import time
pygame.font.init()
myfont = pygame.font.SysFont("mirc", 25)
screen = pygame.display.set_mode((720, 480))
clock = pygame.time.Clock()
health = 10
keys = {"w":False, "a":False, "s":False, "d":False, " ":False}
class Thing:
def __init__(self, picture):
self.texture = pygame.image.load(picture).convert()
self.position = [360, 240]
def draw(self, screen):
screen.blit(self.texture, tuple([int(e) for e in self.position]))
def move(self, direction, distance):
if direction == "UP":
self.position[1] -= distance
elif direction == "DOWN":
self.position[1] += distance
elif direction == "RIGHT":
self.position[0] += distance
elif direction == "LEFT":
self.position[0] -= distance
class Enemy:
def __init__(self, picture):
self.texture = pygame.image.load(picture).convert()
self.position = [15, 110]
def draw(self, screen):
screen.blit(self.texture, tuple([int(e) for e in self.position]))
def move(self, distance):
if player.direction == "UP":
self.position[1] -= distance
elif player.direction == "DOWN":
self.position[0] -= distance
elif player.direction == "RIGHT":
self.position[1] += distance
elif player.direction == "LEFT":
self.position[1] += distance
done = False
black = (0, 0, 0)
player = Thing("2.png")
enemy = Enemy("1.png")
while not done:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
done = True
if event.type == KEYDOWN:
if event.key == K_w:
keys["w"] = True
if event.key == K_a:
keys["a"] = True
if event.key == K_s:
keys["s"] = True
if event.key == K_d:
keys["d"] = True
if event.key == K_SPACE:
keys[" "] = True
if event.type == KEYUP:
if event.key == K_w:
keys["w"] = False
if event.key == K_a:
keys["a"] = False
if event.key == K_s:
keys["s"] = False
if event.key == K_d:
keys["d"] = False
if event.key == K_SPACE:
keys[" "] = False
#Consistent movement
if keys["w"]:
player.move("UP", 2)
if keys["a"]:
player.move("LEFT", 2)
if keys["s"]:
player.move("DOWN", 2)
if keys["d"]:
player.move("RIGHT", 2)
#if keys[" "]:
#Shoot..
#Walls - Player
if player.position[1] <= -2:
player.position[1] += 2
if player.position[1] >= 433:
player.position[1] -= 2
if player.position[0] <= -2:
player.position[0] += 2
if player.position[0] >= 690:
player.position[0] -= 2
#Walls - Enemy
if enemy.position[1] <= -2:
enemy.position[1] += 2
if enemy.position[1] >= 433:
enemy.position[1] -= 2
if enemy.position[0] <= -2:
enemy.position[0] += 2
if enemy.position[0] >= 690:
enemy.position[0] -= 2
#Text
label = myfont.render("Health: " + str(health), 50, (255, 255, 255))
screen.blit(label, (5, 5))
player.draw(screen)
pygame.display.flip()
pygame.quit()
Turns out my original answer was close - your problem is that you're simply drawing the image - you never fill the screen even though you've declared black = (0, 0, 0). You need to put screen.fill(black) before you start drawing everything else.
For the record, here is what a Minimal, Complete, and Verifiable example looks like:
import pygame
from pygame.locals import *
import time
pygame.font.init()
myfont = pygame.font.SysFont("mirc", 25)
screen = pygame.display.set_mode((720, 480))
clock = pygame.time.Clock()
class Thing:
def __init__(self, picture):
self.texture = pygame.image.load(picture).convert()
self.position = [360, 240]
def draw(self, screen):
screen.blit(self.texture, self.position)
done = False
black = (0, 0, 0)
player = Thing(os.path.expanduser("~/Downloads/disapproval.png"))
x_direction = 1
y_direction = 0
while not done:
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
done = True
if player.position[0] < 400:
x_direction = 1
y_direction = 0
elif player.position[0] >= 400 and player.position[1] > 100:
x_direction = 0
y_direction = -1
else:
x_direction = 0
y_direction = 0
player.position[0] += x_direction
player.position[1] += y_direction
# Uncomment this line, and you'll fix your problem
#screen.fill(black)
player.draw(screen)
pygame.display.flip()
pygame.quit()
disapproval.png
I am doing a game where you control a snake and when he dies the game quits. I have tried adding a different function (on) so only while on is true the game will continue. However, this does not restart here is the code I have and could anyone put in a restart function?
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Happy Birthday Mum')
redColour = pygame.Color(255, 0, 0)
blackColour = pygame.Color(0, 0, 0)
whiteColour = pygame.Color(255, 255, 255)
greyColour = pygame.Color(150, 150, 150)
snakePosition = [100,100]
snakeSegments = [[100,100],[80,100],[60,100]]
raspberryPosition = [300,300]
raspberrySpawned = 1
direction = 'right'
changeDirection = direction
diff = 30
def gameOver():
gameOverFont = pygame.font.Font('freesansbold.ttf', 72)
gameOverSurf = gameOverFont.render('Game Over', True, greyColour)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (320, 10)
playSurface.blit(gameOverSurf, gameOverRect)
pygame.display.flip()
time.sleep(5)
pygame.quit()
sys.exit()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
changeDirection = 'right'
if event.key == K_LEFT or event.key == ord('a'):
changeDirection = 'left'
if event.key == K_UP or event.key == ord('w'):
changeDirection = 'up'
if event.key == K_DOWN or event.key == ord('s'):
changeDirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
if event.key == K_1:
diff = 10
if event.key == K_2:
diff = 20
if event.key == K_3:
diff = 30
if event.key == K_4:
diff = 40
if event.key == K_5:
diff = 50
if event.key == K_r:
restart()
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
if direction == 'right':
snakePosition[0] += 20
if direction == 'left':
snakePosition[0] -= 20
if direction == 'up':
snakePosition[1] -= 20
if direction == 'down':
snakePosition[1] += 20
snakeSegments.insert(0,list(snakePosition))
if snakePosition[0] == raspberryPosition[0] and snakePosition[1] == raspberryPosition[1]:
raspberrySpawned = 0
else:
snakeSegments.pop()
if raspberrySpawned == 0:
x = random.randrange(1,32)
y = random.randrange(1,24)
raspberryPosition = [int(x*20),int(y*20)]
raspberrySpawned = 1
playSurface.fill(blackColour)
for position in snakeSegments:
pygame.draw.rect(playSurface,whiteColour,Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface,redColour,Rect(raspberryPosition[0], raspberryPosition[1], 20, 20))
pygame.display.flip()
if snakePosition[0] > 620 or snakePosition[0] < 0:
gameOver()
if snakePosition[1] > 460 or snakePosition[1] < 0:
gameOver()
for snakeBody in snakeSegments[1:]:
if snakePosition[0] == snakeBody[0] and snakePosition[1] == snakeBody[1]:
gameOver()
fpsClock.tick(diff)
You essentially want two while loops - one for when the overall game is running, and a smaller one while the snake is alive.
start pygame and set global variables;
while the program is running:
set all of the initial variables for the game (snake position, etc)
while the snake is alive:
handle input;
check to see if the snake is dead;
I've taken your python code and structured it this way. Pay attention to where I set the variable snake_is_alive to false. See how it makes the inner loop end, but makes the outer loop start over.
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Happy Birthday Mum')
redColour = pygame.Color(255, 0, 0)
blackColour = pygame.Color(0, 0, 0)
whiteColour = pygame.Color(255, 255, 255)
greyColour = pygame.Color(150, 150, 150)
game_is_running = True
while game_is_running:
snakePosition = [100,100]
snakeSegments = [[100,100],[80,100],[60,100]]
raspberryPosition = [300,300]
raspberrySpawned = 1
direction = 'right'
changeDirection = direction
diff = 30
snake_is_alive = True
while snake_is_alive:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
changeDirection = 'right'
if event.key == K_LEFT or event.key == ord('a'):
changeDirection = 'left'
if event.key == K_UP or event.key == ord('w'):
changeDirection = 'up'
if event.key == K_DOWN or event.key == ord('s'):
changeDirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
if event.key == K_1:
diff = 10
if event.key == K_2:
diff = 20
if event.key == K_3:
diff = 30
if event.key == K_4:
diff = 40
if event.key == K_5:
diff = 50
if event.key == K_r:
snake_is_alive = False
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
if direction == 'right':
snakePosition[0] += 20
if direction == 'left':
snakePosition[0] -= 20
if direction == 'up':
snakePosition[1] -= 20
if direction == 'down':
snakePosition[1] += 20
snakeSegments.insert(0,list(snakePosition))
if snakePosition[0] == raspberryPosition[0] and snakePosition[1] == raspberryPosition[1]:
raspberrySpawned = 0
else:
snakeSegments.pop()
if raspberrySpawned == 0:
x = random.randrange(1,32)
y = random.randrange(1,24)
raspberryPosition = [int(x*20),int(y*20)]
raspberrySpawned = 1
playSurface.fill(blackColour)
for position in snakeSegments:
pygame.draw.rect(playSurface,whiteColour,Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface,redColour,Rect(raspberryPosition[0], raspberryPosition[1], 20, 20))
pygame.display.flip()
if snakePosition[0] > 620 or snakePosition[0] < 0:
snake_is_alive = False
if snakePosition[1] > 460 or snakePosition[1] < 0:
snake_is_alive = False
for snakeBody in snakeSegments[1:]:
if snakePosition[0] == snakeBody[0] and snakePosition[1] == snakeBody[1]:
snake_is_alive = False
fpsClock.tick(diff)
gameOverFont = pygame.font.Font('freesansbold.ttf', 72)
gameOverSurf = gameOverFont.render('Game Over', True, greyColour)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (320, 10)
playSurface.blit(gameOverSurf, gameOverRect)
pygame.display.flip()
time.sleep(5)
I got rid of the functions to make it easier to read, but even if you make functions, the overall structure (inner loop and outer loop) should remain the same.
You need to turn your game into a function just like you did with end game. Then in your end game loop instead of exiting just call playGame again. Make sure that you reset all your variables to there original state at the begging of the loop before the while. Something like this: (pseudo code)
import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsClock = pygame.time.Clock()
playSurface = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Happy Birthday Mum')
redColour = pygame.Color(255, 0, 0)
blackColour = pygame.Color(0, 0, 0)
whiteColour = pygame.Color(255, 255, 255)
greyColour = pygame.Color(150, 150, 150)
snakePosition = [100,100]
snakeSegments = [[100,100],[80,100],[60,100]]
raspberryPosition = [300,300]
raspberrySpawned = 1
direction = 'right'
changeDirection = direction
diff = 30
def gameOver():
gameOverFont = pygame.font.Font('freesansbold.ttf', 72)
gameOverSurf = gameOverFont.render('Game Over', True, greyColour)
gameOverRect = gameOverSurf.get_rect()
gameOverRect.midtop = (320, 10)
playSurface.blit(gameOverSurf, gameOverRect)
pygame.display.flip()
time.sleep(5)
playGame();
def playGame():
RESET ALL GAME VARIABLES HERE
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
elif event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == ord('d'):
changeDirection = 'right'
if event.key == K_LEFT or event.key == ord('a'):
changeDirection = 'left'
if event.key == K_UP or event.key == ord('w'):
changeDirection = 'up'
if event.key == K_DOWN or event.key == ord('s'):
changeDirection = 'down'
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
if event.key == K_1:
diff = 10
if event.key == K_2:
diff = 20
if event.key == K_3:
diff = 30
if event.key == K_4:
diff = 40
if event.key == K_5:
diff = 50
if event.key == K_r:
restart()
if changeDirection == 'right' and not direction == 'left':
direction = changeDirection
if changeDirection == 'left' and not direction == 'right':
direction = changeDirection
if changeDirection == 'up' and not direction == 'down':
direction = changeDirection
if changeDirection == 'down' and not direction == 'up':
direction = changeDirection
if direction == 'right':
snakePosition[0] += 20
if direction == 'left':
snakePosition[0] -= 20
if direction == 'up':
snakePosition[1] -= 20
if direction == 'down':
snakePosition[1] += 20
snakeSegments.insert(0,list(snakePosition))
if snakePosition[0] == raspberryPosition[0] and snakePosition[1] == raspberryPosition[1]:
raspberrySpawned = 0
else:
snakeSegments.pop()
if raspberrySpawned == 0:
x = random.randrange(1,32)
y = random.randrange(1,24)
raspberryPosition = [int(x*20),int(y*20)]
raspberrySpawned = 1
playSurface.fill(blackColour)
for position in snakeSegments:
pygame.draw.rect(playSurface,whiteColour,Rect(position[0], position[1], 20, 20))
pygame.draw.rect(playSurface,redColour,Rect(raspberryPosition[0], raspberryPosition[1], 20, 20))
pygame.display.flip()
if snakePosition[0] > 620 or snakePosition[0] < 0:
gameOver()
if snakePosition[1] > 460 or snakePosition[1] < 0:
gameOver()
for snakeBody in snakeSegments[1:]:
if snakePosition[0] == snakeBody[0] and snakePosition[1] == snakeBody[1]:
gameOver()
fpsClock.tick(diff)
playGame();