first commit
This commit is contained in:
commit
d4b977abf6
|
@ -0,0 +1,3 @@
|
||||||
|
log.txt
|
||||||
|
ideas.md
|
||||||
|
__pycache__/
|
|
@ -0,0 +1,12 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Move:
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Idle:
|
||||||
|
pass
|
||||||
|
|
||||||
|
Action = Move | Idle
|
|
@ -0,0 +1,20 @@
|
||||||
|
from enum import Enum
|
||||||
|
from actions import Action, Idle
|
||||||
|
|
||||||
|
class Entity():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Item(Entity):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Character(Entity):
|
||||||
|
def __init__(self):
|
||||||
|
self.action: Action = Idle()
|
||||||
|
|
||||||
|
class Player(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
class Enemy(Character):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
|
@ -0,0 +1,38 @@
|
||||||
|
from enum import Enum
|
||||||
|
from entity import Character, Entity, Item
|
||||||
|
|
||||||
|
class TileType(Enum):
|
||||||
|
WALL = 1
|
||||||
|
AIR = 2
|
||||||
|
|
||||||
|
class Floor:
|
||||||
|
def __init__(self, width, height):
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.grid = [[TileType.AIR] * height] * width
|
||||||
|
self.entities = {
|
||||||
|
Character: {},
|
||||||
|
Item: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_tile(self, x, y):
|
||||||
|
return self.grid[x][y]
|
||||||
|
|
||||||
|
def add_entity(self, x, y, entity: Entity) -> bool:
|
||||||
|
if isinstance(entity, Character):
|
||||||
|
if (x, y) in self.entities[Character]:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
self.entities[Character][(x, y)] = entity
|
||||||
|
return True
|
||||||
|
elif isinstance(entity, Item):
|
||||||
|
if (x, y) not in self.entities[Item]:
|
||||||
|
self.entities[Item][(x,y)] = []
|
||||||
|
self.entities[Item][(x,y)].append(entity)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def pop_character(self, x, y) -> Character | None:
|
||||||
|
if (x, y) in self.entities[Character]:
|
||||||
|
return self.entities[Character].pop((x, y))
|
|
@ -0,0 +1,65 @@
|
||||||
|
from terminal import Terminal
|
||||||
|
from entity import Character, Player, Item
|
||||||
|
from actions import *
|
||||||
|
from floor import Floor, TileType
|
||||||
|
|
||||||
|
TEXTURES = {
|
||||||
|
TileType.WALL: '#',
|
||||||
|
TileType.AIR: '.',
|
||||||
|
Player: '@'
|
||||||
|
}
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self):
|
||||||
|
self.term = Terminal()
|
||||||
|
self.player = Player()
|
||||||
|
self.floor = Floor(20, 10)
|
||||||
|
self.should_exit = False
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""
|
||||||
|
Runs the game
|
||||||
|
"""
|
||||||
|
self.floor.add_entity(3, 3, self.player)
|
||||||
|
while not self.should_exit:
|
||||||
|
self.render()
|
||||||
|
self.get_event()
|
||||||
|
self.step()
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
"""
|
||||||
|
Renders the game
|
||||||
|
"""
|
||||||
|
for x in range(self.floor.width):
|
||||||
|
for y in range(self.floor.height):
|
||||||
|
if (x, y) in self.floor.entities[Character]:
|
||||||
|
self.term.put_char(x, y, TEXTURES[Player])
|
||||||
|
elif (x, y) in self.floor.entities[Item]:
|
||||||
|
self.term.put_char(x, y, 'i')
|
||||||
|
else:
|
||||||
|
self.term.put_char(x, y, TEXTURES[self.floor.get_tile(x, y)])
|
||||||
|
|
||||||
|
def step(self):
|
||||||
|
"""
|
||||||
|
Performs a turn in the game
|
||||||
|
"""
|
||||||
|
for (pos, character) in dict(self.floor.entities[Character]).items():
|
||||||
|
if isinstance(character.action, Move):
|
||||||
|
character = self.floor.entities[Character].pop(pos)
|
||||||
|
self.floor.add_entity(pos[0] + character.action.x, pos[1] + character.action.y, character)
|
||||||
|
|
||||||
|
def get_event(self):
|
||||||
|
"""
|
||||||
|
Waits for a game event to happen
|
||||||
|
"""
|
||||||
|
keycode = self.term.get_key()
|
||||||
|
if keycode == "q":
|
||||||
|
self.should_exit = True
|
||||||
|
elif keycode == "KEY_RIGHT":
|
||||||
|
self.player.action = Move(1, 0)
|
||||||
|
elif keycode == "KEY_LEFT":
|
||||||
|
self.player.action = Move(-1, 0)
|
||||||
|
elif keycode == "KEY_DOWN":
|
||||||
|
self.player.action = Move(0, 1)
|
||||||
|
elif keycode == "KEY_UP":
|
||||||
|
self.player.action = Move(0, -1)
|
|
@ -0,0 +1,8 @@
|
||||||
|
from game import Game
|
||||||
|
|
||||||
|
def main():
|
||||||
|
game = Game()
|
||||||
|
game.run()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -0,0 +1,44 @@
|
||||||
|
import curses
|
||||||
|
|
||||||
|
KEYCODES = {
|
||||||
|
curses.KEY_LEFT: "KEY_LEFT",
|
||||||
|
curses.KEY_RIGHT: "KEY_RIGHT",
|
||||||
|
curses.KEY_UP: "KEY_UP",
|
||||||
|
curses.KEY_DOWN: "KEY_DOWN"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Terminal:
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Perfoms some initial steps to set the terminal ready for the game
|
||||||
|
"""
|
||||||
|
self.scr = curses.initscr()
|
||||||
|
curses.noecho()
|
||||||
|
curses.cbreak()
|
||||||
|
curses.curs_set(0)
|
||||||
|
self.scr.keypad(True)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""
|
||||||
|
Perfoms some cleanup to restore the behaviour of the terminal
|
||||||
|
"""
|
||||||
|
curses.nocbreak()
|
||||||
|
self.scr.keypad(False)
|
||||||
|
curses.echo()
|
||||||
|
curses.endwin()
|
||||||
|
|
||||||
|
def get_key(self) -> str:
|
||||||
|
"""
|
||||||
|
Blocks until a key is read
|
||||||
|
"""
|
||||||
|
ch = self.scr.getch()
|
||||||
|
if ch in KEYCODES:
|
||||||
|
return KEYCODES[ch]
|
||||||
|
else:
|
||||||
|
return chr(ch)
|
||||||
|
|
||||||
|
def put_char(self, x, y, char):
|
||||||
|
"""
|
||||||
|
Prints a char at the specified position
|
||||||
|
"""
|
||||||
|
self.scr.addch(y, x, char)
|
Loading…
Reference in New Issue