I am implementing sprites, at first for the 220x176x2bpp mode. A sprite is basically an own, usually a small size, “screen buffer” with an own palette, and it is layered over the normal screen buffer. There can be many of them. I have now sprites working on HW and under Simulator, but I still have to work on performance. I am not yet sure if they are fast enough to be usable.
how is this different from directBitmap()
?
also the simulator is not very accurate things that flicker on hardware don’t in the simulator for custom graphics
The directBitmap draws immediately to the LCD. Sprite is drawn only when Display::Update() is called. If you draw like this with directBitmap:
- Display::Update() ==> Draws to LCD
- directBitmap() ==> Draws to LCD
Then some of the LCD pixels are drawn twice, which causes flicker.
With the sprite, the normal screen buffer scanlines and sprite scanlines are combined, and the result scanlines are drawn to LCD once => no flicker.
hang on how are you not using a the buffer then?
and you still in 2bpp mode?
Which buffer you mean? I am using the 2bpp screen buffer for background and other graphics. Sprites are layered above them.
Currently, the sprite must also be 2bpp to keep the implementation simple. The biggest challenge is to get drawing optimized for speed.
whats the limitation then? they cant overlap or something?
it just sounds like a second buffer to me
There are no special limitations, sprites can overlap each other.
Yes, they are like extra buffers. The trick is that they (screen buffer & sprite buffers) are combined in Update() by scanline level to LCD, which means:
- the screen buffer is untouched, i.e. it does not contain sprite data, and
- sprites can add more colors to LCD as they have own palettes.
oh ok its a scanline buffer, why not like directBitmap the scanline so you have a full pallet
you could even swap pallet per scanline for effects
and not even bother with the background layer and just press everything into sprites
In other words it’ll be something like this:
class Sprite
{
public:
uint8_t x, y, width, height;
uint8_t paletteIndex; // Colour palette number
uint8_t * data; // Colour data
};
And there will be a list of those, and then on each update the code goes through the list and direct-draws them all at once. Pixels aren’t buffered at any point, there are no ‘scanlines’, the whole screen is represented as a list of sprites - just like old-fashioned hardware sprites.
Right @Hanski?
That is almost a duplicate of my SpriteInfo struct
so are you putting the sprites is a list (vector) of some sort and then look in reverse order wich sprite is drawn last on this coordinate?
its allot of checking per pixel and is probebly realy slow
That is more about the definition of “sprite”. You could call the background screen buffer a full screen sprite. Also, to add more generalization, you could direct the buffer drawing primitives to any sprite buffer
The common thing with all sprites is the need for the scanline combiner, before writing to LCD, to avoid flicker. And yes, the combiner would become very slow very easily. I probably must limit the number and size of sprites radically, if at all possible with a good performance. But that is the fun part: try to get this to work fast
i been looking around for solutions and what do you think of an adaptive tile refresh like method?
Do you mean solutions for scrolling tiles?
yes, basically reducing the amount of stuff to refresh on screen
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(?)