C语言魔塔游戏十层

把以前写的魔塔游戏完善了一下

之前的魔塔游戏博客链接:https://blog.csdn.net/qq_41505957/article/details/103138305

代码及所有图片,音乐等资源:https://download.csdn.net/download/qq_41505957/12287289

增加内容如下:

1.增加了背景音乐(其实这个音乐我是不想加的,因为我感觉无所谓)

2.运行之后不会直接开始游戏了,而是有一个选择的画面

N 新的游戏
J  继续游戏
C 游戏说明
E 退出游戏

不同的按键会转换到不同的界面

开始游戏就是重新开始游戏了

继续游戏是当你在游戏过程中有保存过游戏的话,就按照这个进度来玩,如果没有保存过游戏呢,就是重新开始游戏了。

游戏说明就是游戏中的一些按键的操作,本来这个图我是准备做上面那个界面的,但是有点丑,后来我就改了一下,做这个了,反正这个也没人看。

 

3.增加了保存游戏的功能,在游戏中按Q键会跳出是否保存的界面,选择是会保存游戏,之后再次打开游戏的时候可以加载上次的游戏。

4.增加了9层地图,加上第一层一共10层地图,地图真的是难搞,下面是各个数字代表的东西。

0 墙
1 地板
2 蓝门
3 黄门
4 蓝水晶
5 红水晶
6 蓝钥匙
7 红钥匙
8 红药水
9 蓝药水
10 小蝙蝠
11 小巫师
12 小骷髅
13 大骷髅
14 绿史莱姆
15 红史莱姆
 97 下楼梯子
98 上楼梯子
99 玩家

5.增加了玩家可以升级的功能,每次升级所需经验值=当前等级*1000。

6.修复了当我方防御大于敌方攻击的时候,战斗加血的bug,这个bug是由于我的计算减血量等于敌方攻击减我方防御,当敌方攻击

小于我方防御的时候,减的是一个负数,所以就加血了。

 

下面我来说一下我实现的过程和代码

开始游戏时的菜单:

最开始我做的比较简陋,后来就搜了一个图片,然后我用画图软件加了点字,然后把图片贴到画布上就可以了,再写一个函数用来接收键盘的输入,对应不同的键再有不同的处理

背景音乐:

一行代码,非常简单,注意音乐只能是wav格式,如果想要修改,把音乐复制到文件夹中,修改代码中的文件名就行了。如果没有wav格式的音乐,可以在网上搜一下在线MP3转wav。

void Music()
{
	PlaySound(TEXT("1.wav"), 0, SND_FILENAME|SND_ASYNC|SND_LOOP);
}

 

地图的实现:

在最开始写的时候我的地图是存储在二维数组里面的,因为只有一层,所以用二维数组是比较方便的,现在由于增加的地图,而且还要有保存游戏的功能,所以二维数组是不够用的。

新的程序我使用的三维数组,分别代表层数,行,列。同时把地图存储在txt文件中,在开始游戏的时候读取文件中的地图存储在三维数组中。开始游戏的时候调用函数就可以了。

使用C语言中文件的读取功能,代码:

void NewGame()
{
	initPlayer(); //初始化游戏角色信息
	FILE *fp; //读取保存在map.txt中的地图
	fp = fopen("map.txt", "r");
	for(int k=0; k<10; k++)
		for (int i = 0; i < 13; i++)
			for(int j = 0; j < 13; j++)
				fscanf(fp, "%d", &map[k][i][j]);
	fclose(fp);
}

保存游戏

游戏中按Q键可以保存游戏。

保存游戏其实是和地图差不多,在我游戏的过程中三维数组的值是在不断改变的,当我保存游戏的时候,把三维数组中的值保存到txt文件中即可,需要一起保存的还有玩家的各项属性和位置。

void SaveGame()
{
	FILE *fp;
	fp = fopen("keepmap.txt", "w");
	for (int k = 0; k < 10; k++) {
		for (int i = 0; i < 13; i++) {
			for (int j = 0; j < 13; j++)
				fprintf(fp, "%d ", map[k][i][j]);
			fprintf(fp, "\n");
		}
		fprintf(fp, "\n");
	}
	fprintf(fp, "%d\n", playerh);
	fprintf(fp, "%d\n", playerx);
	fprintf(fp, "%d\n", playery);

	fprintf(fp, "%s\n", player.name);
	fprintf(fp, "%d\n", player.HP);
	fprintf(fp, "%d\n", player.MP);
	fprintf(fp, "%d\n", player.DEF);
	fprintf(fp, "%d\n", player.ATT);
	fprintf(fp, "%d\n", player.Lv);
	fprintf(fp, "%d\n", player.Exp);
	fprintf(fp, "%d\n", player.Num_Blue_Key);
	fprintf(fp, "%d\n", player.Num_Yellow_Key);

	fclose(fp);
}

