diff --git a/ecs.py b/ecs.py new file mode 100644 index 0000000..1329764 --- /dev/null +++ b/ecs.py @@ -0,0 +1,62 @@ + +class ECS: + def __init__(self): + self.entities = {} + self.facts = {} + self.id_counter = 0 + + def entity(self): + self.id_counter += 1 + return self.id_counter + + def set(self, entity_id, obj): + name = obj.__class__.__qualname__ + target = self.entities.get(name, {}) + target[entity_id] = obj + self.entities[name] = target + + def query(self, cls): + return self.entities[cls.__qualname__].items() + + +class Systems: + def __init__(self, ecs): + self.ecs = ecs + + def play_sounds(self): + for eid, entity in ecs.query(Sound): + print("TALKING: ", entity.text) + + def combat(self): + for eid, entity in ecs.query(Combat): + print("FIGHT: ", entity.hp) + + def movement(self): + for eid, entity in ecs.query(Position): + print("MOVE: ", entity.x, entity.y) + +class Combat: + def __init__(self, hp): + self.hp = hp + +class Sound: + def __init__(self, text): + self.text = text + +class Position: + def __init__(self, x, y): + self.x = x + self.y = y + + +ecs = ECS() +systems = Systems(ecs) + +troll = ecs.entity() +ecs.set(troll, Combat(100)) +ecs.set(troll, Sound("ROAR!")) +ecs.set(troll, Position(1, 2)) + +systems.play_sounds() +systems.combat() +systems.movement() diff --git a/phase_07.py b/phase_07.py index de292d7..9e94664 100644 --- a/phase_07.py +++ b/phase_07.py @@ -2,8 +2,8 @@ import curses import sys import random -WALL = 1 -SPACE = 0 +WALL = '#' +SPACE = '.' class Map: def __init__(self, width, height): @@ -15,6 +15,13 @@ class Map: self.hunt_and_kill(grid) self.render_map(grid) + def spawn(self): + while True: + y = random.randrange(0, self.height) + x = random.randrange(0, self.width) + if self.map[y][x] == SPACE: + return x, y + def sample_rooms(self, grid, dead_ends, size, count): grid = self.make_grid() for x, y in random.sample(dead_ends, count): @@ -39,7 +46,7 @@ class Map: for x in range(1, self.width, 2): if grid[y][x] != WALL: continue - found = self.neighborsAB(grid, x, y) + found = self.neighbors(grid, x, y) for found_x, found_y in found: if grid[found_y][found_x] == SPACE: return [[x,y],[found_x, found_y]] @@ -49,7 +56,7 @@ class Map: def inbounds(self, x, y): return x >= 0 and x < self.width and y >= 0 and y < self.height - def neighborsAB(self, grid, x, y): + def neighbors(self, grid, x, y): points = [[x, y - 2], [x, y + 2], [x - 2, y], @@ -61,15 +68,11 @@ class Map: result.append([x,y]) return result - def neighbors(self, grid, x, y): - points = [[x, y - 2], - [x, y + 2], - [x - 2, y], - [x + 2, y]] - + def neighbor_walls(self, grid, x, y): + neighbors = self.neighbors(grid, x, y) result = [] - for x,y in points: - if self.inbounds(x, y) and grid[y][x] == WALL: + for x,y in neighbors: + if grid[y][x] == WALL: result.append([x,y]) return result @@ -79,7 +82,7 @@ class Map: dead_ends = [] while True: - n = self.neighbors(grid, on_x, on_y) + n = self.neighbor_walls(grid, on_x, on_y) if len(n) == 0: dead_ends.append([on_x, on_y]) t = self.find_coord(grid) @@ -107,22 +110,19 @@ class Map: cur_row = "" for x, char in enumerate(y_line): - if char == 0: - cur_row += '.' - else: - cur_row += '#' + cur_row += char self.map.append(cur_row) - def move_player(self, player, target_y, target_x): - if self.map[target_y - 1][target_x - 1] != '#': + def move_player(self, player, target_x, target_y): + if self.map[target_y][target_x] != '#': player.y = target_y player.x = target_x def draw(self, win): - map_line = 1 + map_line = 0 for line in self.map: - win.addstr(map_line, 1, line) + win.addstr(map_line, 0, line) map_line += 1 class UI: @@ -134,7 +134,7 @@ class UI: win = curses.newwin(height, width, begin_y, begin_x) win.keypad(True) - status = win.subwin(status_height, width-2, height-status_height, begin_x+1) + status = win.subwin(status_height, width, height-status_height, begin_x) # keep these for later by assigning to self self.begin_x = 0 @@ -149,23 +149,28 @@ class UI: def set_map(self, the_map): self.map = the_map - def update(self, player): + def update(self, actors): assert self.map, "You forgot to call set_map()" self.win.clear() - self.win.box() - self.status.hline(0,0, curses.ACS_HLINE, self.width - 2) + self.status.box() self.map.draw(self.win) - self.draw_status() - self.draw_player(player) + # this assumes actors[0] is the player + self.draw_status(actors[0]) + + for actor in actors: + self.draw_actor(actor) self.win.refresh() - def draw_status(self): - self.status.addstr(1, 1, "PLAYER STATS") + def draw_status(self, player): + self.status.addstr(1, 1, f"PLAYER AT {player.x},{player.y}") + + def draw_actor(self, actor): + assert self.map.map[actor.y][actor.x] != '#', f"WHAT? actor at {actor.x},{actor.y} but that's a wall!" - def draw_player(self, player): - self.win.addstr(player.y, player.x, '@', curses.A_BOLD) + # actor has to be moved in by 1 for the border + self.win.addstr(actor.y, actor.x, actor.symbol, curses.A_BOLD) - def handle_input(self, y, x): + def handle_input(self, x, y): ch = self.win.getch() if ch == ord('q'): @@ -179,30 +184,49 @@ class UI: elif ch == curses.KEY_LEFT: x = (x - 1) % self.width - return y, x + return x, y class Player: def __init__(self, x, y): self.x = x self.y = y + self.symbol = '@' + +class Enemy: + def __init__(self, x, y, symbol): + self.x = x + self.y = y + self.symbol = symbol class GameEngine: def __init__(self, ui): self.ui = ui - self.player = Player(4, 4) - self.map = Map(77,19) + self.map = Map(ui.width, ui.height - ui.status_height) self.ui = ui ui.set_map(self.map) + def spawn_actors(self): + x, y = self.map.spawn() + self.player = Player(x, y) + + x, y = self.map.spawn() + self.enemy = Enemy(x, y, '{') + + self.actors = [self.player, self.enemy] + def run(self): + self.spawn_actors() + self.map.move_player(self.player, self.player.x, self.player.y) + while True: - self.ui.update(self.player) - new_y, new_x = self.ui.handle_input(self.player.y, self.player.x) - self.map.move_player(self.player, new_y, new_x) + # remember, first one has to be the player + self.ui.update(self.actors) + new_x, new_y = self.ui.handle_input(self.player.x, self.player.y) + self.map.move_player(self.player, new_x, new_y) def main(stdscr): - width=80 - height=26 + width=27 + height=16 ui = UI(stdscr, height, width, 5) game = GameEngine(ui) game.run()