C language imitation cool run game every day

Foreword: The full-text code imitates the game code idea developed by programmer rock. If you want to make step-by-step production according to the video, you can directly go to station b to search. The full-text code is mainly divided into two parts, one is the complete version of the development code (the blogger made it step by step according to the video, and the materials are all from the programmer rock); the other is the reason why the blogger considers his own level. The weakening modification is carried out on the basis of the source code, and the blogger will mention the places that can be modified later, and the material is manually deducted by the blogger ps, which will be described in detail in the following article.

Table of contents

full version

1. Library and macro compilation and some variable settings

2. The init() function is used as the game initialization

3. The creatobstacle() function creates obstacles

4. checkhit() function detects player collision

Five. The fly() function realizes the data update of the picture

6. The updata() function renders the game background

7. The updataren() function performs character image rendering

8. Character jump switch

Nine. Character squat switch

10. The anjian() function handles user keystroke reading

11. The updateEnemy() function handles mob rendering

12. The updatablood() function renders blood bars

Thirteen.updatascore() function handles score rendering

Fourteen. checkover() function to determine the end

15. checkscore() function for score update

16. checkwin() function detects success

Seventeen.drawblood() function is used to draw blood bars

Eighteen.main() main program

complete program

the Show results:

Weakened version

Explain in detail

Next enter the text

full version

1. Library and macro compilation and some variable settings

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include"tools.h"
#include<vector>   

using namespace std;

#define WHIDE 1012
#define HEIGHT 396
#define OBSTACLE_COUNT 10
#define win 20 //win score
//triple loop
IMAGE  imgbgs[3];
int bgx[3];//The x coordinate of the background image
int bgspeed[3] = { 1,2,4 };

IMAGE imgbgsren[12];
int renx;//Character abscissa
int reny;//Character ordinate
int renindex;//The picture frame of the player running
int jumpmax;//character jump height
bool renjump;//Determine whether the character has jumped
int rendownspeed;//decline
bool updata;//Picture Refresh Switch
int blood;//Character HP
int score;//Fraction

//IMAGE imgTortoise;//mob 1
//int torToiseX;//x coordinate of mob 1
//int torToiseY;
//bool torToiseXExist;//Whether there is mob 1 in the current window


typedef enum {             //enumerated type
	guai1, guai2, zhu1, zhu2, zhu3, zhu4,      //Blame 1 is 0, blame 2 is 1
	sum                   //sum to indicate how many monsters there are in total
}obstacle_type;

vector<vector<IMAGE>>obstacleimgs;//Define a variable two-dimensional array, the row represents which kind of obstacle, and the column represents the image of the obstacle

typedef struct obstacle {//Obstacle Encapsulation
	obstacle_type type;//Obstacle type
	int imgindex;//current picture number
	int x, y; //The x,y coordinates of the obstacle
	int speed;//speed
	int power;//Obstacle lethality (commonly known as how much blood is deducted)
	bool exist;//Determine whether an obstacle exists
	bool hit;//Judging whether to collide
	bool passed;//Indicate whether to pass
}obstacle_t;


obstacle_t obstacles[OBSTACLE_COUNT];//Build a pool directly to see how many obstacles there are
int lastobindex;  //The sequence number of the last obstacle

//people squatting
IMAGE   imgrendown[2];
bool rendown;//Character squat judgment


//digital material
IMAGE imgsz[10];

2. The init() function is used as the game initialization

//game initialization
void init() {
	//Create game window
	initgraph(WHIDE, HEIGHT, EX_SHOWCONSOLE);//show console


	//Load background resources
	char name[64];
	for (int i = 0; i < 3; i++) {
		sprintf(name, "res/bg%03d.png", i + 1);
		loadimage(&imgbgs[i], name);
	}

	//Load character frame picture (running)
	for (int i = 0; i < 12; i++) {
		sprintf(name, "res/hero%d.png", i + 1);
		loadimage(&imgbgsren[i], name);
	}

	//Set the player's initial position, it should not change afterwards
	renx = WHIDE / 2 - imgbgsren[0].getwidth() / 2;
	reny = 345 - imgbgsren[0].getheight();
	renindex = 0;
	renjump = false;//The character does not jump at the beginning
	jumpmax = reny - 120;
	rendownspeed = -4;//The rate of decline
	blood = 100;

	//Load mobs 1
	//loadimage(&imgTortoise, "res/t2.png");
	//torToiseXExist = false;//mob 1 initialization
	//torToiseY = 345 - imgTortoise.getheight()+5;
	IMAGE imgguai1;
	loadimage(&imgguai1, "res/t2.png");
	vector<IMAGE>boxguai1;//A container is an array
	boxguai1.push_back(imgguai1);//Then put the one-dimensional array into the two-dimensional array
	obstacleimgs.push_back(boxguai1);

	//Next load mobs 2
	IMAGE imagguai2;
	vector<IMAGE> boxguai2;
	for (int i = 0; i < 6; i++) {
		sprintf(name, "res/p%d.png", i + 1);
		loadimage(&imagguai2, name);
		boxguai2.push_back(imagguai2);
	}
	obstacleimgs.push_back(boxguai2);

	//Initialize the obstacle pool
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		obstacles[i].exist = false;
	}


	//Load squat material
	loadimage(&imgrendown[0], "res/d1.png");
	loadimage(&imgrendown[1], "res/d2.png");
	rendown = false;


	//Obstacles (column animation)
	IMAGE imgH;
	for (int i = 0; i < 4; i++) {
		vector<IMAGE>imgzhu;
		sprintf(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name, 63, 260, true);   //Zoom while recording
		imgzhu.push_back(imgH);
		obstacleimgs.push_back(imgzhu);
	}


	//Preload sound effects
	preLoadSound("res/hit.mp3");    //This thing is the external interface
	mciSendString("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
	lastobindex = -1;
	score = 0;

	//Load digital pictures
	for (int i = 0; i < 10; i++) {
		sprintf(name, "res/sz/%d.png", i);
		loadimage(&imgsz[i], name);
	}
}

