roguepy/game.py

107 lines
3.3 KiB
Python
Raw Normal View History

2023-03-01 19:47:24 +00:00
from terminal import Terminal
2023-03-02 16:51:17 +00:00
from entity import Character, Player, Item, Enemy
2023-03-01 19:47:24 +00:00
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
2023-03-02 16:51:17 +00:00
self.ticks = 0
self.schedule = {}
2023-03-01 19:47:24 +00:00
def run(self):
"""
Runs the game
"""
2023-03-02 16:51:17 +00:00
self.instance_character(3, 3, self.player)
2023-03-02 17:08:02 +00:00
self.render()
2023-03-01 19:47:24 +00:00
while not self.should_exit:
2023-03-02 17:08:02 +00:00
action_was_performed = self.step()
if action_was_performed:
self.render()
2023-03-02 16:51:17 +00:00
def instance_character(self, x, y, character: Character):
2023-03-02 17:00:42 +00:00
"""
Instances a character in space and time
"""
2023-03-02 16:51:17 +00:00
self.floor.entities.add_creature(x, y, character)
self.reschedule(character)
def reschedule(self, character: Character):
"""
Calculates turns for the next avaliable ticks untill player turn
"""
time = (action_timing[character.action.__class__] // character.speed) + self.ticks
if self.schedule.get(time):
self.schedule[time].append(character)
else:
self.schedule[time] = [character]
2023-03-01 19:47:24 +00:00
def render(self):
"""
Renders the game
"""
for x in range(self.floor.width):
for y in range(self.floor.height):
2023-03-02 16:51:17 +00:00
if (x, y) in self.floor.entities.pos_creatures:
2023-03-01 19:47:24 +00:00
self.term.put_char(x, y, TEXTURES[Player])
2023-03-02 16:51:17 +00:00
elif (x, y) in self.floor.entities.items:
2023-03-01 19:47:24 +00:00
self.term.put_char(x, y, 'i')
else:
self.term.put_char(x, y, TEXTURES[self.floor.get_tile(x, y)])
def step(self):
2023-03-02 17:08:02 +00:00
"""
Perfoms a step in the game. Returns True if any creature did an action, and False otherwise
"""
2023-03-02 16:51:17 +00:00
creaturas = self.schedule.get(self.ticks)
if creaturas:
for creatura in creaturas:
if isinstance(creatura, Player):
self.get_event()
elif isinstance(creatura, Enemy):
creatura.calculate_action()
self.reschedule(creatura)
self.perform(creatura)
self.schedule.pop(self.ticks)
2023-03-02 17:08:02 +00:00
self.ticks += 1
return True
else:
self.ticks += 1
return False
2023-03-02 16:51:17 +00:00
def perform(self, character: Character):
2023-03-01 19:47:24 +00:00
"""
2023-03-02 16:51:17 +00:00
Performs an action for a creature
2023-03-01 19:47:24 +00:00
"""
2023-03-02 16:51:17 +00:00
if isinstance(character.action, Move):
pos = self.floor.entities.pop_creature_ref(character)
if pos:
self.floor.entities.add_creature(pos[0] + character.action.x, pos[1] + character.action.y, character)
2023-03-01 19:47:24 +00:00
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)