Reputation: 59
so I am totally new to Python, PyGame and any kind of programming. I have followed a tutorial on making a snake game in PyGame. Now its done but to give myself a challenge I am trying to change the game a bit. First I would like to add borders but I am really lost. I have tried watching other tutorials but they do it with an image which seems to be different. Here is my code (since I didn't know what would help you to help me I sent it all.):
class cube (object):
rows = 20
w = 500
def __init__(self,start,dirnx=1,dirny=0,color = (255,0,0)):
self.pos = start
self.dirnx = 1
self.dirny = 0
self.color = color
def move(self, dirnx, dirny):
self.dirnx = dirnx
self.dirny = dirny
self.pos = (self.pos[0] + self.dirnx, self.pos[1] + self.dirny)
def draw(self, surface, eyes=False):
dis = self.w // self.rows
i = self.pos[0]
j = self.pos[1]
pygame.draw.rect(surface, self.color, (i*dis+1,j*dis+1, dis-2, dis-2))
if eyes:
centre = dis//2
radius = 3
circleMiddle = (i*dis+centre-radius,j*dis+8)
circleMiddle2 = (i*dis + dis -radius*2,j*dis+8)
pygame.draw.circle(surface, (0,0,0), circleMiddle, radius)
pygame.draw.circle(surface, (0,0,0), circleMiddle2, radius)
class snake(object):
body = []
turns = {}
def __init__(self, color, pos):
self.color = color
self.head = cube(pos)
self.body.append(self.head)
self.dirnx = 0
self.dirny = 1
def move(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
for key in keys:
if keys[pygame.K_LEFT]:
self.dirnx = -1
self.dirny = 0
self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]
elif keys[pygame.K_RIGHT]:
self.dirnx = 1
self.dirny = 0
self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]
elif keys[pygame.K_UP]:
self.dirnx = 0
self.dirny = -1
self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]
elif keys[pygame.K_DOWN]:
self.dirnx = 0
self.dirny = 1
self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]
for i, c in enumerate(self.body):
p = c.pos[:]
if p in self.turns:
turn = self.turns[p]
c.move(turn[0], turn[1])
if i == len(self.body)-1:
self.turns.pop(p)
else:
if c.dirnx == -1 and c.pos[0] <= 0: c.pos = (c.rows-1, c.pos[1])
elif c.dirnx == 1 and c.pos[0] >= c.rows-1: c.pos = (0,c.pos[1])
elif c.dirny == 1 and c.pos[1] >= c.rows-1: c.pos = (c.pos[0], 0)
elif c.dirny == -1 and c.pos[1] <= 0: c.pos = (c.pos[0],c.rows-1)
else: c.move(c.dirnx,c.dirny)
def reset(self, pos):
self.head = cube(pos)
self.body = []
self.body.append(self.head)
self.turns = {}
self.dirnx = 0
self.dirny = 1
def addCube(self):
tail = self.body[-1]
dx, dy = tail.dirnx, tail.dirny
if dx == 1 and dy == 0:
self.body.append(cube((tail.pos[0]-1,tail.pos[1])))
elif dx == -1 and dy == 0:
self.body.append(cube((tail.pos[0]+1,tail.pos[1])))
elif dx == 0 and dy == 1:
self.body.append(cube((tail.pos[0],tail.pos[1]-1)))
elif dx == 0 and dy == -1:
self.body.append(cube((tail.pos[0],tail.pos[1]+1)))
self.body[-1].dirnx = dx
self.body[-1].dirny = dy
def draw(self, surface):
for i, c in enumerate(self.body):
if i==0:
c.draw(surface, True)
else:
c.draw(surface)
def drawGrid(w,rows,surface):
rows_space = w // rows
x = 0
y = 0
for l in range(rows):
x += rows_space
y += rows_space
pygame.draw.line(surface, (255,255,255), (x,0), (x,w))
pygame.draw.line(surface, (255,255,255), (0,y), (w,y))
def redrawWindow(surface):
global rows, display_width, s, snack
surface.fill((0,0,0))
s.draw(surface)
snack.draw(surface)
drawGrid(display_width, rows, surface)
pygame.display.update()
def randomSnack(rows,items):
positions = items.body
while True:
x = random.randrange(rows)
y = random.randrange(rows)
if len(list(filter(lambda z:z.pos == (x,y), positions))) > 0:
continue
else:
break
return (x,y)
def message_box(subject,content):
root = tk.Tk()
root.attributes('-topmost', True)
root.withdraw()
messagebox.showinfo(subject, content)
try:
root.destroy()
except:
pass
def main():
global rows, display_width, s, snack
display_width = 500
rows = 20
win = pygame.display.set_mode((display_width, display_width))
s = snake((255,0,0), (10,10))
snack = cube(randomSnack(rows, s), color=(0,255,0))
alive = True
clock = pygame.time.Clock()
while alive:
pygame.time.delay(50)
clock.tick(7)
s.move()
if s.body[0].pos == snack.pos:
s.addCube()
snack = cube(randomSnack(rows, s), color=(0,255,0))
for x in range(len(s.body)):
if s.body[x].pos in list(map(lambda z:z.pos,s.body[x+1:])):
print('Score: ', len(s.body))
message_box('You Lost!', 'Play again!')
s.reset((10,10))
break
redrawWindow(win)
main()
Basically, I want the the same thing to happen when my snake hits a border as when it hits himself. Thank you so much if you could help me!
Upvotes: 1
Views: 1417
Reputation: 2110
well lets just make the window bigger, lets make it one cube size bigger
win = pygame.display.set_mode((display_width + (500//20), display_width + (500//20)))
now we have more space, lets just move everything over so there is a even border around the whole thing
In drawGrid()
draw from one cube size over
pygame.draw.line(surface, (255,255,255), (x,rows_space), (x,w))
pygame.draw.line(surface, (255,255,255), (rows_space,y), (w,y))
Now if you want it coloured, you can draw a rectangle around it the colour your want
pygame.draw.rect(surface,(0,0,200),(0,0,w,rows_space)) #top
pygame.draw.rect(surface,(0,0,200),(0,0,rows_space,w)) #left
pygame.draw.rect(surface,(0,0,200),(0,w,w + rows_space,rows_space)) #bottom
pygame.draw.rect(surface,(0,0,200),(w,0,rows_space,w + rows_space)) #right
If you want a challenge, do the same thing (you can use the method) but instead of increasing the window, decrease the grid size to make a border.
Also, now that you have made snake, try and make it using as little lines as possible, i would look at others first, but its a good thing to do. because personally i think you have over complicated it using a class for each cube of the body.
To end the game when the snake hits an edge is, do the same thing you did for the snake hitting its body, but when the snake is on the border, you have code that checks if the snake goes off the screen and loops it around to the other side, so you can do it there
else:
#if snake off edge
if c.dirnx == -1 and c.pos[0] <= 0: c.pos = (c.rows-1, c.pos[1]);
elif c.dirnx == 1 and c.pos[0] >= c.rows-1: c.pos = (0,c.pos[1])
elif c.dirny == 1 and c.pos[1] >= c.rows-1: c.pos = (c.pos[0], 0)
elif c.dirny == -1 and c.pos[1] <= 0: c.pos = (c.pos[0],c.rows-1)
else: c.move(c.dirnx,c.dirny)
it did not copy and paste well
but now we can change this code from moving the snake to ending the game
outside = False
if c.pos[0] <= 1: outside = True
elif c.pos[0] >= c.rows-1: outside = True
elif c.pos[1] >= c.rows-1: outside = True
elif c.pos[1] <= 1: outside = True
else: c.move(c.dirnx,c.dirny)
if outside:
print('Score: ', len(s.body))
message_box('You Lost!', 'Play again!')
s.reset((10,10))
to fix the snake going onto the border, change the above code to >= 1
instead of 0, this is partly my fault, it is not the best way to do a border, but it is a works, and I'm sure when you go to make snake again, you will make it better
Upvotes: 1