If you want to create a small utility program or a puzzle game then
using SDK would be much wise solution. Time that you spend to program
will be same, exe file will be much shorter, and program installation
process will be cleaner. While you distribute MFC-Based project you
must build it with static MFC libraries ore distribute project with
MFC dlls. There is no any warranty that your customer has dlls for your
program. Old MFC-Based programs must work with new MFC versions. They
must but don't do it always. Your customer will be very glad if after
installing your project some his old software products will begin hang
up.
Either you use SDK or don't you must know it good. A big part of MFC
is SDK interface only. The most MFC window functions are same as SDK.
Difference is very small. CWnd class stores window handle and you must
not use it as the first parameter of function. CDC class stores DC handle
and most of graphic objects are same as SDK functions. CRect is based
on RECT structure, etc. There are good container classes as CArray,
CList, CMap, CString in MFC. But you can easy change them by STL classes.
STL much shorter and is a part of C++ standard. It is multiplatform
library. There are some SDK functions that are absent in MFC and you
use them direct from your code. So, good Windows programmer must know
SDK. The best way to know something is a project creating. If you use
VC++ and never used clean SDK try to write some program and you would
see that you begin understand MFC solutions much better. To understand
how SDK project works you can look at BSSnake sources. They are short
enough.
The game rules are very plane. Snake moves in the window with some
speed. You can turn it left/right. If the snake eats a mouse it grows.
If snake eats hedgehog, its body or window border it dies. The speed
of snake is growing. Your task is to live as long as it possible. Score
is a function of snake length.
OOP model of this project is very simple. There are no such things
as inheritance, polymorphism, abstract classes and RTTI here. I didn't
want to write classic OOP program according all rules that I used in
the big projects. I was trying to make shot and clean program. If you
are beginner in C++ this code is for you! All main games classes are
placed in two files Game.h and Game.cpp. They are short enough for easy
understanding.
Imagine yourself a beginner that makes this snake project. He will create
Snake class and put in it data that describe a snake. For example, some
snake units with (x,y) coordinates. Than he will create method Grow()
that will add new unit to snake. Then he will make method Move(), that
change all coordinates of all units. Then he will understand that the
array is bad solution for snake body storing because every addition
will recreate whole array and he will replace the array by list. Then
he will find that Snake.Draw() method that redraw all snake units is
working too slowly when number of units overload some dozens. At last
he will use DirectX to speed up graphic operations.
I did not so. My snake is not owner of its body! Actually we must not
move all Snake. We can move and redraw only the tail and the head. Other
body units are not changed. So speed of our solution is not depends
from snake length. All information that I need to snake control is storing
in the game field cells. Snake object remembers only its head and tail
coordinates. While head is moving it writes moving direction to its
field cell so we have track to tail moving and tail always gets direction
that it needs from cell of game field.
The game field is a matrix of Cells. A Cell stores direction and its
type and nothing more. Its pixel coordinates can be counted easy. Cell
also draw itself using bitmap drawing function BitBlt. Bitmap is static
member of Cell class and all cells share it.
PlayBox class controls field objects and cells drawing. All process
is execute by CPlayBox::NextTimeStep(). This method is cold every time
step. It calls mice generator and snake moving.
To stop the game I use try/catch/throw mechanism. There are three events
that must stop a game and they occur on the second level under situation
handle. It would be boring to use BOOL return type to process these
events.
The project was creating by Visual Studio(V6.0) Win32 Application
wizard. My changes are very small. I use global object gEngine to encapsulate
all windows message and time tick execution. I always do so because
I don't like long switch constructions.
For time tick generator I did not use WM_TIMER window message because
it has low priority. I replaced GetMessage() function, that was waiting
thread messages, by PeekMessage() that was not stopping the program.
So I created something as OnIdele() method of MFC application class.
You would be very surprised if will try testing your system resources.
The snake eats 100% of processor! Do not afraid. It is only joke of
Microsoft. The program has normal priority and all other process receive
their processor ticks. But other process is sleeping if have not any
to do. Opposite BSSnake executes its own timer.
WinMain Message loop looks so :
while (1)
{
if(!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
// OR: there are no any message. OnIdle;-)
gEngine.TimerProc();
continue;
}
if (!TranslateAccelerator(msg.hwnd, hAccelTable,
&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT){
break;
};
}
Standard Win32 Application wizard generate a project that cannot use
ASSERT macros. I take this macros from MFC and make him working. It
stops later then it must stop but you can see and test the program stack
as you do it using MFC.
Insert this strings into stdafx.h and ASSERT macros begins to work
(but so-so)
#include
#define ASSERT _ASSERT
Symbol (*) marks difficult tasks.
A. (OOA/OOD exercise)