Compare commits
11 Commits
Author | SHA1 | Date |
---|---|---|
Plaza521 | bf638e711e | |
Plaza521 | a89e41cd68 | |
Plaza521 | aff3036a0d | |
Plaza521 | a77fe7840d | |
Plaza521 | 4840b016db | |
Plaza521 | b6a097bbb3 | |
Plaza521 | a96f8fcc71 | |
Plaza521 | 9e82c9478a | |
Plaza521 | 95e1653b1a | |
Plaza521 | 996eebe470 | |
Plaza521 | ffc75251f1 |
|
@ -4,4 +4,5 @@ Snake, but in console
|
||||||
Default keys:
|
Default keys:
|
||||||
--
|
--
|
||||||
W A S D - move
|
W A S D - move
|
||||||
Q - quit
|
Q - quit
|
||||||
|
P - pause
|
||||||
|
|
3
food.py
3
food.py
|
@ -4,9 +4,8 @@ from settings import *
|
||||||
|
|
||||||
|
|
||||||
class Food(Point):
|
class Food(Point):
|
||||||
def __init__(self, x, y, pl):
|
def __init__(self, x, y):
|
||||||
Point.__init__(self, x, y)
|
Point.__init__(self, x, y)
|
||||||
self.pl = pl
|
|
||||||
|
|
||||||
def generate_new(self) -> None:
|
def generate_new(self) -> None:
|
||||||
self.x = randint(0, WIDTH - 1)
|
self.x = randint(0, WIDTH - 1)
|
||||||
|
|
40
frame.py
40
frame.py
|
@ -9,10 +9,10 @@ if platform == "win32":
|
||||||
class COORDSET(Structure):
|
class COORDSET(Structure):
|
||||||
_fields_ = [("X", c_long), ("Y", c_long)]
|
_fields_ = [("X", c_long), ("Y", c_long)]
|
||||||
|
|
||||||
def _set_cursor_position(x: int, y: int) -> None:
|
def set_cursor_position(x: int, y: int) -> None:
|
||||||
windll.kernel32.SetConsoleCursorPosition(STDHANDLE, COORDSET(x, y))
|
windll.kernel32.SetConsoleCursorPosition(STDHANDLE, COORDSET(x, y))
|
||||||
else:
|
else:
|
||||||
def _set_cursor_position(x: int, y: int) -> None:
|
def set_cursor_position(x: int, y: int) -> None:
|
||||||
print(f"\033[{x};{y}H")
|
print(f"\033[{x};{y}H")
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,14 +23,20 @@ class Frame:
|
||||||
self.matrix = [[SPACE] * width for line in range(height)]
|
self.matrix = [[SPACE] * width for line in range(height)]
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
out_string = f"Width:\n {self.width}\n"
|
return (
|
||||||
out_string += f"Height:\n {self.height}\n"
|
f"Width:\n {self.width}\n"
|
||||||
return out_string
|
f"Height:\n {self.height}"
|
||||||
|
)
|
||||||
|
|
||||||
def draw(
|
def draw(
|
||||||
self, x: int, y: int,
|
self,
|
||||||
|
|
||||||
|
x: int,
|
||||||
|
y: int,
|
||||||
|
|
||||||
value: int = WALL,
|
value: int = WALL,
|
||||||
width: int = 1, height: int = 1
|
width: int = 1,
|
||||||
|
height: int = 1
|
||||||
) -> None:
|
) -> None:
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
raise TypeError("Value must be int")
|
raise TypeError("Value must be int")
|
||||||
|
@ -40,27 +46,29 @@ class Frame:
|
||||||
self.matrix[y + line][x + column] = value
|
self.matrix[y + line][x + column] = value
|
||||||
|
|
||||||
def show(self) -> None:
|
def show(self) -> None:
|
||||||
_set_cursor_position(0, 0)
|
set_cursor_position(0, 0)
|
||||||
|
|
||||||
out_string = f"┍{'━' * (self.width * 2)}┑\n"
|
out_string = f"{WALL_COLOR}┍{'━' * (self.width * 2)}┑{RESET_COLOR}\n"
|
||||||
|
|
||||||
for line in self.matrix:
|
for line in self.matrix:
|
||||||
to_str = ''
|
to_str = ''
|
||||||
|
|
||||||
to_str += '│'
|
to_str += f'{WALL_COLOR}│{RESET_COLOR}'
|
||||||
for elem in line:
|
for elem in line:
|
||||||
if elem == SPACE:
|
if elem == SPACE:
|
||||||
to_str += " "
|
to_str += TT_SPACE
|
||||||
elif elem == WALL:
|
elif elem == WALL:
|
||||||
to_str += "██"
|
to_str += TT_WALL
|
||||||
elif elem == FOOD:
|
elif elem == FOOD:
|
||||||
to_str += "@@"
|
to_str += TT_FOOD
|
||||||
elif elem == WALL_FOOD:
|
elif elem == WALL_FOOD:
|
||||||
to_str += "@█"
|
to_str += TT_WALL_FOOD
|
||||||
to_str += '│\n'
|
elif elem == HEAD:
|
||||||
|
to_str += TT_HEAD
|
||||||
|
to_str += f'{WALL_COLOR}│{RESET_COLOR}\n'
|
||||||
|
|
||||||
out_string += to_str
|
out_string += to_str
|
||||||
out_string += f"┕{'━' * (self.width * 2)}┙"
|
out_string += f"{WALL_COLOR}┕{'━' * (self.width * 2)}┙{RESET_COLOR}"
|
||||||
|
|
||||||
print(out_string)
|
print(out_string)
|
||||||
|
|
||||||
|
|
66
main.py
66
main.py
|
@ -1,48 +1,80 @@
|
||||||
# from frame import Frame
|
|
||||||
from settings import *
|
from settings import *
|
||||||
from player import Player
|
from player import Player
|
||||||
import keyboard as kb
|
import keyboard as kb
|
||||||
from out import Out
|
from out import Out
|
||||||
from os import system
|
from os import system
|
||||||
|
from time import sleep, time
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.running = True
|
self.running = True
|
||||||
|
self.is_pause = False
|
||||||
self.pl = Player()
|
self.pl = Player()
|
||||||
self.out = Out()
|
self.out = Out(self.pl)
|
||||||
|
|
||||||
kb.add_hotkey(QUIT_BUTTON, self.stop_game)
|
kb.add_hotkey(QUIT_BUTTON, self.stop_game)
|
||||||
kb.add_hotkey(LEFT_BUTTON, self.pl.left)
|
kb.add_hotkey(PAUSE_BUTTON, self.switch_pause)
|
||||||
kb.add_hotkey(RIGHT_BUTTON, self.pl.right)
|
kb.add_hotkey(
|
||||||
kb.add_hotkey(UP_BUTTON, self.pl.up)
|
LEFT_BUTTON,
|
||||||
kb.add_hotkey(DOWN_BUTTON, self.pl.down)
|
self.pl.left,
|
||||||
|
args=[self]
|
||||||
|
)
|
||||||
|
kb.add_hotkey(
|
||||||
|
RIGHT_BUTTON,
|
||||||
|
self.pl.right,
|
||||||
|
args=[self]
|
||||||
|
)
|
||||||
|
kb.add_hotkey(
|
||||||
|
UP_BUTTON,
|
||||||
|
self.pl.up,
|
||||||
|
args=[self]
|
||||||
|
)
|
||||||
|
kb.add_hotkey(
|
||||||
|
DOWN_BUTTON,
|
||||||
|
self.pl.down,
|
||||||
|
args=[self]
|
||||||
|
)
|
||||||
|
|
||||||
|
def switch_pause(self) -> None:
|
||||||
|
self.is_pause = not self.is_pause
|
||||||
|
|
||||||
def stop_game(self) -> None:
|
def stop_game(self) -> None:
|
||||||
self.running = False
|
if not self.is_pause:
|
||||||
|
self.running = False
|
||||||
def update(self) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def output(self) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def play(self) -> None:
|
def play(self) -> None:
|
||||||
system("clear||cls")
|
system("clear||cls")
|
||||||
|
print()
|
||||||
|
|
||||||
|
start_time = time()
|
||||||
|
different_between_time = 1 / FPS
|
||||||
|
|
||||||
while self.running:
|
while self.running:
|
||||||
try:
|
try:
|
||||||
self.pl.update()
|
sleep(1 / FPS - different_between_time)
|
||||||
self.out.draw(self.pl)
|
start_time = time()
|
||||||
|
|
||||||
|
if not self.is_pause:
|
||||||
|
self.pl.input()
|
||||||
|
self.pl.update()
|
||||||
|
self.out.draw()
|
||||||
|
|
||||||
|
end_time = time()
|
||||||
|
different_between_time = start_time - end_time
|
||||||
|
|
||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
self.running = False
|
self.running = False
|
||||||
print(e)
|
print(e)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
return
|
||||||
|
|
||||||
input("Press enter to leave from game")
|
input("Press enter to leave from game.\n")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
Game().play()
|
game = Game()
|
||||||
|
game.play()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
20
out.py
20
out.py
|
@ -4,26 +4,28 @@ from frame import Frame
|
||||||
|
|
||||||
|
|
||||||
class Out:
|
class Out:
|
||||||
def __init__(self) -> None:
|
def __init__(self, pl: Player) -> None:
|
||||||
self.width = WIDTH
|
self.width = WIDTH
|
||||||
self.height = HEIGHT
|
self.height = HEIGHT
|
||||||
self.fps = FPS
|
self.pl = pl
|
||||||
|
|
||||||
def draw(self, pl: Player) -> None:
|
def draw(self) -> None:
|
||||||
frame = Frame(self.width, self.height)
|
frame = Frame(self.width, self.height)
|
||||||
|
pl = self.pl
|
||||||
|
|
||||||
for point in pl.body:
|
for point in pl.body:
|
||||||
if point.x < 0 or point.y < 0:
|
|
||||||
raise IndexError("Snake has collision with walls")
|
|
||||||
elif point.x >= WIDTH or point.y >= HEIGHT:
|
|
||||||
raise IndexError("Snake has collision with walls")
|
|
||||||
|
|
||||||
frame.draw(
|
frame.draw(
|
||||||
x=point.x, y=point.y,
|
x=point.x, y=point.y,
|
||||||
value=WALL,
|
value=WALL,
|
||||||
width=1, height=1
|
width=1, height=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
frame.draw(
|
||||||
|
x=pl.body[-1].x, y=pl.body[-1].y,
|
||||||
|
value=HEAD,
|
||||||
|
width=1, height=1
|
||||||
|
)
|
||||||
|
|
||||||
if frame.see(pl.food.x, pl.food.y) == WALL:
|
if frame.see(pl.food.x, pl.food.y) == WALL:
|
||||||
frame.draw(
|
frame.draw(
|
||||||
x=pl.food.x, y=pl.food.y,
|
x=pl.food.x, y=pl.food.y,
|
||||||
|
@ -36,4 +38,4 @@ class Out:
|
||||||
)
|
)
|
||||||
|
|
||||||
frame.show()
|
frame.show()
|
||||||
print(F"Score: {pl.score}")
|
print(f"Score: {pl.score}")
|
||||||
|
|
51
player.py
51
player.py
|
@ -1,53 +1,62 @@
|
||||||
from settings import *
|
from settings import *
|
||||||
from point import Point
|
from point import Point
|
||||||
from food import Food
|
from food import Food
|
||||||
from time import sleep
|
|
||||||
from itertools import permutations
|
|
||||||
|
|
||||||
|
|
||||||
class Player:
|
class Player:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
self.start_direciton = MAIN_DIRECTION
|
||||||
self.direction = MAIN_DIRECTION
|
self.direction = MAIN_DIRECTION
|
||||||
self.body = [Point(MAIN_X, MAIN_Y)]
|
self.body = [Point(MAIN_X, MAIN_Y)]
|
||||||
|
|
||||||
self.food = Food(0, 0, self)
|
self.food = Food(0, 0)
|
||||||
self.food.generate_new()
|
self.food.generate_new()
|
||||||
|
|
||||||
self.score = 0
|
self.score = 1
|
||||||
|
|
||||||
def update(self) -> None:
|
|
||||||
sleep(1 / FPS)
|
|
||||||
|
|
||||||
|
def input(self) -> None:
|
||||||
if self.direction == D_UP:
|
if self.direction == D_UP:
|
||||||
# self.body[0].y -= 1
|
|
||||||
self.body.append(Point(self.body[-1].x, self.body[-1].y - 1))
|
self.body.append(Point(self.body[-1].x, self.body[-1].y - 1))
|
||||||
elif self.direction == D_DOWN:
|
elif self.direction == D_DOWN:
|
||||||
# self.body[0].y += 1
|
|
||||||
self.body.append(Point(self.body[-1].x, self.body[-1].y + 1))
|
self.body.append(Point(self.body[-1].x, self.body[-1].y + 1))
|
||||||
elif self.direction == D_LEFT:
|
elif self.direction == D_LEFT:
|
||||||
# self.body[0].x -= 1
|
|
||||||
self.body.append(Point(self.body[-1].x - 1, self.body[-1].y))
|
self.body.append(Point(self.body[-1].x - 1, self.body[-1].y))
|
||||||
elif self.direction == D_RIGHT:
|
elif self.direction == D_RIGHT:
|
||||||
# self.body[0].x += 1
|
|
||||||
self.body.append(Point(self.body[-1].x + 1, self.body[-1].y))
|
self.body.append(Point(self.body[-1].x + 1, self.body[-1].y))
|
||||||
|
|
||||||
|
def _check_collision(body: list[Point]) -> None:
|
||||||
|
for point in body:
|
||||||
|
if point.x < 0 or point.y < 0:
|
||||||
|
raise IndexError("Snake has collision with walls")
|
||||||
|
elif point.x >= WIDTH or point.y >= HEIGHT:
|
||||||
|
raise IndexError("Snake has collision with walls")
|
||||||
|
|
||||||
|
if len(set(body)) != len(body):
|
||||||
|
raise IndexError("Player has collision with self")
|
||||||
|
|
||||||
|
def update(self) -> None:
|
||||||
|
self.start_direction = self.direction
|
||||||
|
|
||||||
if self.body[-1] == self.food:
|
if self.body[-1] == self.food:
|
||||||
self.food.generate_new()
|
self.food.generate_new()
|
||||||
self.score += 1
|
self.score += 1
|
||||||
else:
|
else:
|
||||||
self.body.pop(0)
|
self.body.pop(0)
|
||||||
|
|
||||||
if len(set(self.body)) != len(self.body):
|
Player._check_collision(self.body)
|
||||||
raise IndexError("Player has collision with self")
|
|
||||||
|
|
||||||
def left(self) -> None:
|
def left(self, game) -> None:
|
||||||
self.direction = D_LEFT
|
if not game.is_pause and self.start_direction != D_RIGHT:
|
||||||
|
self.direction = D_LEFT
|
||||||
|
|
||||||
def right(self) -> None:
|
def right(self, game) -> None:
|
||||||
self.direction = D_RIGHT
|
if not game.is_pause and self.start_direction != D_LEFT:
|
||||||
|
self.direction = D_RIGHT
|
||||||
|
|
||||||
def up(self) -> None:
|
def up(self, game) -> None:
|
||||||
self.direction = D_UP
|
if not game.is_pause and self.start_direction != D_DOWN:
|
||||||
|
self.direction = D_UP
|
||||||
|
|
||||||
def down(self) -> None:
|
def down(self, game) -> None:
|
||||||
self.direction = D_DOWN
|
if not game.is_pause and self.start_direction != D_UP:
|
||||||
|
self.direction = D_DOWN
|
||||||
|
|
12
point.py
12
point.py
|
@ -4,13 +4,13 @@ class Point:
|
||||||
self.y = y
|
self.y = y
|
||||||
|
|
||||||
def __eq__(self, other) -> bool:
|
def __eq__(self, other) -> bool:
|
||||||
if isinstance(other, Point):
|
if not isinstance(other, Point):
|
||||||
if self.x == other.x and self.y == other.y:
|
return False
|
||||||
return True
|
|
||||||
else:
|
if self.x == other.x and self.y == other.y:
|
||||||
return False
|
return True
|
||||||
else:
|
else:
|
||||||
raise TypeError("You can compare only Point with Point")
|
return False
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return int(f"{abs(self.x)}000{abs(self.y)}")
|
return int(f"{abs(self.x)}000{abs(self.y)}")
|
||||||
|
|
13
settings.py
13
settings.py
|
@ -2,9 +2,12 @@
|
||||||
WIDTH = 20
|
WIDTH = 20
|
||||||
HEIGHT = 20
|
HEIGHT = 20
|
||||||
FPS = 5
|
FPS = 5
|
||||||
|
WALL_COLOR = "\u001b[31m"
|
||||||
|
RESET_COLOR = "\u001b[0m"
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
QUIT_BUTTON = 'q'
|
QUIT_BUTTON = 'q'
|
||||||
|
PAUSE_BUTTON = 'p'
|
||||||
LEFT_BUTTON = 'a'
|
LEFT_BUTTON = 'a'
|
||||||
RIGHT_BUTTON = 'd'
|
RIGHT_BUTTON = 'd'
|
||||||
UP_BUTTON = 'w'
|
UP_BUTTON = 'w'
|
||||||
|
@ -24,3 +27,13 @@ SPACE = 0
|
||||||
WALL = 1
|
WALL = 1
|
||||||
FOOD = 2
|
FOOD = 2
|
||||||
WALL_FOOD = 3
|
WALL_FOOD = 3
|
||||||
|
HEAD = 4
|
||||||
|
|
||||||
|
TT_SPACE = " "
|
||||||
|
TT_WALL = "\u001b[34m{}\u001b[0m".format("██")
|
||||||
|
TT_FOOD = "\u001b[33m{}\u001b[0m".format("██")
|
||||||
|
TT_WALL_FOOD = "\u001b[32m{}\u001b[0m".format("██")
|
||||||
|
TT_HEAD = "\u001b[36m{}\u001b[0m".format("██")
|
||||||
|
|
||||||
|
# Globals
|
||||||
|
is_pause = False
|
||||||
|
|
Loading…
Reference in New Issue