• 欢迎光临~

C/C++游戏开发(easyx框架)回合制——魔塔

开发技术 开发技术 2022-05-28 次浏览

本游戏用到了图形界面库graphics.h,图形界面库下载安装:
下载链接:https://easyx.cn/download
游戏截图:
C/C++游戏开发(easyx框架)回合制——魔塔
首先是玩家的定义,使用结构体,这个名字是可以自己改变的

struct gamerole{
	char name[20]; //玩家名字
	int HP;   //血量
	int MP;		//魔法
	int DEF;    //防御
	int ATT;  //攻击
	int Lv;   //等级
	int Exp;  //经验
	int Num_Blue_Key; //蓝钥匙数量
	int Num_Yellow_Key; //黄钥匙数量
	int x, y;	//坐标
}player;
int exp_need = 100;	//升级所需经验

怪物属性的定义

struct monster{
	char name[20];	//怪物名字
	int HP;   //血量
	int ATT;  //攻击
	int DEF;  //防御
	int Exp;  //经验
}monsters[15];

初始化玩家属性

void initPlayer(){
	//输入用户名
	printf("Input role name: ");
	scanf("%s", player.name);

	//初始化游戏角色信息
	player.Lv = 0;
	player.ATT = 50;
	player.DEF = 50;
	player.Num_Blue_Key = 0;
	player.Num_Yellow_Key = 0;
	player.HP = 500;
	player.MP = 250;
	player.Exp = 0;
	player.x = -1;
	player.y = -1;
}

初始化怪物属性

void initMonsters() {
	monsters[2] = { "绿史莱姆", 50, 10, 12, 100 };  //绿史莱姆属性
	monsters[3] = { "红史莱姆", 100, 50, 12, 500 }; //红史莱姆属性
	monsters[11] = { "小蝙蝠", 20, 10, 9, 50 };     //小蝙蝠属性
	monsters[12] = { "小巫师", 100, 30, 9, 400 };//小巫师属性
	monsters[13] = { "小骷髅", 30, 20, 10, 200 };  //小骷髅属性
	monsters[14] = { "大骷髅", 60, 50, 25, 300 };   //大骷髅属性
}

加载游戏资源图片
右键打开项目属性,添加 -> 现有项,添加资源图片进项目·。
资源图片链接:https://pan.baidu.com/s/1NZN7yDFAzBbHDHrxBiWEJA?pwd=c685
提取码:c685
C/C++游戏开发(easyx框架)回合制——魔塔

IMAGE img[19], playerInfoBox;	//素材图片
void initgamePicture(){
	//加载游戏角色信息框
	loadimage(&playerInfoBox, "info.jpg");

	//加载地图资源
	//60 * 60 固定尺寸
	loadimage(&img[0], "墙.jpg", 60, 60);
	loadimage(&img[1], "地板.jpg", 60, 60);
	loadimage(&img[2], "绿史莱姆.jpg", 60, 60);
	loadimage(&img[3], "红史莱姆.jpg", 60, 60);
	loadimage(&img[4], "蓝水晶.jpg", 60, 60);
	loadimage(&img[5], "红水晶.jpg", 60, 60);
	loadimage(&img[6], "蓝钥匙.jpg", 60, 60);
	loadimage(&img[7], "黄钥匙.jpg", 60, 60);
	loadimage(&img[8], "小红药水.jpg", 60, 60);
	loadimage(&img[9], "小蓝药水.jpg", 60, 60);
	loadimage(&img[10], "梯子.jpg", 60, 60);
	loadimage(&img[11], "小蝙蝠.jpg", 60, 60);
	loadimage(&img[12], "小巫师.jpg", 60, 60);
	loadimage(&img[13], "骷髅兵.jpg", 60, 60);
	loadimage(&img[14], "大骷髅兵.jpg", 60, 60);
	loadimage(&img[15], "蓝门.jpg", 60, 60);
	loadimage(&img[16], "黄门.jpg", 60, 60);
	loadimage(&img[17], "人.jpg", 60, 60);
}

设置地图,用数字来决定地图的每一个方块是什么类型(与img数组的索引对应)。

