Skip to content

Commit

Permalink
Sprite gen (#76)
Browse files Browse the repository at this point in the history
* Renamed custom char size test resource

* First pass at sprite coloring library

* Refactor Panels to only use draw_char

* Added Sprite Char class

* Refactored Panels to auto convert to char

* Added frame support for Sprite Char

* Added CharModifier class
  • Loading branch information
derpferd authored Oct 25, 2022
1 parent 1e5cea0 commit 42ef463
Show file tree
Hide file tree
Showing 19 changed files with 537 additions and 45 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: Install dependencies
run: |
poetry config virtualenvs.in-project true
poetry install
poetry install -E sprite-editing
- name: Run style checks
run: |
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,5 @@ CYLGame/static/fonts/
\.idea/
.pytest_cache/
.vscode/
generated_*
temp_game
20 changes: 17 additions & 3 deletions CYLGame/Frame.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
from typing import Union

from copy import copy, deepcopy

from CYLGame.Sprite import Char

GRID_CHAR_TYPE = Union[int, str, Char]


def grid_char_to_int(c: GRID_CHAR_TYPE) -> int:
if isinstance(c, int):
return c
if isinstance(c, str) and len(c) == 1:
return ord(c)
if isinstance(c, Char):
return c.value
raise ValueError(f"{c} isn't a char")


class FrameBuffer(object):
# TODO: decide what should go here.
Expand Down Expand Up @@ -56,9 +72,7 @@ def set(self, x, y, char):
y(int):
char(int): The id of the char.
"""
if isinstance(char, str):
assert len(char) == 1
char = ord(char)
char = grid_char_to_int(char)
if not (0 <= x < self.x):
raise IndexError("Trying to draw out of bounds at ({}, {})".format(x, y))
if not (0 <= y < self.y):
Expand Down
99 changes: 68 additions & 31 deletions CYLGame/Panels.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
from typing import List, Tuple, Union

import traceback
from collections import defaultdict
from copy import copy
from functools import reduce

from CYLGame.Sprite import Char
from CYLGame.Utils import deprecated

DEFAULT_CHAR = " "


def is_char(c):
return type(c) == str and len(c) == 1
CHAR_TYPE = Union[str, int, Char]
COORD_TYPE = Union[Tuple[int, int], List[int]]


def to_char(c: CHAR_TYPE) -> str:
if isinstance(c, str) and len(c) == 1:
return c
elif isinstance(c, int):
return chr(c)
elif isinstance(c, Char):
return str(c)
raise ValueError(f"{c} isn't a char")


def is_coord(p):
return type(p) == tuple and len(p) == 2 and type(p[0]) == int and type(p[1]) == int
def to_coord(p: COORD_TYPE) -> Tuple[int, int]:
if type(p) == list:
# per https://github.com/python/mypy/issues/7509 ignore type
p = tuple(p) # type: ignore
if type(p) == tuple and len(p) == 2 and type(p[0]) == int and type(p[1]) == int:
return p
raise ValueError(f"{p} isn't a coord")


class Map(object):
Expand All @@ -27,22 +45,20 @@ class Map(object):
def __init__(self, width, height, default_char=DEFAULT_CHAR):
self.w = width
self.h = height
self.default_char = default_char
self.default_char = to_char(default_char)
self.char_to_ps = defaultdict(set)
self.p_to_char = defaultdict(lambda: self.default_char)
self.changes = {}

def __setitem__(self, key, value):
def __setitem__(self, key: COORD_TYPE, value: CHAR_TYPE):
self.add(value, key)

def __getitem__(self, item):
return self.get_char_at(item)

def get_x_y_dist_to_foo(self, pos, foo, wrapping=False, diagonal_moving=False, default=None):
if type(pos) == list:
pos = tuple(pos)
assert is_coord(pos), "pos is not a coord: %r" % pos
assert is_char(foo), "foo is not a char: %r" % foo
pos = to_coord(pos)
foo = to_char(foo)

dists = []
x, y = pos
Expand All @@ -63,8 +79,7 @@ def get_x_y_dist_to_foo(self, pos, foo, wrapping=False, diagonal_moving=False, d

# checks if pos is in bound of the map
def in_bounds(self, pos):
assert is_coord(pos), "pos: '{}', isn't a coord".format(pos)
x, y = pos
x, y = to_coord(pos)
return 0 <= x < self.w and 0 <= y < self.h

def wrap(self, pos, wrap_x=False, wrap_y=False):
Expand All @@ -84,9 +99,9 @@ def get_diff(self):
return changes

# pos must be tuple
def add(self, char, pos):
assert is_char(char), "'{}' isn't a char".format(char)
def add(self, char: CHAR_TYPE, pos):
assert self.in_bounds(pos), "'{}' isn't in bounds".format(pos)
char = to_char(char)

if pos in self.p_to_char.keys():
self.rm_char(pos)
Expand All @@ -105,7 +120,7 @@ def rm_char(self, pos):

# returns a set of pos
def get_all_pos(self, char):
assert is_char(char)
char = to_char(char)
return copy(self.char_to_ps[char])

# will return default_char if the position is not set
Expand Down Expand Up @@ -324,38 +339,60 @@ def __init__(self, x, y, w, h, background_char=DEFAULT_CHAR, border=PanelBorder(
def draw_char(self, char, pos, frame_buffer):
# TODO: add asserts for these
x, y = pos
assert is_char(char)
char = to_char(char)
frame_buffer.set(x, y, char)

def redraw(self, frame_buffer):
try:
if PanelBorder.TOP in self.border:
for i in range(self.real_w):
frame_buffer.set(self.real_x + i, self.real_y, self.border[PanelBorder.TOP])
self.draw_char(
pos=(self.real_x + i, self.real_y), char=self.border[PanelBorder.TOP], frame_buffer=frame_buffer
)
if PanelBorder.LEFT in self.border:
for i in range(self.real_h):
frame_buffer.set(self.real_x, self.real_y + i, self.border[PanelBorder.LEFT])
self.draw_char(
pos=(self.real_x, self.real_y + i),
char=self.border[PanelBorder.LEFT],
frame_buffer=frame_buffer,
)
if PanelBorder.BOTTOM in self.border:
for i in range(self.real_w):
frame_buffer.set(self.real_x + i, self.real_y + self.real_h - 1, self.border[PanelBorder.BOTTOM])
self.draw_char(
pos=(self.real_x + i, self.real_y + self.real_h - 1),
char=self.border[PanelBorder.BOTTOM],
frame_buffer=frame_buffer,
)
if PanelBorder.RIGHT in self.border:
for i in range(self.real_h):
frame_buffer.set(self.real_x + self.real_w - 1, self.real_y + i, self.border[PanelBorder.RIGHT])
self.draw_char(
pos=(self.real_x + self.real_w - 1, self.real_y + i),
char=self.border[PanelBorder.RIGHT],
frame_buffer=frame_buffer,
)
if PanelBorder.TOP in self.border and PanelBorder.LEFT in self.border:
frame_buffer.set(self.real_x, self.real_y, self.border[PanelBorder.TOP | PanelBorder.LEFT])
self.draw_char(
pos=(self.real_x, self.real_y),
char=self.border[PanelBorder.TOP | PanelBorder.LEFT],
frame_buffer=frame_buffer,
)
if PanelBorder.BOTTOM in self.border and PanelBorder.LEFT in self.border:
frame_buffer.set(
self.real_x, self.real_y + self.real_h - 1, self.border[PanelBorder.BOTTOM | PanelBorder.LEFT]
self.draw_char(
pos=(self.real_x, self.real_y + self.real_h - 1),
char=self.border[PanelBorder.BOTTOM | PanelBorder.LEFT],
frame_buffer=frame_buffer,
)
if PanelBorder.TOP in self.border and PanelBorder.RIGHT in self.border:
frame_buffer.set(
self.real_x + self.real_w - 1, self.real_y, self.border[PanelBorder.TOP | PanelBorder.RIGHT]
self.draw_char(
pos=(self.real_x + self.real_w - 1, self.real_y),
char=self.border[PanelBorder.TOP | PanelBorder.RIGHT],
frame_buffer=frame_buffer,
)
if PanelBorder.BOTTOM in self.border and PanelBorder.RIGHT in self.border:
frame_buffer.set(
self.real_x + self.real_w - 1,
self.real_y + self.real_h - 1,
self.border[PanelBorder.BOTTOM | PanelBorder.RIGHT],
self.draw_char(
pos=(self.real_x + self.real_w - 1, self.real_y + self.real_h - 1),
char=self.border[PanelBorder.BOTTOM | PanelBorder.RIGHT],
frame_buffer=frame_buffer,
)
except IndexError:
raise IndexError(
Expand Down Expand Up @@ -482,14 +519,14 @@ def redraw(self, frame_buffer):
# TODO: optimize this by only clearing what should be changed.
# Clear msg row
for i in range(self.max_len):
frame_buffer.set(self.x + i, self.y + j, self.default_char)
self.draw_char(pos=(self.x + i, self.y + j), char=self.default_char, frame_buffer=frame_buffer)

# Write the message we have to the panel
for j in range(len(msgs_to_display)):
msg = msgs_to_display[j]
# Print msg
for i in range(min(len(msg), self.max_len)):
frame_buffer.set(self.x + i, self.y + j, msg[i])
self.draw_char(pos=(self.x + i, self.y + j), char=msg[i], frame_buffer=frame_buffer)


class StatusPanel(MessagePanel):
Expand Down
2 changes: 1 addition & 1 deletion CYLGame/Server.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def serve(
cls.gamedb.www_cache.safe_replace_cache(os.path.join(os.path.split(__file__)[0], "www"))

if issubclass(game, GridGame):
cls.charset = cls.__copy_in_charset(game.CHAR_SET)
cls.charset = cls.__copy_in_charset(game.get_sprite_set().image_filepath)

setup_logging(
debug_file=debug_log_file.replace("{dbfile}", game_data_path),
Expand Down
Loading

0 comments on commit 42ef463

Please sign in to comment.