3. The creatobstacle() function creates obstacles

void creatobstacle() {
	int i;
	for (i = 0; i < OBSTACLE_COUNT; i++) {
		if (!obstacles[i].exist) {
			break;
		}
	}
	if (i >= OBSTACLE_COUNT) {
		return;
	}

	obstacles[i].exist = true;
	obstacles[i].hit = false;
	obstacles[i].imgindex = 0;
	obstacles[i].type = (obstacle_type)(rand() % 3);//forced conversion

	if (lastobindex >= 0 &&
		obstacles[lastobindex].type >= zhu1 &&
		obstacles[lastobindex].type <= zhu4 &&
		obstacles[i].type == guai2 &&
		obstacles[lastobindex].x > (WHIDE - 500)) {
		obstacles[i].type = guai1;
	}
	lastobindex = i;

	if (obstacles[i].type == zhu1) {    //Optimize the appearance of obstacles
		obstacles[i].type = (obstacle_type)(zhu1 + rand() % 4);
	}
	obstacles[i].x = WHIDE;
	obstacles[i].y = 350 - obstacleimgs[obstacles[i].type][0].getheight();
	if (obstacles[i].type == guai1) {
		obstacles[i].speed = 0;
		obstacles[i].power = 5;   //Mob 1 damage
	}
	else if (obstacles[i].type == guai2) {
		obstacles[i].speed = 4;
		obstacles[i].power = 20;
	}
	else if (obstacles[i].type >= zhu1 && obstacles[i].type <= zhu4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
	obstacles[i].passed = false;
}

4. checkhit() function detects player collision

//Player Collision Detection
void checkhit() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {  //For a rectangle, you only need to know two opposite corners to determine
		if (obstacles[i].exist && obstacles[i].hit == false) {              //Use open source code to detect whether two rectangles intersect
			int alx, aly, a2x, a2y;
			int off = 30;
			if (!rendown) {      //If people are not squatting, they are running or jumping
				alx = renx + off;
				aly = reny + off;
				a2x = renx + imgbgsren[renindex].getwidth() - off;
				a2y = reny + imgbgsren[renindex].getheight();
			}
			else {
				alx = renx + off;
				aly = 345 - imgrendown[renindex].getheight();
				a2x = renx + imgrendown[renindex].getwidth() - off;
				a2y = 345;
			}
			IMAGE img = obstacleimgs[obstacles[i].type][obstacles[i].imgindex];//The first picture of the first obstacle
			int blx = obstacles[i].x + off;
			int bly = obstacles[i].y + off;
			int b2x = obstacles[i].x + img.getwidth() - off;
			int b2y = obstacles[i].y + img.getheight() - 10;
			if (rectIntersect(alx, aly, a2x, a2y, blx, bly, b2x, b2y)) {//Collision
				blood -= obstacles[i].power;
				printf("remaining blood %d\n", blood);
				playSound("res/hit.mp3");
				obstacles[i].hit = true;
			}
		}
	}
}

Five. The fly() function realizes the data update of the picture

//picture mobile
void fly() {
	for (int i = 0; i < 3; i++) {
		bgx[i] -= bgspeed[i];
		if (bgx[i] < -WHIDE)
			bgx[i] = 0;
	}

	//Character Jump Realization
	if (renjump) {                                         //What the hell are you changing, the y coordinates, why can’t you know anything, are you a baby?
		if (reny < jumpmax) {//The first time is to take off, so it starts to be negative, and the next step must be to fall, so it can be positive
			rendownspeed = 4;
		}
		reny += rendownspeed;
		if (reny > 345 - imgbgsren[0].getheight()) {//has fallen to the ground
			renjump = false;
			rendownspeed = -4;
		}
	}
	else if (rendown) {
		static int count = 0;
		int delays[2] = { 4,32 };   //Want to control the station time of the two pictures separately
		count++;
		if (count >= delays[renindex]) {    //The station time is different
			count = 0;
			renindex++;
			if (renindex >= 2) {
				renindex = 0;
				rendown = false;
			}
		}
	}
	else {//neither jump nor squat
		renindex = (renindex + 1) % 12;
	}

	//create obstacles
	static int frameCount = 0;//Static variables are permanently valid
	//static int torToiseFre = 100;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		//if (!torToiseXExist) {
		//torToiseXExist = true;
		//torToiseX = WHIDE;
		//enemyFre = 200 + rand() % 301;
		//}
		enemyFre = 50 + rand() % 50;
		creatobstacle();
	}

	//update coordinates
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bgspeed[2];
			if (obstacles[i].x < -obstacleimgs[obstacles[i].type][0].getheight() * 2) {
				obstacles[i].exist = false;
			}
			int len = obstacleimgs[obstacles[i].type].size();
			obstacles[i].imgindex = (obstacles[i].imgindex + 1) % len;
		}
	}
	//if (torToiseXExist) {
	//Set the movement of mob 1
	//torToiseX -= bgspeed[2];
	//if (torToiseX < -imgTortoise.getwidth()) {
	//torToiseXExist = false;
	//}
	//}
	checkhit();
}

The above creatobstacle function and checkhit function are applied here

6. The updata() function renders the game background

//Render the game background
void updatabg() {
	putimagePNG2(bgx[0], 0, &imgbgs[0]);
	putimagePNG2(bgx[1], 119, &imgbgs[1]);
	putimagePNG2(bgx[2], 330, &imgbgs[2]);
}

7. The updataren() function performs character image rendering

//character image rendering
void updataren() {
	if (!rendown) {
		putimagePNG2(renx, reny, &imgbgsren[renindex]);
	}
	else {
		int y = 345 - imgrendown[renindex].getheight();
		putimagePNG2(renx, y, &imgrendown[renindex]);
	}
}

8. Character jump switch

