treballant en el extendedMap per a les colisións fora de pantalla
This commit is contained in:
@@ -197,6 +197,13 @@ assets:
|
|||||||
- ${PREFIX}/data/enemies/wave.gif
|
- ${PREFIX}/data/enemies/wave.gif
|
||||||
- ${PREFIX}/data/enemies/z80.gif
|
- ${PREFIX}/data/enemies/z80.gif
|
||||||
|
|
||||||
|
# PLATFORMS
|
||||||
|
platforms:
|
||||||
|
ANIMATION:
|
||||||
|
- ${PREFIX}/data/platforms/platform1.yaml
|
||||||
|
BITMAP:
|
||||||
|
- ${PREFIX}/data/platforms/platform1.gif
|
||||||
|
|
||||||
# PLAYER
|
# PLAYER
|
||||||
player:
|
player:
|
||||||
BITMAP:
|
BITMAP:
|
||||||
|
|||||||
BIN
data/platforms/platform1.gif
Normal file
BIN
data/platforms/platform1.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 266 B |
10
data/platforms/platform1.yaml
Normal file
10
data/platforms/platform1.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# platform1 animation
|
||||||
|
tileSetFile: platform1.gif
|
||||||
|
frameWidth: 24
|
||||||
|
frameHeight: 8
|
||||||
|
|
||||||
|
animations:
|
||||||
|
- name: default
|
||||||
|
speed: 0
|
||||||
|
loopFrom: 0
|
||||||
|
frames: [0]
|
||||||
@@ -19,14 +19,14 @@ room:
|
|||||||
tilemap:
|
tilemap:
|
||||||
# Mapa de dibujo (indices de tiles, -1 = vacio)
|
# Mapa de dibujo (indices de tiles, -1 = vacio)
|
||||||
draw:
|
draw:
|
||||||
- [191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
|
||||||
- [167, 165, 184, 166, 165, 184, 165, 165, 167, 165, 165, 166, 165, 165, 184, 165, 165, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 165]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
|
||||||
- [210, 180, 210, 212, 210, 180, 210, 211, 212, 210, 180, 210, 210, 211, 210, 212, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
|
||||||
- [163, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 163, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
|
||||||
- [42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
|
||||||
- [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264, 264]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
|
||||||
- [24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
@@ -48,9 +48,9 @@ tilemap:
|
|||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
@@ -63,4 +63,3 @@ tilemap:
|
|||||||
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0]
|
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0]
|
||||||
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 0, 0, 0, 0, 0]
|
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 0, 0, 0, 0, 0]
|
||||||
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ tilemap:
|
|||||||
- [42, 42, 210, 211, 211, 210, 180, 210, 212, 210, 180, 210, 211, 212, 210, 180, 210, 210, 210, 210, 211, 212, 210, 180, 210, 212, 180, 210, 210, 166, 210, 211]
|
- [42, 42, 210, 211, 211, 210, 180, 210, 212, 210, 180, 210, 211, 212, 210, 180, 210, 210, 210, 210, 211, 212, 210, 180, 210, 212, 180, 210, 210, 166, 210, 211]
|
||||||
- [42, 42, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [42, 42, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [42, 42, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 1, 1, 1]
|
- [42, 42, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 1, 1, 1]
|
||||||
- [33, 33, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48, 5, 25]
|
- [303, 303, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 48, 5, 25]
|
||||||
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 302, 24, 25]
|
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 302, 24, 25]
|
||||||
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
||||||
- [33, 33, -1, 412, 412, 412, 412, -1, -1, -1, -1, 412, 303, 412, 412, 412, -1, -1, -1, -1, 412, 303, 412, 412, 412, 412, 303, -1, -1, -1, 24, 25]
|
- [33, 33, -1, 412, 412, 412, 412, -1, -1, -1, -1, 412, 303, 412, 412, 412, -1, -1, -1, -1, 412, 303, 412, 412, 412, 412, 303, -1, -1, -1, 24, 25]
|
||||||
@@ -32,10 +32,10 @@ tilemap:
|
|||||||
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 410, 24, 25]
|
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 410, 24, 25]
|
||||||
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
- [33, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
||||||
- [33, 33, 412, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 410, 24, 25]
|
- [33, 33, 412, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 410, 24, 25]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, 409, 409, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, 409, 409, 409, 409, -1, -1, 48, 49]
|
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 409, 409, 409, 409, 409, -1, -1, 48, 49]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [-1, -1, 303, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
||||||
@@ -47,7 +47,7 @@ tilemap:
|
|||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
|
||||||
- [0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]
|
- [2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
||||||
- [0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1]
|
- [0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 1]
|
||||||
@@ -55,10 +55,10 @@ tilemap:
|
|||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
||||||
- [0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1]
|
- [0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 1]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 1, 1]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
@@ -90,14 +90,14 @@ items:
|
|||||||
|
|
||||||
# Plataformas móviles en esta habitación
|
# Plataformas móviles en esta habitación
|
||||||
platforms:
|
platforms:
|
||||||
- animation: bin.yaml
|
- animation: platform1.yaml
|
||||||
speed: 30
|
speed: 30
|
||||||
loop: circular
|
loop: circular
|
||||||
easing: cubicInOut
|
easing: cubicInOut
|
||||||
frame: 0
|
frame: 0
|
||||||
path:
|
path:
|
||||||
- {x: 5, y: 18, wait: 2.0}
|
- {x: 5, y: 18, wait: 2}
|
||||||
- {x: 20, y: 18, wait: 2.0}
|
- {x: 20, y: 18, wait: 2}
|
||||||
- {x: 20, y: 13, wait: 2.0}
|
- {x: 20, y: 13, wait: 2}
|
||||||
- {x: 5, y: 13, wait: 2.0}
|
- {x: 5, y: 13, wait: 2}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace Resource {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Resource pack file format
|
// Resource pack file format
|
||||||
// Header: "JDDI" (4 bytes) + Version (4 bytes)
|
// Header: "P26R" (4 bytes) + Version (4 bytes)
|
||||||
// Metadata: Count + array of ResourceEntry
|
// Metadata: Count + array of ResourceEntry
|
||||||
// Data: Encrypted data block
|
// Data: Encrypted data block
|
||||||
class Pack {
|
class Pack {
|
||||||
@@ -49,9 +49,9 @@ namespace Resource {
|
|||||||
[[nodiscard]] auto calculatePackChecksum() const -> uint32_t; // Validation
|
[[nodiscard]] auto calculatePackChecksum() const -> uint32_t; // Validation
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr std::array<char, 4> MAGIC_HEADER = {'J', 'D', 'D', 'I'}; // Pack format constants
|
static constexpr std::array<char, 4> MAGIC_HEADER = {'P', '2', '6', 'R'}; // Pack format constants
|
||||||
static constexpr uint32_t VERSION = 1;
|
static constexpr uint32_t VERSION = 2;
|
||||||
static constexpr const char* DEFAULT_ENCRYPT_KEY = "JDDI_RESOURCES_2024";
|
static constexpr const char* DEFAULT_ENCRYPT_KEY = "P26_RESOURCES_2026";
|
||||||
|
|
||||||
static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t; // Utility methods
|
static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t; // Utility methods
|
||||||
|
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ void Player::update(float delta_time) {
|
|||||||
checkFalling();
|
checkFalling();
|
||||||
|
|
||||||
// 6. Kill tiles
|
// 6. Kill tiles
|
||||||
auto [ktc, kox, koy] = getCollisionContext();
|
const auto& ktc = room_->getTileCollider();
|
||||||
if (ktc.touchesKillTile(x_ + kox, y_ + koy, WIDTH, HEIGHT)) {
|
if (ktc.touchesKillTile(x_, y_, WIDTH, HEIGHT)) {
|
||||||
markAsDead();
|
markAsDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,11 +200,11 @@ void Player::handleJumpAndDrop() {
|
|||||||
|
|
||||||
// Drop-through: plataforma passable
|
// Drop-through: plataforma passable
|
||||||
if (wanna_down_ && state_ == State::ON_GROUND) {
|
if (wanna_down_ && state_ == State::ON_GROUND) {
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
const auto& tc = room_->getTileCollider();
|
||||||
float foot_y = (y_ + oy) + HEIGHT;
|
float foot_y = y_ + HEIGHT;
|
||||||
int foot_row = static_cast<int>(foot_y) / Tile::SIZE;
|
int foot_row = static_cast<int>(foot_y) / Tile::SIZE;
|
||||||
int left_col = static_cast<int>(x_ + ox) / Tile::SIZE;
|
int left_col = static_cast<int>(x_) / Tile::SIZE;
|
||||||
int right_col = static_cast<int>((x_ + ox) + WIDTH - 1) / Tile::SIZE;
|
int right_col = static_cast<int>(x_ + WIDTH - 1) / Tile::SIZE;
|
||||||
|
|
||||||
for (int col = left_col; col <= right_col; ++col) {
|
for (int col = left_col; col <= right_col; ++col) {
|
||||||
if (tc.getTileAt(col, foot_row) == TileCollider::Tile::PASSABLE) {
|
if (tc.getTileAt(col, foot_row) == TileCollider::Tile::PASSABLE) {
|
||||||
@@ -230,43 +230,27 @@ void Player::startJump() {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
void Player::moveHorizontal(float delta_time) {
|
void Player::moveHorizontal(float delta_time) {
|
||||||
if (vx_ == 0.0F) {
|
const auto& tc = room_->getTileCollider();
|
||||||
// Aunque no haya movimiento horizontal, si estamos en slope hay que seguirla
|
|
||||||
// (por si la gravedad nos ha movido o algo)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
|
||||||
float new_x = x_ + (vx_ * delta_time);
|
float new_x = x_ + (vx_ * delta_time);
|
||||||
|
|
||||||
// Colisión con paredes (room actual)
|
// Comprobar ambos muros siempre (el tilemap extendido incluye paredes de rooms
|
||||||
if (vx_ < 0.0F) {
|
// adyacentes; comprobar ambos lados evita solapamiento en zona de borde)
|
||||||
float wall = tc.checkWallLeft(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
float wall = tc.checkWallLeft(new_x, y_, WIDTH, HEIGHT);
|
||||||
if (wall != Collision::NONE) {
|
if (wall != Collision::NONE && wall > new_x) {
|
||||||
new_x = wall - ox;
|
new_x = wall;
|
||||||
}
|
}
|
||||||
} else {
|
wall = tc.checkWallRight(new_x, y_, WIDTH, HEIGHT);
|
||||||
float wall = tc.checkWallRight(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
if (wall != Collision::NONE) {
|
||||||
if (wall != Collision::NONE) {
|
float corrected = wall - WIDTH;
|
||||||
new_x = wall - WIDTH - ox;
|
if (corrected < new_x) { new_x = corrected; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-room: comprobar muros en rooms adyacentes
|
|
||||||
auto cross = getCrossRoomChecks();
|
|
||||||
checkCrossRoomWallH(new_x, cross);
|
|
||||||
|
|
||||||
x_ = new_x;
|
x_ = new_x;
|
||||||
|
|
||||||
// Si estamos en una slope, ajustar Y para seguirla
|
// Slope following y detección solo cuando hay movimiento horizontal
|
||||||
if (state_ == State::ON_SLOPE) {
|
if (vx_ == 0.0F) { return; }
|
||||||
followSlope();
|
if (state_ == State::ON_SLOPE) { followSlope(); }
|
||||||
}
|
if (state_ == State::ON_GROUND) { detectSlopeEntry(); }
|
||||||
|
|
||||||
// Si estamos en suelo plano, detectar entrada a slope
|
|
||||||
if (state_ == State::ON_GROUND) {
|
|
||||||
detectSlopeEntry();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajusta Y del jugador para seguir la superficie de la slope mientras camina.
|
// Ajusta Y del jugador para seguir la superficie de la slope mientras camina.
|
||||||
@@ -274,18 +258,18 @@ void Player::moveHorizontal(float delta_time) {
|
|||||||
// actual y la inferior (las slopes en escalera bajan una fila por tile).
|
// actual y la inferior (las slopes en escalera bajan una fila por tile).
|
||||||
// Si no encuentra slope, llama a exitSlope().
|
// Si no encuentra slope, llama a exitSlope().
|
||||||
void Player::followSlope() {
|
void Player::followSlope() {
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
const auto& tc = room_->getTileCollider();
|
||||||
|
|
||||||
// SLOPE_L (\): pie izquierdo. SLOPE_R (/): pie derecho.
|
// SLOPE_L (\): pie izquierdo. SLOPE_R (/): pie derecho.
|
||||||
float foot_x = (slope_type_ == TileCollider::Tile::SLOPE_L) ? (x_ + ox) : (x_ + ox) + WIDTH - 1;
|
float foot_x = (slope_type_ == TileCollider::Tile::SLOPE_L) ? x_ : x_ + WIDTH - 1;
|
||||||
|
|
||||||
// Calcular Y en la slope actual
|
// Calcular Y en la slope actual
|
||||||
float surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x);
|
float surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x);
|
||||||
y_ = surface_y - HEIGHT - oy;
|
y_ = surface_y - HEIGHT;
|
||||||
|
|
||||||
// Comprobar si hemos salido del tile actual
|
// Comprobar si hemos salido del tile actual
|
||||||
int foot_tile_x = static_cast<int>(foot_x) / Tile::SIZE;
|
int foot_tile_x = static_cast<int>(foot_x) / Tile::SIZE;
|
||||||
int foot_tile_y = static_cast<int>((y_ + oy) + HEIGHT) / Tile::SIZE;
|
int foot_tile_y = static_cast<int>(y_ + HEIGHT) / Tile::SIZE;
|
||||||
|
|
||||||
if (foot_tile_x != slope_tile_x_ || foot_tile_y != slope_tile_y_) {
|
if (foot_tile_x != slope_tile_x_ || foot_tile_y != slope_tile_y_) {
|
||||||
// Buscar slope en el tile calculado y en el de abajo (la escalera de slopes
|
// Buscar slope en el tile calculado y en el de abajo (la escalera de slopes
|
||||||
@@ -297,7 +281,7 @@ void Player::followSlope() {
|
|||||||
slope_tile_y_ = row;
|
slope_tile_y_ = row;
|
||||||
slope_type_ = new_tile;
|
slope_type_ = new_tile;
|
||||||
surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x);
|
surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x);
|
||||||
y_ = surface_y - HEIGHT - oy;
|
y_ = surface_y - HEIGHT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,16 +294,16 @@ void Player::followSlope() {
|
|||||||
// entre filas cuando se sale por el extremo inferior de la slope).
|
// entre filas cuando se sale por el extremo inferior de la slope).
|
||||||
// Si hay suelo, snapea al borde del tile. Si no, empieza a caer.
|
// Si hay suelo, snapea al borde del tile. Si no, empieza a caer.
|
||||||
void Player::exitSlope() {
|
void Player::exitSlope() {
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
const auto& tc = room_->getTileCollider();
|
||||||
float foot_y = (y_ + oy) + HEIGHT;
|
float foot_y = y_ + HEIGHT;
|
||||||
|
|
||||||
// Comprobar suelo en la fila actual y la siguiente (al salir por abajo de una slope,
|
// Comprobar suelo en la fila actual y la siguiente (al salir por abajo de una slope,
|
||||||
// los pies pueden estar en el último pixel de la fila, justo antes del suelo)
|
// los pies pueden estar en el último pixel de la fila, justo antes del suelo)
|
||||||
for (int check = 0; check <= 1; ++check) {
|
for (int check = 0; check <= 1; ++check) {
|
||||||
float check_y = foot_y + check;
|
float check_y = foot_y + check;
|
||||||
if (tc.hasGroundBelow(x_ + ox, check_y, WIDTH)) {
|
if (tc.hasGroundBelow(x_, check_y, WIDTH)) {
|
||||||
int row = static_cast<int>(check_y) / Tile::SIZE;
|
int row = static_cast<int>(check_y) / Tile::SIZE;
|
||||||
y_ = static_cast<float>(row * Tile::SIZE) - HEIGHT - oy;
|
y_ = static_cast<float>(row * Tile::SIZE) - HEIGHT;
|
||||||
transitionToState(State::ON_GROUND);
|
transitionToState(State::ON_GROUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -333,12 +317,12 @@ void Player::exitSlope() {
|
|||||||
// Las slopes en escalera están una fila arriba del suelo, así que checkSlopeBelow
|
// Las slopes en escalera están una fila arriba del suelo, así que checkSlopeBelow
|
||||||
// también mira la fila superior.
|
// también mira la fila superior.
|
||||||
void Player::detectSlopeEntry() {
|
void Player::detectSlopeEntry() {
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
const auto& tc = room_->getTileCollider();
|
||||||
float foot_y = (y_ + oy) + HEIGHT;
|
float foot_y = y_ + HEIGHT;
|
||||||
|
|
||||||
auto slope = tc.checkSlopeBelow(x_ + ox, foot_y, WIDTH);
|
auto slope = tc.checkSlopeBelow(x_, foot_y, WIDTH);
|
||||||
if (slope.on_slope) {
|
if (slope.on_slope) {
|
||||||
y_ = slope.surface_y - HEIGHT - oy;
|
y_ = slope.surface_y - HEIGHT;
|
||||||
slope_tile_x_ = slope.tile_x;
|
slope_tile_x_ = slope.tile_x;
|
||||||
slope_tile_y_ = slope.tile_y;
|
slope_tile_y_ = slope.tile_y;
|
||||||
slope_type_ = slope.type;
|
slope_type_ = slope.type;
|
||||||
@@ -353,29 +337,27 @@ void Player::detectSlopeEntry() {
|
|||||||
void Player::moveVertical(float delta_time) {
|
void Player::moveVertical(float delta_time) {
|
||||||
if (state_ != State::ON_AIR) { return; }
|
if (state_ != State::ON_AIR) { return; }
|
||||||
|
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
const auto& tc = room_->getTileCollider();
|
||||||
float displacement = vy_ * delta_time;
|
float displacement = vy_ * delta_time;
|
||||||
|
|
||||||
float old_y = y_;
|
|
||||||
|
|
||||||
if (vy_ < 0.0F) {
|
if (vy_ < 0.0F) {
|
||||||
// Subiendo: comprobar techo
|
// Subiendo: comprobar techo
|
||||||
float new_y = y_ + displacement;
|
float new_y = y_ + displacement;
|
||||||
float ceiling = tc.checkCeiling(x_ + ox, new_y + oy, WIDTH);
|
float ceiling = tc.checkCeiling(x_, new_y, WIDTH);
|
||||||
if (ceiling != Collision::NONE) {
|
if (ceiling != Collision::NONE) {
|
||||||
y_ = ceiling - oy;
|
y_ = ceiling;
|
||||||
vy_ = 0.0F;
|
vy_ = 0.0F;
|
||||||
} else {
|
} else {
|
||||||
y_ = new_y;
|
y_ = new_y;
|
||||||
}
|
}
|
||||||
} else if (vy_ > 0.0F) {
|
} else if (vy_ > 0.0F) {
|
||||||
// Bajando: comprobar suelo
|
// Bajando: comprobar suelo
|
||||||
float foot_y = (y_ + oy) + HEIGHT;
|
float foot_y = y_ + HEIGHT;
|
||||||
float new_foot_y = foot_y + displacement;
|
float new_foot_y = foot_y + displacement;
|
||||||
auto hit = tc.checkFloor(x_ + ox, foot_y, WIDTH, new_foot_y);
|
auto hit = tc.checkFloor(x_, foot_y, WIDTH, new_foot_y);
|
||||||
|
|
||||||
if (hit.y != Collision::NONE) {
|
if (hit.y != Collision::NONE) {
|
||||||
y_ = hit.y - HEIGHT - oy;
|
y_ = hit.y - HEIGHT;
|
||||||
if (hit.type == TileCollider::Tile::SLOPE_L || hit.type == TileCollider::Tile::SLOPE_R) {
|
if (hit.type == TileCollider::Tile::SLOPE_L || hit.type == TileCollider::Tile::SLOPE_R) {
|
||||||
slope_tile_x_ = hit.tile_x;
|
slope_tile_x_ = hit.tile_x;
|
||||||
slope_tile_y_ = hit.tile_y;
|
slope_tile_y_ = hit.tile_y;
|
||||||
@@ -391,10 +373,6 @@ void Player::moveVertical(float delta_time) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-room: comprobar suelo/techo en rooms adyacentes
|
|
||||||
auto cross = getCrossRoomChecks();
|
|
||||||
checkCrossRoomFloor(old_y, cross);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -404,7 +382,7 @@ void Player::moveVertical(float delta_time) {
|
|||||||
void Player::checkFalling() {
|
void Player::checkFalling() {
|
||||||
if (state_ == State::ON_AIR) { return; }
|
if (state_ == State::ON_AIR) { return; }
|
||||||
|
|
||||||
auto [tc, ox, oy] = getCollisionContext();
|
const auto& tc = room_->getTileCollider();
|
||||||
|
|
||||||
if (state_ == State::ON_SLOPE) {
|
if (state_ == State::ON_SLOPE) {
|
||||||
// Verificar que el tile de slope sigue existiendo
|
// Verificar que el tile de slope sigue existiendo
|
||||||
@@ -419,14 +397,15 @@ void Player::checkFalling() {
|
|||||||
// ON_GROUND: si está sobre una plataforma móvil, no comprobar tiles
|
// ON_GROUND: si está sobre una plataforma móvil, no comprobar tiles
|
||||||
if (on_platform_) { return; }
|
if (on_platform_) { return; }
|
||||||
|
|
||||||
// ON_GROUND: comprobar si sigue habiendo suelo
|
// ON_GROUND: comprobar si sigue habiendo suelo (el tilemap extendido
|
||||||
float foot_y = (y_ + oy) + HEIGHT;
|
// incluye tiles de las rooms adyacentes, así que no hace falta cross-room)
|
||||||
if (!tc.hasGroundBelow(x_ + ox, foot_y, WIDTH)) {
|
float foot_y = y_ + HEIGHT;
|
||||||
|
if (!tc.hasGroundBelow(x_, foot_y, WIDTH)) {
|
||||||
// Sticking: si no hay suelo pero hay slope debajo, snapear a ella
|
// Sticking: si no hay suelo pero hay slope debajo, snapear a ella
|
||||||
// para transición suave suelo→slope (bajada de rampas sin caer)
|
// para transición suave suelo→slope (bajada de rampas sin caer)
|
||||||
auto slope = tc.checkSlopeBelow(x_ + ox, foot_y, WIDTH);
|
auto slope = tc.checkSlopeBelow(x_, foot_y, WIDTH);
|
||||||
if (slope.on_slope) {
|
if (slope.on_slope) {
|
||||||
y_ = slope.surface_y - HEIGHT - oy;
|
y_ = slope.surface_y - HEIGHT;
|
||||||
slope_tile_x_ = slope.tile_x;
|
slope_tile_x_ = slope.tile_x;
|
||||||
slope_tile_y_ = slope.tile_y;
|
slope_tile_y_ = slope.tile_y;
|
||||||
slope_type_ = slope.type;
|
slope_type_ = slope.type;
|
||||||
@@ -434,11 +413,6 @@ void Player::checkFalling() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-room: comprobar suelo en rooms adyacentes antes de declarar caída
|
|
||||||
if (hasCrossRoomGround(getCrossRoomChecks())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vy_ = 0.0F;
|
vy_ = 0.0F;
|
||||||
transitionToState(State::ON_AIR);
|
transitionToState(State::ON_AIR);
|
||||||
}
|
}
|
||||||
@@ -491,52 +465,6 @@ auto Player::handleBorders() const -> Room::Border {
|
|||||||
return Room::Border::NONE;
|
return Room::Border::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setAdjacentRoom(std::shared_ptr<Room> room, Room::Border direction) {
|
|
||||||
adjacent_room_ = std::move(room);
|
|
||||||
adjacent_direction_ = direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::clearAdjacentRoom() {
|
|
||||||
adjacent_room_.reset();
|
|
||||||
adjacent_direction_ = Room::Border::NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Player::getCollisionContext() const -> CollisionContext {
|
|
||||||
if (!adjacent_room_) {
|
|
||||||
return {room_->getTileCollider(), 0.0F, 0.0F};
|
|
||||||
}
|
|
||||||
|
|
||||||
const float CENTER_X = x_ + (WIDTH / 2.0F);
|
|
||||||
const float CENTER_Y = y_ + (HEIGHT / 2.0F);
|
|
||||||
|
|
||||||
switch (adjacent_direction_) {
|
|
||||||
case Room::Border::TOP:
|
|
||||||
if (CENTER_Y < PlayArea::TOP) {
|
|
||||||
return {adjacent_room_->getTileCollider(), 0.0F, static_cast<float>(PlayArea::HEIGHT)};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Room::Border::BOTTOM:
|
|
||||||
if (CENTER_Y > PlayArea::BOTTOM) {
|
|
||||||
return {adjacent_room_->getTileCollider(), 0.0F, -static_cast<float>(PlayArea::HEIGHT)};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Room::Border::LEFT:
|
|
||||||
if (CENTER_X < PlayArea::LEFT) {
|
|
||||||
return {adjacent_room_->getTileCollider(), static_cast<float>(PlayArea::WIDTH), 0.0F};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Room::Border::RIGHT:
|
|
||||||
if (CENTER_X > PlayArea::RIGHT) {
|
|
||||||
return {adjacent_room_->getTileCollider(), -static_cast<float>(PlayArea::WIDTH), 0.0F};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {room_->getTileCollider(), 0.0F, 0.0F};
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::switchBorders() {
|
void Player::switchBorders() {
|
||||||
switch (border_) {
|
switch (border_) {
|
||||||
case Room::Border::TOP:
|
case Room::Border::TOP:
|
||||||
@@ -569,109 +497,6 @@ void Player::syncSpriteAndCollider() {
|
|||||||
collider_box_ = getRect();
|
collider_box_ = getRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-room collision: asigna una room adyacente por índice
|
|
||||||
void Player::setBorderRoom(int index, std::shared_ptr<Room> room) {
|
|
||||||
if (index >= 0 && index < BORDER_ROOM_COUNT) {
|
|
||||||
border_rooms_[index] = std::move(room);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross-room collision: limpia todas las rooms adyacentes
|
|
||||||
void Player::clearBorderRooms() {
|
|
||||||
for (auto& r : border_rooms_) {
|
|
||||||
r.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross-room: construye la lista de rooms adyacentes que solapan con la bbox del jugador
|
|
||||||
auto Player::getCrossRoomChecks() const -> CrossRoomChecks {
|
|
||||||
// Offsets por room: TOP, RIGHT, BOTTOM, LEFT, TR, BR, BL, TL
|
|
||||||
static constexpr float PW = static_cast<float>(PlayArea::WIDTH);
|
|
||||||
static constexpr float PH = static_cast<float>(PlayArea::HEIGHT);
|
|
||||||
static constexpr struct { float ox; float oy; } OFFSETS[BORDER_ROOM_COUNT] = {
|
|
||||||
{0, PH}, {-PW, 0}, {0, -PH}, {PW, 0}, {-PW, PH}, {-PW, -PH}, {PW, -PH}, {PW, PH}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool over_top = y_ < 0.0F;
|
|
||||||
bool over_right = (x_ + WIDTH) > PlayArea::RIGHT;
|
|
||||||
bool over_bottom = (y_ + HEIGHT) > PlayArea::BOTTOM;
|
|
||||||
bool over_left = x_ < 0.0F;
|
|
||||||
bool needed[BORDER_ROOM_COUNT] = {
|
|
||||||
over_top, over_right, over_bottom, over_left,
|
|
||||||
over_top && over_right, over_bottom && over_right,
|
|
||||||
over_bottom && over_left, over_top && over_left
|
|
||||||
};
|
|
||||||
|
|
||||||
CrossRoomChecks result;
|
|
||||||
for (int i = 0; i < BORDER_ROOM_COUNT; ++i) {
|
|
||||||
if (needed[i] && border_rooms_[i]) {
|
|
||||||
result.entries[result.count++] = {&border_rooms_[i]->getTileCollider(), OFFSETS[i].ox, OFFSETS[i].oy};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross-room: comprueba muros horizontales en rooms adyacentes
|
|
||||||
void Player::checkCrossRoomWallH(float& new_x, const CrossRoomChecks& checks) const {
|
|
||||||
for (int i = 0; i < checks.count; ++i) {
|
|
||||||
const auto& [tc, ox, oy] = checks.entries[i];
|
|
||||||
if (vx_ < 0.0F) {
|
|
||||||
float wall = tc->checkWallLeft(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
|
||||||
if (wall != Collision::NONE) {
|
|
||||||
float corrected = wall - ox;
|
|
||||||
if (corrected > new_x) { new_x = corrected; }
|
|
||||||
}
|
|
||||||
} else if (vx_ > 0.0F) {
|
|
||||||
float wall = tc->checkWallRight(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
|
||||||
if (wall != Collision::NONE) {
|
|
||||||
float corrected = wall - WIDTH - ox;
|
|
||||||
if (corrected < new_x) { new_x = corrected; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross-room: comprueba suelo/techo en rooms adyacentes (usa old_y para rango correcto de checkFloor)
|
|
||||||
void Player::checkCrossRoomFloor(float old_y, const CrossRoomChecks& checks) {
|
|
||||||
for (int i = 0; i < checks.count; ++i) {
|
|
||||||
const auto& [tc, ox, oy] = checks.entries[i];
|
|
||||||
if (vy_ < 0.0F) {
|
|
||||||
float ceiling = tc->checkCeiling(x_ + ox, y_ + oy, WIDTH);
|
|
||||||
if (ceiling != Collision::NONE) {
|
|
||||||
float corrected = ceiling - oy;
|
|
||||||
if (corrected > y_) {
|
|
||||||
y_ = corrected;
|
|
||||||
vy_ = 0.0F;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (vy_ > 0.0F) {
|
|
||||||
float old_foot = old_y + oy + HEIGHT;
|
|
||||||
float new_foot = y_ + oy + HEIGHT;
|
|
||||||
auto hit = tc->checkFloor(x_ + ox, old_foot, WIDTH, new_foot);
|
|
||||||
if (hit.y != Collision::NONE) {
|
|
||||||
float corrected = hit.y - HEIGHT - oy;
|
|
||||||
if (corrected < y_) {
|
|
||||||
y_ = corrected;
|
|
||||||
vy_ = 0.0F;
|
|
||||||
transitionToState(State::ON_GROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross-room: comprueba si hay suelo bajo el jugador en alguna room adyacente
|
|
||||||
auto Player::hasCrossRoomGround(const CrossRoomChecks& checks) const -> bool {
|
|
||||||
for (int i = 0; i < checks.count; ++i) {
|
|
||||||
const auto& [tc, ox, oy] = checks.entries[i];
|
|
||||||
float foot = y_ + oy + HEIGHT;
|
|
||||||
if (tc->hasGroundBelow(x_ + ox, foot, WIDTH)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aplica el desplazamiento de una plataforma móvil al jugador
|
// Aplica el desplazamiento de una plataforma móvil al jugador
|
||||||
void Player::applyPlatformDisplacement(float dx, float surface_y) {
|
void Player::applyPlatformDisplacement(float dx, float surface_y) {
|
||||||
y_ = surface_y - HEIGHT; // Snap vertical al top de la plataforma
|
y_ = surface_y - HEIGHT; // Snap vertical al top de la plataforma
|
||||||
|
|||||||
@@ -70,18 +70,11 @@ class Player {
|
|||||||
auto getSpawnParams() -> SpawnData { return {.x = x_, .y = y_, .vx = vx_, .vy = vy_, .last_grounded_position = last_grounded_position_, .state = state_, .flip = sprite_->getFlip()}; }
|
auto getSpawnParams() -> SpawnData { return {.x = x_, .y = y_, .vx = vx_, .vy = vy_, .last_grounded_position = last_grounded_position_, .state = state_, .flip = sprite_->getFlip()}; }
|
||||||
static auto skinToAnimationPath(const std::string& skin_name) -> std::string;
|
static auto skinToAnimationPath(const std::string& skin_name) -> std::string;
|
||||||
void setRoom(std::shared_ptr<Room> room) { room_ = std::move(room); }
|
void setRoom(std::shared_ptr<Room> room) { room_ = std::move(room); }
|
||||||
void setAdjacentRoom(std::shared_ptr<Room> room, Room::Border direction);
|
|
||||||
void clearAdjacentRoom();
|
|
||||||
[[nodiscard]] auto isAlive() const -> bool { return is_alive_; }
|
[[nodiscard]] auto isAlive() const -> bool { return is_alive_; }
|
||||||
[[nodiscard]] auto getVY() const -> float { return vy_; }
|
[[nodiscard]] auto getVY() const -> float { return vy_; }
|
||||||
void applyPlatformDisplacement(float dx, float surface_y);
|
void applyPlatformDisplacement(float dx, float surface_y);
|
||||||
void clearPlatformFlag() { on_platform_ = false; }
|
void clearPlatformFlag() { on_platform_ = false; }
|
||||||
|
|
||||||
// Cross-room collision: rooms adyacentes (TOP=0, RIGHT=1, BOTTOM=2, LEFT=3, TR=4, BR=5, BL=6, TL=7)
|
|
||||||
static constexpr int BORDER_ROOM_COUNT = 8;
|
|
||||||
void setBorderRoom(int index, std::shared_ptr<Room> room);
|
|
||||||
void clearBorderRooms();
|
|
||||||
|
|
||||||
void setPaused(bool value) { is_paused_ = value; }
|
void setPaused(bool value) { is_paused_ = value; }
|
||||||
void setIgnoreInput(bool value) { ignore_input_ = value; }
|
void setIgnoreInput(bool value) { ignore_input_ = value; }
|
||||||
[[nodiscard]] auto getIgnoreInput() const -> bool { return ignore_input_; }
|
[[nodiscard]] auto getIgnoreInput() const -> bool { return ignore_input_; }
|
||||||
@@ -96,18 +89,8 @@ class Player {
|
|||||||
static constexpr int WIDTH = 12;
|
static constexpr int WIDTH = 12;
|
||||||
static constexpr int HEIGHT = 24;
|
static constexpr int HEIGHT = 24;
|
||||||
|
|
||||||
// --- Contexto de colisión (selección de room + traducción de coordenadas) ---
|
|
||||||
struct CollisionContext {
|
|
||||||
const TileCollider& tc;
|
|
||||||
float offset_x;
|
|
||||||
float offset_y;
|
|
||||||
};
|
|
||||||
auto getCollisionContext() const -> CollisionContext;
|
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::shared_ptr<Room> room_;
|
std::shared_ptr<Room> room_;
|
||||||
std::shared_ptr<Room> adjacent_room_;
|
|
||||||
Room::Border adjacent_direction_{Room::Border::NONE};
|
|
||||||
std::unique_ptr<AnimatedSprite> sprite_;
|
std::unique_ptr<AnimatedSprite> sprite_;
|
||||||
|
|
||||||
// --- Posición y física ---
|
// --- Posición y física ---
|
||||||
@@ -142,9 +125,6 @@ class Player {
|
|||||||
Room::Border border_ = Room::Border::TOP;
|
Room::Border border_ = Room::Border::TOP;
|
||||||
int last_grounded_position_ = 0;
|
int last_grounded_position_ = 0;
|
||||||
|
|
||||||
// --- Cross-room collision ---
|
|
||||||
std::shared_ptr<Room> border_rooms_[BORDER_ROOM_COUNT]{};
|
|
||||||
|
|
||||||
// --- Renderizado y sonido ---
|
// --- Renderizado y sonido ---
|
||||||
JA_Sound_t* jump_sound_ = nullptr;
|
JA_Sound_t* jump_sound_ = nullptr;
|
||||||
JA_Sound_t* land_sound_ = nullptr;
|
JA_Sound_t* land_sound_ = nullptr;
|
||||||
@@ -156,21 +136,6 @@ class Player {
|
|||||||
void handleJumpAndDrop();
|
void handleJumpAndDrop();
|
||||||
void moveHorizontal(float delta_time);
|
void moveHorizontal(float delta_time);
|
||||||
void moveVertical(float delta_time);
|
void moveVertical(float delta_time);
|
||||||
|
|
||||||
// Cross-room collision helpers
|
|
||||||
struct CrossRoomEntry {
|
|
||||||
const TileCollider* tc;
|
|
||||||
float ox;
|
|
||||||
float oy;
|
|
||||||
};
|
|
||||||
struct CrossRoomChecks {
|
|
||||||
CrossRoomEntry entries[BORDER_ROOM_COUNT]{};
|
|
||||||
int count{0};
|
|
||||||
};
|
|
||||||
auto getCrossRoomChecks() const -> CrossRoomChecks;
|
|
||||||
void checkCrossRoomWallH(float& new_x, const CrossRoomChecks& checks) const;
|
|
||||||
void checkCrossRoomFloor(float old_y, const CrossRoomChecks& checks);
|
|
||||||
auto hasCrossRoomGround(const CrossRoomChecks& checks) const -> bool;
|
|
||||||
void followSlope();
|
void followSlope();
|
||||||
void exitSlope();
|
void exitSlope();
|
||||||
void detectSlopeEntry();
|
void detectSlopeEntry();
|
||||||
|
|||||||
@@ -1,8 +1,91 @@
|
|||||||
#include "collision_map.hpp"
|
#include "collision_map.hpp"
|
||||||
|
|
||||||
#include <utility> // Para std::move
|
#include <algorithm> // Para std::ranges::fill
|
||||||
|
#include <utility> // Para std::move
|
||||||
|
|
||||||
CollisionMap::CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction)
|
CollisionMap::CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction)
|
||||||
: collision_tile_map_(std::move(collision_tile_map)),
|
: collision_tile_map_(std::move(collision_tile_map)),
|
||||||
|
extended_tile_map_(EW * EH, 0),
|
||||||
conveyor_belt_direction_(conveyor_belt_direction),
|
conveyor_belt_direction_(conveyor_belt_direction),
|
||||||
tile_collider_(collision_tile_map_) {}
|
tile_collider_(extended_tile_map_, EW, EH, CollisionBorder::PX) {
|
||||||
|
buildExtendedCenter();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copia los tiles de la room actual al centro del mapa extendido
|
||||||
|
void CollisionMap::buildExtendedCenter() {
|
||||||
|
std::ranges::fill(extended_tile_map_, 0);
|
||||||
|
|
||||||
|
for (int row = 0; row < MH; ++row) {
|
||||||
|
for (int col = 0; col < MW; ++col) {
|
||||||
|
extended_tile_map_[((row + B) * EW) + (col + B)] =
|
||||||
|
collision_tile_map_[(row * MW) + col];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copia una región rectangular de src (MW×MH) al mapa extendido
|
||||||
|
void CollisionMap::copyRegion(const std::vector<int>& src,
|
||||||
|
int src_col, int src_row,
|
||||||
|
int dst_col, int dst_row,
|
||||||
|
int cols, int rows) {
|
||||||
|
for (int r = 0; r < rows; ++r) {
|
||||||
|
for (int c = 0; c < cols; ++c) {
|
||||||
|
extended_tile_map_[((dst_row + r) * EW) + (dst_col + c)] =
|
||||||
|
src[((src_row + r) * MW) + (src_col + c)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rellena los bordes del mapa extendido con tiles de las habitaciones adyacentes
|
||||||
|
void CollisionMap::updateBorders(const AdjacentData& adj) {
|
||||||
|
// Reconstruir: limpiar bordes y copiar centro
|
||||||
|
buildExtendedCenter();
|
||||||
|
|
||||||
|
// Cardinales
|
||||||
|
// TOP: últimas B filas de la room de arriba → filas 0..B-1 del extendido
|
||||||
|
if (adj.top != nullptr) {
|
||||||
|
copyRegion(*adj.top, 0, MH - B, B, 0, MW, B);
|
||||||
|
}
|
||||||
|
// BOTTOM: primeras B filas de la room de abajo → filas B+MH..B+MH+B-1
|
||||||
|
if (adj.bottom != nullptr) {
|
||||||
|
copyRegion(*adj.bottom, 0, 0, B, B + MH, MW, B);
|
||||||
|
}
|
||||||
|
// LEFT: últimas B columnas de la room izquierda → cols 0..B-1
|
||||||
|
if (adj.left != nullptr) {
|
||||||
|
copyRegion(*adj.left, MW - B, 0, 0, B, B, MH);
|
||||||
|
}
|
||||||
|
// RIGHT: primeras B columnas de la room derecha → cols B+MW..B+MW+B-1
|
||||||
|
if (adj.right != nullptr) {
|
||||||
|
copyRegion(*adj.right, 0, 0, B + MW, B, B, MH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diagonales (esquinas B×B)
|
||||||
|
// TOP-LEFT: esquina inferior-derecha de la room diagonal
|
||||||
|
if (adj.top_left != nullptr) {
|
||||||
|
copyRegion(*adj.top_left, MW - B, MH - B, 0, 0, B, B);
|
||||||
|
}
|
||||||
|
// TOP-RIGHT: esquina inferior-izquierda de la room diagonal
|
||||||
|
if (adj.top_right != nullptr) {
|
||||||
|
copyRegion(*adj.top_right, 0, MH - B, B + MW, 0, B, B);
|
||||||
|
}
|
||||||
|
// BOTTOM-LEFT: esquina superior-derecha de la room diagonal
|
||||||
|
if (adj.bottom_left != nullptr) {
|
||||||
|
copyRegion(*adj.bottom_left, MW - B, 0, 0, B + MH, B, B);
|
||||||
|
}
|
||||||
|
// BOTTOM-RIGHT: esquina superior-izquierda de la room diagonal
|
||||||
|
if (adj.bottom_right != nullptr) {
|
||||||
|
copyRegion(*adj.bottom_right, 0, 0, B + MW, B + MH, B, B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
void CollisionMap::setCollisionTile(int index, int value) {
|
||||||
|
if (index >= 0 && index < static_cast<int>(collision_tile_map_.size())) {
|
||||||
|
collision_tile_map_[index] = value;
|
||||||
|
// Actualizar también el tile correspondiente en el mapa extendido
|
||||||
|
int row = index / MW;
|
||||||
|
int col = index % MW;
|
||||||
|
extended_tile_map_[((row + B) * EW) + (col + B)] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -3,15 +3,31 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "game/gameplay/tile_collider.hpp"
|
#include "game/gameplay/tile_collider.hpp"
|
||||||
|
#include "utils/defines.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Mapa de colisiones de una habitación
|
* @brief Mapa de colisiones de una habitación
|
||||||
*
|
*
|
||||||
* Contiene el collision_tile_map (grid de tipos de tile) y el TileCollider
|
* Contiene el collision_tile_map original (32×21) y un tilemap extendido (38×27)
|
||||||
* que proporciona queries de colisión directas contra el grid.
|
* que incluye tiles de borde de las habitaciones adyacentes.
|
||||||
|
* El TileCollider opera sobre el mapa extendido, permitiendo colisiones cross-room
|
||||||
|
* sin lógica especial en el Player.
|
||||||
*/
|
*/
|
||||||
class CollisionMap {
|
class CollisionMap {
|
||||||
public:
|
public:
|
||||||
|
// Datos de colisión de las habitaciones adyacentes (punteros a sus collision_tile_map).
|
||||||
|
// nullptr = sin habitación en esa dirección (borde queda como EMPTY).
|
||||||
|
struct AdjacentData {
|
||||||
|
const std::vector<int>* top{nullptr};
|
||||||
|
const std::vector<int>* bottom{nullptr};
|
||||||
|
const std::vector<int>* left{nullptr};
|
||||||
|
const std::vector<int>* right{nullptr};
|
||||||
|
const std::vector<int>* top_left{nullptr};
|
||||||
|
const std::vector<int>* top_right{nullptr};
|
||||||
|
const std::vector<int>* bottom_left{nullptr};
|
||||||
|
const std::vector<int>* bottom_right{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction);
|
CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction);
|
||||||
~CollisionMap() = default;
|
~CollisionMap() = default;
|
||||||
|
|
||||||
@@ -20,21 +36,36 @@ class CollisionMap {
|
|||||||
CollisionMap(CollisionMap&&) = delete;
|
CollisionMap(CollisionMap&&) = delete;
|
||||||
auto operator=(CollisionMap&&) -> CollisionMap& = delete;
|
auto operator=(CollisionMap&&) -> CollisionMap& = delete;
|
||||||
|
|
||||||
|
// Rellena los bordes del mapa extendido con tiles de las habitaciones adyacentes.
|
||||||
|
void updateBorders(const AdjacentData& adjacent);
|
||||||
|
|
||||||
[[nodiscard]] auto getTileCollider() const -> const TileCollider& { return tile_collider_; }
|
[[nodiscard]] auto getTileCollider() const -> const TileCollider& { return tile_collider_; }
|
||||||
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
|
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
|
||||||
[[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>& { return collision_tile_map_; }
|
[[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>& { return collision_tile_map_; }
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
void setCollisionTile(int index, int value) {
|
void setCollisionTile(int index, int value);
|
||||||
if (index >= 0 && index < static_cast<int>(collision_tile_map_.size())) {
|
|
||||||
collision_tile_map_[index] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void setConveyorBeltDirection(int direction) { conveyor_belt_direction_ = direction; }
|
void setConveyorBeltDirection(int direction) { conveyor_belt_direction_ = direction; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<int> collision_tile_map_;
|
static constexpr int B = CollisionBorder::TILES; // Tiles de borde
|
||||||
|
static constexpr int MW = Map::WIDTH; // Ancho original (32)
|
||||||
|
static constexpr int MH = Map::HEIGHT; // Alto original (21)
|
||||||
|
static constexpr int EW = ExtendedMap::WIDTH; // Ancho extendido (38)
|
||||||
|
static constexpr int EH = ExtendedMap::HEIGHT; // Alto extendido (27)
|
||||||
|
|
||||||
|
std::vector<int> collision_tile_map_; // Original (32×21)
|
||||||
|
std::vector<int> extended_tile_map_; // Extendido (38×27) — referenciado por TileCollider
|
||||||
int conveyor_belt_direction_;
|
int conveyor_belt_direction_;
|
||||||
TileCollider tile_collider_;
|
TileCollider tile_collider_; // Debe ir después de extended_tile_map_ (usa referencia)
|
||||||
|
|
||||||
|
// Copia el centro (room actual) al mapa extendido. Los bordes quedan como EMPTY (0).
|
||||||
|
void buildExtendedCenter();
|
||||||
|
|
||||||
|
// Copia una región rectangular de un tilemap fuente (MW×MH) al mapa extendido.
|
||||||
|
void copyRegion(const std::vector<int>& src,
|
||||||
|
int src_col, int src_row,
|
||||||
|
int dst_col, int dst_row,
|
||||||
|
int cols, int rows);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -215,6 +215,14 @@ auto Room::getTileCollider() const -> const TileCollider& {
|
|||||||
return collision_map_->getTileCollider();
|
return collision_map_->getTileCollider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Room::getCollisionTileMap() const -> const std::vector<int>& {
|
||||||
|
return collision_map_->getCollisionTileMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Room::updateCollisionBorders(const CollisionMap::AdjacentData& adjacent) {
|
||||||
|
collision_map_->updateBorders(adjacent);
|
||||||
|
}
|
||||||
|
|
||||||
// Devuelve la cadena del fichero de la habitación contigua segun el borde
|
// Devuelve la cadena del fichero de la habitación contigua segun el borde
|
||||||
auto Room::getRoom(Border border) -> std::string { // NOLINT(readability-convert-member-functions-to-static)
|
auto Room::getRoom(Border border) -> std::string { // NOLINT(readability-convert-member-functions-to-static)
|
||||||
switch (border) {
|
switch (border) {
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "game/defaults.hpp" // Para Defaults::Game::Room
|
#include "game/defaults.hpp" // Para Defaults::Game::Room
|
||||||
#include "game/entities/enemy.hpp" // Para EnemyData
|
#include "game/entities/enemy.hpp" // Para EnemyData
|
||||||
#include "game/entities/item.hpp" // Para ItemData
|
#include "game/entities/item.hpp" // Para ItemData
|
||||||
#include "game/entities/moving_platform.hpp" // Para MovingPlatform::Data
|
#include "game/entities/moving_platform.hpp" // Para MovingPlatform::Data
|
||||||
#include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data
|
#include "game/gameplay/collision_map.hpp" // Para CollisionMap::AdjacentData
|
||||||
#include "utils/defines.hpp" // Para Tile::SIZE, Map::WIDTH, Map::HEIGHT
|
#include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data
|
||||||
|
#include "utils/defines.hpp" // Para Tile::SIZE, Map::WIDTH, Map::HEIGHT
|
||||||
class Surface;
|
class Surface;
|
||||||
class EnemyManager;
|
class EnemyManager;
|
||||||
class ItemManager;
|
class ItemManager;
|
||||||
class PlatformManager;
|
class PlatformManager;
|
||||||
class CollisionMap;
|
|
||||||
class TileCollider;
|
class TileCollider;
|
||||||
class TilemapRenderer;
|
class TilemapRenderer;
|
||||||
|
|
||||||
@@ -84,6 +84,8 @@ class Room {
|
|||||||
void setPaused(bool value);
|
void setPaused(bool value);
|
||||||
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
|
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
|
||||||
[[nodiscard]] auto getTileCollider() const -> const TileCollider&;
|
[[nodiscard]] auto getTileCollider() const -> const TileCollider&;
|
||||||
|
[[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>&;
|
||||||
|
void updateCollisionBorders(const CollisionMap::AdjacentData& adjacent);
|
||||||
|
|
||||||
// Método de carga de archivos YAML (delegado a RoomLoader)
|
// Método de carga de archivos YAML (delegado a RoomLoader)
|
||||||
static auto loadYAML(const std::string& file_path, bool verbose = false) -> Data;
|
static auto loadYAML(const std::string& file_path, bool verbose = false) -> Data;
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
#include "game/gameplay/tile_collider.hpp"
|
#include "game/gameplay/tile_collider.hpp"
|
||||||
|
|
||||||
#include <algorithm> // Para std::min, std::max
|
#include <algorithm> // Para std::min, std::max, std::clamp
|
||||||
#include <cmath> // Para std::ceil
|
|
||||||
|
|
||||||
#include "utils/defines.hpp"
|
#include "utils/defines.hpp"
|
||||||
|
|
||||||
TileCollider::TileCollider(const std::vector<int>& collision_tile_map)
|
TileCollider::TileCollider(const std::vector<int>& extended_tile_map, int width, int height, int border_px)
|
||||||
: tile_map_(collision_tile_map) {}
|
: width_(width), height_(height), border_px_(border_px), tile_map_(extended_tile_map) {}
|
||||||
|
|
||||||
// --- Queries básicas ---
|
// --- Queries básicas ---
|
||||||
|
|
||||||
auto TileCollider::getTileAt(int tile_x, int tile_y) const -> Tile {
|
auto TileCollider::getTileAt(int tile_x, int tile_y) const -> Tile {
|
||||||
if (tile_x < 0 || tile_x >= MW || tile_y < 0 || tile_y >= MH) {
|
if (tile_x < 0 || tile_x >= width_ || tile_y < 0 || tile_y >= height_) {
|
||||||
return Tile::EMPTY;
|
return Tile::EMPTY;
|
||||||
}
|
}
|
||||||
int value = tile_map_[(tile_y * MW) + tile_x];
|
int value = tile_map_[(tile_y * width_) + tile_x];
|
||||||
if (value >= 0 && value <= 5) {
|
if (value >= 0 && value <= 5) {
|
||||||
return static_cast<Tile>(value);
|
return static_cast<Tile>(value);
|
||||||
}
|
}
|
||||||
@@ -30,8 +29,8 @@ auto TileCollider::isSolid(int tile_x, int tile_y) const -> bool {
|
|||||||
// SLOPE_L (\): alto a la izquierda, bajo a la derecha. surface = bottom - (7 - x_in_tile)
|
// SLOPE_L (\): alto a la izquierda, bajo a la derecha. surface = bottom - (7 - x_in_tile)
|
||||||
// SLOPE_R (/): alto a la derecha, bajo a la izquierda. surface = bottom - x_in_tile
|
// SLOPE_R (/): alto a la derecha, bajo a la izquierda. surface = bottom - x_in_tile
|
||||||
auto TileCollider::getSlopeY(int tile_x, int tile_y, float px) const -> float {
|
auto TileCollider::getSlopeY(int tile_x, int tile_y, float px) const -> float {
|
||||||
auto tile_bottom = static_cast<float>(((tile_y + 1) * TS) - 1);
|
float tile_bottom = toPixel(tile_y + 1) - 1;
|
||||||
float x_in_tile = px - static_cast<float>(tile_x * TS);
|
float x_in_tile = px - toPixel(tile_x);
|
||||||
x_in_tile = std::clamp(x_in_tile, 0.0F, static_cast<float>(TS - 1));
|
x_in_tile = std::clamp(x_in_tile, 0.0F, static_cast<float>(TS - 1));
|
||||||
|
|
||||||
auto tile = getTileAt(tile_x, tile_y);
|
auto tile = getTileAt(tile_x, tile_y);
|
||||||
@@ -54,7 +53,7 @@ auto TileCollider::checkWallLeft(float x, float y, float w, float h) const -> fl
|
|||||||
|
|
||||||
for (int row = top_row; row <= bot_row; ++row) {
|
for (int row = top_row; row <= bot_row; ++row) {
|
||||||
if (isSolid(col, row)) {
|
if (isSolid(col, row)) {
|
||||||
return static_cast<float>((col + 1) * TS);
|
return toPixel(col + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collision::NONE;
|
return Collision::NONE;
|
||||||
@@ -67,7 +66,7 @@ auto TileCollider::checkWallRight(float x, float y, float w, float h) const -> f
|
|||||||
|
|
||||||
for (int row = top_row; row <= bot_row; ++row) {
|
for (int row = top_row; row <= bot_row; ++row) {
|
||||||
if (isSolid(col, row)) {
|
if (isSolid(col, row)) {
|
||||||
return static_cast<float>(col * TS);
|
return toPixel(col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collision::NONE;
|
return Collision::NONE;
|
||||||
@@ -84,7 +83,7 @@ auto TileCollider::checkCeiling(float x, float y, float w) const -> float {
|
|||||||
auto tile = getTileAt(col, top_row);
|
auto tile = getTileAt(col, top_row);
|
||||||
// Slopes actúan como techo (no se atraviesan desde abajo)
|
// Slopes actúan como techo (no se atraviesan desde abajo)
|
||||||
if (tile == Tile::WALL || tile == Tile::SLOPE_L || tile == Tile::SLOPE_R) {
|
if (tile == Tile::WALL || tile == Tile::SLOPE_L || tile == Tile::SLOPE_R) {
|
||||||
return static_cast<float>((top_row + 1) * TS);
|
return toPixel(top_row + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collision::NONE;
|
return Collision::NONE;
|
||||||
@@ -93,7 +92,7 @@ auto TileCollider::checkCeiling(float x, float y, float w) const -> float {
|
|||||||
// --- Colisión con suelo (landing) ---
|
// --- Colisión con suelo (landing) ---
|
||||||
|
|
||||||
// Busca suelo entre foot_y_current y foot_y_new (rango de caída del frame).
|
// Busca suelo entre foot_y_current y foot_y_new (rango de caída del frame).
|
||||||
// WALL: siempre bloquea.
|
// WALL: bloquea si los pies estaban por encima (como PASSABLE).
|
||||||
// PASSABLE: solo si los pies estaban por encima del borde superior del tile.
|
// PASSABLE: solo si los pies estaban por encima del borde superior del tile.
|
||||||
// SLOPE: siempre bloquea (las slopes son sólidas, como muros en diagonal).
|
// SLOPE: siempre bloquea (las slopes son sólidas, como muros en diagonal).
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
@@ -111,9 +110,12 @@ auto TileCollider::checkFloor(float x, float foot_y_current, float w, float foot
|
|||||||
float floor_y = Collision::NONE;
|
float floor_y = Collision::NONE;
|
||||||
|
|
||||||
if (tile == Tile::WALL) {
|
if (tile == Tile::WALL) {
|
||||||
floor_y = static_cast<float>(row * TS);
|
float tile_top = toPixel(row);
|
||||||
|
if (foot_y_current <= tile_top) {
|
||||||
|
floor_y = tile_top;
|
||||||
|
}
|
||||||
} else if (tile == Tile::PASSABLE) {
|
} else if (tile == Tile::PASSABLE) {
|
||||||
auto tile_top = static_cast<float>(row * TS);
|
float tile_top = toPixel(row);
|
||||||
// Solo cuenta como suelo si los pies estaban por encima antes del movimiento
|
// Solo cuenta como suelo si los pies estaban por encima antes del movimiento
|
||||||
if (foot_y_current <= tile_top) {
|
if (foot_y_current <= tile_top) {
|
||||||
floor_y = tile_top;
|
floor_y = tile_top;
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ class TileCollider {
|
|||||||
float surface_y{0};
|
float surface_y{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit TileCollider(const std::vector<int>& collision_tile_map);
|
// Constructor: recibe el tilemap extendido y sus dimensiones.
|
||||||
|
// border_px es el offset en píxeles para traducir coordenadas de room-space a extended-map.
|
||||||
|
TileCollider(const std::vector<int>& extended_tile_map, int width, int height, int border_px);
|
||||||
|
|
||||||
// Queries básicas
|
// Queries básicas
|
||||||
[[nodiscard]] auto getTileAt(int tile_x, int tile_y) const -> Tile;
|
[[nodiscard]] auto getTileAt(int tile_x, int tile_y) const -> Tile;
|
||||||
@@ -53,10 +55,19 @@ class TileCollider {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int TS = ::Tile::SIZE;
|
static constexpr int TS = ::Tile::SIZE;
|
||||||
static constexpr int MW = ::Map::WIDTH;
|
|
||||||
static constexpr int MH = ::Map::HEIGHT;
|
int width_; // Ancho total del tilemap extendido (en tiles)
|
||||||
|
int height_; // Alto total del tilemap extendido (en tiles)
|
||||||
|
int border_px_; // Offset en píxeles (CollisionBorder::PX)
|
||||||
|
|
||||||
const std::vector<int>& tile_map_;
|
const std::vector<int>& tile_map_;
|
||||||
|
|
||||||
[[nodiscard]] static auto toTile(int px) -> int { return px / TS; }
|
// Convierte píxeles en room-space a índice de tile en el mapa extendido.
|
||||||
|
// Nota: asume que px >= -border_px_ (el jugador no puede estar más allá del borde).
|
||||||
|
[[nodiscard]] auto toTile(int px) const -> int { return (px + border_px_) / TS; }
|
||||||
|
|
||||||
|
// Convierte índice de tile del mapa extendido a píxeles en room-space.
|
||||||
|
[[nodiscard]] auto toPixel(int tile) const -> float {
|
||||||
|
return static_cast<float>((tile * TS) - border_px_);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ Game::Game(Mode mode)
|
|||||||
initPlayer(spawn_data_, room_);
|
initPlayer(spawn_data_, room_);
|
||||||
game_backbuffer_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
|
game_backbuffer_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
|
||||||
changeRoom(current_room_);
|
changeRoom(current_room_);
|
||||||
|
buildCollisionBorders();
|
||||||
|
|
||||||
if (Console::get() != nullptr) {
|
if (Console::get() != nullptr) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@@ -131,6 +132,7 @@ Game::Game(Mode mode)
|
|||||||
// Recargar la habitación desde disco (con los cambios del editor)
|
// Recargar la habitación desde disco (con los cambios del editor)
|
||||||
Resource::Cache::get()->reloadRoom(current_room_);
|
Resource::Cache::get()->reloadRoom(current_room_);
|
||||||
changeRoom(current_room_);
|
changeRoom(current_room_);
|
||||||
|
buildCollisionBorders();
|
||||||
player_->setRoom(room_);
|
player_->setRoom(room_);
|
||||||
};
|
};
|
||||||
GameControl::revert_editor = []() -> std::string {
|
GameControl::revert_editor = []() -> std::string {
|
||||||
@@ -310,39 +312,6 @@ void Game::updatePlaying(float delta_time) {
|
|||||||
player_->clearPlatformFlag();
|
player_->clearPlatformFlag();
|
||||||
checkPlayerAndPlatforms();
|
checkPlayerAndPlatforms();
|
||||||
|
|
||||||
// Cross-room collision: precargar rooms adyacentes para colisiones
|
|
||||||
{
|
|
||||||
player_->clearBorderRooms();
|
|
||||||
auto loadBorder = [&](Room::Border b) -> std::shared_ptr<Room> {
|
|
||||||
auto name = room_->getRoom(b);
|
|
||||||
return (name != "0") ? getOrCreateRoom(name) : nullptr;
|
|
||||||
};
|
|
||||||
auto top = loadBorder(Room::Border::TOP);
|
|
||||||
auto right = loadBorder(Room::Border::RIGHT);
|
|
||||||
auto bottom = loadBorder(Room::Border::BOTTOM);
|
|
||||||
auto left = loadBorder(Room::Border::LEFT);
|
|
||||||
if (top) { player_->setBorderRoom(0, top); }
|
|
||||||
if (right) { player_->setBorderRoom(1, right); }
|
|
||||||
if (bottom) { player_->setBorderRoom(2, bottom); }
|
|
||||||
if (left) { player_->setBorderRoom(3, left); }
|
|
||||||
// Diagonales
|
|
||||||
auto loadDiag = [&](const std::shared_ptr<Room>& a, Room::Border ab,
|
|
||||||
const std::shared_ptr<Room>& b, Room::Border ba) -> std::shared_ptr<Room> {
|
|
||||||
std::string name;
|
|
||||||
if (a) { name = a->getRoom(ab); }
|
|
||||||
if ((name.empty() || name == "0") && b) { name = b->getRoom(ba); }
|
|
||||||
return (!name.empty() && name != "0") ? getOrCreateRoom(name) : nullptr;
|
|
||||||
};
|
|
||||||
auto tr = loadDiag(top, Room::Border::RIGHT, right, Room::Border::TOP);
|
|
||||||
auto br = loadDiag(bottom, Room::Border::RIGHT, right, Room::Border::BOTTOM);
|
|
||||||
auto bl = loadDiag(bottom, Room::Border::LEFT, left, Room::Border::BOTTOM);
|
|
||||||
auto tl = loadDiag(top, Room::Border::LEFT, left, Room::Border::TOP);
|
|
||||||
if (tr) { player_->setBorderRoom(4, tr); }
|
|
||||||
if (br) { player_->setBorderRoom(5, br); }
|
|
||||||
if (bl) { player_->setBorderRoom(6, bl); }
|
|
||||||
if (tl) { player_->setBorderRoom(7, tl); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// Maneja el arrastre del jugador con el ratón (debug)
|
// Maneja el arrastre del jugador con el ratón (debug)
|
||||||
handleDebugMouseDrag(delta_time);
|
handleDebugMouseDrag(delta_time);
|
||||||
@@ -452,6 +421,7 @@ void Game::transitionToState(State new_state) {
|
|||||||
// Respawn room y player
|
// Respawn room y player
|
||||||
room_ = getOrCreateRoom(current_room_);
|
room_ = getOrCreateRoom(current_room_);
|
||||||
initPlayer(spawn_data_, room_);
|
initPlayer(spawn_data_, room_);
|
||||||
|
buildCollisionBorders();
|
||||||
// Pausar ambos
|
// Pausar ambos
|
||||||
room_->setPaused(true);
|
room_->setPaused(true);
|
||||||
player_->setPaused(true);
|
player_->setPaused(true);
|
||||||
@@ -825,6 +795,47 @@ auto Game::getOrCreateRoom(const std::string& room_path) -> std::shared_ptr<Room
|
|||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construye el tilemap extendido de la room actual con los bordes de las adyacentes
|
||||||
|
void Game::buildCollisionBorders() {
|
||||||
|
// Helper: obtiene el collision tilemap de una room adyacente (nullptr si no existe)
|
||||||
|
auto getAdjacentCollision = [&](Room::Border b) -> const std::vector<int>* {
|
||||||
|
auto name = room_->getRoom(b);
|
||||||
|
if (name == "0") { return nullptr; }
|
||||||
|
return &getOrCreateRoom(name)->getCollisionTileMap();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper: obtiene el collision tilemap de una room diagonal (A→B o C→D)
|
||||||
|
auto getDiagCollision = [&](Room::Border first, Room::Border second) -> const std::vector<int>* {
|
||||||
|
// Camino 1: room en dirección 'first', luego su adyacente en dirección 'second'
|
||||||
|
auto name1 = room_->getRoom(first);
|
||||||
|
if (name1 != "0") {
|
||||||
|
auto r = getOrCreateRoom(name1);
|
||||||
|
auto name2 = r->getRoom(second);
|
||||||
|
if (name2 != "0") { return &getOrCreateRoom(name2)->getCollisionTileMap(); }
|
||||||
|
}
|
||||||
|
// Camino 2: room en dirección 'second', luego su adyacente en dirección 'first'
|
||||||
|
auto name3 = room_->getRoom(second);
|
||||||
|
if (name3 != "0") {
|
||||||
|
auto r = getOrCreateRoom(name3);
|
||||||
|
auto name4 = r->getRoom(first);
|
||||||
|
if (name4 != "0") { return &getOrCreateRoom(name4)->getCollisionTileMap(); }
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
CollisionMap::AdjacentData adj;
|
||||||
|
adj.top = getAdjacentCollision(Room::Border::TOP);
|
||||||
|
adj.bottom = getAdjacentCollision(Room::Border::BOTTOM);
|
||||||
|
adj.left = getAdjacentCollision(Room::Border::LEFT);
|
||||||
|
adj.right = getAdjacentCollision(Room::Border::RIGHT);
|
||||||
|
adj.top_left = getDiagCollision(Room::Border::TOP, Room::Border::LEFT);
|
||||||
|
adj.top_right = getDiagCollision(Room::Border::TOP, Room::Border::RIGHT);
|
||||||
|
adj.bottom_left = getDiagCollision(Room::Border::BOTTOM, Room::Border::LEFT);
|
||||||
|
adj.bottom_right = getDiagCollision(Room::Border::BOTTOM, Room::Border::RIGHT);
|
||||||
|
|
||||||
|
room_->updateCollisionBorders(adj);
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza los enemigos de las habitaciones adyacentes a la actual
|
// Actualiza los enemigos de las habitaciones adyacentes a la actual
|
||||||
void Game::updateAdjacentRooms(float delta_time) {
|
void Game::updateAdjacentRooms(float delta_time) {
|
||||||
for (auto border : {Room::Border::TOP, Room::Border::RIGHT, Room::Border::BOTTOM, Room::Border::LEFT}) {
|
for (auto border : {Room::Border::TOP, Room::Border::RIGHT, Room::Border::BOTTOM, Room::Border::LEFT}) {
|
||||||
@@ -869,26 +880,8 @@ void Game::checkPlayerIsOnBorder() {
|
|||||||
|
|
||||||
// Crear nueva habitación y reposicionar jugador
|
// Crear nueva habitación y reposicionar jugador
|
||||||
if (changeRoom(ROOM_NAME)) {
|
if (changeRoom(ROOM_NAME)) {
|
||||||
// Pasar la room saliente como adyacente al player (para colisiones offscreen)
|
// Construir el tilemap extendido de la nueva room con los bordes adyacentes
|
||||||
// La dirección es la opuesta: si salimos por TOP, la vieja queda en BOTTOM
|
buildCollisionBorders();
|
||||||
Room::Border opposite = Room::Border::NONE;
|
|
||||||
switch (BORDER) {
|
|
||||||
case Room::Border::TOP:
|
|
||||||
opposite = Room::Border::BOTTOM;
|
|
||||||
break;
|
|
||||||
case Room::Border::BOTTOM:
|
|
||||||
opposite = Room::Border::TOP;
|
|
||||||
break;
|
|
||||||
case Room::Border::LEFT:
|
|
||||||
opposite = Room::Border::RIGHT;
|
|
||||||
break;
|
|
||||||
case Room::Border::RIGHT:
|
|
||||||
opposite = Room::Border::LEFT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
player_->setAdjacentRoom(transition_old_room_, opposite);
|
|
||||||
|
|
||||||
player_->switchBorders();
|
player_->switchBorders();
|
||||||
spawn_data_ = player_->getSpawnParams();
|
spawn_data_ = player_->getSpawnParams();
|
||||||
@@ -908,10 +901,6 @@ void Game::checkPlayerIsOnBorder() {
|
|||||||
killPlayer();
|
killPlayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Jugador dentro de los límites: liberar la room adyacente que se mantuvo
|
|
||||||
// tras endTransition() para evitar frames sin datos de colisión offscreen.
|
|
||||||
player_->clearAdjacentRoom();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,9 +914,6 @@ void Game::endTransition() {
|
|||||||
transition_timer_ = 0.0F;
|
transition_timer_ = 0.0F;
|
||||||
transition_old_room_.reset();
|
transition_old_room_.reset();
|
||||||
transition_direction_ = Room::Border::NONE;
|
transition_direction_ = Room::Border::NONE;
|
||||||
// No limpiar adjacent room aquí: el jugador puede estar más allá del borde
|
|
||||||
// y necesita los datos de colisión de la room adyacente en los frames siguientes.
|
|
||||||
// Se limpia en checkPlayerIsOnBorder() cuando el jugador está dentro de los límites.
|
|
||||||
Screen::get()->setRenderOffset(0, 0);
|
Screen::get()->setRenderOffset(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ class Game {
|
|||||||
static void renderPostFadeEnding(); // Renderiza el juego en estado POST_FADE_ENDING (pantalla negra)
|
static void renderPostFadeEnding(); // Renderiza el juego en estado POST_FADE_ENDING (pantalla negra)
|
||||||
auto changeRoom(const std::string& room_path) -> bool; // Cambia de habitación
|
auto changeRoom(const std::string& room_path) -> bool; // Cambia de habitación
|
||||||
auto getOrCreateRoom(const std::string& room_path) -> std::shared_ptr<Room>; // Obtiene una habitación del caché o la crea
|
auto getOrCreateRoom(const std::string& room_path) -> std::shared_ptr<Room>; // Obtiene una habitación del caché o la crea
|
||||||
|
void buildCollisionBorders(); // Rellena el tilemap extendido de la room actual con bordes adyacentes
|
||||||
void updateAdjacentRooms(float delta_time); // Actualiza enemigos de las habitaciones adyacentes
|
void updateAdjacentRooms(float delta_time); // Actualiza enemigos de las habitaciones adyacentes
|
||||||
void handleInput(); // Comprueba el teclado
|
void handleInput(); // Comprueba el teclado
|
||||||
void checkPlayerIsOnBorder(); // Comprueba si el jugador esta en el borde de la pantalla y actua
|
void checkPlayerIsOnBorder(); // Comprueba si el jugador esta en el borde de la pantalla y actua
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ void Console::toggle() {
|
|||||||
input_line_.clear();
|
input_line_.clear();
|
||||||
cursor_timer_ = 0.0F;
|
cursor_timer_ = 0.0F;
|
||||||
cursor_visible_ = true;
|
cursor_visible_ = true;
|
||||||
// El mensaje inicial ("JDD Console v1.0") aparece completo, sin typewriter
|
// El mensaje inicial (nombre de la consola) aparece completo, sin typewriter
|
||||||
typewriter_chars_ = static_cast<int>(msg_lines_[0].size());
|
typewriter_chars_ = static_cast<int>(msg_lines_[0].size());
|
||||||
typewriter_timer_ = 0.0F;
|
typewriter_timer_ = 0.0F;
|
||||||
SDL_StartTextInput(SDL_GetKeyboardFocus());
|
SDL_StartTextInput(SDL_GetKeyboardFocus());
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class Console {
|
|||||||
static constexpr float SLIDE_SPEED = 180.0F;
|
static constexpr float SLIDE_SPEED = 180.0F;
|
||||||
|
|
||||||
// Constantes de consola
|
// Constantes de consola
|
||||||
static constexpr std::string_view CONSOLE_NAME = "JDD Console";
|
static constexpr std::string_view CONSOLE_NAME = "Projecte 2026 Console";
|
||||||
static constexpr std::string_view CONSOLE_VERSION = "v2.2";
|
static constexpr std::string_view CONSOLE_VERSION = "v2.2";
|
||||||
static constexpr int MAX_LINE_CHARS = 32;
|
static constexpr int MAX_LINE_CHARS = 32;
|
||||||
static constexpr int MAX_HISTORY_SIZE = 20;
|
static constexpr int MAX_HISTORY_SIZE = 20;
|
||||||
|
|||||||
@@ -1194,7 +1194,7 @@ auto CommandRegistry::execute(const std::string& keyword, const std::vector<std:
|
|||||||
|
|
||||||
auto CommandRegistry::generateTerminalHelp() const -> std::string {
|
auto CommandRegistry::generateTerminalHelp() const -> std::string {
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
out << "=== JDD CONSOLE COMMANDS ===" << '\n';
|
out << "=== Project 2026 CONSOLE COMMANDS ===" << '\n';
|
||||||
|
|
||||||
std::string current_category;
|
std::string current_category;
|
||||||
for (const auto& cmd : commands_) {
|
for (const auto& cmd : commands_) {
|
||||||
|
|||||||
@@ -21,6 +21,19 @@ namespace Map {
|
|||||||
constexpr int HEIGHT = 21; // Alto del mapa en tiles (pantalla menos 3 tiles de statusbar)
|
constexpr int HEIGHT = 21; // Alto del mapa en tiles (pantalla menos 3 tiles de statusbar)
|
||||||
} // namespace Map
|
} // namespace Map
|
||||||
|
|
||||||
|
// Borde extra alrededor del tilemap de colisión para cross-room collision.
|
||||||
|
// Debe ser >= ceil(max(Player::WIDTH, Player::HEIGHT) / Tile::SIZE).
|
||||||
|
namespace CollisionBorder {
|
||||||
|
constexpr int TILES = 3; // Tiles de borde por lado
|
||||||
|
constexpr int PX = TILES * Tile::SIZE; // Píxeles de borde por lado
|
||||||
|
} // namespace CollisionBorder
|
||||||
|
|
||||||
|
// Tilemap de colisión extendido (room + bordes de las adyacentes)
|
||||||
|
namespace ExtendedMap {
|
||||||
|
constexpr int WIDTH = Map::WIDTH + (2 * CollisionBorder::TILES); // 38
|
||||||
|
constexpr int HEIGHT = Map::HEIGHT + (2 * CollisionBorder::TILES); // 27
|
||||||
|
} // namespace ExtendedMap
|
||||||
|
|
||||||
namespace PlayArea {
|
namespace PlayArea {
|
||||||
constexpr int TOP = (0 * Tile::SIZE);
|
constexpr int TOP = (0 * Tile::SIZE);
|
||||||
constexpr int BOTTOM = (Map::HEIGHT * Tile::SIZE);
|
constexpr int BOTTOM = (Map::HEIGHT * Tile::SIZE);
|
||||||
|
|||||||
Reference in New Issue
Block a user