Advice on my pong code - python-3.x

I am doing a clone of pong. It is just a barebone version of pong. And It would be nice if you guys could help me refine it. I am mainly doing it as a learning exercise, So i have just kept it to a basic functions.
import time
import pygame
done = False
pygame.init()
myfont = pygame.font.SysFont("monospace", 15)
screen_size = [320,240]
white = [255,255,255]
black = [0,0,0]
gutter = 10
score_1 = 0
score_2 = 0
ball_pos = [160,120]
ball_vel = [1,1]
paddle_1 = [0,0]
paddle_2 = [screen_size[0]-5,0]
vel_1 = [0,0]
vel_2 = [0,0]
P1 = False
P2 = False
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("mygame")
while not done:
time.sleep(0.02)
screen.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if pygame.key.get_pressed()[pygame.K_DOWN]:
vel_2[1] += 2
P1 = True
if pygame.key.get_pressed()[pygame.K_UP]:
P1 = True
vel_2[1] -= 2
if pygame.key.get_pressed()[pygame.K_s]:
P2 = True
vel_1[1] += 2
if pygame.key.get_pressed()[pygame.K_w]:
P2 = True
vel_1[1] -= 2
if event.type == pygame.KEYUP:
if(P1):
vel_2 = [0,0]
P1 = False
if (P2):
vel_1 = [0,0]
P2 = False
if ball_pos[1] in range(paddle_1[1],paddle_1[1]+30) and ball_pos[0] in range(0,gutter+10) :
ball_vel[0] *= -1
if ball_pos[1] in range(paddle_2[1],paddle_2[1]+30) and ball_pos[0] in range(310,320):
ball_vel[0] *= -1
if ball_pos[0] > 320:
score_1 += 1
ball_pos = [160,120]
if ball_pos[0] < 5:
score_2 += 1
ball_pos = [160,120]
if ball_pos[1] > 230 or ball_pos[1] < 5:
ball_vel[1] *= -1
paddle_1[0] += vel_1[0]
paddle_1[1] += vel_1[1]
paddle_2[0] += vel_2[0]
paddle_2[1] += vel_2[1]
ball_pos[0] += ball_vel[0]
ball_pos[1] += ball_vel[1]
## pygame.draw.line(screen,white,(gutter,0),(gutter,screen_size[1]))
## pygame.draw.line(screen,white,(screen_size[0]-gutter,0),(screen_size[0]-gutter,screen_size[1]))
pygame.draw.line(screen,white,(screen_size[0]/2,0),(screen_size[0]/2,screen_size[1]),1)
pygame.draw.circle(screen,white,ball_pos,10,0)
pygame.draw.line(screen,white,[paddle_1[0]+5,paddle_1[1]],[paddle_1[0]+5,paddle_1[1]+50],gutter)
pygame.draw.line(screen,white,paddle_2,[paddle_2[0],paddle_2[1]+50],gutter)
label_1 = myfont.render(str(score_1), 1, (255,255,0))
label_2 = myfont.render(str(score_2), 1, (255,255,0))
screen.blit(label_1, (100, 100))
screen.blit(label_2, (220, 100))
pygame.display.flip()
pygame.quit()

There are a few things that you should improve in your code:
1) Constants vs Variables
When you define
white = [255,255,255]
black = [0,0,0]
you should instead do:
WHITE = (255,255,255)
BLACK = ( 0, 0, 0)
Constants should usually be created as tuples so that you do not mistakenly change their values. Also, since you only ever read a constant and never change its value a tuple is more appropriate. It also runs slightly faster
2) Creating Classes
Whenever you make a game, it is recommended that you create the objects as classes. In this case, you would have classes such as Player and Ball. In these classes you can define functions such as update and draw. This will allow you to easily draw an object or update its location, speed etc by a single line of code. Eg:
player.update()
player.draw()
ball.draw()
3) Time vs Timer
Instead of using import time, I recommend that you use the pygame built-in Timer option for controlling the FPS of the game. Here's an example:
timer = pygame.time.Clock()
then at the start of your while loop, you can simply do:
timer.tick(60) #if you want 60 to be the number of frames per second
I know it is a lot to take in but in the end the effort will be more than worth it and it will make future game making with pygame much cleaner.
GREAT RESOURCE BOOK
HAPPY PYGAMING!

Try to encapsulate the ball and the paddles in proper Ball and Paddle classes. This way, you make your code cleaner and more reusable, since both paddles will share the same code.

