无引擎游戏开发(2):最简游戏框架 | EasyX制作井字棋小游戏I

一、EasyX中的坐标系

不同于数理中的坐标系,EasyX中的y轴是竖直向下的

二、渲染缓冲区

之前的程序添加了这三个函数改善了绘图时闪烁的情况:

小球在"画布“上移动的过程就是我们在调用绘图函数,这个”画布“就是渲染缓冲区,先绘制的内容可能被后面绘制的内容覆盖掉,所以调用cleardevice()函数,相当于用当前背景颜色覆盖画布实现”清屏“。小球”闪烁“的原因在于,绘制过程并不是一瞬间,而是”逐渐“发生的,先前绘制的小球被不断清除,而人眼同时观察到”绘制“与”清除“,所以有种”闪烁“的感觉。

而在调用BeginBatchDraw函数后,EasyX会为我们新建一个画布(渲染缓冲区):

这个缓冲区是默认不可见的,后面进行的所有绘图操作都会绘制在新的画布上:

而在调用FlushBatchDraw或EndBatchDraw函数时EasyX会将前后两个缓冲区进行快速对调:

所以我们将不会再看见在一张画布上由于绘图频繁而导致的”闪烁“。

三、游戏框架

在之前程序中我们运用了死循环来阻塞程序来防止窗口退出,同时在循环中不断执行清屏和绘制操作,这其实已经完成了游戏框架最核心的部分”主循环“,在主循环中不断读取玩家鼠标操作并将这些操作翻译成对数据的处理逻辑,最后再根据现有的逻辑将画面内容绘制出来。也即读取操作——处理数据——绘制画面,在循环中不断执行这些操作便可以完成几乎所有游戏的逻辑设计:

先前代码如下;

#include<graphics.h>int main() {initgraph(1280, 720);int x, y;//BeginBatchDraw();while (1) {ExMessage msg;while (peekmessage(&msg)) {if (msg.message == WM_MOUSEMOVE) {x = msg.x;y = msg.y;}}cleardevice();solidcircle(x, y, 100);//FlushBatchDraw();}//EndBatchDraw();return 0;}

peekmessage这部分就是读取操作:

将读取到的鼠标坐标赋值给先前定义的x、y就是处理数据:

然后solidcircle便是绘制画面。

还有,一开始需要初始化,最后需要释放资源。

四、设计本地环境的井字棋

井字棋共九格,X/O双方先后落子,同一颗棋子斜或竖连成一线则一方获胜,如果棋盘被填满则平局。

依据框架确定设计思路:①读取操作:双方只使用鼠标游玩,所以只需要读取鼠标消息。 ②处理数据:根据数据检测输赢平局情况,以弹窗形式告知,然后退出主循环。③绘制画面:使用line函数绘制直线将画布分割为3 x 3棋盘,绘制X棋子时只需要使用line函数绘制对应网格的对角线即可完成;绘制O棋子时只需要使用circle函数绘制以对应网格中心为圆心的圆即可。除此之外,在棋盘上方给出当前落子类型给予玩家提示。

接下来便是组织游戏的数据结构,可以使用二维数组表示棋盘

数组默认值为‘-’,代表没有棋子。

游戏结束的条件:①某玩家获胜,可能情况有8种—竖行三种、横行三种、斜角两种 ②平局,在没有玩家获胜前提下,数组中没有‘-’默认值。

开始写代码:首先是读取操作创建ExMessage存储消息/peekmessage获取消息

#include<graphics.h>int main() {initgraph(600, 600);ExMessage msg;bool running = true;//加一个控制变量控制循环,想要结束时改成false即可终止循环while (running) {while (peekmessage(&msg)) {}}return 0;}

接下来是数据处理:把数据拿过来进行判断指定棋子玩家是否获胜—创建CheckWin函数,这个函数接受char类型变量并返回布尔值用来检测对应棋子玩家是否满足获胜条件;创建CheckDraw函数,不传入参数返回布尔值来判断是否平局。当检测到玩家获胜,我们调用MessageBox函数弹窗,同时修改主循环控制条件使游戏结束运行。

小插曲:对MessageBox函数的解释

MessageBox函数接收4个参数,分别为父窗口句柄(相当于win系统中用于指向窗口对象的指针,可使用GetHWnd函数获取用来获取当前绘图窗口的句柄)、提示内容、弹窗标题、弹窗样式

接下来就可以编写获胜情况了:

