Overview
Una Aventura Inesperada uses the Nintendo DS tile-based rendering system to display all gameplay graphics on the sub-screen. The game organizes tiles into a 32×24 tile map where each 8×8 pixel tile can be individually indexed. Characters, enemies, and objects are composed of 2×2 tile groups (16×16 pixels) to create larger sprites.Tile Memory Organization
Memory Pointers
Tile and map memory are configured during initialization (main.c:171-172):Points to tile base 1 in sub-screen VRAM. Stores the actual pixel data for all tiles.Base address:
BG_TILE_RAM_SUB(1)Tile size: 64 bytes each (8×8 pixels, 8 bits per pixel)Capacity: Hundreds of tiles (exact limit depends on VRAM configuration)Points to map base 0 in sub-screen VRAM. Stores tile indices for the visible map.Base address:
BG_MAP_RAM_SUB(0)Map size: 32×32 tiles (1024 entries), though only 32×24 is visibleEntry format: 16-bit tile index (0-1023)Memory Layout
Map indexing: The map is addressed as
mapMemory[fila*32 + columna] where:fila∈ [0, 23] (row, Y coordinate)columna∈ [0, 31] (column, X coordinate)
Tile Initialization
TheInicializarTeselas() function (main.c:1065-1185) loads all tile graphics into VRAM using DMA transfers. This is called once during startup (main.c:204).
Complete Tile Loading Sequence
Total tiles loaded: 94 tiles (indices 0-93)Memory usage: 94 × 64 bytes = 6,016 bytes (~6KB)The menu title alone uses 48 tiles (46-93), demonstrating the modular nature of the tile system.
Tile Indices and Mapping
Gameplay Tile Reference
Player sprite, first animation frame (normal floor)
Player sprite on green grass floor
Player sprite, second animation frame
Enemy sprite, first animation frame
Enemy sprite, second animation frame
Non-player character, first animation frame
Non-player character, second animation frame
Pushable box (2×2 tiles)
Wall oriented on the left side
Wall oriented on the right side
Standard wall segments
Floor tile at level exit
Floor tile at goal position
Green grass floor tile
Black void (impassable)
Collision tile that triggers
ConsultarSistemaDialogo() (main.c:476)2x2 Tile Sprites
All game entities (player, enemies, NPCs, boxes) are composed of 2×2 tile arrangements to create 16×16 pixel sprites:Player Sprite Layout
Enemy Sprite Layout (Frame 1)
Box Sprite Layout
Animation Frames
The game alternates between two animation frames (F1 and F2) for all animated entities:Frame Toggle Mechanism
Controlled by the global flagesFotograma1Activo (main.c:99), toggled by ActualizarAnimacion() (main.c:981):
Player Animation
The player’s animation is more complex because it blends with the floor type. TheElegirFondoJugador() function (main.c:464) selects tiles based on:
- Tile part (0-3 for the 2×2 sprite)
- Current floor type (read from
mapMemory) - Animation frame (
esFotograma1Activo)
Player animation tiles:Frame 1 (Normal floor): 0, 8, 9, 10Frame 1 (Grass floor): 6, 11, 12, 13Frame 2 (All floors): 34, 35, 36, 37This allows the player sprite to visually blend with grass tiles while maintaining animation.
Enemy and NPC Animation
Enemies and NPCs use simpler frame swapping (main.c:998-1042): Enemies:- Frame 1: Tiles 5, 14, 15, 16
- Frame 2: Tiles 42, 43, 44, 45
- Frame 1: Tiles 38, 39, 40, 41
- Frame 2: Tiles 30, 31, 32, 33
Tile Data Format
Each tile is 8×8 pixels stored as 64 bytes in tile memory:Memory Structure
Collision Detection with Tiles
Movement validation checks tile indices to determine passability:Impassable Tiles
FromTeclasJugador() (main.c:274, 323, 362, 399):
- 7, 17 (left walls)
- 24, 25 (right walls)
- 26, 27, 28, 29 (generic walls)
- 18 (void)
Interactive Tiles
Box (tile 19):- Triggers
MoverObstaculo()if pushable - Blocks movement if obstructed
- Triggers
MoverEnemigo()if space available - Blocks movement if no space to push
- Sets
puedeJugadorMoverse = falseif eliminated
- Calls
ConsultarSistemaDialogo()(main.c:476) - Advances to quiz/next level
Floor Restoration
When entities move, the game restores original floor tiles usingComprobarSuelo() (main.c:446):
Why use
mapaAcutal instead of mapMemory?mapaAcutal (main.c:121) stores the original level data before any entities moved. mapMemory contains the current state with sprites overlaid on floors. Checking mapaAcutal ensures the correct floor tile is restored.Performance Considerations
Tile Memory Efficiency
- Total tiles loaded: 94 tiles (6KB)
- Map memory: 768 active entries (1.5KB)
- VRAM overhead: Minimal (~8KB total)
Update Performance
Tile map updates are extremely fast:Tile-based rendering is ideal for the DS because:
- Small memory footprint - Reuse tiles across the map
- Fast updates - Single writes change 8×8 pixel regions
- Hardware-accelerated - DS GPU handles tile rendering