Compare commits

..

11 Commits
2 ... main

Author SHA1 Message Date
Plaza521 bf638e711e
fix creating Player object 2023-03-16 23:14:44 +03:00
Plaza521 a89e41cd68
fix bug with turn 2023-03-06 01:30:06 +03:00
Plaza521 aff3036a0d
fix issue #1 and fix pause 2022-11-06 22:18:02 +03:00
Plaza521 a77fe7840d
add color 2022-10-29 04:25:09 +03:00
Plaza521 4840b016db
refactor 2022-10-27 19:59:23 +03:00
Plaza521 b6a097bbb3
refactor food and rename pause_game function 2022-10-27 17:41:10 +03:00
Plaza521 a96f8fcc71
delete unused var 2022-10-27 17:29:22 +03:00
Plaza521 9e82c9478a
refactor 2022-10-27 17:03:11 +03:00
Plaza521 95e1653b1a
Update README.md 2022-10-27 15:30:05 +03:00
Plaza521 996eebe470
add pause and refactor 2022-10-27 15:29:28 +03:00
Plaza521 ffc75251f1
small refactor 2022-10-27 00:29:36 +03:00
8 changed files with 136 additions and 72 deletions

View File

@ -4,4 +4,5 @@ Snake, but in console
Default keys:
--
W A S D - move
Q - quit
Q - quit
P - pause

View File

@ -4,9 +4,8 @@ from settings import *
class Food(Point):
def __init__(self, x, y, pl):
def __init__(self, x, y):
Point.__init__(self, x, y)
self.pl = pl
def generate_new(self) -> None:
self.x = randint(0, WIDTH - 1)

View File

@ -9,10 +9,10 @@ if platform == "win32":
class COORDSET(Structure):
_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))
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")
@ -23,14 +23,20 @@ class Frame:
self.matrix = [[SPACE] * width for line in range(height)]
def __str__(self) -> str:
out_string = f"Width:\n {self.width}\n"
out_string += f"Height:\n {self.height}\n"
return out_string
return (
f"Width:\n {self.width}\n"
f"Height:\n {self.height}"
)
def draw(
self, x: int, y: int,
self,
x: int,
y: int,
value: int = WALL,
width: int = 1, height: int = 1
width: int = 1,
height: int = 1
) -> None:
if not isinstance(value, int):
raise TypeError("Value must be int")
@ -40,27 +46,29 @@ class Frame:
self.matrix[y + line][x + column] = value
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:
to_str = ''
to_str += ''
to_str += f'{WALL_COLOR}{RESET_COLOR}'
for elem in line:
if elem == SPACE:
to_str += " "
to_str += TT_SPACE
elif elem == WALL:
to_str += "██"
to_str += TT_WALL
elif elem == FOOD:
to_str += "@@"
to_str += TT_FOOD
elif elem == WALL_FOOD:
to_str += "@█"
to_str += '\n'
to_str += TT_WALL_FOOD
elif elem == HEAD:
to_str += TT_HEAD
to_str += f'{WALL_COLOR}{RESET_COLOR}\n'
out_string += to_str
out_string += f"{'' * (self.width * 2)}"
out_string += f"{WALL_COLOR}{'' * (self.width * 2)}{RESET_COLOR}"
print(out_string)

66
main.py
View File