if(CheckWin('X')){MessageBox(GetHwnd(), _T("X玩家获胜"), _T("游戏结束"), MB_OK);running = false;
}
else if(CheckWin('O'){MessageBox(GetHWnd(), _T("O玩家获胜"), _T("游戏结束"), MB_OK);running = false;
}
else if(CheckDraw()){MessageBox(GetHWnd(), _T("平局!"), _T("游戏结束"), MB_OK);running = false;
}

GetHwnd() 获取当前绘图窗口的句柄,_T(" ")决定显示界面输出内容,MB_OK决定显示界面只出现OK按钮。

接下来便是游戏画面的绘制,首先确保开启了批量绘图BeginBatchDraw() + EndBatchDraw(),并且在每次绘图后刷新批量绘图的渲染缓冲区FlushBatchDraw()。随后在每次绘图前清空画面cleardevice()。定义DrawBoard函数绘制棋盘网格。定义DrawPiece函数绘制棋子。定义DrawTipText函数定义当前棋子的文本提示信息。

全局大致框架如下:

#include<graphics.h>bool CheckWin(char c) {}bool CheckDraw() {}void DrawBoard() {}void DrawPiece() {}void DrawTipText() {}
int main() {initgraph(600, 600);ExMessage msg;BeginBatchDraw();bool running = true;while (running) {while (peekmessage(&msg)) {}if (CheckWin('X')) {MessageBox(GetHWnd(), _T("X玩家获胜"), _T("游戏结束"), MB_OK);running = false;}else if (CheckWin('O')) {MessageBox(GetHWnd(), _T("O玩家获胜"), _T("游戏结束"), MB_OK);running = false;}else if (CheckDraw()) {MessageBox(GetHWnd(), _T("平局!"), _T("游戏结束"), MB_OK);running = false;}cleardevice();DrawBoard();DrawPiece();DrawTipText();FlushBatchDraw();}EndBatchDraw();return 0;}

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

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

相关文章

AI在创造音乐

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;其在音乐领域的应用也日益广泛&#xff0c;从音乐生成到声音合成&#xff0c;AI正逐渐成为音乐创作者的有力助手。然而&#xff0c;这一技术的兴起也引发了关于AI是否会毁掉音乐的讨论。以下从几个方面对这一…

【配置】Notion自动化备份到github方案

步骤 打开notion网页&#xff0c;获取到需要的值 token_v2 找到请求getSpaces的 Cookie 值 token_v2 space_id 找到请求getSpaces的响应结果space,如下图&#xff1a; file_token 找个页面点击导出&#xff0c;之后拿到这个配置项 注意&#xff1a;配置项会过期&#xff0c…

基于一种改进熵方法的旋转机械故障诊断模型(MATLAB)

熵的概念起源于热力学&#xff0c;1884年&#xff0c;玻尔兹曼定义熵&#xff0c;用以描述分子热运动的无序性和混乱度。1948年&#xff0c;Shannon在其发表的《AMathematicalTheoryofCommunication》中提出香农熵&#xff0c;首次将“熵”引入信息度量范畴&#xff0c;为信息论…

RK3568技术笔记十三 Ubuntu的编译

Ubuntu文件系统编译 在编译前需要按照前面的方法初始化编译环境&#xff0c;否则会导致编译失败&#xff08;若配置过则无需重复配置&#xff09;。 按下述方法编译的Ubuntu系统&#xff0c;用户名是&#xff1a;dianyu 密码&#xff1a;1 编译Ubuntu&#xff0c;执…

机械臂 CoppeliaSim Simulink联合仿真

实现机械臂在CoppeliaSim&#xff08;以前称为V-REP&#xff09;和Simulink上的联合仿真涉及多个步骤&#xff0c;包括环境设置、模型导入、通信配置、控制算法设计和测试调试。 前期准备 安装软件配置工作环境创建和配置CoppeliaSim场景 导入机械臂模型配置机械臂参数在Simuli…

javafx打包成exe可执行程序

写文章有点累 我做了个视频录制操作流程 把idea的项目迁移到eclipse, 在eclipse中新建项目, 修改pom文件,拷贝对应java文件, 新建一个java类 里面加载自己的javafx启动application修改项目的jdk版本, 拷贝xml 资源文件, 运行程序如果能运行则迁移成功 接下来导出jar包, 拷贝jd…

webp图片格式怎么转换成jpg?值得收藏的四种转换方法介绍!

webp图片格式怎么转换成jpg&#xff1f;在当今数字图像处理领域&#xff0c;新兴的WebP格式以其独特的特性和兼容性&#xff0c;迅速成为备受追捧的图像格式之一&#xff0c;这一格式以其高效的压缩能力和优秀的网络传输速度著称&#xff0c;为网络图像的传输和存储提供了全新的…

【python】基于python聊天工具

目录 一、概述 二、socket通信 2.1 服务器 2.1.1 建立socket类 2.1.2 绑定端口 2.1.3 监听 2.1.4 等待连接 2.2 客户端 2.2.1 连接 2.2.2 发送 2.2.3 接收 三、基于python的聊天程序的流程设计 3.1 服务器端的流程 3.2 客户端的流程 四、基于python的聊天程序的…

Web爬虫-edu_SRC-目标列表爬取

免责声明:本文仅做技术交流与学习... 爬取后,结合暗黑搜索引擎等等进行进一步搜索. edu_src.py import requests, time from bs4 import BeautifulSoup for i in range(1, 20):url fhttps://src.sjtu.edu.cn/rank/firm/0/?page{i}print(f"正在获取第{i}页数据")s …

一种稀疏贝叶斯学习的旋转机械故障诊断方法(MATLAB)

轴承的故障诊断技术是通过检测轴承故障特征信息来判断轴承的具体故障为位置或损伤程度。在轴承发生损坏时&#xff0c;故障特征信息会随着工作时间的增长变得明显。轴承的损坏过程可以分为四个阶段。第一个阶段为损伤初始阶段&#xff0c;轴承故障特征信号一般无法测量。第二个…

SQLite vs MySQL vs PostgreSQL对比总结

开发业务系统时&#xff0c;是绕不开RDBMS&#xff08;关系型数据库&#xff09;的。虽然现在诞生了各种NoSQL的数据库&#xff0c;RDBMS在业务系统中的严谨和优势依然无法取代。 近几年大大小小的项目中&#xff0c;常用的三种RDBMS&#xff08;SQLite&#xff0c;MySQL&#…

基于SSM+Jsp的书店仓库管理系统

摘要&#xff1a;仓库作为储存货物的核心功能之一&#xff0c;在整个仓储中具有非常重要的作用&#xff0c;是社会物质生产的必要条件。良好的仓库布局环境能够对货物进入下一个环节前的质量起保证作用&#xff0c;能够为货物进入市场作好准备&#xff0c;在设计中我们根据书店…

【人工智能】音乐大模型的深入探讨——当机器有了创意,是机遇还是灾难?

&#x1f440;国内外音乐大模型基本情况&#x1f440; ♥概述♥ ✈✈✈如FreeCompose、一术科技等&#xff0c;这些企业专注于开发人工智能驱动的语音、音效和音乐生成工具&#xff0c;致力于利用核心技术驱动文化产业升级。虽然具体公司未明确提及&#xff0c;但可以预见的是…

产业园区空间优化设计的创新实践者

树莓集团在产业园区运营中的空间优化设计方面&#xff0c;通过全面规划与科学布局、绿色智能与可持续发展、个性化定制与灵活多变、创新实践与数字化升级等措施&#xff0c;为企业提供了高品质、高效率的空间环境和服务支持。 一、全面规划与科学布局 明确产业定位&#xff1a…

Nuxt3 实战 (十一):添加路由 Transition 过渡效果和 Loading 动画

页面过渡效果 Nuxt3 利用 Vue 的 组件 在页面和布局之间应用过渡效果。 nuxt.config.ts 文件配置&#xff1a; export default defineNuxtConfig({app: {pageTransition: { name: page, mode: out-in }}, })在页面之间添加过渡效果&#xff0c;在 app.vue 文件中添加以下 CS…

USAD: 多元时间序列的无监督异常检测

USAD: 多元时间序列的无监督异常检测 原创 小王搬运工 时序课堂 2024-06-20 10:43 四川 论文地址&#xff1a;https://dl.acm.org/doi/abs/10.1145/3394486.3403392 论文源码&#xff1a;https://github.com/manigalati/usad 期刊&#xff1a;KDD 20: Proceedings of the 26…

嵌入式开发二十:定时器之基本定时器

定时器是微控制器中的关键外设&#xff0c;用于精确控制时间和事件。通过配置时钟源、预分频器、计数周期和比较值&#xff0c;可以实现各种时间控制任务&#xff0c;如定时中断、PWM生成和时间测量。理解定时器的工作原理和配置方法是嵌入式系统开发中的基本技能。 STM32F407 …

人工智能的头号威胁:投毒攻击

随着掌管数字生活入口的万亿美元俱乐部企业——苹果公司跳入人工智能&#xff08;AI&#xff09;赛道&#xff0c;AI技术民主化的大幕正式拉开&#xff0c;同时也将AI安全问题推向舆论的风口浪尖。 根据瑞银本周一的智能手机调查报告&#xff0c;在中国以外的智能手机用户中&am…

安装MySQL5.7版本步骤遇到问题

方法一&#xff1a;下载zip版本&#xff08;我用的这个&#xff09; 参考视频&#xff08;已收藏&#xff09;&#xff1a;windows安装MySQL5.7_哔哩哔哩_bilibili 下载zip压缩包的MySQL的网址&#xff1a;上面这个视频中有哦。 my.ini文件内容如下&#xff1a; [client] p…

深入了解python装饰器(decorator)

什么是装饰器&#xff1f; 装饰器是 Python 中的一种高级功能&#xff0c;它允许你在不修改现有代码的情况下为函数或方法添加新的行为。装饰器本质上是一个接受函数并返回另一个函数的高阶函数。这使得它们非常适合用于横切关注点&#xff08;如日志记录、权限检查、性能计时…