//character jump switch
void jump() {
	renjump = true;
	updata = true;    //Character frame waiting (just don't wait for 30ms, just refresh directly)
}

Nine. Character squat switch

//Character squat switch
void down() {
	rendown = true;
	updata = true;
	renindex = 0;
}

10. The anjian() function handles user keystroke reading

//Handle user keystroke input
void anjian() {
	char ch;
	if (kbhit()) {   //Determine whether there is input
		ch = getch();//getch reads characters directly, there is no buffer
		if (ch == ' ') {
			jump();
		}
		else if (ch == 'b') {
			down();
		}
	}

}

11. The updateEnemy() function handles mob rendering

void updateEnemy() {
	//render mobs 1
	//if (torToiseXExist) {
	//	putimagePNG2(torToiseX, torToiseY, WHIDE, &imgTortoise);
	//}
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist)
		{
			putimagePNG2(obstacles[i].x, obstacles[i].y, WHIDE, &obstacleimgs[obstacles[i].type][obstacles[i].imgindex]);
		}
	}
}

12. The updatablood() function renders blood bars

//render health bar
void updatablood() {
	drawblood(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, blood / 100.0);
}

Thirteen.updatascore() function handles score rendering

void updatascore() {
	char str[3];
	sprintf(str, "%d", score);

	int x = 20;
	int y = 25;
	for (int i = 0; str[i] != '\0'; i++) {
		int sz = str[i] - '0';
		putimagePNG(x, y, &imgsz[sz]);
		x = x + imgsz[sz].getwidth() + 5;
	}
}

Fourteen. checkover() function to determine the end

void checkover() {
	if (blood <= 0) {
		loadimage(0, "res/over.png");
		FlushBatchDraw();
		mciSendString("stop res/bg.mp3", 0, 0, 0);
		system("pause");

		//Ready to set a button to start the next set
		if (getch() == 'w') {
			blood = 100;
			score = 0;
			mciSendString("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
		}
	}
}

15. checkscore() function for score update

void checkscore() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist && obstacles[i].passed == false && obstacles[i].x + obstacleimgs[obstacles[i].type][0].getwidth() < renx && obstacles[i].hit == false) {
			score++;
			obstacles[i].passed = true;
			printf("score=%d\n", score);
		}
	}
}

16. checkwin() function detects success

void checkwin() {
	if (score >= win) {
		FlushBatchDraw();
		mciSendString("play res/win.mp3", 0, 0, 0);
		Sleep(2000);
		loadimage(0, "res/win.png");
		FlushBatchDraw();
		system("pause");
		if (getch() == 'w') {   //Restart
			mciSendString("stop res/win.mp3", 0, 0, 0);
			blood = 100;
			score = 0;
			("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
		}
	}
}

Seventeen.drawblood() function is used to draw blood bars

//draw blood
void drawblood(int x, int y, int width, int height, int lineWidth, int boardColor, int emptyColor, int fillColor, float percent) {
	LINESTYLE lineStyle;
	getlinestyle(&lineStyle);
	int lineColor = getlinecolor();
	int fileColor = getfillcolor();

	if (percent < 0) {
		percent = 0;
	}

	setlinecolor(BLUE);
	setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);
	setfillcolor(emptyColor);
	fillrectangle(x, y, x + width, y + height);
	setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);
	setfillcolor(fillColor);
	setlinecolor(fillColor);
	if (percent > 0) {
		fillrectangle(x + 0.5 * lineWidth, y + lineWidth * 0.5, x + width * percent, y + height - 0.5 * lineWidth);
	}

	setlinecolor(lineColor);
	setfillcolor(fillColor);
	setlinestyle(&lineStyle);
}

Eighteen.main() main program

int main() {
	init();
	int time = 0;
	loadimage(0, "res/over.png");
	if (getch() == ' ') {
		while (1) {
			anjian();
			time += getDelay();//background frame wait
			if (time > 30) {  //Frame waiting can be optimized
				time = 0;
				updata = true;
			}
			if (updata) {
				updata = false;
				BeginBatchDraw();
				updatabg();
				//putimagePNG2(renx, reny, &imgbgsren[renindex]);
				updataren();
				updateEnemy();
				updatablood();
				updatascore();
				checkwin();
				EndBatchDraw();
				checkover();
				checkscore();
				fly();
			}
		}
	}

	system("pause");
	return 0;
}

I know that many people will not read one by one, and put the full version of the code directly.  

complete program

#define _CRT_SECURE_NO_WARNINGS
/*development log
* 1.Create game window
* 2.import material
* 3.Create game page
* (1)how to make pictures move
* (2)Render the background to make the background transparent (delete the black background of the png image)
* 4.protagonist debut
* character running
* The character jumps (space means jump)
* 5.frame wait
* 6.mobs show
* 7.Struct Encapsulation
*    1.Define the obstacle structure
*    2.Use c++ variable array to load pictures of different obstacles
*    3.Create an obstacle pool (that is, an array of structures)
* 8.Character squat operation
*     At this point, the character rendering function is encapsulated
* 9.Set up hanging obstacles
* Optimize the frequency of obstacles
* 10.Core Algorithm ==== Collision Algorithm--No sound for the first collision, solution, external interface
* 11.add health bar
* 12.Solve some bug s: mobs appear too frequently and cannot be avoided
*            Simple solution: when the pillar is detected, we don't generate mobs 2
* 13.final packaging
*/

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include"tools.h"
#include<vector>   

using namespace std;

#define WHIDE 1012
#define HEIGHT 396
#define OBSTACLE_COUNT 10
#define win 20 //win score
//triple loop
IMAGE  imgbgs[3];
int bgx[3];//The x coordinate of the background image
int bgspeed[3] = { 1,2,4 };

IMAGE imgbgsren[12];
int renx;//Character abscissa
int reny;//Character ordinate
int renindex;//The picture frame of the player running
int jumpmax;//character jump height
bool renjump;//Determine whether the character has jumped
int rendownspeed;//decline
bool updata;//Picture Refresh Switch
int blood;//Character HP
int score;//Fraction

