Я делал в своё время всякие гуи. Могу поделиться опытом. Сначала всё рисуется в памяти микраша (пусть это будет кэш, для определённости). Размер - размер дисплея. На дисплей выводится сразу весь кэш. То есть перерисовка только всего экрана. Спрайты состоят из кусочков знакомест. Выводятся в кэш по OR, AND, XOR и тупо копированием. Это сделано для того, что с каждым спрайтом идёт его маска, которой можно чистить место под спрайт. Спрайт может быть произвольной формы, так как положение каждого кусочка указано относительно верхнего левого угла самого спрайта. Таким образом можно сделать спрайт-рамку, который не будет разрушать изображение внутри себя.
/*************************************************************************
**
** File: graphics_n3310.h
** Summary: Header file for sprite library of Nokia 84x48 graphic LCD.
** Version: 1.0
** Date: 20.01.2015
**
**************************************************************************
**
** Functions:
**
**
** Compiler: IAR AVR 3.20c
** Remarks:
**
**************************************************************************/
#ifndef _GRAPHICS_N3310_H
#define _GRAPHICS_N3310_H
/*************************************************************************/
#include "LCD_n3310.h"
#include "useful_macro.h"
#include <types.h>
/*************************************************************************/
/*
Sequence of writing data bytes into RAM with horizontal addressing (V = 0).
-------------------------------------
| 0 | 1 | 2 | | | | | | 83| 0
------------------------------------- .
| 84| 85| 86| | | | | |167| .
------------------------------------- .
|168|169|170| | | | | |251| .
------------------------------------- . Y-address
|252|253|254| | | | | |335| .
------------------------------------- .
|336|337|338| | | | | |419| .
------------------------------------- .
|420|421|422| | | | | |503| 5
-------------------------------------
0 .............................83
X-address */
/*************************************************************************/
#define LCD_X_RES 84
#define LCD_Y_RES 48
#define LCD_CACHE_SIZE ((LCD_X_RES * LCD_Y_RES) / 8)
/*************************************************************************/
#define NULL 0
#define FALSE 0
#define TRUE 1
/*************************************************************************/
/*
Sprite fragment size is 7x8 bits.
Total size of sprite field is 12x6.
Format of sprite (for example sprite consists of 4 fragments)
---------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | - bytes
---------------------------------
|Len| Data | - 1st fragment
---------------------------------
|Pos| Data | - 2nd fragment
---------------------------------
|Pos| Data | - 3rd fragment
---------------------------------
|Pos| Data | - 4th fragment
---------------------------------
Len - size of sprite in fragments
Pos - X and Y relative coordinates of fragments
---------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | - bits
---------------------------------
| | Y-pos | X-pos |
---------------------------------
*/
/*------------------------------------------------------------------------*/
typedef enum { PUT, PUT_AND, PUT_OR, PUT_XOR } PutLCDMode ;
typedef enum { LEFT, RIGHT, UP, DOWN} ScrollScrDir ;
typedef enum { CYCLIC, NORMAL} ScrollScrMode ;
/*************************************************************************/
typedef struct {
union {
u8 len;
struct {
u8 x : 4;
u8 y : 3;
u8 dumm : 1;
} pos_bit;
};
u8 data[7];
} SpriteFrame;
/*************************************************************************/
typedef struct
{
u8 ROM *Font; // Pointer to font
u8 Len; // Number of chars in the font
u8 SizeX; // Width of char (in bytes)
u8 SizeY; // Height of char (in bits)
u8 CharOffset;// Offset from begin
} FontFrame;
/*************************************************************************/
class CGraphics
{
public:
static void DrawSprite(u8 num, u8 x, u8 y, u8 mode);
static u8 *GetShadowRAM();
static void DrawPixel(u8, u8, u8);
static void DrawRect(u8, u8, u8, u8, u8);
static void Init();
static void SetFont(u8);
static void LcdClear();
static void LcdUpdate();
static void DrawChar(u8, u8, u8, u8);
static void ScrollScreenHor(ScrollScrDir, u8, ScrollScrMode);
static void ScrollScreenVert(ScrollScrDir, u8, ScrollScrMode);
private:
static SpriteFrame ROM Sprites[];
static u8 LcdCache[LCD_CACHE_SIZE];
static u8 ChWidth;
static u8 ChHight;
static u8 FontLen;
static void PutToLcdCache(u8, u8, u8);
static u16 LcdCacheIdx;
static u16 LoWaterMark;
static u16 HiWaterMark;
static u8 ROM *pFontTable;
static bool UpdateLcd;
static ROM u8 FontLookup [][5];
static ROM u8 FontLookup1[][4];
static ROM u8 FontLookup2[][4];
static ROM FontFrame FontTable[];
};
/*************************************************************************/
#endif
А вот для интереса прочитайте книгу "Программирование игр на ZX-Spectrum" вторую часть. Там дохрена про спрайты написано. Я оттудова много что почерпнул.