Related

Pygame set_alpha not working with attempted background fading

I've been trying to create a short code to use for a project that can fade in and from black, but for some reason only the function that fades in is working while the fade out function is being skipped more or less. By giving them parameters I confirmed that the problem is in the second function and that the transparency isn't changing at all. Here's my code-
import pygame
screen = pygame.display.set_mode((800,600))
image = pygame.image.load_extended('Map.png').convert_alpha()
image = pygame.transform.scale(image,(530,300))
image.set_alpha(0)
x = 0
y = 255
def fade_in(x):
while True:
screen.blit(image,(0,0))
pygame.display.update()
image.set_alpha(x)
pygame.time.delay(100)
if x < 255:
x += 5
else:
pygame.time.delay(500)
x = 0
fade_out(y)
def fade_out(y):
while True:
screen.blit(image,(0,0))
pygame.display.update()
image.set_alpha(y)
pygame.time.delay(100)
if y > 0:
y -= 5
else:
pygame.time.delay(500)
y = 255
fade_in(x)
while True:
fade_in(x)
Does anyone have an idea of what the problem might be?
When you draw a transparent surface on the screen, the surface is blended with the current contents of the screen. Hence you need to clear the screen before drawing the fading background with screen.fill(0).
Do not try to control the application recursively or with loops within the application loop. Do not delay the game. delay causes the game to stop responding.
Use the application loop and use pygame.time.Clock to control the frames per second and thus the game speed.
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick():
This method should be called once per frame.
That means that the loop:
clock = pygame.time.Clock()
run = True
while run:
clock.tick(60)
Example:
import pygame
pygame.init()
screen = pygame.display.set_mode((400,300))
clock = pygame.time.Clock()
try:
image = pygame.image.load_extended('Map.png').convert_alpha()
image = pygame.transform.scale(image,(530,300))
except:
image = pygame.Surface(screen.get_size())
pygame.draw.circle(image, (255, 0, 0), screen.get_rect().center, min(*screen.get_size()) // 2 - 20)
alpha = 0
alpha_change = 1
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
alpha += alpha_change
if not 0 <= alpha <= 255:
alpha_change *= -1
alpha = max(0, min(alpha, 255))
screen.fill(0)
alpha_image = image.copy()
alpha_image.set_alpha(alpha)
screen.blit(alpha_image, (0, 0))
pygame.display.flip()
pygame.quit()
exit()

Why is this simple pygame program lagging?

So, I've been studying programming for a short time and decided to make the snake game in pygame. However, while making the base of the program I realized that the rectangle (snake) controlled by the player is teleporting (maybe by the lag) every second while moving. Here is the code:
import pygame
pygame.init()
# Window
window = (1280, 720)
center = (window[0]//2, window[1]//2)
screen = pygame.display.set_mode(window)
pygame.display.set_caption("Snake")
# Colors
COLOR_LIGHT_GREY = (200, 200, 200)
COLOR_DARK_GREY = pygame.Color('gray12')
# Game loop
game_loop = True
game_clock = pygame.time.Clock()
# Create image
def img(name):
img_path = "./assets/natanael.lucena_" + name + ".png"
return pygame.image.load(img_path).convert_alpha()
# Set object coordinates
def set_obj_coordinates(obj, x, y):
obj.x = x
obj.y = y
# Check player key press
def check_player_key(b):
global snake_direction
if event.key == pygame.K_w or event.key == pygame.K_s or event.key == pygame.K_a or event.key == pygame.K_d:
snake_direction[event.key] = b
# Check key events in-game
def event_conditional():
global game_loop
if event.type == pygame.QUIT:
game_loop = False
elif event.type == pygame.KEYDOWN:
check_player_key(True)
elif event.type == pygame.KEYUP:
check_player_key(False)
# Check if the snake collided and the game is over
def game_over():
if snake.y < 0 or snake.y > 720 or snake.x < 0 or snake. x > 1280:
return True
# Snake
snake_img = img("snake")
snake = snake_img.get_rect()
move_keys = [pygame.K_w, pygame.K_d, pygame.K_s, pygame.K_a]
snake_direction = {k: False for k in move_keys}
snake_score = 0
snake_vel = 10
set_obj_coordinates(snake, center[0], center[1])
# Apple
apple_img = img("apple")
apple = apple_img.get_rect()
apple_eaten = False
set_obj_coordinates(apple, 40, 40)
# Main game loop
while game_loop:
for event in pygame.event.get():
event_conditional()
# score_text = text_render(snake_score)
if not game_over():
for i in range(4):
if i % 2:
coord_aux = "x "
else:
coord_aux = "y "
if i % 3:
op = "+= "
else:
op = "-= "
if snake_direction[move_keys[i]]:
exec("snake." + coord_aux + op + "snake_vel")
# the for loop above is equivalent to :
# if snake_direction[move_keys[0]]:
# snake.y -= snake_vel
# if snake_direction[move_keys[1]]:
# snake.x += snake_vel
# if snake_direction[move_keys[2]]:
# snake.y += snake_vel
# if snake_direction[move_keys[3]]:
# snake.x -= snake_vel
screen.fill(COLOR_DARK_GREY)
screen.blit(snake_img, snake)
screen.blit(apple_img, apple)
# Update screen
pygame.display.flip()
game_clock.tick(60)
pygame.quit()
If someone can tell me the reason for the problem, I really appreciate it.
Edit: looks like the problem is just happening with me
Thats a common problem with pygame, especially since pygame 2/sdl 2 where you can't use the directx video driver and enable vsync anymore.
You should do the following:
keep track of the sub-pixel coordinates of your moving game objects. A Rect can only store integer values in its x and y attributes, so you'll need another variable to store this. I usually use a Vector2 because it's easy to use and the performance hit usually does not matter anyway.
use an accurate clock. Pygame's clock object only uses milliseconds, which is not accurate enough for really smooth movement. If you're on windows, usually the best method for timing is the GetSystemTimePreciseAsFileTime function.
use a delta timing.
You could also use different threads for the parts of your game that needs different timing methods (e.g. your game logic expects fixed 30 or 60 FPS and your drawing code wants to run as fast as possible), but that's overkill for your small game.
So here's an example I hacked together that gives you smooth movement (at least that's what I use usually since it works fine for me. Note that it's windows specific):
import pygame
import ctypes.wintypes
pygame.init()
screen = pygame.display.set_mode((1280, 720))
center = screen.get_rect().center
pygame.display.set_caption("Snake")
game_loop = True
# https://stackoverflow.com/a/28574340/142637
def utcnow_microseconds():
system_time = ctypes.wintypes.FILETIME()
ctypes.windll.kernel32.GetSystemTimePreciseAsFileTime(ctypes.byref(system_time))
large = (system_time.dwHighDateTime << 32) + system_time.dwLowDateTime
return large // 10 - 11644473600000000
# Snake
snake_img = pygame.Surface((40, 40))
snake_img.fill('white')
snake = snake_img.get_rect()
snake_vel = 10
snake_pos = pygame.Vector2(center[0], center[1])
snake.topleft = snake_pos.x, snake_pos.y
# Apple
apple_img = pygame.Surface((40, 40))
apple_img.fill('red')
apple = apple_img.get_rect(topleft=(40, 40))
dt = 0
while game_loop:
t1 = utcnow_microseconds()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_loop = False
keys = pygame.key.get_pressed()
snake_pos.x += (keys[pygame.K_d] - keys[pygame.K_a]) * snake_vel * dt
snake_pos.y += (keys[pygame.K_s] - keys[pygame.K_w]) * snake_vel * dt
snake.topleft = snake_pos.x, snake_pos.y
screen.fill('darkgrey')
screen.blit(snake_img, snake)
screen.blit(apple_img, apple)
pygame.display.flip()
t2 = utcnow_microseconds()
dt = (t2 - t1) / 1000. / 1000. * 30
pygame.quit()
Further reading.
Very likely the bottleneck is the line
exec("snake." + coord_aux + op + "snake_vel")
exec has to parse and interpret the text in the argument.
This code can be easily improved
if not game_over():
for i in range(4):
if snake_direction[move_keys[i]]:
sign = 1 if i % 3 else -1
if i % 2:
snake.x += sign * snake_vel
else:
snake.y += sign * snake_vel
Since snake is a pygame.Rect object, you can even do the following:
if not game_over():
for i in range(4):
if snake_direction[move_keys[i]]:
sign = 1 if i % 3 else -1
snake[(i+1) % 2] += sign * snake_vel
However:
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.
pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement.
Use pygame.key.get_pressed() for a smooth continuous movement:
# Main game loop
while game_loop:
for event in pygame.event.get():
event_conditional()
# score_text = text_render(snake_score)
if not game_over():
keys = pygame.key.get_pressed()
snake.x += (keys[pygame.K_d] - keys[pygame.K_a]) * snake_vel
snake.y += (keys[pygame.K_s] - keys[pygame.K_w]) * snake_vel
# [...]

Pacman - Collision Detection Problems (Pygame)

I am relatively new to Pygame and I'm attempting to create a Pacman game for a project. I'm having trouble with collision detection between Pacman and this block (imported image). Pacman goes right through the block which I don't want to happen; I want it so that Pacman can't pass through it. I've searched many websites and many forums and tried many different methods that I've seen other people have used but I can't seem to get my head around collision detection. Below is my current code.
def Pacman():
pygame.init()
# Creating screen
global screen
screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN)
screen = pygame.display.set_mode((0,0), pygame.RESIZABLE)
# Setting window caption
pygame.display.set_caption('Pacman')
# Loading two images
pacman_image = pygame.image.load("pacmanphoto.png").convert_alpha()
block_image = pygame.image.load("blockphoto.png").convert_alpha()
rect1 = pacman_image.get_rect()
rect2 = block_image.get_rect()
rect1.x = 100
rect1.y = 200
rect2.x = 300
rect2.y = 400
clock = pygame.time.Clock()
x = 10
y = 10
pygame.key.set_repeat(10, 10)
# Movement
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
y -= 10
if event.key == pygame.K_DOWN:
y += 10
if event.key == pygame.K_RIGHT:
x += 10
if event.key == pygame.K_LEFT:
x -= 10
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if rect1.colliderect(rect2):
y -=10
##### where collision detection should be ####
# Displaying images on screen
screen.blit(pacman_image, (x,y))
screen.blit(block_image, (50,50))
clock.tick(12)
pygame.display.update()
screen.fill(BLACK)
If anyone can help me in any way please let me know :)
Thanks
First of all, your code is fairly unorganized. I recommend using classes so that the Pacman function looks a lot clearer, readable and everything isn't squeezed inside only one function.
If you don't want the Pacman to go through the blocks, you should know what you're up to. You don't want the Pacman to pass through the blocks, which basically means that if the Pacman's y(y-axis value) is between the block's y-axis and the same for the x-axis, then collision occurred, from here on you can just set the pacman_x and pacman's y to the block's x and y.
# Inside The Pacman Function
pac_x = 10
pac_y = 10
block_x = 50
block_y = 50
# getting the block's height and width
block_width, block_height = block_image.get_size()
##### where collision detection should be ####
if block_x + block_width > pac_x > block_x:
if block_y + block_height > pac_y > block_y:
print('Collision occurred.')
pac_x = block_x
pac_y = block_y
# Here you can add more functionality to your game
# Displaying images on screen
screen.blit(pacman_image, (pac_x,pac_y))
screen.blit(block_image, (block_x, block_y))

