从零到屎山系列-游戏开发(Day2)

2024-05-05 07:04
文章标签 开发 系列 游戏 day2 零到

本文主要是介绍从零到屎山系列-游戏开发(Day2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

这次就来一个比较简单的小游戏贪吃蛇

贪吃蛇

游戏规则就是一串珠子不断的移动,碰到场景里面的食物变长一点,碰到墙壁游戏结束。

开始动手

设计绘制设备

首先我计划从一个控制台游戏开始,需要一个控制台下的绘图机制,希望是在一个网格上面可以根据输入坐标来显示各种元素。就像下图这样,每个方块或者圆圈就好比是一个像素,我们可以通过坐标位置来控制像素绘制的位置,通过输入每个像素的属性来控制画出来的是方块还是圆圈还是空白。

首先定义好每个像素快的属性,属性中有两个描述,一个是颜色,一个是图案类别,目前我们有三种,分别是方块,圆圈和空白。定义如下。

enum PixelColor
{White = 0
};enum PixelType
{None = 0,Square,Circle,
};struct ScreenAttribute
{PixelType mPixel = PixelType::None;PixelColor mColor = PixelColor::White;
};

然后定义一个虚拟设备(BlockDisplayDevice)负责在控制台绘制东西,如下代码片段,通过向mRenderQueue中输入绘制信息,绘制设备每帧都会通过读取mRenderQueue中的内容填充到mBlockBuffer中,通过mPixelMap来映射最终画在屏幕上的到底是什么字符。

struct RenderElement
{ivec2 mPosition;ScreenAttribute mAttribute;
};class BlockDisplayDevice
{std::vector<std::vector<ScreenAttribute>> mBlockBuffer;std::vector<std::string> mPixelMap = { "  ","■", "●" };std::vector<RenderElement> mRenderQueue;
public:...void Display(){for (auto& block : mRenderQueue){int x = block.mPosition.mX;int y = block.mPosition.mY;if (x < mBlockBuffer.size() && y < mBlockBuffer[x].size()){mBlockBuffer[block.mPosition.mX][block.mPosition.mY] = block.mAttribute;}}for (int i = 0; i < mBlockBuffer.size(); i++){for (int j = 0; j < mBlockBuffer[i].size(); j++){std::cout << mPixelMap[mBlockBuffer[i][j].mPixel];}std::cout << std::endl;}mRenderQueue.clear();}
};

定义游戏元素

游戏元素有三种,蛇、障碍物、食物,这三种元素对于游戏来说都是普通的物件,可以被绘制,也可以有处理逻辑,所以需要一类概念来表示这些物件,这里称之为GameObject,如下代码片段。因为三个物件都是可以被绘制的,所以定义了RenderObject来表示绘制信息,这样就可以在绘制不同物件的时候只需要关注每个物件中的RenderObject中的内容,拿了数据就可以无脑绘制了。

struct RenderObject
{PixelType mPixel = PixelType::None;PixelColor mColor = PixelColor::White;std::vector<ivec2> mPositions;
};class GameObject
{
protected:RenderObject mRenderObject;
public:GameObject() {}RenderObject& GetRenderObject(){return mRenderObject;}
};

然后就可以从这个类派生出我们需要类来表示我们的游戏元素,如下代码片段,Food需要一个position来表示位置,Snake中一个队列来表示蛇,贪吃蛇游戏就是典型的队列数据结构的应用,我们先把更新逻辑放在Update中。至于障碍物目前没有什么功能,所以就先用GameObject基类表示。

class Food : public GameObject
{ivec2 mPosition;
public:...
};class Snake : public GameObject
{std::queue<ivec2> mPositions;bool mNeedGrow = false;
public:...void Update(){// Update logicauto head = mPositions.back();head += ivec2::Right();if (!mNeedGrow)mPositions.pop();mPositions.push(head);mNeedGrow = false;// Update render datamRenderObject.mPositions.clear();int queueSize = mPositions.size();for (int i = 0; i < queueSize; i++){auto pos = mPositions.front();mRenderObject.mPositions.push_back(pos);mPositions.push(pos);mPositions.pop();}}
};

游戏主逻辑

Initialize中把游戏元素都设置好,然后UpdateFrame中每帧都更新,先更新渲染,再更新逻辑,如下代码片段。

class Game
{GameObject mWall;Food mFood;Snake mSnake;
public:Game() {}void Initialize(){auto& wall = mWall.GetRenderObject();wall.mPixel = PixelType::Square;for (int i = 0; i < 30; i++){wall.mPositions.push_back(ivec2(i, 0));wall.mPositions.push_back(ivec2(0, i));wall.mPositions.push_back(ivec2(i, 29));wall.mPositions.push_back(ivec2(29, i));}mSnake.Start();mFood.Start();mFood.SetPosition(ivec2(10, 4));}void UpdateFrame(){BlockDisplayDevice::Instance().AppenndRenderQueue(mWall.GetRenderObject());BlockDisplayDevice::Instance().AppenndRenderQueue(mSnake.GetRenderObject());BlockDisplayDevice::Instance().AppenndRenderQueue(mFood.GetRenderObject());BlockDisplayDevice::Instance().Display();// TODO:Get inputif (mSnake.Collide(mFood.GetPosition())){	mSnake.Grow();}mSnake.Update();mFood.Update();BlockDisplayDevice::Instance().Clear();}
};

初步效果

这次就先实现这么多,还有输入没有实现,目前还没必要搞一个GameObjectManager出来去维护所有的GameObject,但是这里已经做好准备未来会用到。

https://github.com/ARTELE/GameDev.git

这篇关于从零到屎山系列-游戏开发(Day2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961073

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。