The Update method of View is the workhorse of our program. It creates the image in the buffer. We then call InvalidateRectangle to force the repaint of our window (the last parameter, FALSE, tells Windows not to clear the previous image — we don't want it to flash white before every frame).
Here's the class View, with the three bitmaps.
class View {
public:
View(HINSTANCE hInst);
void SetSize(int cxNew, int cyNew) {
_cx = cxNew;
_cy = cyNew;
}
void Step { ++_tick; }
void Update(Canvas& canvas);
void Paint(Canvas& canvas);
private:
int _cx, _cy;
int _tick;
Bitmap _bitmapBuf; // for double buffering
Bitmap _background;
int _widthBkg, _heightBkg;
Bitmap _sprite;
Bitmap _mask;
int _widthSprite, _heightSprite;
};
View::View(HINSTANCE hInst) : _tick (0) {
// Load bitmap from file
_background.Load("picture.bmp");
// Load bitmap from resource
_background.GetSize(_widthBkg, _heightBkg);
// Load bitmaps from resources
_sprite.Load(hInst, IDB_FANNY);
_mask.Load(hInst, IDB_MASK);
_sprite.GetSize(_widthSprite, _heightSprite);
DesktopCanvas canvas;
_bitmapBuf.CreateCompatible(canvas, 1, 1);
_cx = 1;
_cy = 1;
}
And here's the implementation of Update. We create a bitmap canvas in memory, making it compatible with the current display canvas. We blit the background image into it, then blit the mask and the sprite (notice the change of position for each frame). Finally, we transfer the complete bitmap into our buffer (overloaded assignment operator at work!).
void View::Update(Canvas& canvas) {
const double speed = 0.01;
Bitmap bmp(canvas, _cx, _cy);
BitmapCanvas bmpCanvas(canvas, bmp);
RECT rect = { 0, 0, _cx, _cy };
bmpCanvas.WhiteWash(rect);
// Do the off-line drawing
Blitter bltBkg(_background);
bltBkg.BlitTo(bmpCanvas);
int xRange = (_widthBkg - _widthSprite) / 2;
int yRange = (_heightBkg - _heightSprite) / 2;
int x = xRange + static_cast<int>(xRange * sin(speed * _tick));