can't stop program randomizing. Pygame

Ye i know this is quite noob question but problem is this.
i'm making a game and i wanna randomize stars to a huge space area
But results that i get are:
The space keeps recaculating places of stars so everything moves.
It Shows only 1 star on the upper left corner of window.
Here is the full code:
import os
import pygame
from pygame.locals import *
import random
gstars = 500
gstarmax = 0
red = (255,0,0)
yellow = (240,250,60)
timer = 0
size = [1600, 1000]
screen = pygame.display.set_mode((1600, 1000), HWSURFACE | DOUBLEBUF | RESIZABLE)
pygame.display.set_caption('planet system test')
clock = pygame.time.Clock()
area = pygame.image.load("screenMonitor.png")
done = False
while done == False:
pygame.event.pump()
mouse_x, mouse_y = pygame.mouse.get_pos()
timer += 1
if timer > 99:
timer = 0
screen.fill((0,0,0))
pygame.draw.rect(screen, red, (20, 20, 1350, 480), 2)
pygame.draw.rect(screen,yellow,(2,2,2,2),2)
go = True
if go == True:
for i in range(gstars):
s1 = random.randrange(1,1600)
s2 = random.randrange(1,1000)
colorSelect = random.randrange(0,5)
if colorSelect == 1:
yellow = (240,250,60)
if colorSelect == 2:
yellow = (249,173,60)
if colorSelect == 3:
yellow = (226,43,68)
if colorSelect == 4:
yellow = (52,173,84)
go = False
pygame.draw.rect(screen,yellow,(2+s1,2+s2,2,2),2)
pygame.display.flip()
clock.tick(30)
pygame.quit()
The trouble is in the main/event loop.
You put the code for position your stars inside the main loop. Since it is randomize at every iteration, it will move.
I remove the go = False that probably cause the error to display only one star.
In the following code, I create a list of star that have the position in indices 0 and 1, and the tuple of the color in 2.
The tuple of color is randomly choose using the random.choice(Sequence) function. https://docs.python.org/2/library/random.html
import pygame
from pygame import *
import random
gstars = 500
gstarmax = 0
red = (255,0,0)
yellow = (240,250,60)
timer = 0
size = [1600, 1000]
pygame.init()
pygame.display.set_caption('planet system test')
screen = pygame.display.set_mode((size[0], size[1]))
clock = pygame.time.Clock()
area = pygame.image.load("screenMonitor.png")
color = ((240,250,60),(249,173,60),(226,43,68),(52,173,84))
stars = []
for i in range(gstars):
s1 = random.randrange(1,1600)
s2 = random.randrange(1,1000)
starcolor = random.choice(color)
stars.append([s1, s2, starcolor])
done = False
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT: #Quit the game if X
done = False
screen.fill(0)
pygame.draw.rect(screen, red, (20, 20, 1350, 480), 2)
pygame.draw.rect(screen,yellow,(2,2,2,2),2)
for star in stars:
pygame.draw.rect(screen,star[2],(2+star[0],2+star[1],2,2),2)
pygame.display.flip()
clock.tick(30)
EDIT : Correct the code following the advice of Ted Klein Bergman.