//IMAGE imgTortoise;//mob 1
//int torToiseX;//x coordinate of mob 1
//int torToiseY;
//bool torToiseXExist;//Whether there is mob 1 in the current window


typedef enum {             //enumerated type
	guai1, guai2, zhu1, zhu2, zhu3, zhu4,      //Blame 1 is 0, blame 2 is 1
	sum                   //sum to indicate how many monsters there are in total
}obstacle_type;

vector<vector<IMAGE>>obstacleimgs;//Define a variable two-dimensional array, the row represents which kind of obstacle, and the column represents the image of the obstacle

typedef struct obstacle {//Obstacle Encapsulation
	obstacle_type type;//Obstacle type
	int imgindex;//current picture number
	int x, y; //The x,y coordinates of the obstacle
	int speed;//speed
	int power;//Obstacle lethality (commonly known as how much blood is deducted)
	bool exist;//Determine whether an obstacle exists
	bool hit;//Judging whether to collide
	bool passed;//Indicate whether to pass
}obstacle_t;


obstacle_t obstacles[OBSTACLE_COUNT];//Build a pool directly to see how many obstacles there are
int lastobindex;  //The sequence number of the last obstacle

//people squatting
IMAGE   imgrendown[2];
bool rendown;//Character squat judgment


//digital material
IMAGE imgsz[10];

//game initialization
void init() {
	//Create game window
	initgraph(WHIDE, HEIGHT, EX_SHOWCONSOLE);//show console


	//Load background resources
	char name[64];
	for (int i = 0; i < 3; i++) {
		sprintf(name, "res/bg%03d.png", i + 1);
		loadimage(&imgbgs[i], name);
	}

	//Load character frame picture (running)
	for (int i = 0; i < 12; i++) {
		sprintf(name, "res/hero%d.png", i + 1);
		loadimage(&imgbgsren[i], name);
	}

	//Set the player's initial position, it should not change afterwards
	renx = WHIDE / 2 - imgbgsren[0].getwidth() / 2;
	reny = 345 - imgbgsren[0].getheight();
	renindex = 0;
	renjump = false;//The character does not jump at the beginning
	jumpmax = reny - 120;
	rendownspeed = -4;//The rate of decline
	blood = 100;

	//Load mobs 1
	//loadimage(&imgTortoise, "res/t2.png");
	//torToiseXExist = false;//mob 1 initialization
	//torToiseY = 345 - imgTortoise.getheight()+5;
	IMAGE imgguai1;
	loadimage(&imgguai1, "res/t2.png");
	vector<IMAGE>boxguai1;//A container is an array
	boxguai1.push_back(imgguai1);//Then put the one-dimensional array into the two-dimensional array
	obstacleimgs.push_back(boxguai1);

	//Next load mobs 2
	IMAGE imagguai2;
	vector<IMAGE> boxguai2;
	for (int i = 0; i < 6; i++) {
		sprintf(name, "res/p%d.png", i + 1);
		loadimage(&imagguai2, name);
		boxguai2.push_back(imagguai2);
	}
	obstacleimgs.push_back(boxguai2);

	//Initialize the obstacle pool
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		obstacles[i].exist = false;
	}


	//Load squat material
	loadimage(&imgrendown[0], "res/d1.png");
	loadimage(&imgrendown[1], "res/d2.png");
	rendown = false;


	//Obstacles (column animation)
	IMAGE imgH;
	for (int i = 0; i < 4; i++) {
		vector<IMAGE>imgzhu;
		sprintf(name, "res/h%d.png", i + 1);
		loadimage(&imgH, name, 63, 260, true);   //Zoom while recording
		imgzhu.push_back(imgH);
		obstacleimgs.push_back(imgzhu);
	}


	//Preload sound effects
	preLoadSound("res/hit.mp3");    //This thing is the external interface
	mciSendString("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
	lastobindex = -1;
	score = 0;

	//Load digital pictures
	for (int i = 0; i < 10; i++) {
		sprintf(name, "res/sz/%d.png", i);
		loadimage(&imgsz[i], name);
	}
}

//draw blood
void drawblood(int x, int y, int width, int height, int lineWidth, int boardColor, int emptyColor, int fillColor, float percent) {
	LINESTYLE lineStyle;
	getlinestyle(&lineStyle);
	int lineColor = getlinecolor();
	int fileColor = getfillcolor();

	if (percent < 0) {
		percent = 0;
	}

	setlinecolor(BLUE);
	setlinestyle(PS_SOLID | PS_ENDCAP_ROUND, lineWidth);
	setfillcolor(emptyColor);
	fillrectangle(x, y, x + width, y + height);
	setlinestyle(PS_SOLID | PS_ENDCAP_FLAT, 0);
	setfillcolor(fillColor);
	setlinecolor(fillColor);
	if (percent > 0) {
		fillrectangle(x + 0.5 * lineWidth, y + lineWidth * 0.5, x + width * percent, y + height - 0.5 * lineWidth);
	}

	setlinecolor(lineColor);
	setfillcolor(fillColor);
	setlinestyle(&lineStyle);
}


