Saturday, June 23, 2018

Week 5 -- It's Alive!

Week 5 -- It's Alive!

Overview

  • Map rendering working
  • Remaining Dialog texts ported

Details

Your image looks corrupted and you definitely ruled out pointer errors? Well, it’s a pointer error anyway.
Or endianess. Or both together…
It took a while to realize that subtile indices are stored as uint16BE but now I AM BACK IN BUSINESS!

Next

This weekend I want to add viewport clipping and map masking so you don’t see the whole map ingame like in the above image. There’s also some tile specific code left to implement (like the water in the sewers) but that’s for another time. Finally we can get going on implementing the actual gameplay \o/

Monday, June 18, 2018

Week 4 -- Show me the World

Week 4 -- Show me the World
(Here is supposed to be a video of the map)

Overview

  • Map rendering
  • Improving dialog handling

Unfortunately the map rendering kept breaking so there’s no video of it right now. While there are improvements in other areas like the dialog handling, the map renderer blocked me for most of the week.
Below I describe the structure of the MAZE.CMP file that stores static background tiles and how it is used.

Details

struct Map { // MAZE.CMP
	byte tileIndex[128][20]
	byte subTileIndex[146][64]
	byte bitmap[1832][32]
}

Compared to sprites from animation files (discussed in Week 2) the static background is composed of tiles from MAZE.CMP. Those tiles in turn are made of subtiles of 8x8 to save space by assembling the bigger tiles of the smaller ones. So the tileIndex are offsets into subTileIndex that again are offsets to the 8x8 pixel data in bitmap.

On every frame an indexMap is generated of the currently visible subtiles. The reason is not only for caching but for clipping tiles (that’s what kAnimationShadow* are for) and general tile manipulation depending on game state.
34x18 tiles are shown at a time on screen. There will be overdraw as the viewport is only 256x128 but it doesn’t matter as the video buffer is 320x200 and it is clipped off by the frame border in the end. Currently my implementation draws the frame border first for “clearing” the screen as it was convenient to just blit the fullscreen image without the need for transparency.

Next Week

The most urgent feature right now is renderering the map. Not only does it help to visually convey the progress better but other features like player movement, rendering of NPCs, Objects, animation of static objects like torches, collision, … depend on it. Besides that, the definitions for the all objects, … will need to be ported over as well.

Monday, June 11, 2018

Week 3 -- Game intro running

Week 3 -- Game intro running

Overview

  • Text rendering
  • Basic Dialog implementation for intro
  • Logic abstraction

The porting process is tougher than I had anticipated. I described my problems with the animations in Week 2 and continued with correctly positioning sprites in the dialog. Fortunately I [found my mistake](link to Renderer::drawSprite pos calc) and dialogs not only for the intro, but in general will be solved soon.

Details

The logic differentiates between different states like showing a dialog, the game, a cutscene, and so on. This helps the logic to know when to update what so that for example you are not slain while still picking up items from a chest. link
The characters for text rendering are stored in general2.anm that use the ASCII value as an offset to access the sprite in the animation (link to Dialog::update default case). The dialog strings contain information directly for fadein/out, what type of dialog it should be (Yes/No, Ok, multipage, immediate) and so on.
In general the implementation is quite simple. The engine iterates over every char one after another and either executes the ‘meta char’ (e.g. ‘|’ for fade in text) or renders the sprite for the character. When the null terminator is reached and no further string is to be loaded, the dialog rendering terminates and depending on if the dialog expects user input (password, yes/no, ok) the logic either waits on a keypress before switching back to its ‘game state’ and continues where the player left off.

Next Week

Judging from my current speed, I hope to get our hero making its first steps in the first level and ironing out the remaining dialog bugs.