int map[13][13] = {
	0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,10,6,2,3,2,1,1,1,1,1,1,0,
	0,0,0,0,0,0,0,0,0,0,0,1,0,
	0,8,1,1,15,1,0,0,1,1,1,1,0,
	0,1,14,1,0,1,0,0,5,0,0,1,0,
	0,0,15,0,0,1,15,11,12,11,0,1,0,
	0,6,1,1,0,1,0,0,0,0,0,1,0,
	0,1,14,1,0,1,0,0,0,0,0,1,0,
	0,0,15,0,0,1,1,0,0,0,0,1,0,
	0,1,1,1,0,0,15,0,0,0,0,15,0,
	0,8,1,9,0,6,1,6,0,6,11,1,0,
	0,8,1,9,0,1,17,1,0,2,6,2,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0
};

接下来就是定义画布,然后加载图片,我用一个二维数组存下了地图,不同的数字代表不同的图片,然后根据二维数组的值把不同的地方贴上不同的图片。

void SetMap(int x, int y){
	for (int i = 0; i < y; i++){
		for (int j = 0; j < x; j++){
			putimage(j * 60, i * 60, &img[map[i][j]]);
			if (map[i][j] == 17) {
				player.x = i;
				player.y = j;
			}
		}
	}
	//地图没有角色
	if (player.x == -1) {
		MessageBox(hwnd, "地图没找到角色", "错误", MB_ICONWARNING);
		closegraph();
		exit(-1);
	}
}

在地图右边显示角色信息

void SetPlayer(){
	static char temp[16];
	//打印游戏角色信息框
	putimage(13 * 60, 0, &playerInfoBox);
	setbkmode(TRANSPARENT);	//透明背景
	outtextxy(60 * 13 + 12, 100, player.name);
	outtextxy(60 * 13 + 12, 180, _itoa(player.Lv, temp, 10));
	outtextxy(60 * 13 + 12, 235, _itoa(player.Exp, temp, 10));
	outtextxy(60 * 13 + 12, 362, _itoa(player.HP, temp, 10));
	outtextxy(60 * 13 + 12, 420, _itoa(player.MP, temp, 10));
	outtextxy(60 * 13 + 12, 517, _itoa(player.ATT, temp, 10));
	outtextxy(60 * 13 + 12, 567, _itoa(player.DEF, temp, 10));
	outtextxy(60 * 13 + 12, 689, _itoa(player.Num_Yellow_Key, temp, 10));
	outtextxy(60 * 13 + 12, 759, _itoa(player.Num_Blue_Key, temp, 10));
}

C/C++游戏开发(easyx框架)回合制——魔塔
接下来就是人物的移动和战斗了,人物的移动我就是直接对上下左右四种情况分别讨论。

void playGame() {
	static char dir;
	dir = _getch();
	switch (dir) {
		//左
		case 'a':
		case 'A':
		case 75:
			step(player.x, player.y - 1);
			break;
		//右
		case 'd':
		case 'D':
		case 77:
			step(player.x, player.y + 1);
			break;
		//上
		case 'w':
		case 'W':
		case 72:
			step(player.x - 1, player.y);
			break;
		//下
		case 's':
		case 'S':
		case 80:
			step(player.x + 1, player.y);
			break;
		default:
			break;
	}
}

在人物走动的时候要判断能不能走,不能走就不处理,如果能走,就把走到的那个位置上变成人,把之前人的位置变成地板。
如果是钥匙,把对应的钥匙数量加1。
如果是门,判断一下对应颜色的钥匙是否足够,如果足够,钥匙数量减1,然后把对应位置上的门变为空地。
如果是药水,吃了之后会增加生命。
如果是水晶,根据水晶的颜色加对应的属性。
如果是楼梯,就游戏胜利。
当遇到怪物的时候回产生战斗。

void step(int dstx, int dsty) {
	if (map[dstx][dsty] == 1) {     //下一步是地板
	}
	else if (map[dstx][dsty] == 15) {   //下一步是蓝门
		if (player.Num_Blue_Key <= 0) {
			return;
		}
		player.Num_Blue_Key--;
	}
	else if (map[dstx][dsty] == 10) {   //下一步是蓝门
		MessageBox(hwnd, "游戏结束了", "通关", MB_OK);
		closegraph();
		exit(0);
	}
	else if (map[dstx][dsty] == 16) {   //下一步是黄门
		if (player.Num_Yellow_Key <= 0) {
			return;
		}
		player.Num_Yellow_Key--;
	}
	else if (map[dstx][dsty] == 4) {   //下一步是蓝水晶
		player.DEF += 2;
	}
	else if (map[dstx][dsty] == 5) {   //下一步是红水晶
		player.ATT += 2;
	}
	else if (map[dstx][dsty] == 6) {   //下一步是蓝钥匙
		player.Num_Blue_Key++;
	}
	else if (map[dstx][dsty] == 7) {   //下一步是黄钥匙
		player.Num_Yellow_Key++;
	}
	else if (map[dstx][dsty] == 8) {   //下一步是红药水
		player.HP += 50;
	}
	else if (map[dstx][dsty] == 9) {   //下一步是蓝药水
		player.MP += 50;
	}
	else if (map[dstx][dsty] != 0) {   //下一步是怪物
		if (!Combat(map[dstx][dsty])) {//不打怪物
			return;
		}
	}
	else {								//其他情况
		return;
	}
	//移动
	drawMapCell(player.x, player.y, 1);
	drawMapCell(dstx, dsty, 17);
	player.x = dstx;
	player.y = dsty;
}

