无引擎游戏开发(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;
	
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】致远OA webmail.do 任意文件下载 (CNVD-2020-62422)

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

摄影构图:人像摄影和风景摄影的一些建议

写在前面 博文内容涉及摄影中人像摄影和风景摄影的简单介绍《高品质摄影全流程解析》 读书笔记整理理解不足小伙伴帮忙指正 &#x1f603; 生活加油 不必太纠结于当下&#xff0c;也不必太忧虑未来&#xff0c;当你经历过一些事情的时候&#xff0c;眼前的风景已经和从前不一样…

C++ | Leetcode C++题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> twoSum(vector<int>& numbers, int target) {int low 0, high numbers.size() - 1;while (low < high) {int sum numbers[low] numbers[high];if (sum target) {return {low …

前端技术栈三(vue+Axios)

一、Vue 1 基本介绍 1.1 Vue 是什么? Vue (读音 /vjuː/&#xff0c;类似于 view) 是一个前端框架, 易于构建用户界面 Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或项目整合 支持和其它类库结合使用 开发复杂的单页应用非常方便 Vue 是…

海外优青ppt美化_海优ppt录音视频制作

海外优青 优秀青年科学基金项目&#xff08;海外&#xff09;旨在吸引和鼓励在自然科学、工程技术等方面已取得较好成绩的海外优秀青年学者&#xff08;含非华裔外籍人才&#xff09;回国&#xff08;来华&#xff09;工作&#xff0c;自主选择研究方向开展创新性研究&#xf…

在 Visual Studio 2022 (Visual C++ 17) 中使用 Visual Leak Detector

在 Visual C 2022 中使用 Visual Leak Detector 1 问题描述1.1 内存泄漏的困扰和解决之道1.2 内存泄漏检测工具的选择1.3 VLD的现状 2 安装和设置VLD的环境变量2.1 安装VLD文件2.2 VLD安装后的目录和文件说明2.2.1 include子目录说明2.2.2 lib子目录说明2.2.2.1 目录整理 2.2.3…

centOS Stream9配置NAT8网络

首先将VMware关机&#xff0c;添加网络适配器 启动虚拟机&#xff0c;查看ens192是否打开连接 安装的图形化需要查看右上角电源处网卡是否连接 最小化安装一般不会出现未连接的状态 使用ip a 查看 配置网卡文件 cd /etc/NetworkManager/system-connections/cd到当前目录下…

【stm32-新建工程-HAL库版本】

stm32-新建工程-HAL库版本 ■ HAL库版本目录■ Drivers■ Middlewares 文件夹&#xff0c; 同寄存器版本一样。■ Output 文件夹&#xff0c; 同寄存器版本一样。■ Projects 文件夹&#xff0c; 同寄存器版本一样。■ User 文件夹 ■ HAL库版本目录 ■ Drivers ① &#xff0c…

leetcode119 杨辉三角②

给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0 输出: [1]示例 3: 输入: rowIndex 1 输出: [1,1] pub…

【实战指南】SpringBoot结合Zookeeper/Nacos构建Dubbo微服务

1、微服务架构 微服务架构是一种设计复杂应用程序的方法&#xff0c;它提倡将单一应用程序开发为一组小型、独立的服务&#xff0c;每个服务运行在其自己的进程中&#xff0c;并通过轻量级通信&#xff08;通常是HTTP协议&#xff09;进行交互。每个服务都是围绕业务功能构建的…

绘唐3官网体验入口绘唐官网

绘唐3官网体验入口绘唐官网 绘唐3官网体验入口是指进入绘唐3官网的入口。绘唐是一款中国传统绘画软件&#xff0c;绘唐3是绘唐系列的最新版本。通过绘唐3官网&#xff0c;用户可以了解绘唐3的功能特点、下载安装包、查看新闻动态、参与社区讨论等。以下是绘唐3官网的体验入口&…

今年618各云厂商的香港服务器优惠活动汇总

又到了一年618年中钜惠活动时间&#xff0c;2024年各大云服务器厂商都有哪些活动呢&#xff1f;有哪些活动包括香港服务器呢&#xff1f;带着这些问题&#xff0c;小编给大家一一讲解各大知名厂商的618活动有哪些值得关注的地方&#xff0c;如果对你有帮助&#xff0c;欢迎点赞…

Spring Bean详解

Spring Bean作用域 默认情况下&#xff0c;所有的 Spring Bean 都是单例的&#xff0c;也就是说在整个 Spring 应用中&#xff0c; Bean 的实例只有一个 如果我们需要创建多个实例的对象&#xff0c;那么应该将 Bean 的 scope 属性定义为 prototype&#xff0c;如果 Spring 需…

【STM32】矩阵计算器

【STM32】矩阵计算器 资料链接请在文章末尾获取~ 1.说明 使用元器件&#xff1a;stm32f103c8t6最小系统板x1&#xff0c;0.96寸OLED显示屏四角x1&#xff0c;4x4矩阵按键x1; 参考&#xff1a;正点原子有关4脚OLED驱动float型数据的驱动文件&#xff0c;CSDN有关矩阵横向扫描…

【LeetCode:394. 字符串解码 + 栈 | 递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

SpringMVC 写个 HelloWorld

文章目录 一、SpringMVC简介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特点 二、HelloWorld1、开发环境2、创建maven工程a>添加web模块b>打包方式&#xff1a;warc>引入依赖 3、配置web.xmla>默认配置方式b>扩展配置方式 4、创建请求控制器5、创建springMVC…

NoMaD: Goal Masked Diffusion Policies for Navigation and Exploration

引言 机器人学习的背景和挑战 本文的研究重点 现有方法的局限性 本文的创新点 相关工作 事先准备 视觉目标条件策略 ViNT在目标条件导航中表现出最先进的性能&#xff0c;但它不能执行无方向探索&#xff0c;需要外部的子目标建议机制。Nomad扩展了Vint&#xff0c;同时支持目…

HMI之王 STM32H7S7

还要什么自行车啊 感谢原厂精彩培训和慷慨赠板&#xff01; 以下列示几个关注的点&#xff0c;计划做成系列&#xff0c;随缘更新&#xff0c;尽量填。 0&#xff09;1024*600分辨率配5寸触屏&#xff1b;Type-C with USB 2.0 HS interface, dual‑role‑power 终于不用2根线…

读AI新生:破解人机共存密码笔记06人工智能生态系统

1. 深蓝 1.1. “深蓝”的胜利虽然令人印象深刻&#xff0c;但它只是延续了几十年来显而易见的趋势 1.2. 国际象棋算法的基本设计是由克劳德香农在1950年提出的 1.2.1. 这一基本设计在20世纪60年代初实现了重大改进 1.2.2. 最优秀的国际象棋程序的等级评分稳步提高&#xff…

tedsign vue3 web-端框架中封装一个验证码组件 以及对应node 接口逻辑说明

一个这样的组件 我直接上代码了 <template><t-loading size"small" :loading"loading" show-overlay><div class"container" click"refresh"><div v-if"svg" class"svg" v-html"svg&…