|
1 | 1 | """A collection of game states.""" |
2 | 2 | from __future__ import annotations |
3 | 3 |
|
| 4 | +from typing import Final |
| 5 | + |
4 | 6 | import attrs |
5 | 7 | import tcod.console |
6 | 8 | import tcod.event |
7 | 9 | from tcod.event import KeySym |
8 | 10 |
|
| 11 | +import g |
| 12 | +from game.components import Gold, Graphic, Position |
| 13 | +from game.tags import IsItem, IsPlayer |
| 14 | + |
| 15 | +DIRECTION_KEYS: Final = { |
| 16 | + # Arrow keys |
| 17 | + KeySym.LEFT: (-1, 0), |
| 18 | + KeySym.RIGHT: (1, 0), |
| 19 | + KeySym.UP: (0, -1), |
| 20 | + KeySym.DOWN: (0, 1), |
| 21 | + # Arrow key diagonals |
| 22 | + KeySym.HOME: (-1, -1), |
| 23 | + KeySym.END: (-1, 1), |
| 24 | + KeySym.PAGEUP: (1, -1), |
| 25 | + KeySym.PAGEDOWN: (1, 1), |
| 26 | + # Keypad |
| 27 | + KeySym.KP_4: (-1, 0), |
| 28 | + KeySym.KP_6: (1, 0), |
| 29 | + KeySym.KP_8: (0, -1), |
| 30 | + KeySym.KP_2: (0, 1), |
| 31 | + KeySym.KP_7: (-1, -1), |
| 32 | + KeySym.KP_1: (-1, 1), |
| 33 | + KeySym.KP_9: (1, -1), |
| 34 | + KeySym.KP_3: (1, 1), |
| 35 | + # VI keys |
| 36 | + KeySym.h: (-1, 0), |
| 37 | + KeySym.l: (1, 0), |
| 38 | + KeySym.k: (0, -1), |
| 39 | + KeySym.j: (0, 1), |
| 40 | + KeySym.y: (-1, -1), |
| 41 | + KeySym.b: (-1, 1), |
| 42 | + KeySym.u: (1, -1), |
| 43 | + KeySym.n: (1, 1), |
| 44 | +} |
9 | 45 |
|
10 | | -@attrs.define(eq=False) |
11 | | -class ExampleState: |
12 | | - """Example state with a hard-coded player position.""" |
13 | 46 |
|
14 | | - player_x: int |
15 | | - """Player X position, left-most position is zero.""" |
16 | | - player_y: int |
17 | | - """Player Y position, top-most position is zero.""" |
| 47 | +@attrs.define() |
| 48 | +class InGame: |
| 49 | + """Primary in-game state.""" |
18 | 50 |
|
19 | 51 | def on_event(self, event: tcod.event.Event) -> None: |
20 | | - """Move the player on events and handle exiting. Movement is hard-coded.""" |
| 52 | + """Handle events for the in-game state.""" |
| 53 | + (player,) = g.world.Q.all_of(tags=[IsPlayer]) |
21 | 54 | match event: |
22 | 55 | case tcod.event.Quit(): |
23 | 56 | raise SystemExit() |
24 | | - case tcod.event.KeyDown(sym=KeySym.LEFT): |
25 | | - self.player_x -= 1 |
26 | | - case tcod.event.KeyDown(sym=KeySym.RIGHT): |
27 | | - self.player_x += 1 |
28 | | - case tcod.event.KeyDown(sym=KeySym.UP): |
29 | | - self.player_y -= 1 |
30 | | - case tcod.event.KeyDown(sym=KeySym.DOWN): |
31 | | - self.player_y += 1 |
| 57 | + case tcod.event.KeyDown(sym=sym) if sym in DIRECTION_KEYS: |
| 58 | + player.components[Position] += DIRECTION_KEYS[sym] |
| 59 | + # Auto pickup gold |
| 60 | + for gold in g.world.Q.all_of(components=[Gold], tags=[player.components[Position], IsItem]): |
| 61 | + player.components[Gold] += gold.components[Gold] |
| 62 | + print(f"Picked up {gold.components[Gold]}g, total: {player.components[Gold]}g") |
| 63 | + gold.clear() |
32 | 64 |
|
33 | 65 | def on_draw(self, console: tcod.console.Console) -> None: |
34 | | - """Draw the player with print. Bounds do not need to be checked with this function.""" |
35 | | - console.print(self.player_x, self.player_y, "@") |
| 66 | + """Draw the standard screen.""" |
| 67 | + for entity in g.world.Q.all_of(components=[Position, Graphic]): |
| 68 | + pos = entity.components[Position] |
| 69 | + if not (0 <= pos.x < console.width and 0 <= pos.y < console.height): |
| 70 | + continue |
| 71 | + graphic = entity.components[Graphic] |
| 72 | + console.rgb[["ch", "fg"]][pos.y, pos.x] = graphic.ch, graphic.fg |
0 commit comments