void drawMapCell(int x, int y, int type) {
	putimage(y * 60, x * 60, &img[type]);
	map[x][y] = type;
}

Combat函数,判断玩家和那个怪物进行战斗。
VS函数,用于计算战斗是否成功,如果成功,会加相应的属性,如果失败,则会弹出打不过的窗口。
C/C++游戏开发(easyx框架)回合制——魔塔

bool Combat(int monsterType){
	int ID;
	char msg[36];
	sprintf(msg, "遇到%s,是否攻击?", monsters[monsterType].name);
	ID = MessageBox(hwnd, msg, "战斗阶段", MB_YESNO);
	if (ID == IDYES) {
		if (VS(player.HP, player.ATT, player.DEF, monsters[monsterType].HP, monsters[monsterType].ATT, monsters[monsterType].DEF)) {	//胜利
			//获得经验值
			player.Exp += monsters[monsterType].Exp;
			while (player.Exp >= exp_need) {	//升级
				player.Lv++;
				player.Exp -= exp_need;
				exp_need *= player.Lv;
			}
			return true;
		}
		else {	//失败
			MessageBox(hwnd, "你死了", "打不过", MB_ICONWARNING);
			return false;
		}
	}
	return false;
}

bool VS(int playHP, int playATT, int playDEF, int monHP, int monATT, int monDEF){
	while (playHP > 0 || monHP > 0){
		monHP -= playATT < monDEF ? 0 : playATT - monDEF;
		if (monHP < 0)
			break;
		playHP -= monATT < playDEF ? 0 : monATT - playDEF;
	}
	if (playHP > 0) {
		player.HP = playHP;
		return true;
	}
	return false;
}

游戏流程

int main() {
	initPlayer();
	initMonsters();
	initgamePicture();
	initgraph(60 * 14, 60 * 13);
	putimage(0, 0, &playerInfoBox);
	SetMap(13, 13);
	SetPlayer();
	while (player.HP > 0) {
		playGame();
		SetPlayer();
	}
	closegraph();
	return 0;
}

完整的代码

#define _CRT_SECURE_NO_WARNINGS //去掉scanf_s问题
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <graphics.h>
using namespace std;


void initgamePicture();  //加载游戏图片
void SetPlayer();    //显示角色信息
void initPlayer();   //初始化游戏角色
void initMonsters();   //初始化游戏怪物
void SetMap(int x, int y);     //加载游戏地图
void playGame();     //开始游戏
void step(int dstx, int dsty);	//移动
void drawMapCell(int x, int y, int type);	//画图
bool VS(int playHP, int playATT, int playDEF, int monHP, int monATT, int monDEF);	//打架
bool Combat(int monstersTpye);	//战斗阶段

//地图二维数组
int map[13][13] = {
	0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,10,6,2,3,2,1,1,1,1,1,1,0,
	0,0,0,0,0,0,0,0,0,0,0,1,0,
	0,8,1,1,15,1,0,0,1,1,1,1,0,
	0,1,14,1,0,1,0,0,5,0,0,1,0,
	0,0,15,0,0,1,15,11,12,11,0,1,0,
	0,6,1,1,0,1,0,0,0,0,0,1,0,
	0,1,14,1,0,1,0,0,0,0,0,1,0,
	0,0,15,0,0,1,1,0,0,0,0,1,0,
	0,1,1,1,0,0,15,0,0,0,0,15,0,
	0,8,1,9,0,6,1,6,0,6,11,1,0,
	0,8,1,9,0,1,17,1,0,2,6,2,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0
};

struct gamerole{
	char name[20]; //玩家名字
	int HP;   //血量
	int MP;		//魔法
	int DEF;    //防御
	int ATT;  //攻击
	int Lv;   //等级
	int Exp;  //经验
	int Num_Blue_Key; //蓝钥匙数量
	int Num_Yellow_Key; //黄钥匙数量
	int x, y;	//坐标
}player;

