Game Development (III)--WIN32 Othello (three)--the reality of the game screen

Source: Internet
Author: User
Tags textout

The whole game is divided into 3 parts.

1. The reality of chess game

2, the reality of AI

3, the reality of the game screen

Provide complete project download


This is the third part: the display of the screen


This part is actually relatively simple, white is the API stack.


Learn about the message mechanism of windows and how to draw


The main is to encapsulate the next to the chessboard, chess pieces, and the current turn who, the current score is how much, is the game screen on the different parts of the drawing.

void Drawreversiboard (); void Drawreversipieces (enumreversipiecestype type, int row_y, int column_x); void Drawreversiresult (enumreversiresult res, enumreversipiecestype type); void Drawpiecescount (Byte black, byte white);

4 functions, drawing different parts respectively.


Then the main problem is that the game screen is not directly drawn to the screen, the background created a single hdc, all the picture is drawn to this hdc, and then from this hdc with BitBlt copy to the screen, bitblt faster than the individual part of the direct drawing to the screen , much faster, usually using such an internal cache to solve the problem of direct drawing of the splash screen.


Then make a list of the APIs that are used primarily:

Draw the line: Movetoex,lineto

Draw a rectangle: Rectangle

Painted Oval: Ellipse

Choose what kind of brush (that is, the line of the drawing, the circle, the rectangle's border line) Getstockobject (Black_pen),

Black_pen is one of several system-supplied brushes and is a black brush. You can also customize the brushes.

Choose what brush (i.e. circle, interior of rectangle with what style, color fill) getstockobject (Black_brush),

Black_brush is one of several system-supplied brushes that are filled with black. You can also customize the brush.

Output text: TextOut

Set the color of text: SetTextColor

Set the color of the text background: SetBkColor


Create a drawing layer from the screen DC CreateCompatibleDC, get an hdc, the above circle, rectangle, line is drawn to this HDC.

Create a bitmap createcompatiblebitmap, get a hbitmap, and end up with this hbitmap, then bitblt to the DC on the screen.

SelectObject (hdc, HBITMAP); This hbitmap is applied on the HDC drawing layer.


And then there's a menu on the game window, how does this thing work:

Add a resource file called Xxx.rc in the project, for example, called Game.rc. This is the resource file for the WIN32 project.

Write something like this in the inside.

#include "resource.h" #include "afxres.h"//////////////////////////////////////////////////////////////////////// Menu//reversi menu Discardablebegin    POPUP "Begin"    begin        MENUITEM "Player first",              idm_ Player_first        MENUITEM "AI first",                  Idm_ai_first    endend
Of course you can also do it directly inside the IDE tool, now generally support the Visual menu creation, click the mouse to come out.

But its essence is similar to the above-stated code.


where resource.h

#define Idm_player_first101#define idm_ai_first102

Is the definition of the menu item corresponding to the key value, player initiator corresponding to the 101,ai initiator corresponding to 102.

This key value is used in the Windows message mechanism, which is used to differentiate which menu is used for mouse points.


#include "Afxres.h"

This is a header file of the MFC library, VC6.0 may be reported below this header file can not be found, first you look at the VC installation path \vc98\mfc\include This directory is not included in, if added, but do not have this file, In addition to the web search for a download down, paste directly into the VC6.0 installation directory to go to the same can be used. After the VC6.0 version of the IDE, basically no problem.


The message that the game uses in the Windows Messaging mechanism:

Wm_create: The creation of the window. Initialize the various objects in this message, and then create a timer settimer.

Wm_timer: The timer that was created above will send a message periodically. In this message, refresh the game screen, whether or not there is a change in the picture. For example, when the SetTimer is set to 17 milliseconds, the message is received and processed every 17 milliseconds, that is, every 17 milliseconds the game screen is refreshed. 17 milliseconds is approximately the frequency of 60 frames per second (1000/60 = 16.667).

Wm_destroy: The closing of the window releases the message. Do some necessary recycling in this message, such as the above timer to killtimer off.

Wm_keydown: Is the keyboard key message. This message contains the parameter wparam, which represents the different key values. Here to determine whether the Vk_escape (Esc key), if the player presses ESC, equivalent to the point of the upper left corner of the effect of the X, so PostMessage (hwnd, Wm_destroy, 0, 0) to manually send a WM_DESTROY message. The program then receives Wm_destroy and processes and eventually exits.

Wm_lbuttondown the left mouse button, click the message. This message takes two parameters, representing the relative coordinate position of the pixel relative to the upper-left corner of the window (0,0). In this message, the mouse point (x, y)

Convert the grid coordinates to the checkerboard, then handle the player's lazi in this position, that is, the play method that calls the Player object, then PostMessage (hwnd, Wm_timer, 0, 0), manually send a timer message, refresh the game screen. After judging whether the AI can lazi, if the turn Ai Lazi, then PostMessage (hwnd, Wm_do_ai, 0, 0) manually send a Wm_do_ai message to notify AI Lazi

Wm_do_ai, this is a custom message # define Wm_do_ai Wm_user + 0x0001. In this message, the AI performs a search, finds the coordinates of the optimal position, and lazi in this position. Then also manually send a timer message, refresh the game screen. Then determine whether or not AI lazi, because after the AI Lazi, the player may have no sub-can, so determine whether the next step or Ai Lazi, is the words continue PostMessage (hwnd, Wm_do_ai, 0, 0), let the next wm_do_ai continue to deal with the AI Lazi ROM. If the AI Lazi after the player Lazi, then do nothing, such as the player Lazi can be.

WM_COMMAND, this is the menu message, with a parameter, indicating the number of the menu, that is, the menu number defined in the above resource.h, if the player points out the menu during the game, then the start again, the object is re-initialized, the chess game to start again.


Finally, the window is created.

First need registerclass, register a window, the main register is the small window icon, the mouse style, the name of the window, the name of the menu, the window's message processing function, and so on such information.

Then CreateWindow, mainly the window's length and width, the initial coordinate position, the window style, such as there is no title that column, the upper right corner there is no maximization, minimize the button, etc.


Here's the code to put on the game screen.

ReversiScene.h

#ifndef _reversiscene_h_#define _reversiscene_h_#include <windows.h> #include "ReversiCommon.h" #include " ReversiBitBoard.h "//Checkerboard one cell length width each 60 pixels const int Reversi_game_grid = 60;//piece radius, example cell boundary 5 pixels const int REVERSI_PIECES_R = REVERSI_GAME_GRID/2-5;//The top left corner of the checkerboard on the window coordinates the const int reversi_game_row_y = 10;const int reversi_game_column_x = 10;//game scene size C onst int reversi_scene_width = 700;const int reversi_scene_height = 600;class reversiscene{public:reversiscene (); ~ Reversiscene (), void Init (hdc hdc), void Draw (reversibitboard& reversi), void Drawtoscreen ();p rivate:void Drawreversiboard (); void Drawreversipieces (enumreversipiecestype type, int row_y, int column_x); void Drawreversiresult (Enumreversiresult res, enumreversipiecestype type); void Drawpiecescount (Byte black, byte white); HDC m_hDC; HDC M_HMEMDC; Hbitmap M_hmembitmap; Reversibitboard M_lastmap;}; #endif


ReversiScene.cpp

#include "ReversiScene.h" Reversiscene::reversiscene () {M_HMEMDC = Null;m_hmembitmap = NULL;} Reversiscene::~reversiscene () {DeleteObject (M_HMEMDC);D eleteobject (M_HMEMBITMAP);} void Reversiscene::init (hdc hdc) {M_HDC = HDC;M_HMEMDC = CreateCompatibleDC (M_HDC); m_hmembitmap = CreateCompatibleBitmap (M_HMEMDC, Reversi_scene_width, reversi_scene_height); SelectObject (M_HMEMDC, M_hmembitmap);D Rawreversiboard (); void Reversiscene::D raw (reversibitboard& reversi) {Enumreversipiecestype type1; Enumreversipiecestype type2;for (int i = 0; i < Reversi_max_row; i++) {for (int j = 0; J < Reversi_max_column; J + +) {T Ype1 = Reversi. Getpieces (i, j); type2 = M_lastmap.getpieces (i, j); if (type1! = type2) {drawreversipieces (Type1, I, j); m_ Lastmap.setpieces (Type1, I, j);}} Drawreversiresult (Reversi. Isgameover (), Reversi. Getcurrtype ()); int black = Reversi. GetCount (enum_reversipieces_black); int white = Reversi. GetCount (enum_reversipieces_white);D rawpiecescount (black, white);} void Reversiscene::D rawtoscreen () {BITBLt (m_hdc, 0, 0, reversi_scene_width, reversi_scene_height, M_HMEMDC, 0, 0, srccopy);} void Reversiscene::D rawreversiboard () {int begin_row_y = Reversi_game_row_y;int begin_column_x = reversi_game_column_x ; SelectObject (M_HMEMDC, Getstockobject (White_pen)); SelectObject (M_HMEMDC, Getstockobject (White_brush)); Rectangle (M_HMEMDC, 0, 0, reversi_scene_width, reversi_scene_height); SelectObject (M_HMEMDC, Getstockobject (Black_pen)); for (int i = 0; I <= reversi_max_row; i++) {Movetoex (M_HMEMDC, begin _row_y + i * reversi_game_grid, begin_column_x, NULL); LineTo (M_HMEMDC, begin_row_y + i * reversi_game_grid, begin_column_x + reversi_max_column * reversi_game_grid);} for (int i = 0; I <= reversi_max_column; i++) {Movetoex (M_HMEMDC, begin_row_y, begin_column_x + i * reversi_game_grid, N ULL); LineTo (M_HMEMDC, begin_row_y + reversi_max_row * Reversi_game_grid, begin_column_x + i * Reversi_game_grid);}} void Reversiscene::D rawreversipieces (enumreversipiecestype type, int row_y, int column_x) {int Begin_row_y = reversi_game_row_y + 1 + reversi_game_grid/2-reversi_pieces_r + row_y * reversi_game_grid;int begin_column_x = R eversi_game_column_x + 1 + reversi_game_grid/2-reversi_pieces_r + column_x * reversi_game_grid;int end_row_y = REVERSI _game_row_y-(REVERSI_GAME_GRID/2-Reversi_pieces_r) + (row_y + 1) * Reversi_game_grid;int end_column_x = REVERSI_GAME _column_x-(REVERSI_GAME_GRID/2-Reversi_pieces_r) + (column_x + 1) * REVERSI_GAME_GRID;IF (Enum_reversipieces_black = = Type) {SelectObject (M_HMEMDC, Getstockobject (Black_pen)); SelectObject (M_HMEMDC, Getstockobject (Black_brush));} else if (enum_reversipieces_white = = type) {SelectObject (M_HMEMDC, Getstockobject (Black_pen)); SelectObject (M_HMEMDC, Getstockobject (White_brush));} Else{selectobject (M_HMEMDC, Getstockobject (White_pen)); SelectObject (M_HMEMDC, Getstockobject (White_brush));} Ellipse (M_HMEMDC, begin_column_x, begin_row_y, end_column_x, end_row_y);} void Reversiscene::D rawreversiresult (enumreversiresult res, EnumreversipieCestype type) {WCHAR wscurrres[20];if (enum_reversi_playing = = res) {if (Enum_reversipieces_black = = type) {wcscpy_s ( Wscurrres, L "Current turn: Sunspot"); else{wcscpy_s (Wscurrres, M, L "Current turn: White");}} else if (Enum_reversi_win_black = = res) {wcscpy_s (Wscurrres, M, L "Black wins!) Game Over ");} else if (Enum_reversi_win_white = = res) {wcscpy_s (Wscurrres, M, L "Baek Seung!) Game Over ");} else{wcscpy_s (Wscurrres, M, L "Draw! Game Over ");} SetTextColor (M_HMEMDC, RGB (0, 0, 0)); SetBkColor (M_HMEMDC, RGB (255, 255, 255)); TextOut (M_HMEMDC, reversi_game_column_x + reversi_max_column * reversi_game_grid + +, Wscurrres, wcslen (wscurrres) ) ;} void Reversiscene::D rawpiecescount (Byte black, byte white) {WCHAR wscurrblack[20]; WCHAR wscurrwhite[20];wsprintf (Wscurrblack, L "Current sunspot:%02d", black); wsprintf (Wscurrwhite, L "Current white Child:%02d", Bai); SetTextColor (M_HMEMDC, RGB (0, 0, 0)); SetBkColor (M_HMEMDC, RGB (255, 255, 255)); TextOut (M_HMEMDC, reversi_game_column_x + reversi_max_column * reversi_game_grid + +, Wscurrblack, wcslen ( Wscurrblack)); TextOut (M_HMEMDC, Reversi_game_column_x + reversi_max_column * reversi_game_grid +, Wscurrwhite, wcslen (Wscurrwhite));} 

Final game of the main ROM game.cpp

#define Win32_lean_and_mean #include <windows.h> #include "Resource.h" #include "ReversiBitBoard.h" #include " ReversiScene.h "#include" ReversiPlayer.h "#include" ReversiAI.h "Reversibitboard g_reversi; Reversiplayer G_player; Reversiai G_ai; Reversiscene g_scene;const int windows_width = reversi_scene_width + 6;const int windows_height = REVERSI_SCENE_HEIGHT + 2 5; #define Wm_do_ai Wm_user + 0x0001lresult CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (hinstance hIn Stance, hinstance hPrevInstance, PSTR szcmdline, int icmdshow) {WCHAR szappname[] = L "Reversi"; HWND hwnd; MSG msg; Wndclass wndclass; wndclass.style = Cs_hredraw | Cs_vredraw;wndclass.lpfnwndproc = Wndproc;wndclass.cbclsextra = 0;wndclass.cbwndextra = 0;wndclass.hInstance = Hinstance;wndclass.hicon = LoadIcon (null, idi_application); wndclass.hcursor = LoadCursor (null, idc_arrow); Wndclass.hbrbackground = (hbrush) getstockobject (white_brush); wndclass.lpszmenuname = Szappname; Wndclass.lpszclassname = szappname;if(! RegisterClass (&wndclass)) {MessageBox (NULL, L "This program requires Windows nt!", Szappname, Mb_iconerror); return 0 ;} hwnd = CreateWindow (szappname,szappname,ws_overlapped | ws_caption | Ws_sysmenu | ws_minimizebox,//overlapping windows, with title bar, System menu, minimized, no maximum 0,0,windows_width,windows_height,null,null,hinstance,null); ShowWindow (hwnd, icmdshow); UpdateWindow (HWND), while (GetMessage (&msg, NULL, 0, 0)) {translatemessage (&msg);D ispatchmessage (&msg);} return 0;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM WPARAM, LPARAM LPARAM) {switch (message) {case Wm_create:{g_scene. Init (GetDC (HWND)); G_reversi.init (); G_player.init (enum_reversipieces_black); G_ai. Init (Enum_reversipieces_white); G_scene.draw (G_reversi); SetTimer (hwnd, 1, N, NULL);} Return 0;case Wm_destroy:{killtimer (hwnd, 1); PostQuitMessage (0);} Return 0;case Wm_command:{switch (LoWord (WParam)) {case idm_player_first:{g_reversi.init (); G_player.init (enum_ Reversipieces_black); G_ai. Init (Enum_reversipieces_white); G_scene.draw (G_reversi);}return 0;case idm_ai_first:{g_reversi.init (); G_player.init (enum_reversipieces_white); G_ai. Init (enum_reversipieces_black); G_ai. Play (G_reversi); G_scene.draw (G_reversi);} return 0;}} Return 0;case Wm_keydown:{switch (wParam) {case Vk_escape:{postmessage (hwnd, Wm_destroy, 0, 0);} return 0;}} Return 0;case wm_do_ai:{if (g_reversi.getcurrtype () = = G_ai. Getplayertype () && g_reversi.canplay (G_ai. Getplayertype ())) {G_ai. Play (G_reversi); G_scene.draw (G_reversi); PostMessage (hwnd, Wm_timer, 0, 0); if (g_reversi.getcurrtype () = = G_ai. Getplayertype ()) {PostMessage (hwnd, Wm_do_ai, 0, 0);}}} return 0;case Wm_lbuttondown:{int y = hiword (lParam); int x = LoWord (lParam); int row_y = (y-reversi_game_row_y)/REVERSI _game_grid;int column_x = (x-reversi_game_column_x)/Reversi_game_grid;if (g_reversi.getcurrtype () = = G_ Player.getplayertype () &&g_reversi.canplay (G_player.getplayertype (), row_y, column_x)) {G_Player.Play (g_ Reversi, row_y, column_x); G_scene.draw (G_reversi); PostMessage (hwnd, Wm_timer, 0, 0); if (G_reversi.canplay (G_ai). Getplayertype ())) {PostMessage (hwnd, Wm_do_ai, 0, 0);}}} Return 0;case Wm_rbuttondown:{g_player.cancel (g_reversi); G_scene.draw (G_reversi); PostMessage (hwnd, Wm_timer, 0, 0);} Return 0;case Wm_timer: {G_scene.drawtoscreen ();} return 0;} Return DefWindowProc (HWND, message, WParam, LParam);}



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.