Render paths
This commit is contained in:
parent
146aa11675
commit
d9916579b6
8 changed files with 132 additions and 26 deletions
|
|
@ -2,7 +2,7 @@ import random
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import map.quest_map
|
import map.quest_map
|
||||||
from map.quest_map import QuestMap, MapEncounter, EncounterType
|
from map.quest_map import QuestMap, MapEncounter, EncounterType, QuestPath as QP
|
||||||
|
|
||||||
|
|
||||||
def generate_encounter_inaccessible() -> MapEncounter:
|
def generate_encounter_inaccessible() -> MapEncounter:
|
||||||
|
|
@ -21,6 +21,10 @@ def generate_encounter_town():
|
||||||
|
|
||||||
def generate_map() -> QuestMap:
|
def generate_map() -> QuestMap:
|
||||||
quest_map = QuestMap()
|
quest_map = QuestMap()
|
||||||
|
|
||||||
|
# Generate encounters
|
||||||
|
|
||||||
|
# TODO: Use sample as if drawing from a deck
|
||||||
encounters_rows = []
|
encounters_rows = []
|
||||||
for r in range(11):
|
for r in range(11):
|
||||||
row: List[MapEncounter] = []
|
row: List[MapEncounter] = []
|
||||||
|
|
@ -39,4 +43,21 @@ def generate_map() -> QuestMap:
|
||||||
encounters_rows.append(row)
|
encounters_rows.append(row)
|
||||||
|
|
||||||
quest_map.encounters = encounters_rows
|
quest_map.encounters = encounters_rows
|
||||||
|
|
||||||
|
# Generate paths
|
||||||
|
diagonals_deck = [QP.NO_PATH] * 8 + [QP.FORWARD_LEFT] * 5 + [QP.FORWARD_RIGHT] * 5
|
||||||
|
random_paths_it = iter(random.sample(diagonals_deck, len(diagonals_deck)))
|
||||||
|
path_rows = []
|
||||||
|
for r in range(11 - 1):
|
||||||
|
row: List[QP]
|
||||||
|
if r == 0:
|
||||||
|
row = [QP.FORWARD, QP.NO_PATH, QP.FORWARD, QP.NO_PATH, QP.FORWARD]
|
||||||
|
elif r == 9:
|
||||||
|
row = [QP.NO_PATH, QP.FORWARD_RIGHT, QP.FORWARD, QP.FORWARD_LEFT, QP.NO_PATH]
|
||||||
|
else:
|
||||||
|
row = [QP.FORWARD, next(random_paths_it), QP.FORWARD, next(random_paths_it), QP.FORWARD]
|
||||||
|
path_rows.append(row)
|
||||||
|
|
||||||
|
quest_map.paths = path_rows
|
||||||
|
|
||||||
return quest_map
|
return quest_map
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
from map.quest_map import MapEncounter, QuestMap, EncounterType
|
import dataclasses
|
||||||
|
|
||||||
|
from map.quest_map import MapEncounter, QuestMap, EncounterType, QuestPath
|
||||||
|
|
||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
|
|
||||||
_ICONS = {
|
_ENCOUNTER_ICONS = {
|
||||||
EncounterType.BATTLE_REGULAR: 'noun_Battle_3647629_cropped.png',
|
EncounterType.BATTLE_REGULAR: 'noun_Battle_3647629_cropped.png',
|
||||||
EncounterType.BATTLE_ELITE: 'noun_Shield_3806325_cropped.png',
|
EncounterType.BATTLE_ELITE: 'noun_Shield_3806325_cropped.png',
|
||||||
EncounterType.BATTLE_BOSS: 'noun_dragon_3820621_cropped.png',
|
EncounterType.BATTLE_BOSS: 'noun_dragon_3820621_cropped.png',
|
||||||
|
|
@ -18,9 +20,39 @@ _ICONS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def render_map(quest_map: QuestMap) -> List[Dict]:
|
_PATH_ICONS = {
|
||||||
rendered_encounters = []
|
QuestPath.FORWARD: 'arrow_down.png',
|
||||||
|
QuestPath.FORWARD_LEFT: 'arrow_down_left.png',
|
||||||
|
QuestPath.FORWARD_RIGHT: 'arrow_down_right.png',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class RenderedElement:
|
||||||
|
description: str
|
||||||
|
src: str
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
w: int
|
||||||
|
h: int
|
||||||
|
|
||||||
|
|
||||||
|
class RenderedEncounter(RenderedElement):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RenderedPath(RenderedElement):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass(frozen=True)
|
||||||
|
class RenderedMap:
|
||||||
|
encounters: List[RenderedEncounter]
|
||||||
|
paths: List[RenderedPath]
|
||||||
|
|
||||||
|
|
||||||
|
def render_map(quest_map: QuestMap) -> RenderedMap:
|
||||||
|
rendered_encounters = []
|
||||||
row: List[MapEncounter]
|
row: List[MapEncounter]
|
||||||
for r, row in enumerate(quest_map.encounters):
|
for r, row in enumerate(quest_map.encounters):
|
||||||
for c, encounter in enumerate(row):
|
for c, encounter in enumerate(row):
|
||||||
|
|
@ -28,23 +60,62 @@ def render_map(quest_map: QuestMap) -> List[Dict]:
|
||||||
if rendered_encounter is not None:
|
if rendered_encounter is not None:
|
||||||
rendered_encounters.append(rendered_encounter)
|
rendered_encounters.append(rendered_encounter)
|
||||||
|
|
||||||
return rendered_encounters
|
rendered_paths = []
|
||||||
|
row: List[QuestPath]
|
||||||
|
for r, row in enumerate(quest_map.paths):
|
||||||
|
for c, path in enumerate(row):
|
||||||
|
rendered_path = _render_path(r, c, path)
|
||||||
|
if rendered_path is not None:
|
||||||
|
rendered_paths.append(rendered_path)
|
||||||
|
|
||||||
|
return RenderedMap(rendered_encounters, rendered_paths)
|
||||||
|
|
||||||
|
|
||||||
def _render_encounter(r: int, c: int, encounter: MapEncounter) -> Optional[Dict]:
|
_ENCOUNTER_W = 40
|
||||||
|
_ENCOUNTER_H = 40
|
||||||
|
_ARROW_W = 40
|
||||||
|
_ARROW_H = 20
|
||||||
|
_PADDING_W = 10
|
||||||
|
_PADDING_V = 5
|
||||||
|
_ENCOUNTER_COLUMN_W = _ENCOUNTER_W + _PADDING_W
|
||||||
|
_PATH_COLUMN_W = _ARROW_W + _PADDING_W
|
||||||
|
_COLUMN_W = _ENCOUNTER_COLUMN_W + _PATH_COLUMN_W
|
||||||
|
_ROW_H = _ENCOUNTER_H + _PADDING_V + _ARROW_H + _PADDING_V
|
||||||
|
|
||||||
|
|
||||||
|
def _render_encounter(r: int, c: int, encounter: MapEncounter) -> Optional[RenderedEncounter]:
|
||||||
if encounter.type == EncounterType.INACCESSIBLE:
|
if encounter.type == EncounterType.INACCESSIBLE:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
icon = f'map/{_ICONS[encounter.type]}'
|
icon = f'map/{_ENCOUNTER_ICONS[encounter.type]}'
|
||||||
x = 120 * c
|
x = _COLUMN_W * c
|
||||||
y = 100 * r
|
y = _ROW_H * r
|
||||||
w = 40
|
w = _ENCOUNTER_W
|
||||||
h = 40
|
h = _ENCOUNTER_H
|
||||||
return {
|
return RenderedEncounter(
|
||||||
'description': encounter.description,
|
description=encounter.description,
|
||||||
'src': icon,
|
src=icon,
|
||||||
'x': x,
|
x=x,
|
||||||
'y': y,
|
y=y,
|
||||||
'w': w,
|
w=w,
|
||||||
'h': h,
|
h=h
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _render_path(r: int, c: int, path: QuestPath) -> Optional[RenderedPath]:
|
||||||
|
if path == QuestPath.NO_PATH:
|
||||||
|
return None
|
||||||
|
|
||||||
|
icon = f'map/{_PATH_ICONS[path]}'
|
||||||
|
x = _ENCOUNTER_COLUMN_W * ((c + 1) // 2) + _PATH_COLUMN_W * (c // 2)
|
||||||
|
y = (_ENCOUNTER_H + _PADDING_V) + _ROW_H * r
|
||||||
|
w = _ARROW_W
|
||||||
|
h = _ARROW_H
|
||||||
|
return RenderedEncounter(
|
||||||
|
description=path.description,
|
||||||
|
src=icon,
|
||||||
|
x=x,
|
||||||
|
y=y,
|
||||||
|
w=w,
|
||||||
|
h=h
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -46,13 +46,17 @@ class QuestPath(enum.Enum):
|
||||||
FORWARD_LEFT = 'forward_left'
|
FORWARD_LEFT = 'forward_left'
|
||||||
FORWARD_RIGHT = 'forward_right'
|
FORWARD_RIGHT = 'forward_right'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def description(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
class MapEncounter:
|
class MapEncounter:
|
||||||
type: EncounterType
|
type: EncounterType
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self) -> str:
|
||||||
return str(self.type)
|
return str(self.type)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -63,5 +67,6 @@ class QuestMap:
|
||||||
# Inaccessible encounters can be None (like in last line).
|
# Inaccessible encounters can be None (like in last line).
|
||||||
self.encounters: List[List[MapEncounter]] = []
|
self.encounters: List[List[MapEncounter]] = []
|
||||||
|
|
||||||
# List of rows of diagonal paths, each row has 2 paths.
|
# List of rows of straight and diagonal paths, each row has 5 paths:
|
||||||
self.diagonals: List[List[QuestPath]] = []
|
# 3 on the columns and 2 between them, sorted from left to right.
|
||||||
|
self.paths: List[List[QuestPath]] = []
|
||||||
|
|
|
||||||
BIN
questhelper/map/static/map/arrow_down.png
Normal file
BIN
questhelper/map/static/map/arrow_down.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
questhelper/map/static/map/arrow_down_left.png
Normal file
BIN
questhelper/map/static/map/arrow_down_left.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
questhelper/map/static/map/arrow_down_right.png
Normal file
BIN
questhelper/map/static/map/arrow_down_right.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
|
|
@ -4,7 +4,15 @@
|
||||||
<h1>Map</h1>
|
<h1>Map</h1>
|
||||||
|
|
||||||
<div style="position: relative">
|
<div style="position: relative">
|
||||||
{% for e in encounters %}
|
{% for e in map.encounters %}
|
||||||
|
<img src="{% static e.src %}"
|
||||||
|
alt="{{e.description}}"
|
||||||
|
title="{{e.description}}"
|
||||||
|
style="position: absolute; left: {{e.x}}; top: {{e.y}};"
|
||||||
|
width="{{e.w}}"
|
||||||
|
height="{{e.h}}">
|
||||||
|
{% endfor %}
|
||||||
|
{% for e in map.paths %}
|
||||||
<img src="{% static e.src %}"
|
<img src="{% static e.src %}"
|
||||||
alt="{{e.description}}"
|
alt="{{e.description}}"
|
||||||
title="{{e.description}}"
|
title="{{e.description}}"
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ from django.template import loader
|
||||||
|
|
||||||
from map import map_generator
|
from map import map_generator
|
||||||
from map import map_renderer
|
from map import map_renderer
|
||||||
|
from map.map_renderer import RenderedMap
|
||||||
from map.quest_map import QuestMap
|
from map.quest_map import QuestMap
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
quest_map: QuestMap = map_generator.generate_map()
|
quest_map: QuestMap = map_generator.generate_map()
|
||||||
rendered_map = map_renderer.render_map(quest_map)
|
rendered_map: RenderedMap = map_renderer.render_map(quest_map)
|
||||||
|
|
||||||
template = loader.get_template('map/index.html')
|
template = loader.get_template('map/index.html')
|
||||||
context = {'encounters': rendered_map}
|
context = {'map': rendered_map}
|
||||||
return HttpResponse(template.render(context, request))
|
return HttpResponse(template.render(context, request))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue