C++绘制游戏世界(享元模式实例)

一、定义

享元模式的定义:
运用共享技术来有效的支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
享元模式主要包含以下角色:
(1)抽象享元角色:所有具体享元类的基类,为具体享元规范需要实现的公共接口。
(2)具体享元角色:实现抽象享元角色中所规定的的接口。
(3)非享元角色:是不可以共享的外部状态。
(4)享元工厂角色:负责创建和管理享元角色。
其结构如下图所示:
在这里插入图片描述该部分主要参考:享元模式(详解版),详情请点击该链接。

二、创建世界功能

如果我们希望创建一个游戏世界,那个可以能会有草地、丘陵、河流等很多地形。为了方便我们便基于区块来建立地形表:将世界划分为由微小区块组成的巨大网格,每个区块都被一种地形覆盖。
地形有以下特性:
(1)移动开销
(2)是否可通行
(3)用于渲染的纹理。
由此,我们直接声明一个Terrain类,来保存这些数据。

在创建地形表的时候,如果我们选择1000*1000的地形,为每个位置都创建一个地形对象,便会占用大量的时间和内存(创建对象消耗的时间)。此外,我们可以发现这些创建的地形对象大部分都是重复的,其唯一的区别是地形在哪里。使用享元的术语来说,就是地形的所有状态都是“上下文无关的”。因此对于这些地形对象,我们进行共享。使用享元模式和不使用享元模式的性能差距还是很大的。

我们计算一下使用享元模式和不使用享元模式,64位系统下,100*100的地图的花销上的不同
如:
共有部分介绍:
Terrain类的三个属性分别为int、bool、char三种类型,其大小为:8字节。
创建一个Terrain对象,要0.01ms。
地形表中有10000个指针,总大小为:80000字节。
不使用享元模式:
创建10000个对象,占用内存:80000字节,时间消耗:100ms
使用享元模式:
由于本文中只有三种地形,因此只需3个对象,占用内存:24字节,时间消耗:0.03ms。

可以看见在100100的地图上,使用享元和不使用享元的差距都如此之大,如果是10001000的地图呢?10000*10000呢?

详情请点击以下链接:
游戏设计模式-享元模式

三、具体代码实现

3.1、前置准备

导入头文件和设置地图大小。

/*
作者:lbb
版本:v0.1
更改时间:2021/10/21
*/
#include<iostream>
//世界大小
const int HEIGHT=10;
const int WIDTH=20;

3.2、地形类

声明三个属性特性,提供获取属性函数。具体享元类。


//地形类
class Terrain{
    
    
	public:
	//构造函数
	Terrain(int movementCost,bool isWater,const char texture):movementCost_(movementCost),isWater_(isWater),texture_(texture){
    
    }
	//获取属性函数
	int GetMovementCost(){
    
    return movementCost_;}
	int IsWater() const {
    
    return isWater_;}
	const char& GetTexture()const{
    
    return texture_;}
	private:
	int movementCost_;//移动花费
	bool isWater_;//是否是墙
	char texture_;//贴图
};

3.3、世界类

初始化三种地形,随机生成世界地形,存储地形表。变相的享元工厂类。


//世界类
class World{
    
    
	public:
	//创建时初始化三种地形
	World():grassTerrain_(1,false,' '),
		hillTerrain_(2,false,'^'),
		riverTerrain_(3,true,'w')
	{
    
    
		GenerateTerrain();
	}
	//生成世界地形
	void GenerateTerrain();
	//获取(x,y)的地区
	const Terrain& GetTile(int x,int y)const;
	private:
	Terrain grassTerrain_;//草原地形
	Terrain hillTerrain_;//丘陵地形
	Terrain riverTerrain_;//河流地形
	Terrain* tiles_[HEIGHT][WIDTH];//世界地形数组

};
void World::GenerateTerrain(){
    
    
	for(int i=0;i<HEIGHT;i++)
	{
    
    
		for(int j=0;j<WIDTH;j++)
		{
    
    
			if(rand()%10==0){
    
    
				tiles_[i][j]=&hillTerrain_;
			}
			else{
    
    
				tiles_[i][j]=&grassTerrain_;
			}
		}
	}
	int i=rand()%HEIGHT;
	for(int j=0;j<WIDTH;j++)
	{
    
    
		tiles_[(i-1)%HEIGHT][j]=&riverTerrain_;
		tiles_[i][j]=&riverTerrain_;
		tiles_[(i+1)%HEIGHT][j]=&riverTerrain_;
	}
}
const Terrain& World::GetTile(int x,int y) const{
    
    
	return *tiles_[x][y];
}

3.4、主函数

输出游戏世界

int main(void)
{
    
       
	World myWorld;
	//输出世界
	for(int i=0;i<HEIGHT;i++)
	{
    
    
		for(int j=0;j<WIDTH;j++)
		{
    
    

			std::cout<<myWorld.GetTile(i,j).GetTexture();
		}
		std::cout<<std::endl;
	}
	return 0;

}

四、输出结果

输出截图如下:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41487299/article/details/120923247
今日推荐