继续游戏

继续游戏可以继续上次的游戏,保存游戏后,即使关闭运行窗口,下次游戏将会重保存游戏的地方开始游戏。继续游戏后会读取keepmap.txt中的地图和人物属性。

void KeepGame()
{
	FILE *fp; //读取保存在keepmap.txt中的地图
	fp = fopen("keepmap.txt", "r");
	for (int k = 0; k < 10; k++)
		for (int i = 0; i < 13; i++)
			for (int j = 0; j < 13; j++)
				fscanf(fp, "%d", &map[k][i][j]);

	fscanf(fp, "%d", &playerh);
	fscanf(fp, "%d", &playerx);
	fscanf(fp, "%d", &playery);

	fscanf(fp, "%s", &player.name);
	fscanf(fp, "%d", &player.HP);
	fscanf(fp, "%d", &player.MP);
	fscanf(fp, "%d", &player.DEF);
	fscanf(fp, "%d", &player.ATT);
	fscanf(fp, "%d", &player.Lv);
	fscanf(fp, "%d", &player.Exp);
	fscanf(fp, "%d", &player.Num_Blue_Key);
	fscanf(fp, "%d", &player.Num_Yellow_Key);
	fclose(fp);
}

上下楼的处理

在上下楼的时候,将会更改整个地图,相应的,人物的位置都将改变,这里我用一个函数来解决这个问题。

我用h代表层数,用0代表这层是下楼梯来的,1代表这层是上楼梯来的,记录上下楼梯的位置,之后就可以对玩家的x和y的坐标进行改变。

//根据不同楼层显示角色的初始位置
void Change(int h, int temp)
{
	switch (h)
	{
		case 0:
			if (temp == 0) {
				playerx = 1;
				playery = 2;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 1:
			if (temp == 1) {
				playerx = 11;
				playery = 10;
				map[playerh][playerx][playery] = 99;
			}
			else {
				playerx = 2;
				playery = 1;
				map[playerh][playerx][playery] = 99;
			}
			break; 
		case 2:
			if (temp == 1) {
				playerx = 7;
				playery = 2;
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 8;
				playery = 10;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 3:
			if (temp == 1) {
				playerx = 11;
				playery = 2;
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 4;
				playery = 11;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 4:
			if (temp == 1) {
				playerx = 11;
				playery = 5;
				
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 1;
				playery = 2;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 5:
			if (temp == 1) {
				playerx = 6;
				playery = 7;
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 4;
				playery = 7;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 6:
			if (temp == 1) {
				playerx = 10;
				playery = 6;
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 2;
				playery = 6;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 7:
			if (temp == 1) {
				playerx = 3;
				playery = 8;
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 3;
				playery = 4;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 8:
			if (temp == 1) {
				playerx = 2;
				playery = 11;
				map[playerh][playerx][playery] = 99;
			}
			else
			{
				playerx = 10;
				playery = 11;
				map[playerh][playerx][playery] = 99;
			}
			break;
		case 9:
			if (temp == 1) {
				playerx = 10;
				playery = 6;
				map[playerh][playerx][playery] = 99;
			}
			
			break;
	}
}

战斗升级

这个没什么好说的,每次战斗结束后调用一下函数就可以了。

void CaLv()
{
	if (player.Exp >= player.Lv * 1000) {
		player.Exp -= player.Lv * 1000;
		player.Lv++;
		player.ATT += 10;
		player.DEF += 10;
		player.HP += 100;
	}

}

修改了bug

一个小错误,在VS函数中加一个小判断

if (playDEF > monATT)
    return 1;

 

部分游戏截图

 

 

注意,如果出现

error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>g:\windows kits\10\include\10.0.17763.0\ucrt\stdio.h(208): note: 参见“fopen”的声明

错误,尝试以下操作:

项目 > 属性>C/C++  --> 预处理器  -->  预处理器定义  添加:_CRT_SECURE_NO_WARNINGS

 

 

 

 

评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张宜强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值