-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodels.py
137 lines (114 loc) · 4.63 KB
/
models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import random
import pygame
class Colors:
GREY = pygame.Color(71, 106, 111)
WHITE = pygame.Color(0, 0, 0)
SNAKE = [
pygame.Color(91, 80, 122),
pygame.Color(91, 97, 138),
pygame.Color(185, 226, 140),
pygame.Color(158, 173, 200),
pygame.Color(216, 214, 79),
pygame.Color(78, 205, 196),
pygame.Color(48, 99, 142),
pygame.Color(98, 108, 102),
pygame.Color(155, 151, 178),
pygame.Color(250, 207, 173)
]
RED = pygame.Color(209, 73, 91)
DARKER_RED = pygame.Color(214, 26, 26)
class Snake:
MOVE_EVENT = pygame.USEREVENT
def __init__(self, screen):
self.screen = screen
self.delay = 300 # 1 pixel per x ms
pygame.time.set_timer(self.MOVE_EVENT, self.delay)
self.rects = [SnakePixel(0, 0, 50, 50, direction='+x', index=0)]
self.draw()
@property
def size(self):
return len(self.rects)
@property
def lefts(self):
for i in self.rects:
yield i.left
@property
def tops(self):
for i in self.rects:
yield i.top
def move(self):
for n, i in enumerate(reversed(self.rects)):
n = self.size - 1 - n
if n != 0: # first element
if self.rects[n - 1].turn_at and self.rects[n - 1].turn_at[0][:2] == (i.left, i.top):
i.direction = self.rects[n - 1].turn_at[0][2]
if self.size > n + 1:
i.turn_at.append((i.left, i.top, i.direction))
del self.rects[n - 1].turn_at[0]
i.move()
def draw(self):
for i in self.rects:
pygame.draw.rect(self.screen, i.color, i)
def turn(self, direction):
self.rects[0].direction = direction
if self.size > 1:
self.rects[0].turn_at.append((self.rects[0].left, self.rects[0].top, self.rects[0].direction))
def grow(self):
if self.rects[-1].direction == '+x':
self.rects.append(SnakePixel(self.rects[-1].left - 50, self.rects[-1].top, 50, 50, direction=self.rects[-1].direction, index=self.size))
if self.rects[-1].direction == '-x':
self.rects.append(SnakePixel(self.rects[-1].left + 50, self.rects[-1].top, 50, 50, direction=self.rects[-1].direction, index=self.size))
if self.rects[-1].direction == '+y':
self.rects.append(SnakePixel(self.rects[-1].left, self.rects[-1].top - 50, 50, 50, direction=self.rects[-1].direction, index=self.size))
if self.rects[-1].direction == '-y':
self.rects.append(SnakePixel(self.rects[-1].left, self.rects[-1].top + 50, 50, 50, direction=self.rects[-1].direction, index=self.size))
# speed up slightly after every apple eaten
self.delay *= 0.9
self.delay = int(self.delay)
self.delay = max(self.delay, 100)
pygame.time.set_timer(self.MOVE_EVENT, self.delay)
def colliderect(self, rect):
for i in self.rects:
if i.colliderect(rect):
return True
return False
def inside(self, rect):
for i in self.rects:
if not rect.contains(i):
return False
return True
def is_self_collide(self):
for i in self.rects:
for j in self.rects:
if i.index != j.index and i.colliderect(j):
return True
return False
class SnakePixel(pygame.Rect):
def __init__(self, *args, **kwargs):
self.index = kwargs.pop('index')
self.direction = kwargs.pop('direction')
self.color = random.choice(Colors.SNAKE)
self.turn_at = []
super().__init__(*args, **kwargs)
def move(self):
if self.direction == '+x':
self.left += 50
if self.direction == '-x':
self.left -= 50
if self.direction == '+y':
self.top += 50
if self.direction == '-y':
self.top -= 50
class Apple:
def __init__(self, screen, snake):
self.screen = screen
self.snake = snake
self.rect = pygame.Rect(random.randint(0, (800 - 50) // 50) * 50, random.randint(0, (800 - 50) // 50) * 50, 50, 50)
pygame.draw.rect(screen, Colors.RED, self.rect)
def regenerate(self):
self.rect.left = random.randint(0, (800 - 50) // 50) * 50
self.rect.top = random.randint(0, (800 - 50) // 50) * 50
while self.rect.left in self.snake.lefts or self.rect.top in self.snake.tops:
self.rect.left = random.randint(0, (800 - 50) // 50) * 50
self.rect.top = random.randint(0, (800 - 50) // 50) * 50
pygame.draw.rect(self.screen, Colors.RED, self.rect)