void creatobstacle() {
	int i;
	for (i = 0; i < OBSTACLE_COUNT; i++) {
		if (!obstacles[i].exist) {
			break;
		}
	}
	if (i >= OBSTACLE_COUNT) {
		return;
	}

	obstacles[i].exist = true;
	obstacles[i].hit = false;
	obstacles[i].imgindex = 0;
	obstacles[i].type = (obstacle_type)(rand() % 3);//forced conversion

	if (lastobindex >= 0 &&
		obstacles[lastobindex].type >= zhu1 &&
		obstacles[lastobindex].type <= zhu4 &&
		obstacles[i].type == guai2 &&
		obstacles[lastobindex].x > (WHIDE - 500)) {
		obstacles[i].type = guai1;
	}
	lastobindex = i;

	if (obstacles[i].type == zhu1) {    //Optimize the appearance of obstacles
		obstacles[i].type = (obstacle_type)(zhu1 + rand() % 4);
	}
	obstacles[i].x = WHIDE;
	obstacles[i].y = 350 - obstacleimgs[obstacles[i].type][0].getheight();
	if (obstacles[i].type == guai1) {
		obstacles[i].speed = 0;
		obstacles[i].power = 5;   //Mob 1 damage
	}
	else if (obstacles[i].type == guai2) {
		obstacles[i].speed = 4;
		obstacles[i].power = 20;
	}
	else if (obstacles[i].type >= zhu1 && obstacles[i].type <= zhu4) {
		obstacles[i].speed = 0;
		obstacles[i].power = 20;
		obstacles[i].y = 0;
	}
	obstacles[i].passed = false;
}




//Player Collision Detection
void checkhit() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {  //For a rectangle, you only need to know two opposite corners to determine
		if (obstacles[i].exist && obstacles[i].hit == false) {              //Use open source code to detect whether two rectangles intersect
			int alx, aly, a2x, a2y;
			int off = 30;
			if (!rendown) {      //If people are not squatting, they are running or jumping
				alx = renx + off;
				aly = reny + off;
				a2x = renx + imgbgsren[renindex].getwidth() - off;
				a2y = reny + imgbgsren[renindex].getheight();
			}
			else {
				alx = renx + off;
				aly = 345 - imgrendown[renindex].getheight();
				a2x = renx + imgrendown[renindex].getwidth() - off;
				a2y = 345;
			}
			IMAGE img = obstacleimgs[obstacles[i].type][obstacles[i].imgindex];//The first picture of the first obstacle
			int blx = obstacles[i].x + off;
			int bly = obstacles[i].y + off;
			int b2x = obstacles[i].x + img.getwidth() - off;
			int b2y = obstacles[i].y + img.getheight() - 10;
			if (rectIntersect(alx, aly, a2x, a2y, blx, bly, b2x, b2y)) {//Collision
				blood -= obstacles[i].power;
				printf("remaining blood %d\n", blood);
				playSound("res/hit.mp3");
				obstacles[i].hit = true;
			}
		}
	}
}



//picture mobile
void fly() {
	for (int i = 0; i < 3; i++) {
		bgx[i] -= bgspeed[i];
		if (bgx[i] < -WHIDE)
			bgx[i] = 0;
	}

	//Character Jump Realization
	if (renjump) {                                         //What the hell are you changing, the y coordinates, why can’t you know anything, are you a baby?
		if (reny < jumpmax) {//The first time is to take off, so it starts to be negative, and the next step must be to fall, so it can be positive
			rendownspeed = 4;
		}
		reny += rendownspeed;
		if (reny > 345 - imgbgsren[0].getheight()) {//has fallen to the ground
			renjump = false;
			rendownspeed = -4;
		}
	}
	else if (rendown) {
		static int count = 0;
		int delays[2] = { 4,32 };   //Want to control the station time of the two pictures separately
		count++;
		if (count >= delays[renindex]) {    //The station time is different
			count = 0;
			renindex++;
			if (renindex >= 2) {
				renindex = 0;
				rendown = false;
			}
		}
	}
	else {//neither jump nor squat
		renindex = (renindex + 1) % 12;
	}

	//create obstacles
	static int frameCount = 0;//Static variables are permanently valid
	//static int torToiseFre = 100;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		//if (!torToiseXExist) {
		//torToiseXExist = true;
		//torToiseX = WHIDE;
		//enemyFre = 200 + rand() % 301;
		//}
		enemyFre = 50 + rand() % 50;
		creatobstacle();
	}

	//update coordinates
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bgspeed[2];
			if (obstacles[i].x < -obstacleimgs[obstacles[i].type][0].getheight() * 2) {
				obstacles[i].exist = false;
			}
			int len = obstacleimgs[obstacles[i].type].size();
			obstacles[i].imgindex = (obstacles[i].imgindex + 1) % len;
		}
	}
	//if (torToiseXExist) {
	//Set the movement of mob 1
	//torToiseX -= bgspeed[2];
	//if (torToiseX < -imgTortoise.getwidth()) {
	//torToiseXExist = false;
	//}
	//}
	checkhit();
}


//Render the game background
void updatabg() {
	putimagePNG2(bgx[0], 0, &imgbgs[0]);
	putimagePNG2(bgx[1], 119, &imgbgs[1]);
	putimagePNG2(bgx[2], 330, &imgbgs[2]);
}



//character image rendering
void updataren() {
	if (!rendown) {
		putimagePNG2(renx, reny, &imgbgsren[renindex]);
	}
	else {
		int y = 345 - imgrendown[renindex].getheight();
		putimagePNG2(renx, y, &imgrendown[renindex]);
	}
}


//character jump switch
void jump() {
	renjump = true;
	updata = true;    //Character frame waiting (just don't wait for 30ms, just refresh directly)
}

//Character squat switch
void down() {
	rendown = true;
	updata = true;
	renindex = 0;
}



//Handle user keystroke input
void anjian() {
	char ch;
	if (kbhit()) {   //Determine whether there is input
		ch = getch();//getch reads characters directly, there is no buffer
		if (ch == ' ') {
			jump();
		}
		else if (ch == 'b') {
			down();
		}
	}

}


void updateEnemy() {
	//render mobs 1
	//if (torToiseXExist) {
	//	putimagePNG2(torToiseX, torToiseY, WHIDE, &imgTortoise);
	//}
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist)
		{
			putimagePNG2(obstacles[i].x, obstacles[i].y, WHIDE, &obstacleimgs[obstacles[i].type][obstacles[i].imgindex]);
		}
	}
}

//render health bar
void updatablood() {
	drawblood(10, 10, 200, 10, 2, BLUE, DARKGRAY, RED, blood / 100.0);
}