How to generate the food for a snake game

I can not figure out how to generate the food for the snake to eat. I know the position of the snake at line 97 and 98, I have created a class to generate a pixel where I want to draw a peace of food at line 22 (EDIT: should probably be a function, commented #def (?) in the code). All I have to do is add 15 pixels at the x and y coordinates from the position that is randomly allocated and print it to get a block.
The problem is to check if I eat it or not. It should be something like:
if x >= x_food && x <= x_food + 15 || y >= y_food && y <= y_food + 15:
...add a point and make snake longer...
The problem is putting it all together for some reason.. Can some one give me a hint or solve how I should write this class so I can continue with other problems? Thank you!
import pygame
import random
#Global variables
#Color
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
#Start length of snake
snake_length = 3
#Set the width of the segments of the snake
segment_width = 15
segment_height = 15
# Margin within each segment
segment_margin = 3
#Set initial speed
x_change = segment_width + segment_margin
y_change = 0
#def (?)
class Food():
#Class to print food
x_food = random.randint(0, 785)
y_food = random.randint(0, 585)
class Segment(pygame.sprite.Sprite):
""" Class to represent the segment of the snake. """
# Methods
# Constructer function
def __init__(self, x, y):
#Call the parents constructor
super().__init__()
#Set height, width
self.image = pygame.Surface([segment_width, segment_height])
self.image.fill(WHITE)
#Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
#Call this function so the Pygame library can initialize itself
pygame.init()
#Create an 800x600 size screen
screen = pygame.display.set_mode([800, 600])
#Set the title of the window
pygame.display.set_caption("Snake")
allspriteslist = pygame.sprite.Group()
#Create an initial snake
snake_segments = []
for i in range(snake_length):
x = 250 - (segment_width + segment_margin) * i
y = 30
segment = Segment(x, y)
snake_segments.append(segment)
allspriteslist.add(segment)
clock = pygame.time.Clock()
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#Set the speed based on the key pressed
#We want the speed to be enough that we move a full
#Segment, plus the margin
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = (segment_width + segment_margin) * -1
y_change = 0
if event.key == pygame.K_RIGHT:
x_change = (segment_width + segment_margin)
y_change = 0
if event.key == pygame.K_UP:
x_change = 0
y_change = (segment_height + segment_margin) * -1
if event.key == pygame.K_DOWN:
x_change = 0
y_change = (segment_width + segment_margin)
#Get rid of last segment of the snake
#.pop() command removes last item in list
old_segment = snake_segments.pop()
allspriteslist.remove(old_segment)
#Figure out where new segment will be
x = snake_segments[0].rect.x + x_change
y = snake_segments[0].rect.y + y_change
segment = Segment(x, y)
#Insert new segment to the list
snake_segments.insert(0, segment)
allspriteslist.add(segment)
#Draw
#Clear screen
screen.fill(BLACK)
allspriteslist.draw(screen)
#Flip screen
pygame.display.flip()
#Pause
clock.tick(5)
pygame.quit()
i took your code and i think i work something out, pls note that this only monitors when the snake goes over the block, then it prints: yummy, so you will have to add the detail, also note that i dont use your class to generate the food:
import pygame
import random
#Global variables
#Color
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
#Start length of snake
snake_length = 3
#Set the width of the segments of the snake
segment_width = 15
segment_height = 15
# Margin within each segment
segment_margin = 3
#Set initial speed
x_change = segment_width + segment_margin
y_change = 0
#def (?)
class Food():
#Class to print food
x_food = random.randint(0, 785)
y_food = random.randint(0, 585)
class Segment(pygame.sprite.Sprite):
""" Class to represent the segment of the snake. """
# Methods
# Constructer function
def __init__(self, x, y):
#Call the parents constructor
super().__init__()
#Set height, width
self.image = pygame.Surface([segment_width, segment_height])
self.image.fill(WHITE)
#Make our top-left corner the passed-in location.
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
#Call this function so the Pygame library can initialize itself
pygame.init()
#Create an 800x600 size screen
screen = pygame.display.set_mode([800, 600])
#Set the title of the window
pygame.display.set_caption("Snake")
allspriteslist = pygame.sprite.Group()
#Create an initial snake
snake_segments = []
for i in range(snake_length):
x = 250 - (segment_width + segment_margin) * i
y = 30
segment = Segment(x, y)
snake_segments.append(segment)
allspriteslist.add(segment)
clock = pygame.time.Clock()
done = False
x_food = random.randint(0, 785)
y_food = random.randint(0, 585)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#Set the speed based on the key pressed
#We want the speed to be enough that we move a full
#Segment, plus the margin
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = (segment_width + segment_margin) * -1
y_change = 0
if event.key == pygame.K_RIGHT:
x_change = (segment_width + segment_margin)
y_change = 0
if event.key == pygame.K_UP:
x_change = 0
y_change = (segment_height + segment_margin) * -1
if event.key == pygame.K_DOWN:
x_change = 0
y_change = (segment_width + segment_margin)
if y < y_food+30:
if x > x_food and x < x_food+30 or x+20 > x_food and x+20<x_food+30:
print('yummy')
#Get rid of last segment of the snake
#.pop() command removes last item in list
old_segment = snake_segments.pop()
allspriteslist.remove(old_segment)
#Figure out where new segment will be
x = snake_segments[0].rect.x + x_change
y = snake_segments[0].rect.y + y_change
segment = Segment(x, y)
#Insert new segment to the list
snake_segments.insert(0, segment)
allspriteslist.add(segment)
#Draw
#Clear screen
screen.fill(BLACK)
pygame.draw.rect(screen, WHITE, [x_food, y_food, 30, 30])
allspriteslist.draw(screen)
#Flip screen
pygame.display.flip()
#Pause
clock.tick(5)
pygame.quit()
hope this helped, thanks!
if x >= x_food && x <= x_food + 15 || y >= y_food && y <= y_food + 15:
Why do you OR these pairs of conditions? Don't all 4 tests have to be true at the same time?
if x >= x_food && x <= x_food + 15 && y >= y_food && y <= y_food + 15:
how about using:
if snake_headx == foodx and snake_heady == foody:
food_eated()
snake_grow()
just a suggestion though
didnt read all ur code, just thought u might find it usefull.
actuely ive came to a solution, so basicly what you want is a square, and when the snake comes near that square something should happen?, well ive got a racegame that makes you crash when you hit a square car, so il just copy the code here:
if y < thing_starty+thing_height:
if x > thing_startx and x < thing_startx+thing_width or x+car_width > thing_startx and x+car_width<thing_startx+thing_width:
snake_eated()
snake_grow()
this monitors the x and y of your car (or snake) and checks when the thing (or food) 's y is smaller than your car, then it checks the x's and alot of other things, and basicly it creates a big line all around your square that you cannot cross in your case you'd just need to add the rest, would this work?
Make your food a sprite with a simple filled rectangle as the image, and then use sprite collision pygame.sprite.spritecollide() to check if your snake collides with your food. Pygame will take care of the actual logic whether two rectangles overlap for you.
Also, since you are already using sprite groups, I suggest you write an update function for your snake segments which moves them instead of creating a new segment every turn. Then you can simply call allspriteslist.update() in your main game loop, which will call the update function for every snake segment.
Finally, you might want to have a look at the numerous snake examples on the pygame website.

Resources