A game make by Grauw, great new!
Dialogue, quests and puzzles, but no battle mode
No battle mode but I hope a little action.
@wyrdwad Thanks for mentioning those games, it’s good reference material. Yes I know Corpse Party! Haven’t played it, but watched a playthrough on Youtube partially. There’s a lot of text, I think I’ll try to do a little less of that. This game won’t have a horror theme though, it’s not really my genre . But maybe some scary part would be nice.
@DarkSchneider Thanks for your suggestions, and elaboration on how you handle sprites.
Yeah I’ll have to tweak the rain colour. Also while it’s raining I need to change the palette to something more gloomy. And as it clears up, reduce the amount of drops one by one .
I think I’ll do the character animation next. Code-wise it’s simple, but I’ve only got one sideways walking animation so I need to draw some more, while this character sprite is probably not going to be the main character . Oh well, good practice and I can probably still use it somewhere.
As for sprite handling, I used to have a Sprite class which could be registered on a sprite manager, which would write all the data and such. It added a lot of overhead and complexity though. I’ve simplified it by removing those systems, instead I just have DrawSpriteAttributes/Colors/Patterns methods on the objects, which I call manually in the right order from the game loop. If I need variable z-ordering at some point I can add it there. I intend to carefully plan my sprites usage so I won’t need more than 32 sprites, so no code to support flickering.
Attributes and colors are drawn every frame, in single VRAM access sequences. No optimisation to skip unchanged colours, since in the worst case I need to update them all anyway. Updating them currently takes 1.4 + 3.2 = 4.6 ms (28% frame time). Patterns are pre-loaded, but for the player sprite animation I will update the patterns with a HMMM.
Everything is double buffered. Since attribute and colour tables share a base address, and in the future I want to update attributes every frame while only drawing colours every other frame, I will need to set the attributes in the ISR. I could either blit from a SAT buffer in RAM, or write to different VRAM areas and blit with a HMMM. Biggest question: how to do this without conflicting with VRAM access / command execution in the main loop.
To illustrate, the rain code looks like this:
; ; Rain effect ; Rain_PATTERN: equ 8 Rain_SPRITES: equ 8 Rain_DROPOFFSET: equ 2B20H Rain: MACRO x: db 0 y: db 0 ENDM ; ix = this Rain_Construct: ret ; ix = this Rain_Tick: ld a,(ix + Rain.x) add a,128 - 2 ld (ix + Rain.x),a ld a,(ix + Rain.y) add a,8 ld (ix + Rain.y),a ret ; c = transfer port ; ix = this ; iy = sprite attribute table Rain_DrawSpriteAttributes: ld a,(ix + Rain.x) add a,(iy + SpriteAttributeTable.cameraOffsetX) ld h,a ld a,(ix + Rain.y) add a,(iy + SpriteAttributeTable.cameraOffsetY) ld l,a ld b,Rain_PATTERN << 2 ld de,Rain_DROPOFFSET call SpriteAttributeTable_WriteAttributeIY REPT Rain_SPRITES - 1 add hl,de call SpriteAttributeTable_WriteAttributeIY ENDM ret ; c = transfer port ; ix = this ; iy = sprite color table Rain_DrawSpriteColors: REPT Rain_SPRITES ld hl,SpriteColor_solid1 call SpriteColorTable_DrawIY ENDM ret ; ix = this ; iy = sprite pattern table Rain_DrawSpritePatterns: ld a,Rain_PATTERN call SpritePatternTable_SetPatternWriteIY ld hl,Rain_pattern call SpritePatternTable_WritePatternIY ret ; Rain_pattern: SpritePattern 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Main loop does approximately this:
call Player_Tick call Rain_Tick call SpriteAttributeTable_SetWriteIY call Player_DrawSpriteAttributes call Rain_DrawSpriteAttributes call SpriteColorTable_SetWriteIY call Player_DrawSpriteColors call Rain_DrawSpriteColors
No optimisation to skip unchanged colours, since in the worst case I need to update them all anyway
Look more for average case. It is rare you need to update all, typically a character frame is kept at least 3-4 drawing frames (at 60 fps). You would only get the worst case if all the characters in screen changes the character frame at the same time.
So, you could save the 3/4 data copy per character, if it keeps it let's say about 3-4 drawing frames as said.
If you can copy at once and with HMMM then I suppose each character frame is complete, not formed by a set of sprites that could not be contiguous. The HMMM also requires alignment, 8 sprites is aligned, 2 lines for SC5. Remember you have to draw it in an also aligned destination, not something like the 3rd sprite.
For a variable-framerate game like Xak it’s fine to improve the average case. But for a solid 60 fps game where I don’t want any hiccups from dropped frames, I can’t assume that the worst case won’t occur. Which can happen pretty easily when z-sorting the sprites, or if a sprite disappears.
Even when the maximum case is improved in practice (because sprites use the same colour), since the time is so variable and depends on the levels built, it’s difficult to know exactly how much time that is. If I estimate too low and use that time for other things, I’ll be in trouble if I exceed the maximum.
I don’t want to run into the case where I am happily making nice levels, and when the game starts nearing completion I begin noticing frame drops in certain places under certain conditions, and I find that the only way to fix that is to drop features. I’d rather just always spend the worst case amount of time, and incorporate that in my frame budget.
Once the game is more complete and if I badly need more time, I can look at whether all colours really need to be redrawn every other frame. For instance (some) sprites may never need to be z-sorted, or I can hide unused sprites instead of removing them to avoid changing the sprite priorities. But even then I would prefer to optimise by skipping those particular colour table updates explicitly, rather than something which dynamically checks if colours have changed.
At least that’s my current point of view .
As for copying sprite data with HMMM, there were two cases I mentioned: the SAT table, this is always aligned. The player sprite patterns, I ensure that it uses patterns 0-7, which is 256 aligned bytes.
In the mean while, since I got the sprites in better shape, I had a stab at a nice full screen rain effect. Took me just an hour orso to make, nice evidence that the sprites code is good now .
Video (make sure to watch at 60fps): ▶️
Hi, cool!
No hope i guess to have this on a regular msx2, right?
No… I did consider adding V9990 support for MSX1/2 users, but I dropped that idea to keep the scope down. It will work on MSX2’s with VDP replaced by a V9958 though.
So for clarify, that video is taken from MSX2+ with Z80 turbo mode or is turbo R? Screen 4 or 5? It looks pretty impressive, sincerely let's hope you can finish it
Thanks! It’s going to run on MSX2+, so although I recorded on an emulated turboR, the R800 mode is disabled. Graphics are in screen 5.
Currently using 80% CPU time with the bulk of the CPU-heavy work being done, and with some room for optimisation. Tile drawing is still a bit too slow; 45% CPU time with diagonal movement, while I should be able to do it in 30-35%. And there’s the 30 fps animation 60 fps motion trick I mentioned earlier as well, which also accounts for some 10%. So I think performance-wise it’ll be allright on the Z80.
As I said before, it looks super pretty and smooth. I'm starting to wonder now if there are already some concepts for game mechanics and maybe even a story.