void updatascore() {
	char str[3];
	sprintf(str, "%d", score);

	int x = 20;
	int y = 25;
	for (int i = 0; str[i] != '\0'; i++) {
		int sz = str[i] - '0';
		putimagePNG(x, y, &imgsz[sz]);
		x = x + imgsz[sz].getwidth() + 5;
	}
}

void checkover() {
	if (blood <= 0) {
		loadimage(0, "res/over.png");
		FlushBatchDraw();
		mciSendString("stop res/bg.mp3", 0, 0, 0);
		system("pause");

		//Ready to set a button to start the next set
		if (getch() == 'w') {
			blood = 100;
			score = 0;
			mciSendString("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
		}
	}
}

void checkscore() {
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		if (obstacles[i].exist && obstacles[i].passed == false && obstacles[i].x + obstacleimgs[obstacles[i].type][0].getwidth() < renx && obstacles[i].hit == false) {
			score++;
			obstacles[i].passed = true;
			printf("score=%d\n", score);
		}
	}
}

void checkwin() {
	if (score >= win) {
		FlushBatchDraw();
		mciSendString("play res/win.mp3", 0, 0, 0);
		Sleep(2000);
		loadimage(0, "res/win.png");
		FlushBatchDraw();
		system("pause");
		if (getch() == 'w') {   //Restart
			mciSendString("stop res/win.mp3", 0, 0, 0);
			blood = 100;
			score = 0;
			("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
		}
	}
}

int main() {
	init();
	int time = 0;
	loadimage(0, "res/over.png");
	if (getch() == ' ') {
		while (1) {
			anjian();
			time += getDelay();//background frame wait
			if (time > 30) {  //Frame waiting can be optimized
				time = 0;
				updata = true;
			}
			if (updata) {
				updata = false;
				BeginBatchDraw();
				updatabg();
				//putimagePNG2(renx, reny, &imgbgsren[renindex]);
				updataren();
				updateEnemy();
				updatablood();
				updatascore();
				checkwin();
				EndBatchDraw();
				checkover();
				checkscore();
				fly();
			}
		}
	}

	system("pause");
	return 0;
}

  Show results:

 

 

Weakened version

Next is the weakened version of the code:

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include"tools.h" 


#define WHIDE 1012
#define HEIGHT 396
#define win 10 //win score

IMAGE guai1;//Mob 1
int guai1x;//The x coordinate of mob 1
int guai1y;
bool guai1exist;//Is there any mobs in the current window 1
bool hit1;
bool pass1;

IMAGE guai2;
int guai2x;
int guai2y;
bool guai2exist;
bool hit2;
bool pass2;

IMAGE guai3;
int guai3x;
int guai3y;
bool guai3exist;
bool hit3;
bool pass3;

IMAGE guai4;
int guai4x;
int guai4y;
bool guai4exist;
bool hit4;
bool pass4;


//Double cycle
IMAGE  imgbgs[2];
int bgx[2];//The x coordinate of the background image
int bgspeed[2] = { 0,4 };

IMAGE imgbgsren[12];
int renx;//Character abscissa
int reny;//Character ordinate
int renindex;//The picture frame of the player running
int jumpmax;//character jump height
bool renjump;//Determine whether the character has jumped
int rendownspeed;//decline
int score;//Fraction

//people squatting
IMAGE   imgrendown[2];
bool rendown;//Character squat judgment


//digital material
IMAGE imgsz[10];



void init() {
	//Create game window
	initgraph(WHIDE, HEIGHT);//show console


	//Load background resources
	char name[64];
	for (int i = 0; i < 2; i++) {
		sprintf(name, "res/bg%03d.png", i + 1);
		loadimage(&imgbgs[i], name);
	}

	//Load character frame picture (running)
	for (int i = 0; i < 12; i++) {
		sprintf(name, "res/hero%d.png", i + 1);
		loadimage(&imgbgsren[i], name);
	}

	//Set the player's initial position, it should not change afterwards
    renx = WHIDE / 2 - imgbgsren[0].getwidth() / 2;
   reny = 345 - imgbgsren[0].getheight();
   renindex = 0;
   renjump = false;//The character does not jump at the beginning
   jumpmax = reny - 130;
   rendownspeed = -3;//The rate of decline

//Load mobs 1
   loadimage(&guai1, "res/t2.png");
   guai1exist = false;//mob 1 initialization
   guai1y = 355 - guai1.getheight();

//load mobs 2
   loadimage(&guai2, "res/t1.png");
   guai2exist = false;
   guai2y = 355 - guai2.getheight();

//load mobs 3
   loadimage(&guai3, "res/h1.png",63,260);
   guai3exist = false;
   guai3y = -10;

 //load mobs 4
   loadimage(&guai4, "res/h4.png",63,260);
   guai4exist = false;
   guai4y = -10;

//Load squat material
   loadimage(&imgrendown[0], "res/d1.png");
   loadimage(&imgrendown[1], "res/d2.png");
   rendown = false;



//Preload sound effects
   preLoadSound("res/hit.mp3");    //This thing is the external interface
   mciSendString("play res/bg.mp3 repeat", 0, 0, 0);  //Background music
   score = 0;

//Load digital pictures
for (int i = 0; i < 10; i++) {
	sprintf(name, "res/sz/%d.png", i);
	loadimage(&imgsz[i], name);
}
}

//Player Collision Detection
void checkhit() {
	int alx, aly, a2x, a2y, b1x, b2x, b1y, b2y;
	int off = 30;
	if (guai1exist == true && hit1 == false) {
		if (!rendown) {      //If people are not squatting, they are running or jumping
			alx = renx + off;
			aly = reny + off;
			a2x = renx + imgbgsren[renindex].getwidth() - off;
			a2y = reny + imgbgsren[renindex].getheight();
		}
		else {
			alx = renx + off;
			aly = 345 - imgrendown[renindex].getheight();
			a2x = renx + imgrendown[renindex].getwidth() - off;
			a2y = 345;
		}
		b1x = guai1x + off+10;
		b1y = guai1y + off+10;
		b2x = guai1x + guai1.getwidth() - off;
		b2y = guai1y + guai1.getheight() - 10;
		if (rectIntersect(alx, aly, a2x, a2y, b1x, b1y, b2x, b2y)) {//Collision
			hit1 = true;
			mciSendString("play res/hit.mp3",0,0,0);
			if (score > 0) {
				score--;
			}
		}
	}
    if (guai2exist == true && hit2 == false) {
		if (!rendown) {      //If people are not squatting, they are running or jumping
			alx = renx + off;
			aly = reny + off;
			a2x = renx + imgbgsren[renindex].getwidth() - off;
			a2y = reny + imgbgsren[renindex].getheight();
		}
		else {
			alx = renx + off;
			aly = 345 - imgrendown[renindex].getheight();
			a2x = renx + imgrendown[renindex].getwidth() - off;
			a2y = 345;
		}
		b1x = guai2x + off+10;
		b1y = guai2y + off+10;
		b2x = guai2x + guai2.getwidth() - off;
		b2y = guai2y + guai2.getheight() - 10;
		if (rectIntersect(alx, aly, a2x, a2y, b1x, b1y, b2x, b2y)) {//Collision
			hit2 = true;
			mciSendString("play res/hit.mp3", 0, 0, 0);
			if (score > 0) {
				score--;
			}
		}
	}

	if (guai3exist == true && hit3 == false) {
		if (!rendown) {      //If people are not squatting, they are running or jumping
			alx = renx + off;
			aly = reny + off;
			a2x = renx + imgbgsren[renindex].getwidth() - off;
			a2y = reny + imgbgsren[renindex].getheight();
		}
		else {
			alx = renx + off;
			aly = 345 - imgrendown[renindex].getheight();
			a2x = renx + imgrendown[renindex].getwidth() - off;
			a2y = 345;
		}
		b1x = guai3x + off;
		b1y = guai3y + off;
		b2x = guai3x + guai3.getwidth() - off;
		b2y = guai3y + guai3.getheight() - 10;
		if (rectIntersect(alx, aly, a2x, a2y, b1x, b1y, b2x, b2y)) {//Collision
			hit3 = true;
			mciSendString("play res/hit.mp3", 0, 0, 0);
			if (score > 0) {
				score--;
			}
		}
	}

	if (guai4exist == true && hit4 == false) {
		if (!rendown) {      //If people are not squatting, they are running or jumping
			alx = renx + off;
			aly = reny + off;
			a2x = renx + imgbgsren[renindex].getwidth() - off;
			a2y = reny + imgbgsren[renindex].getheight();
		}
		else {
			alx = renx + off;
			aly = 345 - imgrendown[renindex].getheight();
			a2x = renx + imgrendown[renindex].getwidth() - off;
			a2y = 345;
		}
		b1x = guai4x + off;
		b1y = guai4y + off;
		b2x = guai4x + guai4.getwidth() - off;
		b2y = guai4y + guai4.getheight() - 10;
		if (rectIntersect(alx, aly, a2x, a2y, b1x, b1y, b2x, b2y)) {//Collision
			hit4 = true;
			mciSendString("play res/hit.mp3", 0, 0, 0);
			if (score > 0) {
				score--;
			}
		}
	}
}

//picture mobile
void fly() {
	for (int i = 0; i < 2; i++) {
		bgx[i] -= bgspeed[i];
		if (bgx[i] < -WHIDE)
			bgx[i] = 0;
	}

	//Character Jump Realization
	if (renjump) {                                    
		if (reny < jumpmax) {//The first time is to take off, so it starts to be negative, and the next step must be to fall, so it can be positive
			rendownspeed = 4;
		}
		reny += rendownspeed;
		if (reny > 345 - imgbgsren[0].getheight()) {//has fallen to the ground
			renjump = false;
			rendownspeed = -4;
		}
	}
	else if (rendown) {
		static int count = 0;
		int delays[2] = { 4,32 };   //Want to control the station time of the two pictures separately
		count++;
		if (count >= delays[renindex]) {    //The station time is different
			count = 0;
			renindex++;
			if (renindex >= 2) {
				renindex = 0;
				rendown = false;
			}
		}
	}
	else {//neither jump nor squat
		renindex = (renindex + 1) % 12;
	}

	//create obstacles
	static int frameCount = 0;//Static variables are permanently valid
	static int guai1count = 0;
	static int guai2count = 1;
	static int guai3count = 2;
	static int guai4count = 3;
	static int enemyFre = 50;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		int count = rand() % 4;
		if (!guai1exist && count == guai1count) {
			guai1exist = true;
			hit1 = false;
			pass1=false;
			guai1x = WHIDE;
			enemyFre = 50 + rand() % 50;
		}
	    if (!guai2exist && count == guai2count) {
			guai2exist = true;
			hit2 = false;
			pass2 = false;
			guai2x = WHIDE;
			enemyFre = 50+ rand() % 50;
		}
		if (!guai3exist && count == guai3count) {
			guai3exist = true;
			hit3 = false;
			pass3 = false;
			guai3x = WHIDE;
			enemyFre = 50 + rand() % 50;
		}
		if(!guai4exist && count == guai4count){
			guai4exist = true;
			hit4 = false;
			pass4 = false;
			guai4x = WHIDE;
			enemyFre = 50 + rand() % 50;
		}
	}


	//update coordinates
	//Set the movement of mob 1
	if (guai1exist) {
	guai1x -= bgspeed[1];
	 if (guai1x < -guai1.getwidth()) {
	     guai1exist = false;
	   }
	}
	//Set the movement of mobs 2
	if (guai2exist) {
		guai2x -= bgspeed[1];
		if (guai2x < -guai2.getwidth()) {
			guai2exist = false;
		}
	}
	//Set the movement of mobs 3
	if (guai3exist) {
		guai3x -= bgspeed[1];
		if (guai3x < -guai3.getwidth()) {
		guai3exist = false;
		}
	}
	//Set the movement of mobs 4
	if (guai4exist) {
		guai4x -= bgspeed[1];
		if (guai4x < -guai4.getwidth()) {
			guai4exist = false;
		}
	}
	checkhit();
}


