一、角色信息的定义与绘制

继障碍物后,重要的就是要把敌人加进来。敌人加进来之后需要与其进行战斗。而战斗则与属性等数值挂钩。我们需要建立侧边栏,实时显示出角色的数值来监测战斗。因此,现在我们的任务是将 SideBar 类实现一部分。

再看一看 SideBar.h:

class SideBar
{std::vector<COperator> operators; // 当前干员COperator currentOperator; // 当前出战的干员int ingot; // 源石锭int cost; // 部署费用
};

注意 COperatorMCharacter 的不同。COperator 是只存在于 SideBar 中的数据,而 MCharacter 是需要实际被绘制在地图上的角色。当 MCharacter 与其他地图元素发生交互时(与敌人战斗,捡到宝物等等),就会将信息返回给 SideBar,由 SideBar 处理结果。

SideBar 的头文件:

#pragma once
#include <vector>
#include "Coperator.h"
class SideBar
{std::vector<COperator*> operators; // 当前干员COperator* currentOperator; // 当前出战的干员unsigned int ingot; // 源石锭unsigned int cost; // 部署费用
public:unsigned int getIngot() { return ingot; }unsigned int getCost() { return cost; }void setIngot(unsigned int i) { ingot = i; }void setCost(unsigned int c) { cost = c; }
};

现在添加一系列绘图函数与变量以将边栏绘制出来。

准备好斯卡蒂的头像 Skadi.bmp:

边栏的材质图片 SideBar.bmp(灰色纯色,测试材质 qwq):

创建句柄:

HBITMAP hSideBar; // 边栏图句柄
HBITMAP hAvatar; // 边栏干员头像

先在 Game_Init() 中加入边栏材质载入的内容:

hAvatar = (HBITMAP)LoadImage(NULL, L"res/Skadi.bmp", IMAGE_BITMAP, CELL_SIZE, CELL_SIZE, LR_LOADFROMFILE);hSideBar = (HBITMAP)LoadImage(NULL, L"res/SideBar.bmp", IMAGE_BITMAP, CELL_SIZE * 6, CELL_SIZE * 12, LR_LOADFROMFILE);

再新建一个 SideBar_Paint() 函数。

VOID SideBar_Paint(HWND hwnd); // 边栏信息的绘制

好的。到这里我发现,绘图的内容太多了。如果每个都一个一个打到 hdc 上去显示,很容易又导致闪烁问题出现。因此这里采用缓冲显示,先将所有内容绘制到缓冲区,再一次性打到 hdc 上。

创建缓冲 DC 和一个默认的位图:

