您的位置:首页 > 编程语言 > C语言/C++

使用C++与SFML编写一个简单的撞球游戏Part5——对象管理

2012-06-28 17:04 1461 查看
这一part,我们将创建一个对象管理器来统一管理我们的对象。

在这个项目里,对象的数目寥寥无几,为什么要那么麻烦创建这个管理器呢?

这是一个关于布局的问题,如果我们正在写一个射击游戏,要管理数以百计的子弹或者敌人时,这个管理器就很有必要了。

废话就少说了,我们将这管理器名为GameObjectManager,其代码如下

GameObjectManager.h

#pragma once
#include "VisibleGameObject.h"

class GameObjectManager
{
public:
GameObjectManager();
~GameObjectManager();

void Add(std::string name, VisibleGameObject* gameObject);
void Remove(std::string name);
int GetObjectCount() const;
VisibleGameObject* Get(std::string name) const;

void DrawAll(sf::RenderWindow& renderWindow);

private:
//键值对关联容器map,键为对象名称,值为对象指针
std::map<std::string, VisibleGameObject*> _gameObjects;

//重载操作符()来得到一个用于清理VisibleGameObject对象内存的函子(functor)
//函子,简单来说是指被当成函数使用的对象,在这里是指GameObjectDeallocator()
struct GameObjectDeallocator
{
void operator()(const std::pair<std::string,VisibleGameObject*> & p) const
{
delete p.second;
}
};
};


GameObjectManager.cpp

#include "stdafx.h"
#include "GameObjectManager.h"

GameObjectManager::GameObjectManager()
{
}

GameObjectManager::~GameObjectManager()
{
//释放map容器里面所有VisibleGameObject对象的内存
std::for_each(_gameObjects.begin(),_gameObjects.end(),GameObjectDeallocator());
}

void GameObjectManager::Add(std::string name, VisibleGameObject* gameObject)
{
//通过一个pair把对象名跟对象添加进容器
_gameObjects.insert(std::pair<std::string,VisibleGameObject*>(name,gameObject));
}

void GameObjectManager::Remove(std::string name)
{
//用容器的find方法查找对象,若找到则释放其内存并清除键名
std::map<std::string, VisibleGameObject*>::iterator results = _gameObjects.find(name);
if(results != _gameObjects.end() )
{
delete results->second;
_gameObjects.erase(results);
}
}

VisibleGameObject* GameObjectManager::Get(std::string name) const
{
//find方法查找对象,找到则返回对象
std::map<std::string, VisibleGameObject*>::const_iterator results = _gameObjects.find(name);
if(results == _gameObjects.end() )
return NULL;
return results->second;

}

int GameObjectManager::GetObjectCount() const
{
return _gameObjects.size();
}

void GameObjectManager::DrawAll(sf::RenderWindow& renderWindow)
{
//把对象添加进游戏场景里面
std::map<std::string,VisibleGameObject*>::const_iterator itr = _gameObjects.begin();
while(itr != _gameObjects.end())
{
itr->second->Draw(renderWindow);
itr++;
}
}


另外Game类也要做出相应的改变

Game.h

#pragma once
//#include "SFML/Window.hpp"
//#include "SFML/Graphics.hpp"
#include "PlayerPaddle.h"
#include "GameObjectManager.h"

class Game
{

public:
static void Start();

private:
static bool IsExiting();
static void GameLoop();

static void ShowSplashScreen();
static void ShowMenu();

//用枚举类型来代替常量表示游戏状态
enum GameState { Uninitialized, ShowingSplash, Paused,
ShowingMenu, Playing, Exiting };

static GameState _gameState;
static sf::RenderWindow _mainWindow;

//static PlayerPaddle _player1;

static GameObjectManager _gameObjectManager;
};


Game.cpp

#include "stdafx.h"
#include "Game.h"
#include "MainMenu.h"
#include "SplashScreen.h"

void Game::Start(void)
{
if(_gameState != Uninitialized)
return;

//设置窗口参数,对于像1024,768这样的常量是不应该以这种形式出现的,
//在之后的文章将会更改
_mainWindow.create(sf::VideoMode(1024,768,32),"BallGame!");

//添加玩家弹板并设置其位置
PlayerPaddle *player1 = new PlayerPaddle();
player1->Load("images/paddle.png");
player1->SetPosition((1024/2)-45,700);

_gameObjectManager.Add("Paddle1",player1);

_gameState = Game::ShowingSplash;

//游戏循环,当游戏状态为Exiting则退出游戏
while(!IsExiting())
{
GameLoop();
}

_mainWindow.close();
}

bool Game::IsExiting()
{
if(_gameState == Game::Exiting)
return true;
else
return false;
}

void Game::GameLoop()
{
sf::Event currentEvent;
//从消息队列里面拿出消息
_mainWindow.pollEvent(currentEvent);

switch(_gameState)
{
case Game::ShowingSplash:
{
ShowSplashScreen();
break;
}
case Game::ShowingMenu:
{
ShowMenu();
break;
}
case Game::Playing:
{
//用黑色填充游戏画面
_mainWindow.clear(sf::Color(0,0,0));

//_player1.Draw(_mainWindow);
_gameObjectManager.DrawAll(_mainWindow);

_mainWindow.display();

if(currentEvent.type == sf::Event::Closed)
{
_gameState = Game::Exiting;
}
if(currentEvent.type == sf::Event::KeyPressed)
{
if(currentEvent.key.code == sf::Keyboard::Escape) ShowMenu();
}
break;
}
}
}

void Game::ShowSplashScreen()
{
SplashScreen splashScreen;
splashScreen.Show(_mainWindow);
_gameState = Game::ShowingMenu;
}

void Game::ShowMenu()
{
MainMenu mainMenu;
MainMenu::MenuResult result = mainMenu.Show(_mainWindow);
switch(result)
{
case MainMenu::Exit:
_gameState = Exiting;
break;
case MainMenu::Play:
_gameState = Playing;
break;
}
}

//此处要手动声明静态变量,不然编译器会报错
Game::GameState Game::_gameState = Uninitialized;
sf::RenderWindow Game::_mainWindow;
//PlayerPaddle Game::_player1;
GameObjectManager Game::_gameObjectManager;


变化不大,请自行对照,最后按F5确认一下吧~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: