控制台RPG 游戏实现双缓冲无屏闪,玩家类,地图类

 

重整控制台RPG——双缓冲无屏闪以及第一个无中生有的地图类,玩家类_哔哩哔哩_bilibili

是鄙人解说鄙人的代码

#include <iostream>
#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)																// 便于移植到非微软的编译器里 
using namespace std;// 加入的游戏背景数据,通常不修改,放到 Bkmap 进行修改
class Gamemap
{public:Gamemap(int height,int wide){this->wide=wide;this->height=height;this->gamemap=new int*[this->height];for(int i=0; i<height; i++){this->gamemap[i]=new int[this->wide];for(int j=0; j<this->wide; j++){this->gamemap[i][j]=0;}}}~Gamemap();public:int** gamemap;															// 游戏地图数组int wide;																// 游戏长宽int height;
};
// 游戏背景操作网格数组,可以通过坐标直接改
class Bkmap
{public:Bkmap(int height,int wide){this->wide=wide;this->height=height;this->bkmap=new char*[this->height];for(int i=0; i<height; i++){this->bkmap[i]=new char[this->wide];for(int j=0; j<wide; j++){this->bkmap[i][j]='\0';}}}public:char** bkmap;														// 游戏地图操作网格数组int wide;															// 操作网格长宽int height;public:// 测试用,程序闪退,检测当时哪里数组溢出,哪里数据缺失void adddata(){for(int i=0; i<this->height; i++)								// 地图数据写入{for(int j=0; j<this->wide-1; j++){this->bkmap[i][j]='*';}this->bkmap[i][this->wide-1]='\0';							// 截至符号,防止后续粘贴多粘贴其他奇奇怪怪的旧数据}}// 刷新缓冲区,清除之前的数据,防止混合新数据形成奇奇怪怪的bugvoid fresh(Gamemap* gamemap){for(int i=0; i<gamemap->height; i++)								// 地图复印到操作网格区{this->bkmap[i][0]='#';											// 最左侧是边界for(int j=1; j<gamemap->wide; j++){if(gamemap->gamemap[i][j]==0)this->bkmap[i][j]=' ';									// 这里决定地图打印在屏幕的样子}this->bkmap[i][gamemap->wide]='#';								// 设置截断点,防止残留数据this->bkmap[i][gamemap->wide+1]='\0';}for(int j=0; j<gamemap->wide; j++)this->bkmap[gamemap->height][j]='#';							// 底部也有边界线this->bkmap[gamemap->height][gamemap->wide+1]='\0';}};
// 字符串缓冲类
class Showmap
{public:Showmap(int height,int wide){this->showmap=new char[wide*height+1000];strcpy(showmap,"");
//			showmap={};												// 不能这样写,否则报错,指针重新变空}public:char* showmap;												// 显示区缓冲public:// 加入缓冲数据,用于一键打出,多个 cout printf 反而会打印慢,有一行行残影void adddata(Bkmap* bkmap){if(showmap==NULL){cout<<"NULL";cout<<"函数因空指针结束"<<endl;return;}strcpy(showmap,"");										// 清空旧数据 ,实际上是把标志位放到开头,保证从头粘贴数据for(int i=0; i<bkmap->height; i++)						// 选区加入到打印缓冲区{strcat(showmap,bkmap->bkmap[i]);strcat(this->showmap,"\n");}}// 一键显示到屏幕void show(){cout<<this->showmap;}
};// 玩家类,移动,攻击,地图修改
class Player
{public:Player(int x,int y,int limity,int limitx){this->playerx=x;this->playery=y;is_atk=0;is_buff=0;flag_x=0;flag_y=0;this->limitx=limitx;this->limity=limity;}~Player();public:char player='1';int playerx;int playery;int flag_x;int flag_y;int limitx;int limity;int is_atk;int is_buff;public://玩家移动检测void checkmove(HWND hwnd){flag_x=0;flag_y=0;if (KEY_DOWN_FOREGROUND(hwnd, 0x41))			// A{flag_x -= 1;}if (KEY_DOWN_FOREGROUND(hwnd, 0x57))			// W{flag_y -= 1;}if (KEY_DOWN_FOREGROUND(hwnd, 0x44))			// D{flag_x += 1;}if (KEY_DOWN_FOREGROUND(hwnd, 0x53))			// S{flag_y += 1;}}// 打包速度检测void checkspeed(){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;}// 改变玩家位置void move(){if (flag_x)															// 位移改变playerx += flag_x;if (flag_y)playery += flag_y;}
//		边界检测void checkboundary(){if (playerx >= limitx)												// 角色位置限制playerx = limitx - 1;else if (playerx < 0)												// 左侧边界,可以修改成 1 这样就不会进入栅栏,和'#’重叠了playerx = 0;if (playery >= limity)playery = limity - 1;else if (playery < 0)playery = 0;}void putinmap(Bkmap* bkmap){bkmap->bkmap[playery][playerx]=player;}
//		检测攻击void checkatk(HWND hwnd){if (is_atk == 0 ){if( KEY_DOWN_FOREGROUND(hwnd, 0x4A))			// j 键攻击is_atk = 1;else if(KEY_DOWN_FOREGROUND(hwnd,0x31))			// 1 键攻击is_atk=2;}}
//		检测buffvoid checkbuff(HWND hwnd){if (is_buff == 0 && KEY_DOWN_FOREGROUND(hwnd, 0x4B))		// k 键增加范围 buff{is_buff = 1;}}// 绘制地图void drawmap(HWND hwnd,Gamemap* gamemap){if (KEY_DOWN_FOREGROUND(hwnd, 0x30))								// 0 键绘制地图gamemap->gamemap[playery][playerx] = 0;if (KEY_DOWN_FOREGROUND(hwnd, 0x36))								// 6 键绘制地图gamemap->gamemap[playery][playerx] = 6;if (KEY_DOWN_FOREGROUND(hwnd, 0x37))								// 7 键绘制地图gamemap->gamemap[playery][playerx] = 7;if (KEY_DOWN_FOREGROUND(hwnd, 0x38))								// 8 键绘制地图gamemap->gamemap[playery][playerx] = 8;if (KEY_DOWN_FOREGROUND(hwnd, 0x39))								// 9 键绘制地图gamemap->gamemap[playery][playerx] = 9;}
};
// 攻击类,这里直线攻击做测试
class Aking
{public:Aking(int height,int wide,int atk_time,int number){this->height=height;this->wide=wide;this->number=number;this->atk_time=atk_time;atk_count=0;}public:int height;																// 攻击范围长宽int wide;int number;																// 攻击序号,因为有多个攻击技能,所以编号,可以查找攻击int atk_time;															// 攻击时长int atk_count;															// 当前攻击持续时间public:// 攻击中void atking(Bkmap* bkmap,Player* player){if (atk_count != atk_time)										// 攻击{atk_count++;for(int j=0; j<10; j++){bkmap->bkmap[player->playery][player->playerx+1+j]='P';}}else{atk_count=0;player->is_atk=0; 												// 玩家状态复位}}
};
// 攻击类v2继承之前的攻击类,这里做范围攻击做测试
class Akingv2:public Aking
{public:Akingv2(int height,int wide,int atk_time,int number):Aking( height,wide,atk_time,number){this->height=height;this->wide=wide;this->number=number;this->atk_time=atk_time;atk_count=0;}public:void atkingv2(Bkmap* bkmap,Player* player){if (atk_count != atk_time)										// 攻击{atk_count++;for(int i=0; i<10; i++)for(int j=0; j<10; j++){bkmap->bkmap[player->playery-5+i][player->playerx+1+j]='P';}}else{atk_count=0;player->is_atk=0; 												// 玩家状态复位}}
};int main()
{Gamemap* gamemap = new Gamemap(20,50);Bkmap* bkmap=new Bkmap(20+3,50);Showmap* showmap= new Showmap(20,80);Aking* ak = new Aking(10,1,12,1);										// 直线攻击,长 10 宽 1 持续时间 12 次循环,序号是1Akingv2* akv2 = new Akingv2(10,1,12,2);Player* player = new Player(0,0,20,50);bkmap->fresh(gamemap);
//	bkmap->adddata();														// 测试数据 改bug 测试用showmap->adddata(bkmap);
//	showmap->show();HWND hwnd = GetForegroundWindow();										// 获取前端窗口句柄,由于程序刚运行时是在前端,所以这就是本程序的窗口句柄//获取默认标准显示缓冲区句柄HANDLE hOutput;COORD coord= {0,0};hOutput=GetStdHandle(STD_OUTPUT_HANDLE);//创建新的缓冲区HANDLE hOutBuf = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,CONSOLE_TEXTMODE_BUFFER,NULL);//设置新的缓冲区为活动显示缓冲SetConsoleActiveScreenBuffer(hOutBuf);//隐藏两个缓冲区的光标CONSOLE_CURSOR_INFO cci;cci.bVisible=0;cci.dwSize=1;SetConsoleCursorInfo(hOutput, &cci);SetConsoleCursorInfo(hOutBuf, &cci);//双缓冲处理显示DWORD bytes=0;char data[4900];while(1){if (KEY_DOWN_FOREGROUND(hwnd, VK_ESCAPE)){printf("游戏退出\n");break;}player->checkmove(hwnd);											// 移动按键检测player->checkatk(hwnd);												// 攻击按键检测player->checkspeed();												// 速度检测player->move();														// 玩家移动player->checkboundary();											// 边界检测bkmap->fresh(gamemap);												// 清空操作网格区数据player->putinmap(bkmap);											// 玩家位置写入操作网格区switch (player->is_atk) 											// 攻击选择方式{case 1:ak->atking(bkmap,player);									// 攻击写入操作网格区break;case 2:akv2->atkingv2(bkmap,player);break;}cout<<"冲冲冲"<<endl;showmap->adddata(bkmap);											// 操作网格区写入显示缓冲区
//		system("cls");														// 双缓冲时,去除清屏命令cout<<"玩家位置:"<<player->playerx<<","<<player->playery<<endl;showmap->show();cout<<endl;cout<<endl;cout<<endl;cout<<endl;															// 用于顶到顶部,把一些奇奇怪怪的数据顶出屏幕Sleep(50);ReadConsoleOutputCharacterA(hOutput, data, 4900, coord, &bytes);SetConsoleTextAttribute(hOutBuf, FOREGROUND_INTENSITY | FOREGROUND_RED);WriteConsoleOutputCharacterA(hOutBuf, data, 4900, coord, &bytes);cout<<"测试数据位置。";}return 0;}

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

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

相关文章

Stable diffusion 加载扩展列表报错解决方法

项目场景&#xff1a; 在使用Stable diffusion webui时&#xff0c;使用扩展列表出现错误 问题描述 点击loadfrom后&#xff0c;出现加载扩展列表报错 原因分析&#xff1a; 下载的扩展的时候&#xff0c;都是github 的url&#xff0c;需要科学上网&#xff0c;如果不能科学…

【MySQL】聚合函数和分组聚合

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习计网、mysql和算法 ✈️专栏&#xff1a;MySQL学习 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac…

AttributeError: module ‘wandb‘ has no attribute ‘init‘解决办法

安装对应的库 pip install wandb -i https://pypi.tuna.tsinghua.edu.cn/simple拓展——wandb是什么模块&#xff0c;有什么作用 wandb是一个用于跟踪、可视化和协作机器学习项目的工具。它提供了许多功能&#xff0c;包括实时的指标跟踪、超参数调整、模型的可视化等&#x…

MongoDB 启动异常

Failed to start up WiredTiger under any compatibility version. 解决方案: 删除WiredTiger.lock 和 mongod.lock两个文件&#xff0c;在重新启动。回重新生成新的文件。

传输层 --- UDP

目录 1. 传输层是什么呢&#xff1f; 2. 再谈端口号 2.1. 端口号是什么 2.2. 协议号是什么 2.3. 认识知名端口号 2.4. 端口号的相关问题 2.4.1. 一个进程可以绑定多个端口号吗&#xff1f; 2.4.2. 一个端口号可以被多个进程绑定吗&#xff1f; 2.4.3. 为什么不使用P…

【学习】渗透测试有哪些重要性

随着信息技术的迅猛发展&#xff0c;网络安全问题日益凸显。渗透测试作为网络安全防御的重要手段之一&#xff0c;旨在模拟黑客攻击&#xff0c;发现并修复潜在的安全漏洞&#xff0c;提高网络系统的安全性。本文将介绍渗透测试的概念、重要性、实施步骤及实践案例&#xff0c;…

黑盒测试—场景测试法

场景测试法是一种通过模拟真实用户使用场景来验证软件系统的功能、性能和安全性的方法。 就是模拟多个实际场景会产生的多种结果&#xff0c;将实际场景进行组合&#xff0c;并推测组合后会产生的结果。 例题&#xff1a; 以ATM机存款业务&#xff0c;来设计场景法设计测试用例…

Makefile:make install的实现(十一)

1、make install的概念 在Linux环境下有些时候软件或者服务会通过源码安装&#xff0c;执行一些make、make install、make clean的指令。例如&#xff1a;redis make&#xff1a;编译所有的文件、生成一些动态库、静态库、可执行程序等等make install&#xff1a;通常会创建一个…

BTN7960B 电机驱动芯片 TO-263-7 智能车驱动器

BTN7960B是一种半桥式驱动器&#xff0c;适用于直流刷式电机。它具有高侧和低侧MOSFET驱动器&#xff0c;可以操控电机的正转和反转。此外&#xff0c;它还具有过流保护、欠压确定和热关断等功能&#xff0c;以保证体系在各种工作条件下的安全和安稳运转。 制造商: Infineon…

绿联 安装zfile,创建属于自己的网盘,支持直链分享

绿联 安装zfile&#xff0c;创建属于自己的网盘&#xff0c;支持直链分享 1、镜像 zhaojun1998/zfile:latest ZFile ZFile 是一个适用于个人的在线网盘(列目录)程序&#xff0c;可以将你各个存储类型的存储源&#xff0c;统一到一个网页中查看、预览、维护&#xff0c;再也不用…

C++ 标准库类型stackqueue

C/C总述&#xff1a;Study C/C-CSDN博客 栈与队列详解&#xff08;数据结构&#xff09;&#xff1a;栈与队列_禊月初三-CSDN博客 stack&#xff08;栈&#xff09; stack的常用函数 函数说明功能说明stack()构造空栈push(T& val)将元素val压入栈中size()返回栈中元素个…

面经分享(Flask,轻量级Web框架)

1. Flask的核心特点 a. 轻量级&#xff1a;核心简洁&#xff0c;只提供了基本的功能&#xff0c;其他高级功能可以通过插件或扩展来添加。 b. 灵活性&#xff1a;允许开发者选择适合自己项目的组件和工具&#xff0c;没有强制的项目结构和设计模式。 c. 易于扩展&#xff1a;提…

HTML:框架

案例&#xff1a; <frameset cols"5%,*" ><frame src"left_frame.html"><frame src"right_frame.html"> </frameset> 一、<frameset>标签 <frameset>标签&#xff1a;称为框架标记&#xff0c;将一个HTML…

mysql 判断一张表是否存在的方法

查询表是否存在 使用 SHOW TABLES SHOW TABLES LIKE %tbl_tabl%;结果: 查询 INFORMATION_SCHEMA // like 匹配 SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA test AND TABLE_NAME like %tbl%; // 完全匹配 SELECT TABLE_NAME FROM INFORMATION_SC…

element UI中设置图片的高度并支持PC和手机自适应

系列文章目录 一、elementui 导航菜单栏和Breadcrumb 面包屑关联 二、elementui 左侧导航菜单栏与main区域联动 三、elementui 中设置图片的高度并支持PC和手机自适应 四、elementui 实现一个固定位置的Pagination&#xff08;分页&#xff09;组件 文章目录 系列文章目录…

《Java面试自救指南》(专题二)计算机网络

文章目录 力推的计网神课get请求和post请求的区别在浏览器网址输入一个url后直到浏览器显示页面的过程常用状态码session 和 cookie的区别TCP的三次握手和四次挥手七层OSI模型&#xff08;TCP/IP协议模型&#xff09;各种io模型的知识http协议和tcp协议的区别https和http的区别…

【Unity每日一记】如何让Sprite精灵图集的背景图层变成透明,方便切割

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

Pygame基础10-物理模拟

PyMunk PyMunk是一个模拟物理的库。 注意&#xff0c;PyMunk只是进行物理模拟&#xff0c;不包含可视化的功能。如果需要可视化&#xff0c;可使用pygame等库。 可用pip安装pymunk pip install pymunk pymunk中的概念&#xff1a; space&#xff1a; 物理空间。 包含gravity 模…

AJAX —— 学习(一)

目录 一、原生 AJAX &#xff08;一&#xff09;AJAX 介绍 1.理解 2.作用 3.最大的优势 4.应用例子 &#xff08;二&#xff09;XML 介绍 1.理解 2.作用 &#xff08;三&#xff09;AJAX 的特点 1.优点 2.缺点 二、HTTP 协议 &#xff08;一&#xff09;HTTP 介…

C语言中的结构体:揭秘数据的魔法盒

前言 在C语言的广阔天地中&#xff0c;结构体无疑是一颗璀璨的明珠。它就像是一个魔法盒&#xff0c;能够容纳各种不同类型的数据&#xff0c;并按我们的意愿进行组合和排列。那么&#xff0c;这个魔法盒究竟有何神奇之处呢&#xff1f;让我们一探究竟。 一、结构体的诞生&…