C++ Getting Started - Implementing Push Box Game

Reference resources C and C++ Game Fun Programming Kid Crystal ...
Reference resources
Push Box Game

Reference resources

  1. C and C++ Game Fun Programming Kid Crystal

Push Box Game

Players use keyboards to control the characters and push all the yellow boxes to the white squares

Store level data in character array

There are six elements in the game:
(1) Blank area: Players can go through, boxes can be pushed up; English name: empty; abbreviation:'e'

(2) Wall: Players cannot pass, boxes cannot push past; English name: wall; abbreviation:'w'

(3) Box: Players can push without obstacles in front; English name: box; abbreviation:'b'

(4) Blank target: requires player to push box up; English name: target; abbreviation:'t'

(5) Achieving goals: the overlapping status of a box on the target; English name: achieved; abbreviation:'a'

(6) Game characters: Keyboard controls movement to push box to reach target; English name: player; Abbreviation:'p'

Define a global variable, level, to store map data, and draw patterns in the show() function based on the level[i][j]:

#include <graphics.h> #include <conio.h> #include <stdio.h> #define B_SIZE 60//Square Size #define B_NUM 8 // Number of squares, a total of 8*8 squares // Storing map data in a character two-dimensional array char level[B_NUM][B_NUM + 1] = { "wwwwwwww", "wwwtbeew", "weeeeeew", "weeeeeew", "weeeeeew", "weepaeew", "weeewwww", "wwwwwwww" }; void startup() { initgraph(B_NUM * B_SIZE, B_NUM * B_SIZE); setbkcolor(RGB(150, 150, 150)); // Gray Background BeginBatchDraw(); // Start batch drawing } void show() { int i, j; cleardevice(); for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'e') // white space { setfillcolor(RGB(150, 150, 150));// Draw gray ground setlinecolor(RGB(150, 150, 150)); fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); } else if (level[i][j] == 'w') // wall { setfillcolor(RGB(155, 0, 0)); setlinecolor(RGB(150, 150, 150));// Box with light red and grey lines fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); } else if (level[i][j] == 'b') // case { setfillcolor(RGB(255, 255, 0)); // Yellow Square setlinecolor(RGB(150, 150, 150)); fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); } else if (level[i][j] == 't') // target { setfillcolor(RGB(250, 250, 250));// Small white square fillrectangle((j + 0.3) * B_SIZE, (i + 0.3) * B_SIZE, (j + 0.7) * B_SIZE, (i + 0.7) * B_SIZE); } else if (level[i][j] == 'a') // Goal Completed { setlinecolor(RGB(150, 150, 150)); setfillcolor(RGB(255, 255, 0)); // Small yellow square fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); setfillcolor(RGB(250, 250, 250));// Small white square fillrectangle((j + 0.3) * B_SIZE, (i + 0.3) * B_SIZE, (j + 0.7) * B_SIZE, (i + 0.7) * B_SIZE); } else if (level[i][j] == 'p') // Game player { setfillcolor(RGB(255, 0, 0)); // Red Round Face fillcircle((j + 0.5) * B_SIZE, (i + 0.5) * B_SIZE, 0.4 * B_SIZE); setfillcolor(RGB(80, 80, 80)); // Black eyes setlinecolor(RGB(80, 80, 80)); fillcircle((j + 0.3) * B_SIZE, (i + 0.45) * B_SIZE, 0.08 * B_SIZE); fillcircle((j + 0.7) * B_SIZE, (i + 0.45) * B_SIZE, 0.08 * B_SIZE); setlinestyle(PS_SOLID, 3); line((j + 0.35) * B_SIZE, (i + 0.7) * B_SIZE, (j + 0.65) * B_SIZE, (i + 0.7) * B_SIZE); setlinestyle(PS_SOLID, 1); } } } FlushBatchDraw(); } void update() { } int main() { startup(); while (1) { show(); update(); } return 0; }

Keyboard controls character movement

Define the structure Player to record player positions:

struct Player { int i; int j; }; Player player;

Traverse the two-dimensional array level to find the position of'p', that is, the player's position, assign it to the player, and change'p'to'e':

int i, j; for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'p') { player.i = i; player.j = j; level[i][j] = 'e'; } } }

Separate the drawing of the player in show() and draw the player according to the location stored in the player:

