1. Moves more assets-related stuff from `init` to `engine/assets`.
2. Removes `SDL_audiolib` dependency from `soundsample.h`.
3. Cleans up some unused/missing includes.
Untangles dependencies by splitting up `engine.{h,cpp}` into 3 files:
1. `primitive_render`
2. `ticks` -- only contains `GetAnimationFrame` for now.
3. `GetWidth2` renamed to `CalculateSpriteTileCenterX` and moved to `levels/dun_tile.hpp`.
Stairs can have the same `TileProperties` as floors but do not
always follor the same graphics layout as floors, so we shouldn't
apply optimizations to them.
The only floors affected seem to be:
1. Caves: tile 48 sub-tile 171 frame 461 (TileProperties: None)
2. Hell: tile 46 sub-tile 141 frame 386 (TileProperties: BlocksMissile)
Note that the few broken in pixels in caves are actually incorrectly
attributed to the non-Solid tile, really they should be part of the
solid tile 49.
As there doesn't seem to be a quick and easy way to check if a frame
is part of Stairs, we add a check for BlocksMissile tile property
instead.
This fixes Hell but isn't enough to fix Caves.
To fix Caves, we then add a `BlocksMissile` flag to the broken sub-tile.
During `ReencodeDungeonCels`, extracts floor tile foliage into
a triangle with the floor frame and a separate 16-px tall `TransparentSquare`.
This means that the floor frames are now always triangles and
the foliage can be rendered directly without masking.
Dungeon graphics sizes:
Map | Frames | Foliage frames | Byte size | Before PR | After PR
-----|--------|---------------:|-----------:|----------:|----------:
Town | 3,803 | 41 | 2,317,832 | 2,242,056 | 2,242,190
L1 | 1,119 | 11 | 738,836 | 721,604 | 721,110
L4 | 1,091 | 6 | 603,140 | 584,500 | 584,242
RG99 binary size reduced by ~4 KiB: 2,426,380 bytes -> 2,421,388 bytes
The final line wasn't encoded correctly.
Also removes unnecessary `src` increments at the end of the encoding
functions.
```
Re-encoding dungeon CELs: 1,119 frames, 738,836 bytes
Re-encoded dungeon CELs: 1,119 frames, 721,604 bytes
```
Triangles in the dungeon CEL data have two redundant 0x00 pixels every other row.
Re-encodes the dungeon CEL data to remove these pixels in order to save RAM and simplify the rendering code.
Example RAM savings:
```
VERBOSE: Re-encoding dungeon CELs: 1,119 frames, 738,836 bytes
VERBOSE: Re-encoded dungeon CELs: 1,119 frames, 722,552 bytes
```
Performance remains the same. The rendering code is now a bit simpler.
This greatly speeds up level generation as there is no need to search for the fitness of 127 (or 256 as in the original) rooms if only 23 where created.
For monsters with the same sprite, load the sprite from the file system only once.
Example:
```
VERBOSE: Loaded monster graphics: falspear\phall 452 KiB x1
VERBOSE: Loaded monster graphics: skelbow\sklbw 618 KiB x1
VERBOSE: Loaded monster graphics: skelsd\sklsr 610 KiB x1
VERBOSE: Loaded monster graphics: goatbow\goatb 832 KiB x1
VERBOSE: Loaded monster graphics: bat\bat 282 KiB x2 <-- here we only load the sprite once
VERBOSE: Loaded monster graphics: rhino\rhino 1306 KiB x1
VERBOSE: Loaded monster graphics: golem\golem 298 KiB x1
VERBOSE: Total monster graphics: 4401 KiB 4684 KiB
```
Here, the bat sprite will be loaded from the MPQ only once.
For the second sprite, we simply clone the first sprite before applying TRNs.
This also reduces the size of `MonsterData` from 88 bytes to 80.
When we migrate monster data to a TSV, the sprite IDs can be generated automatically at load time.
This has little or no effect on the optimized build
but significantly improves performance of the headless debug build
`timedemo_test` on my machine goes from 3s to 2s.
Adds handy helpers for performing algorithms on the entire container.
They're prefixed with `c_` for container.
This naming convention is identical to some popular C++ libraries, such
as Abseil.
Done with the following script:
```ruby
Dir["Source/**/*.{h,c,cc,cpp,hpp}"].each do |path|
v = File.read(path)
next if !v.include?("uint32_t") || v.include?("cstdint")
lines = v.lines
line_num = if lines[2].start_with?(" *")
lines.index { |l| l.start_with?(" */") } + 3
else
3
end
lines.insert(line_num, "#include <cstdint>\n")
File.write(path, lines.join(""))
end
```
then fixed-up manually