struct monster{
	char name[20];	//怪物名字
	int HP;   //血量
	int ATT;  //攻击
	int DEF;  //防御
	int Exp;  //经验
}monsters[15];

IMAGE img[19], playerInfoBox;	//素材图片

HWND hwnd;	//弹窗窗口句柄

int exp_need = 100;	//升级所需经验

int main() {
	initPlayer();
	initMonsters();
	initgamePicture();
	initgraph(60 * 14, 60 * 13);
	putimage(0, 0, &playerInfoBox);
	SetMap(13, 13);
	SetPlayer();
	while (player.HP > 0) {
		playGame();
		SetPlayer();
	}
	closegraph();
	return 0;
}

/*
* 输入用户名,初始化游戏角色信息
*/
void initPlayer(){
	//输入用户名
	printf("Input role name: ");
	scanf("%s", player.name);

	//初始化游戏角色信息
	player.Lv = 0;
	player.ATT = 50;
	player.DEF = 50;
	player.Num_Blue_Key = 0;
	player.Num_Yellow_Key = 0;
	player.HP = 500;
	player.MP = 250;
	player.Exp = 0;
	player.x = -1;
	player.y = -1;
}

/*
* 初始化游戏怪物
*/
void initMonsters() {
	monsters[2] = { "绿史莱姆", 50, 10, 12, 100 };  //绿史莱姆属性
	monsters[3] = { "红史莱姆", 100, 50, 12, 500 }; //红史莱姆属性
	monsters[11] = { "小蝙蝠", 20, 10, 9, 50 };     //小蝙蝠属性
	monsters[12] = { "小巫师", 100, 30, 9, 400 };//小巫师属性
	monsters[13] = { "小骷髅", 30, 20, 10, 200 };  //小骷髅属性
	monsters[14] = { "大骷髅", 60, 50, 25, 300 };   //大骷髅属性
}

/*
*  加载游戏资源图片
*/
void initgamePicture(){
	//加载游戏角色信息框
	loadimage(&playerInfoBox, "info.jpg");

	//加载地图资源
	//60 * 60 固定尺寸
	loadimage(&img[0], "墙.jpg", 60, 60);
	loadimage(&img[1], "地板.jpg", 60, 60);
	loadimage(&img[2], "绿史莱姆.jpg", 60, 60);
	loadimage(&img[3], "红史莱姆.jpg", 60, 60);
	loadimage(&img[4], "蓝水晶.jpg", 60, 60);
	loadimage(&img[5], "红水晶.jpg", 60, 60);
	loadimage(&img[6], "蓝钥匙.jpg", 60, 60);
	loadimage(&img[7], "黄钥匙.jpg", 60, 60);
	loadimage(&img[8], "小红药水.jpg", 60, 60);
	loadimage(&img[9], "小蓝药水.jpg", 60, 60);
	loadimage(&img[10], "梯子.jpg", 60, 60);
	loadimage(&img[11], "小蝙蝠.jpg", 60, 60);
	loadimage(&img[12], "小巫师.jpg", 60, 60);
	loadimage(&img[13], "骷髅兵.jpg", 60, 60);
	loadimage(&img[14], "大骷髅兵.jpg", 60, 60);
	loadimage(&img[15], "蓝门.jpg", 60, 60);
	loadimage(&img[16], "黄门.jpg", 60, 60);
	loadimage(&img[17], "人.jpg", 60, 60);
}

/*
*打印游戏地图
*/
void SetMap(int x, int y){
	for (int i = 0; i < y; i++){
		for (int j = 0; j < x; j++){
			putimage(j * 60, i * 60, &img[map[i][j]]);
			if (map[i][j] == 17) {
				player.x = i;
				player.y = j;
			}
		}
	}
	//地图没有角色
	if (player.x == -1) {
		MessageBox(hwnd, "地图没找到角色", "错误", MB_ICONWARNING);
		closegraph();
		exit(-1);
	}
}

