I think if you’re intending to draw the sprites to a scanline buffer or in order from top left to bottom right you’ll ideally want some kind of sorted data structure to keep the sprites ordered (by y first, then x).
using a vector would help and having functions to push it to the back or to the front
having to pass a sort every time a new sprite instance pops up could slow down stuff even more, theres just to much going on imo
About scrolling: If you use direct drawing mode, maybe it is possible to set visible screen width in LCD to a bit less than 220 pixels, say 212 pixels? And then use LCD HW scrolling. Then you should only draw 8x176 rect on LCD each frame
it doesn’t work like that, to explain hw scrolling the easiest it sets the starting index of the screen buffer
you cant disable the sides of the screen to not draw the buffer
you just have to deal with the edge flickering i guess
unless the screen buffer on the display chip is larger then the screen
How about this?
- In the ST7775R spec: "9.2.21 Horizontal and Vertical RAM Address Position (R36h, R37h, R38h, R39h) "
To me it looks like you can set the visible window(?)
From what I was reading when I looked at it, if you set a window, you can’t then draw outside that window at all. So setting a window is of very little use for things like that.
I wouldn’t like to speculate too much without testing, but I doubt doing an
O(n) sort on a list just before rendering would be ideal for performance if less than
n sprites are being updated each frame.
If every sprite is being moved (e.g. in a game like asteroids) then it might be optimal to sort just before rendering, but if a reasonable number of sprites aren’t moving then it would probably be better to maintain a sorted list and then only update the ones that have moved since the last frame.
I am afraid that the sprite list will be quite short…but tough to say yet.
Phew! Finally, I got sprites to work and was able to squash remaining visual bugs. Per-pixel-optimizing is tough and takes a lot of time. Now, I am able to use 8 Hi-Res sprites over the Hi-Res screen buffer. Each sprite has own 4-color palette. So you can draw any graphics on the background, i.e. screen buffer, using the screen buffer palette, and then draw sprites over it with own colors. Much like sprites in C-64 (thought C-64 had fixed palette).
The main benefits using sprites over using the drawBitmap or directDrawBitmap functions are:
- Own palette for each sprite.
- Built-in dirty rect handling for the sprite background.
- Sprites are inherently flicker-free as pixels of the background screen buffer and all the sprites are combined before writing to LCD.
Performance-wise the sprites are quite fast. In preliminary testing, I ran 8 (32x16 pixel) sprites with no-dip in the throttled 16 fps on HW (there is that limit somewhere in the code…), but performance depends on sprite movement and positions as it affects to the total background area needed to draw. Scanline drawing to LCD is optimized so that only the required area is being drawn each frame.
Video coming soon…
Sound great! Would it be straight forward to add to other screen modes? In think the fixed number of sprites is a great idea, perhaps have the pallets match the screen mode?
The sprite code is heavily optimized for the Hi-Res screen mode so modifying it to another screen mode is not straightforward, but not particularly hard either, if you are familiar to bit blitting code. What makes it easier is that you can develop it under the simulator. The code is almost identical to HW. It is also possible to modify it so that the sprites are in different color mode than the screen buffer.
Edit: the max sprite count is a compile-time define for building for optimized number of sprites for the game.
Here is a video of the sprites system in action.
The screen buffer is in Hi-Res mode (220x176, 4 colors) and Hi-Res sprites are blitted over it. As you see in the video, the fps for one sprite is 50 and for 8 sprites between 25-16, depending heavily on where the sprites are on screen, as that affects how much of the background image must be drawn behind sprites.
As there are 8 sprites on screen in this demo the total number of colors on Hi-Res screen is: 4 + 8*3 = 28 (!). Note that 1 color is for transparency in each sprite.
That is awesome!
I’d love to see your code for this, it would be nice to add sprites to mode13 at some point.
Here it is Works both under Simulator and on HW. I have also added on-screen FPS counter (that is drawn vertically for performance reasons).
Here is the binary also:
spritetest.bin (51.5 KB)
P.s. Just merged the latest PokittoLib to my repo so it is up-to-date.
Sprites are available when my merge request is accepted for PokittoLib.
Sprites are implemented only for the Hi-Res (220x176, 4 colors) screen mode. The sprites itself are also drawn in this mode. There are no pixel size limitations for the sprites. By default the max number of sprites is 4, but that can be increased (or decreased, to optimize for speed) via the define like this:
#define SPRITE_COUNT 8
Each sprite contain own 4 color palette. The color of index 0 is ignored as it is considered as transparent
The sprite 0 is drawn first and so it is the lowermost sprite
Using sprites is very simple. An example is in
Examples/Sprites/main.cpp. You do not have to care about storing or redrawing the sprite background as the sprite moves. Normally, use
game.display.persistence = 1 with sprites to keep the performance good. Use
game.Update(false) only if the screen buffer (background) graphics has been changed.
To create sprite just call the function below. To disable sprite, just call the same function with
NULLas bitmap pointer.
setSpriteBitmap(uint8_t index, const uint8_t* bitmap, const uint16_t* palette4x16bit, int16_t x, int16_t y );
To move the sprite you just need the sprite index and the coordinates:
setSpritePos(uint8_t index, int16_t x, int16_t y);
- I have also implemented automatic on-screen FPS counter for Hi-Res mode (works also without sprites). It is enabled by:
Merged! thanks @Hanski
Now added to online mbed team page
Do animated bitmaps work with this? Or would they needed to be saved as individual bitmaps swapped out?
You can create several bitmaps and swap them to create animation. There is no built-in animation support.