```cpp void show() { i = player.i; j = player.j; setfillcolor(RGB(255, 0, 0)); // Red Round Face fillcircle((j + 0.5) * B_SIZE, (i + 0.5) * B_SIZE, 0.4 * B_SIZE); setfillcolor(RGB(80, 80, 80)); // Black eyes setlinecolor(RGB(80, 80, 80)); fillcircle((j + 0.3) * B_SIZE, (i + 0.45) * B_SIZE, 0.08 * B_SIZE); fillcircle((j + 0.7) * B_SIZE, (i + 0.45) * B_SIZE, 0.08 * B_SIZE); setlinestyle(PS_SOLID, 3); line((j + 0.35) * B_SIZE, (i + 0.7) * B_SIZE, (j + 0.65) * B_SIZE, (i + 0.7) * B_SIZE); setlinestyle(PS_SOLID, 1); FlushBatchDraw(); }

In update(), control the role movement according to the user keys:

if (input == 'A' || input == 'S' || input == 'D' || input == 'W') { int goal_i = player.i; // Define variable storage destination int goal_j = player.j; int goalNext_i = goal_i; // Store target location and previous location int goalNext_j = goal_j; if (input == 'A') // Towards the left { goal_j = player.j - 1; goalNext_j = goal_j - 1; } else if (input == 'D') // Towards the right { goal_j = player.j + 1; goalNext_j = goal_j + 1; } else if (input == 'S') // down { goal_i = player.i + 1; goalNext_i = goal_i + 1; } else if (input == 'W') // Up { goal_i = player.i - 1; goalNext_i = goal_i - 1; }

Element Update

Assuming the role moves to the right, there are 13 scenarios:
(1) To the right of the character is empty. You can move it now.

(2) To the right of the role is the target. You can move it now.

(3) The right side of the character is the wall. It cannot be moved at this time.

(4) The right side of the role is box, and the right side is empty.

(5) The right side of the role is box, and then the right side is target. At this time, the role and box move to the right together

(6) The right side of the role is achieved, and the right side is empty.

(7) The right side of the role is achieved, and the right side is achieved. At this point, the role and box move to the right together

(8) The role has a box on the right and a wall on the right. It cannot be moved at this time.

(9) The role has a box on the right and a box on the right. It cannot be moved at this time.

(10) The role has a box on the right and achieved on the right. It cannot be moved at this time.

(11) The right side of the role is achieved, and the right side is wall. It cannot be moved at this time.

(12) The role has achieved on the right and box on the right. It cannot be moved at this time.

(13) The right side of the role is achieved, and the right side is achieved. It cannot be moved at this time.

Depending on the user's input, the variables goal_i and goal_j store the target location where the game character moves, and goalNext_i and goalNext_j store the target location one more place forward. There are six scenarios that move the game character and update the level elements to achieve the corresponding processing in update():

void update() { if (_kbhit()) { char input = _getch(); if (input == 'A' || input == 'S' || input == 'D' || input == 'W') { int goal_i = player.i; // Define variable storage destination int goal_j = player.j; int goalNext_i = goal_i; // Store target location and previous location int goalNext_j = goal_j; if (input == 'A') // Towards the left { goal_j = player.j - 1; goalNext_j = goal_j - 1; } else if (input == 'D') // Towards the right { goal_j = player.j + 1; goalNext_j = goal_j + 1; } else if (input == 'S') // down { goal_i = player.i + 1; goalNext_i = goal_i + 1; } else if (input == 'W') // Up { goal_i = player.i - 1; goalNext_i = goal_i - 1; } // Update elements according to different situations if (level[goal_i][goal_j] == 'e' || level[goal_i][goal_j] == 't') // Target location is empty or target { player.i = goal_i; player.j = goal_j; } else if (level[goal_i][goal_j] == 'b' && level[goalNext_i][goalNext_j] == 'e') // The target location is box, followed by empty { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 'e'; // Target location becomes empty level[goalNext_i][goalNext_j] = 'b'; // Turn into a box in front } else if (level[goal_i][goal_j] == 'b' && level[goalNext_i][goalNext_j] == 't') // Target is box, followed by target { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 'e'; // Target location becomes empty level[goalNext_i][goalNext_j] = 'a'; // Beyond that becomes achieved } else if (level[goal_i][goal_j] == 'a' && level[goalNext_i][goalNext_j] == 'e') // The target location is achieved, followed by empty { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 't'; // Target position becomes target level[goalNext_i][goalNext_j] = 'b'; // Turn into a box in front } else if (level[goal_i][goal_j] == 'a' && level[goalNext_i][goalNext_j] == 't') // The target location is achieved, followed by target { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 't'; // Target position becomes target level[goalNext_i][goalNext_j] = 'a'; // Beyond that becomes achieved } else { return; } } } }

Game Win Judgment

Define the number of global variables to store target s and achieved s:

int targetNum, achievedNum;

When traversing a two-dimensional array in startup(), add targetNum to 1 if the map element is target or achieved:

for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'p') { player.i = i; player.j = j; level[i][j] = 'e'; } else if (level[i][j] == 't' || level[i][j] == 'a') { targetNum++; } } }

In the update() function, the number of achieved s for which the statistical element has been updated:

achievedNum = 0; int i, j; for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'a') { achievedNum++; } } }

If you achieve your goal, display the winning message in show():

if (achievedNum == targetNum) // If Goals are Achieved { setbkmode(TRANSPARENT); // Transparent display text settextcolor(RGB(0, 255, 255)); settextstyle(80, 0, _T("Song Style")); outtextxy(80, 200, _T("Game victory")); } FlushBatchDraw();

Multi-level implementation

Define a three-dimensional array levels to store all card map data, define a current LevelNum to represent the first level you are playing, and a two-dimensional array levels to store map data for the level you are playing:

// Get map data for the current tube for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { level[i][j] = levels[currentLevelNum][i][j]; } }

In update(), if the current level is complete, add currentLevelNum to 1 and call startup() to start the initialization of the next level:

if (achievedNum == targetNum) { show(); // Call to display the game winning screen if (currentLevelNum < LEVEL_TOTALNUM - 1) { currentLevelNum++; startup(); // Start Initialization of Next Level } }

In show(), if there are still unfinished levels, show which level the game will start; if all levels are completed, prompt the game to win:

if (achievedNum == targetNum) // If Goals are Achieved { setbkmode(TRANSPARENT); // Transparent display text settextcolor(RGB(0, 255, 100)); TCHAR str[20]; if (currentLevelNum < LEVEL_TOTALNUM - 1) // There are still unfinished levels { settextstyle(50, 0, _T("Song Style")); swprintf_s(str, _T("Beginning%d shut", currentLevelNum + 2)); // Prompt to start level outtextxy(120, 160, str); outtextxy(10, 250, _T("Press the space bar to play the current level again")); } else { settextstyle(80, 0, _T("Song Style")); outtextxy(80, 200, _T("Game victory")); } FlushBatchDraw(); Sleep(2500); }

Complete Code

#include <graphics.h> #include <conio.h> #include <stdio.h> #define B_SIZE 60//Square Size #define B_NUM 8 // Number of squares, a total of 8*8 squares #define LEVEL_TOTALNUM 5 //How many levels in total struct Player { int i; int j; }; Player player; char levels[LEVEL_TOTALNUM][B_NUM][B_NUM + 1] = { {"wwwwwwww", "wwwtbeew", "weeeeeew", "weeeeeew", "weeeeeew", "wepbteew", "weeewwww", "wwwwwwww"}, {"wwwwwwww", "wwweewww", "wpetbwww", "weeebeww", "wewteeww", "weeeeeww", "weepwwww", "wwwwwwww"}, {"wwwwwwww", "wwpeewww", "weeweeww", "webabeww", "weeteeww", "wwetewww", "wwwwwwww", "wwwwwwww"}, {"wwwwwwww", "wwwwwwww", "weeeewww", "weeettew", "webbbpew", "weewetww", "wwwwwwww", "wwwwwwww"}, {"wwwwwwww", "wwwwwwww", "wwteewww", "weewebpw", "weewewew", "weaeebtw", "weeeewww", "wwwwwwww"} }; int currentLevelNum = 0; char level[B_NUM][B_NUM + 1]; int targetNum, achievedNum; void startup() { initgraph(B_NUM * B_SIZE, B_NUM * B_SIZE); setbkcolor(RGB(150, 150, 150)); // Gray Background BeginBatchDraw(); // Start batch drawing int i, j; // Get map data for the current tube for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { level[i][j] = levels[currentLevelNum][i][j]; } } targetNum = 0; achievedNum = 0; for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'p') { player.i = i; player.j = j; level[i][j] = 'e'; } else if (level[i][j] == 't' || level[i][j] == 'a') { targetNum++; } } } } void show() { int i, j; cleardevice(); for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'e') // white space { setfillcolor(RGB(150, 150, 150));// Draw gray ground setlinecolor(RGB(150, 150, 150)); fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); } else if (level[i][j] == 'w') // wall { setfillcolor(RGB(155, 0, 0)); setlinecolor(RGB(150, 150, 150));// Box with light red and grey lines fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); } else if (level[i][j] == 'b') // case { setfillcolor(RGB(255, 255, 0)); // Yellow Square setlinecolor(RGB(150, 150, 150)); fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); } else if (level[i][j] == 't') // target { setfillcolor(RGB(250, 250, 250));// Small white square fillrectangle((j + 0.3) * B_SIZE, (i + 0.3) * B_SIZE, (j + 0.7) * B_SIZE, (i + 0.7) * B_SIZE); } else if (level[i][j] == 'a') // Goal Completed { setlinecolor(RGB(150, 150, 150)); setfillcolor(RGB(255, 255, 0)); // Small yellow square fillrectangle(j * B_SIZE, i * B_SIZE, (j + 1) * B_SIZE, (i + 1) * B_SIZE); setfillcolor(RGB(250, 250, 250));// Small white square fillrectangle((j + 0.3) * B_SIZE, (i + 0.3) * B_SIZE, (j + 0.7) * B_SIZE, (i + 0.7) * B_SIZE); } } } // Draw Player i = player.i; j = player.j; setfillcolor(RGB(255, 0, 0)); // Red Round Face fillcircle((j + 0.5) * B_SIZE, (i + 0.5) * B_SIZE, 0.4 * B_SIZE); setfillcolor(RGB(80, 80, 80)); // Black eyes setlinecolor(RGB(80, 80, 80)); fillcircle((j + 0.3) * B_SIZE, (i + 0.45) * B_SIZE, 0.08 * B_SIZE); fillcircle((j + 0.7) * B_SIZE, (i + 0.45) * B_SIZE, 0.08 * B_SIZE); setlinestyle(PS_SOLID, 3); line((j + 0.35) * B_SIZE, (i + 0.7) * B_SIZE, (j + 0.65) * B_SIZE, (i + 0.7) * B_SIZE); setlinestyle(PS_SOLID, 1); if (achievedNum == targetNum) // If Goals are Achieved { setbkmode(TRANSPARENT); // Transparent display text settextcolor(RGB(0, 255, 100)); TCHAR str[20]; if (currentLevelNum < LEVEL_TOTALNUM - 1) // There are still unfinished levels { settextstyle(50, 0, _T("Song Style")); swprintf_s(str, _T("Beginning%d shut"), currentLevelNum + 2); // Prompt to start level outtextxy(120, 160, str); outtextxy(10, 250, _T("Press the space bar to play the current level again")); } else { settextstyle(80, 0, _T("Song Style")); outtextxy(80, 200, _T("Game victory")); } FlushBatchDraw(); Sleep(2500); } FlushBatchDraw(); } void update() { if (_kbhit() && (achievedNum < targetNum)) { char input = _getch(); if (input == ' ') { startup(); } if (input == 'A' || input == 'S' || input == 'D' || input == 'W') { int goal_i = player.i; // Define variable storage destination int goal_j = player.j; int goalNext_i = goal_i; // Store target location and previous location int goalNext_j = goal_j; if (input == 'A') // Towards the left { goal_j = player.j - 1; goalNext_j = goal_j - 1; } else if (input == 'D') // Towards the right { goal_j = player.j + 1; goalNext_j = goal_j + 1; } else if (input == 'S') // down { goal_i = player.i + 1; goalNext_i = goal_i + 1; } else if (input == 'W') // Up { goal_i = player.i - 1; goalNext_i = goal_i - 1; } // Update elements according to different situations if (level[goal_i][goal_j] == 'e' || level[goal_i][goal_j] == 't') // Target location is empty or target { player.i = goal_i; player.j = goal_j; } else if (level[goal_i][goal_j] == 'b' && level[goalNext_i][goalNext_j] == 'e') // The target location is box, followed by empty { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 'e'; // Target location becomes empty level[goalNext_i][goalNext_j] = 'b'; // Turn into a box in front } else if (level[goal_i][goal_j] == 'b' && level[goalNext_i][goalNext_j] == 't') // Target is box, followed by target { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 'e'; // Target location becomes empty level[goalNext_i][goalNext_j] = 'a'; // Beyond that becomes achieved } else if (level[goal_i][goal_j] == 'a' && level[goalNext_i][goalNext_j] == 'e') // The target location is achieved, followed by empty { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 't'; // Target position becomes target level[goalNext_i][goalNext_j] = 'b'; // Turn into a box in front } else if (level[goal_i][goal_j] == 'a' && level[goalNext_i][goalNext_j] == 't') // The target location is achieved, followed by target { player.i = goal_i; // Player moves to target position player.j = goal_j; level[goal_i][goal_j] = 't'; // Target position becomes target level[goalNext_i][goalNext_j] = 'a'; // Beyond that becomes achieved } else { return; } } achievedNum = 0; int i, j; for (i = 0; i < B_NUM; i++) { for (j = 0; j < B_NUM; j++) { if (level[i][j] == 'a') { achievedNum++; } } } if (achievedNum == targetNum) { show(); // Call to display the game winning screen if (currentLevelNum < LEVEL_TOTALNUM - 1) { currentLevelNum++; startup(); // Start Initialization of Next Level } } } } int main() { startup(); while (1) { show(); update(); } return 0; }

5 October 2021, 14:29 | Views: 4749

Add new comment

For adding a comment, please log in
or create account

0 comments