HDC bufDC; // 缓冲DC
HBITMAP bufMap;
...
bufMap = CreateCompatibleBitmap(hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
SelectObject(bufDC, bufMap);

将原来的所有与 hdc 相关的贴图操作都改为 bufDC,然后再在 Game_Paint() 中加一句:

BitBlt(hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, bufDC, 0, 0, SRCCOPY);

这次真的是彻底解决了闪烁问题……

愿人世间再无画面闪烁 qwq

那么可以安心写 SideBar_Paint() 的实现了:

VOID SideBar_Paint(HWND hwnd)
{SelectObject(mdc, hSideBar);BitBlt(bufDC, CELL_SIZE * 12, 0, CELL_SIZE * 6, CELL_SIZE * 12, mdc, 0, 0, SRCCOPY);SelectObject(mdc, hAvatar);BitBlt(bufDC, CELL_SIZE * 12 + CELL_SIZE / 2, CELL_SIZE / 2, CELL_SIZE, CELL_SIZE, mdc, 0, 0, SRCCOPY);
}

现在要绘制文字以显示信息。

但由于源石锭、部署费用这些东西以及文字说明其实都是固定不动的,为了节省资源将他们直接画在图片上,而不再使用 BitBlt().

从代码中大伙都知道了:边栏的大小为:6 倍单元格大小 x 12 倍单元格大小。图片尺寸我们设为 192x384.

SideBar.bmp:

现在,我们将游戏内的文字显示在这上面。

首先加一个表示字体大小的宏:

#define FONT_SIZE 24

Game_Init() 中创建字体:

// 全局变量
HFONT hFont; // 字体句柄
...
// Game_Init()函数
hFont = CreateFont(FONT_SIZE, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, L"微软雅黑");

SideBar_Paint() 中加入字体绘制:

    wchar_t fName[20], fIngots[20], fCosts[20];wsprintf(fName, L"Skadi");wsprintf(fIngots, L"%d", sidebar.getIngot());wsprintf(fCosts, L"%d", sidebar.getCost());TextOut(bufDC, CELL_SIZE * 12 + CELL_SIZE * 1.75, CELL_SIZE, fName, wcslen(fName));

稍微像模像样一点的边栏出现了。

然而,SideBar 类中的 COperator 仍然没有得到使用。现在我们将文件和角色联系起来,创建出与角色挂钩的信息……

新建一个 Operators.hOperators.cpp 用于初始化各个干员。

// Operators.h
#pragma once
#include "COperator.h"void Operator_Init(COperator& op, double hp, double ad, double dp, double mr, AttackType type, double hpg, double dpg, double adg);
void Operators_Init();// Operators.cpp
#include "Operators.h"void Operator_Init(COperator& op, double hp, double ad, double dp, double mr, AttackType type, double hpg, double dpg, double adg)
{op.SetHealthPoint(hp);op.SetAttackDamage(ad);op.SetDefensePoint(dp);op.SetMagicResistance(mr);op.SetAttackType(type);op.SetHealthPointGrow(hpg);op.SetDefensePointGrow(dpg);op.SetAttackDamageGrow(adg);op.SetHealthPointNow(Skadi.getHealthPoint());
}// 主程序源文件
void Operators_Init()
{// Skadi:Operator_Init(Skadi, 1000.0, 100.0, 50.0, 0.0, AttackType::Physical, 400.0, 40.0, 50.0);
}

在主程序中 include 该文件,并在 Game_Init() 中调用 Operators_Init()

总感觉 Game_Init() 越来越臃肿了,背负的东西太多了捏……

设初始的干员堆只有斯卡蒂一人,由此初始化。

接着,我们实现 SideBar 中关于当前干员的操作。

添加一个友元函数 SideBar_Init():

void SideBar_Init()
{sidebar.ingot = 32;sidebar.cost = 10;sidebar.operators.push_back(&Skadi);
}

在主程序中调用这个函数。

对了,还要对每个角色加上角色名这一属性。在 COperator 类中添加 GetName()SetName() 函数,并在 SideBar 类中添加 GetCurrentOperator() 函数。具体内容就不一一展示了(比较简单了吧),其中角色名是 const wchar_t* 类型的。相应的修改一系列初始化函数,最后把 SideBar_Paint() 中的

wsprintf(fName, L"Skadi");

改为

wsprintf(fName, sidebar.GetCurrentOperator()->GetName());

就可以了!

二、干员切换功能

现在我们尝试增加切换干员的功能。

首先在 SideBar 类中添加一个函数用于切换干员:

// .h
bool ShiftOperator();// .cpp
bool SideBar::ShiftOperator()
{if (operators.empty())return false;COperator* tmp = currentOperator;currentOperator = operators.back();operators.push_back(tmp);return true;
}

除此之外,为了让其在地图上的贴图也正确改变,还需要为 COperator 类添加一个变量用于指定贴图 id。

再次修改 SideBar_Init():

void SideBar_Init()
{sidebar.ingot = 32;sidebar.cost = 10;sidebar.currentOperator = &Skadi;gamePlayer.SetID(sidebar.currentOperator->GetID());
}

为 SideBar 类新建一个 ShiftOperator() 函数:

bool SideBar::ShiftOperator()
{if (operators.empty())return false;COperator* tmp = currentOperator;currentOperator = operators.back();operators.push_back(tmp);return true;
}

查 Windows 虚拟键表,将几个常用字母的宏定义定好:

// 虚拟键表宏定义
#define KEYBOARD_E 69
#define KEYBOARD_Q 81
#define KEYBOARD_L 76
#define KEYBOARD_S 83

再在消息处理程序中添加 KEYBOARD_E 的响应事件。

case KEYBOARD_E:sidebar.ShiftOperator(); // 边栏信息修改gamePlayer.SetID(sidebar.GetCurrentOperator()->GetID()); // 地图信息修改break;

函数完成,现在我们再加一个干员 Surtr,其素材:

103.bmp

Surtr.bmp

有点抽象,不过先凑合着测试啦哈哈

Operators_Init() 中:

// Surtr:Operator_Init(Surtr, 800.0, 70.0, 40.0, 15.0, AttackType::Magic, 350.0, 40.0, 48.0, L"Surtr", 103);

按 E 切换干员!

再将干员的四维(生命值,防御力,攻击力,法抗) 显示出来。这里略过了(位图绘制之前写过太多了 qwq)

效果:

从零开始用 Windows C++ 桌面程序制作方舟同人游戏(五)相关推荐

  1. 从零开始用 Windows C++ 桌面程序制作方舟同人游戏(一)

    前言 阅读本博客的前置技能: C++ 基础 好像没了 qwq 为什么开这个坑 很惭愧,虽然每每想要认真的做一个游戏 demo 时,我要么只是停留在了纸面描述上,要么只是建了几个新类,用一个又一个框架/ ...

  2. 【原创游戏】合金弹头S——Unity制作的同人游戏

    --纪念合金弹头陪伴的童年,回味横版过关射击快感 合金弹头S是一款Unity制作的同人游戏,由于当时我只是一个学了3个月游戏的同学,所以尚有一些不足之处,但这是我用Unity做的第一个原创作品 下载地 ...

  3. Go实战--使用golang开发Windows Gui桌面程序(lxn/walk)

    生命不止,继续 go go go!!! golang官方并没有提供Windows gui库,但是今天还是要跟大家分享一下使用golang开发Windows桌面程序,当然又是面向github编程了. 知 ...

  4. windows之桌面程序引导功能

    文章目录 一.首先是获取桌面窗口句柄 二.获取桌面图标位置 三.效果展示 经常使用windows系统的同学可能都会遇到这样一种情况,刚按照完的应用程序,可能会在桌面产生一个提示信息,指示当前快捷方式可 ...

  5. 基于Windows的桌面程序——记事本的制作

    1.新建项目 启动Visual Studio .NET ,在"文件"菜单上,指向"添加",然后单击"新建项目"打开"新建项目&qu ...

  6. 【android】从零开始学习安卓录制回放程序制作需要多少天?

    文章目录 序 功能需求 总结 编写目标程序 测试程序编写 测试程序界面代码 Xposed学习 夜神模拟器下载安装 测试程序Hook思路 hook EditText hook click listene ...

  7. windows下安装程序制作

    引用链接: https://blog.csdn.net/signjing/article/details/7855855 工具: 1.脚本编辑工具 hmnisedit_downcc.zip 百度云盘链 ...

  8. Windows下Qt程序打包

    Windows下Qt程序打包 将windeployqt.exe 目录添加到系统环境变量 windeployqt.exe目录如下: 命令行打包 1.打开命令行 2.执行打包命令 windeployqt ...

  9. .net Windows服务程序和安装程序制作图解

    最近项目中用到window服务程序,以前没接触过,比较陌生,花了两天的时间学习了下,写了个简单的服务,但在制作安装程序的时候,参照网上很多资料,却都制作不成功,可能是开发环境或项目配置的不同,这里把自 ...

  10. python卸载_如何为Python程序制作Windows安装包?

    我们使用Python可以编写很多提高工作和学习效率的小工具,在编写完之后,如果我们想将其分享给更多的人使用,那么最便捷的方法就是将其打包为可执行程序. 在Windows环境下,我们使用Pyinstal ...

最新文章

  1. golang:mime.Decode、mime.DecodeHeader
  2. 八十九、Python的GUI系列 | 使用PyQt5 快速构建一个GUI 应用
  3. Minimum Diameter Tree
  4. 小米12系列或首发2亿像素主摄:配原生1英寸超大底
  5. H3C 常用信息查看命令
  6. IIS出现 分析器错误消息: 在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的...
  7. read.table--R语言
  8. 这 10 个 Python 可视化工具,你用过哪些?
  9. 模拟器打开开发者模式
  10. oracle的档案软件,思源档案管理系统(WEB版)
  11. 微信公众平台、微信开放平台、微信商户平台的区别
  12. 12306刷票工具(简单易学)
  13. 快手Android一面复盘
  14. (29)Verilog实现倍频【方法二】
  15. PCL函数库摘要——3D点云特征描述与提取
  16. 怎么维护linux环境,Linux系统是如何维护时间的
  17. 驱动程序开发:基于ICM20608六轴传感器 --- 使用Regmap API 的 SPI 读取数据 之 IIO驱动
  18. 仓储委外加工/周转加工
  19. 剑网3哪5区人哪个服务器最多,剑网3哪个区服人最多?只有选对了游戏区才能体会到多人的乐趣...
  20. android alarmmanager 收不到广播,关于安卓AlarmManager定时会失效的问题,请指点

热门文章

  1. 支付宝小程序开发笔记
  2. python爬取b站番剧链接,Scrapy爬虫爬取B站视频标题及链接
  3. 如何修改文件格式(win11)
  4. ps换证件照背景颜色
  5. 企业微信聊天记录如何转移到新手机上?
  6. Python中具有不确定个数参数的函数
  7. 服务器光纤存储系统,光纤存储服务器 配置
  8. MDK5中F103C8T6的RCC时钟配置时指向RCC_AHB1PeriphClockCmd但报错identifier “RCC_AHB1Periph_GPIOB is undefined的解决
  9. 方案分享丨基于海思Hi3519智能 IP 摄像机解决方案
  10. 虚拟机win7装oracle,大神教你win7系统安装Oracle VM VirtualBox虚拟机的处理教程