void updatabg() {
	putimagePNG2(-100, 0, &imgbgs[0]);
	putimagePNG2(bgx[1], 330, &imgbgs[1]);
}


//character image rendering
void updataren() {
	if (!rendown) {
		putimagePNG(renx, reny, &imgbgsren[renindex]);
	}
	else {
		int y = 345 - imgrendown[renindex].getheight();
		putimagePNG(renx, y, &imgrendown[renindex]);
	}
}

//character jump switch
void jump() {
	renjump = true;
}

//Character squat switch
void down() {
	rendown = true;
	renindex = 0;
}


//rendering score
void updatascore() {
	char str[3];
	sprintf(str, "%d", score);

	int x = 512;
	int y = 25;
	for (int i = 0; str[i] != '\0'; i++) {
		int sz = str[i] - '0';
		putimagePNG(x, y, &imgsz[sz]);
		x = x + imgsz[sz].getwidth() + 5;
	}
}


void updateEnemy() {
	//render mobs 1
	if (guai1exist) {
		putimagePNG2(guai1x, guai1y, WHIDE, &guai1);
	}
	if (guai2exist) {
		putimagePNG2(guai2x, guai2y, WHIDE, &guai2);
	}
	if (guai3exist) {
		putimagePNG2(guai3x, guai3y, WHIDE, &guai3);
	}
	if (guai4exist) {
		putimagePNG2(guai4x, guai4y, WHIDE, &guai4);
	}
}