/*
*显示角色信息
*/
void SetPlayer(){
	static char temp[16];
	//打印游戏角色信息框
	putimage(13 * 60, 0, &playerInfoBox);
	setbkmode(TRANSPARENT);
	outtextxy(60 * 13 + 12, 100, player.name);
	outtextxy(60 * 13 + 12, 180, _itoa(player.Lv, temp, 10));
	outtextxy(60 * 13 + 12, 235, _itoa(player.Exp, temp, 10));
	outtextxy(60 * 13 + 12, 362, _itoa(player.HP, temp, 10));
	outtextxy(60 * 13 + 12, 420, _itoa(player.MP, temp, 10));
	outtextxy(60 * 13 + 12, 517, _itoa(player.ATT, temp, 10));
	outtextxy(60 * 13 + 12, 567, _itoa(player.DEF, temp, 10));
	outtextxy(60 * 13 + 12, 689, _itoa(player.Num_Yellow_Key, temp, 10));
	outtextxy(60 * 13 + 12, 759, _itoa(player.Num_Blue_Key, temp, 10));
}

void playGame() {
	static char dir;
	dir = _getch();
	switch (dir) {
		//左
		case 'a':
		case 'A':
		case 75:
			step(player.x, player.y - 1);
			break;
		//右
		case 'd':
		case 'D':
		case 77:
			step(player.x, player.y + 1);
			break;
		//上
		case 'w':
		case 'W':
		case 72:
			step(player.x - 1, player.y);
			break;
		//下
		case 's':
		case 'S':
		case 80:
			step(player.x + 1, player.y);
			break;
		default:
			break;
	}
}

void step(int dstx, int dsty) {
	if (map[dstx][dsty] == 1) {     //下一步是地板
	}
	else if (map[dstx][dsty] == 15) {   //下一步是蓝门
		if (player.Num_Blue_Key <= 0) {
			return;
		}
		player.Num_Blue_Key--;
	}
	else if (map[dstx][dsty] == 10) {   //下一步是蓝门
		MessageBox(hwnd, "游戏结束了", "通关", MB_OK);
		closegraph();
		exit(0);
	}
	else if (map[dstx][dsty] == 16) {   //下一步是黄门
		if (player.Num_Yellow_Key <= 0) {
			return;
		}
		player.Num_Yellow_Key--;
	}
	else if (map[dstx][dsty] == 4) {   //下一步是蓝水晶
		player.DEF += 2;
	}
	else if (map[dstx][dsty] == 5) {   //下一步是红水晶
		player.ATT += 2;
	}
	else if (map[dstx][dsty] == 6) {   //下一步是蓝钥匙
		player.Num_Blue_Key++;
	}
	else if (map[dstx][dsty] == 7) {   //下一步是黄钥匙
		player.Num_Yellow_Key++;
	}
	else if (map[dstx][dsty] == 8) {   //下一步是红药水
		player.HP += 50;
	}
	else if (map[dstx][dsty] == 9) {   //下一步是蓝药水
		player.MP += 50;
	}
	else if (map[dstx][dsty] != 0) {   //下一步是怪物
		if (!Combat(map[dstx][dsty])) {//不打怪物
			return;
		}
	}
	else {								//其他情况
		return;
	}
	//移动
	drawMapCell(player.x, player.y, 1);
	drawMapCell(dstx, dsty, 17);
	player.x = dstx;
	player.y = dsty;
}

void drawMapCell(int x, int y, int type) {
	putimage(y * 60, x * 60, &img[type]);
	map[x][y] = type;
}

bool Combat(int monsterType){
	int ID;
	char msg[36];
	sprintf(msg, "遇到%s,是否攻击?", monsters[monsterType].name);
	ID = MessageBox(hwnd, msg, "战斗阶段", MB_YESNO);
	if (ID == IDYES) {
		if (VS(player.HP, player.ATT, player.DEF, monsters[monsterType].HP, monsters[monsterType].ATT, monsters[monsterType].DEF)) {	//胜利
			//获得经验值
			player.Exp += monsters[monsterType].Exp;
			while (player.Exp >= exp_need) {	//升级
				player.Lv++;
				player.Exp -= exp_need;
				exp_need *= player.Lv;
			}
			return true;
		}
		else {	//失败
			MessageBox(hwnd, "你死了", "打不过", MB_ICONWARNING);
			return false;
		}
	}
	return false;
}

bool VS(int playHP, int playATT, int playDEF, int monHP, int monATT, int monDEF){
	while (playHP > 0 || monHP > 0){
		monHP -= playATT < monDEF ? 0 : playATT - monDEF;
		if (monHP < 0)
			break;
		playHP -= monATT < playDEF ? 0 : monATT - playDEF;
	}
	if (playHP > 0) {
		player.HP = playHP;
		return true;
	}
	return false;
}
程序员灯塔
转载请注明原文链接:C/C++游戏开发(easyx框架)回合制——魔塔
喜欢 (0)