@ -1,48 +1,80 @@
# from frame import Frame
from settings import *
from player import Player
import keyboard as kb
from out import Out
from os import system
from time import sleep, time
class Game:
def __init__(self) -> None:
self.running = True
self.is_pause = False
self.pl = Player()
self.out = Out()
self.out = Out(self.pl)
kb.add_hotkey(QUIT_BUTTON, self.stop_game)
kb.add_hotkey(LEFT_BUTTON, self.pl.left)
kb.add_hotkey(RIGHT_BUTTON, self.pl.right)
kb.add_hotkey(UP_BUTTON, self.pl.up)
kb.add_hotkey(DOWN_BUTTON, self.pl.down)
kb.add_hotkey(PAUSE_BUTTON, self.switch_pause)
kb.add_hotkey(
LEFT_BUTTON,
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:
self.running = False
def update(self) -> None:
pass
def output(self) -> None:
pass
if not self.is_pause:
self.running = False
def play(self) -> None:
system("clear||cls")
print()
start_time = time()
different_between_time = 1 / FPS
while self.running:
try:
self.pl.update()
self.out.draw(self.pl)
sleep(1 / FPS - different_between_time)
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:
self.running = False
print(e)
except KeyboardInterrupt:
return
input("Press enter to leave from game")
input("Press enter to leave from game.\n")
def main() -> None:
Game().play()
game = Game()
game.play()
if __name__ == '__main__':

20
out.py
View File

@ -4,26 +4,28 @@ from frame import Frame
class Out:
def __init__(self) -> None:
def __init__(self, pl: Player) -> None:
self.width = WIDTH
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)
pl = self.pl
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(
x=point.x, y=point.y,
value=WALL,
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:
frame.draw(
x=pl.food.x, y=pl.food.y,
@ -36,4 +38,4 @@ class Out:
)
frame.show()
print(F"Score: {pl.score}")
print(f"Score: {pl.score}")

View File

@ -1,53 +1,62 @@
from settings import *
from point import Point
from food import Food
from time import sleep
from itertools import permutations
class Player:
def __init__(self) -> None:
self.start_direciton = MAIN_DIRECTION
self.direction = MAIN_DIRECTION
self.body = [Point(MAIN_X, MAIN_Y)]
self.food = Food(0, 0, self)
self.food = Food(0, 0)
self.food.generate_new()
self.score = 0
def update(self) -> None:
sleep(1 / FPS)
self.score = 1
def input(self) -> None:
if self.direction == D_UP:
# self.body[0].y -= 1
self.body.append(Point(self.body[-1].x, self.body[-1].y - 1))
elif self.direction == D_DOWN:
# self.body[0].y += 1
self.body.append(Point(self.body[-1].x, self.body[-1].y + 1))
elif self.direction == D_LEFT:
# self.body[0].x -= 1
self.body.append(Point(self.body[-1].x - 1, self.body[-1].y))
elif self.direction == D_RIGHT:
# self.body[0].x += 1
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:
self.food.generate_new()
self.score += 1
else:
self.body.pop(0)
if len(set(self.body)) != len(self.body):
raise IndexError("Player has collision with self")
Player._check_collision(self.body)
def left(self) -> None:
self.direction = D_LEFT
def left(self, game) -> None:
if not game.is_pause and self.start_direction != D_RIGHT:
self.direction = D_LEFT
def right(self) -> None:
self.direction = D_RIGHT
def right(self, game) -> None:
if not game.is_pause and self.start_direction != D_LEFT:
self.direction = D_RIGHT
def up(self) -> None:
self.direction = D_UP
def up(self, game) -> None:
if not game.is_pause and self.start_direction != D_DOWN:
self.direction = D_UP
def down(self) -> None:
self.direction = D_DOWN
def down(self, game) -> None:
if not game.is_pause and self.start_direction != D_UP:
self.direction = D_DOWN

View File

@ -4,13 +4,13 @@ class Point:
self.y = y
def __eq__(self, other) -> bool:
if isinstance(other, Point):
if self.x == other.x and self.y == other.y:
return True
else:
return False
if not isinstance(other, Point):
return False
if self.x == other.x and self.y == other.y:
return True
else:
raise TypeError("You can compare only Point with Point")
return False
def __hash__(self) -> int:
return int(f"{abs(self.x)}000{abs(self.y)}")

View File

@ -2,9 +2,12 @@
WIDTH = 20
HEIGHT = 20
FPS = 5
WALL_COLOR = "\u001b[31m"
RESET_COLOR = "\u001b[0m"
# Buttons
QUIT_BUTTON = 'q'
PAUSE_BUTTON = 'p'
LEFT_BUTTON = 'a'
RIGHT_BUTTON = 'd'
UP_BUTTON = 'w'
@ -24,3 +27,13 @@ SPACE = 0
WALL = 1
FOOD = 2
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