void checkwin() {
	if (score >= win) {
		updatascore();
		FlushBatchDraw();
		mciSendString("play res/win.mp3", 0, 0, 0);
		Sleep(2000);
		loadimage(0, "res/win.png");
		FlushBatchDraw();
		system("pause");              //Continue the game
			mciSendString("stop res/win.mp3", 0, 0, 0);
			score = 0;
	}
}


void checkscore() {
	if (guai1exist && pass1 == false && guai1x + guai1.getwidth() < renx && hit1 == false) {
		score++;
		pass1 = true;
	}
	if (guai2exist && pass2 == false && guai2x + guai2.getwidth() < renx && hit2 == false) {
		score++;
		pass2 = true;
	}
	if (guai3exist && pass3 == false && guai3x + guai3.getwidth() < renx && hit3 == false) {
		score++;
		pass3 = true;
	}
	if (guai4exist && pass4 == false && guai4x + guai4.getwidth() < renx && hit4 == false) {
		score++;
		pass4 = true;
	}
}


int main() {
	while (1) {
		init();
		loadimage(0, "res/over.png");
		if (getch() == 'o') {    //start the game
			while (1) {
				char ch;
				if (kbhit()) {   //Determine whether there is input
					ch = getch();//getch reads characters directly, there is no buffer
					if (ch == 'w') {
						jump();
					}
					else if (ch == 's') {
						down();
					}
					else if (ch == 'p') {
						break;
					}
				}
				BeginBatchDraw();
				updatabg();
				updataren();
				updateEnemy();
				updatascore();
				checkscore();
				checkwin();
				EndBatchDraw();
				fly();
				Sleep(20);
			}
		}
	}
	system("pause");
	return 0;
}

The code here is composed of the most basic code, even a very novice can easily understand it.

Let me show you the effect:

 

 

 

Since the frame animation of the characters is really hard to find and difficult to make (mainly because the blogger is a ps novice and not particularly good at it), I just use the materials in the rock directly, haha. The sound effects and background music are also edited by the blogger himself.

Explain in detail

It is a detailed explanation, just to tell you about the difficulties I encountered in the process of writing code and the tips I have summed up, which can reduce the time for everyone to take detours.

1. You will find that there is a tools.h header file in the game code. This is actually a header file written by the rock programmer himself. I will not post the details here. I will put the material extraction address at the end of the article . It needs to be added to the program when writing the game. It is recommended that you use vs to write and add it directly.

2. Many small partners find that vs will report an error when copying the code directly. Here are some adjustments to the settings.

 Open the property interface as shown in the figure (right-click "Cool Running in the Picture"), open "Advanced", find "Character Set", drop down and select "Use Multi-Byte Character Set"; then open "c/c++ ", open "General", select "SDL Check", the option is "No". This should work.

3. When beginners modify the code, they can add an array to the obstacle, or use a structure to encapsulate and then add an array, which can greatly reduce the running space and code length; of course, if you are too lazy to use your brain, just copy my weakened version Just keep adding variables.

4. When writing a program, it is recommended to put the code, header files, and materials in the same folder, so that it is not easy to make mistakes.

5. When you are writing a small game, if you want to use the if--else if--else statement multiple times, it is recommended not to use the else if multiple times, you can directly use the if judgment multiple times, the blogger has tried to use it in the weakened version Else if, as a result, a certain segment of else if will fail to run, the program will not report an error, and there is no problem with the grammar, so let’s take it as an experience.

6. When writing small games, it is recommended to define more global variables, but it is not suitable for large-scale games. Encapsulate more functions so that it is not easy to confuse.

Ok. . . . So be it.

Next, provide the material address:

Link: https://pan.baidu.com/s/1sgm2xraVIhFAfzeIvHdIgA?pwd=n3pe Extraction code: n3pe (weakened version material)

Link: https://pan.baidu.com/s/12u29t1FbXj8WRiY6o_DYKQ?pwd=v8iv Extraction code: v8iv (full version material)

Tags: C++ C programming language

Posted by skaforey on Mon, 02 Jan 2023 06:12:20 +1030