简介
Game Programming Patterns,游戏编程模式,大致看完了点,记录一下,以后再看再次深入学习时再补充,电子书地址。
命令模式
译者原话:“命令是具现化的方法调用”。意味着将概念变成数据 ——一个对象——可以存储在变量中,传给函数。 所以称命令模式为“具现化方法调用”,意思是方法调用被存储在对象中。听起来像是回调
命令模式是一种回调的面向对象实现。
function makeMoveUnitCommand(unit, x, y) {
// 这个函数就是命令对象:
return function() {
unit.moveTo(x, y);
}
}
//行动以及撤销
function makeMoveUnitCommand(unit, x, y) {
var xBefore, yBefore;
return {
execute: function() {
xBefore = unit.x();
yBefore = unit.y();
unit.moveTo(x, y);
},
undo: function() {
unit.moveTo(xBefore, yBefore);
}
};
}
更多的使用回调函数实现,将方法封装好
在按键控制角色移动跳跃等按键控制上 可以实现更多的自定义 而不是很多的绑定,每一个按键的事件都是一个回调
原型模式
三个怪物,基本,弓兵,长矛兵
不用建一个怪物基类,然后下面创建三种
而是在基本兵的基础上,衍生出弓兵与长矛兵,以基本兵为原型
单例模式
游戏中,很多例如声音,声音管理器,特效,特效管理器,模型,模型管理器等
很多的管理器都成了单例类
例如,一个子弹,子弹管理器
class Bullet
{
public:
int getX() const { return x_; }
int getY() const { return y_; }
void setX(int x) { x_ = x; }
void setY(int y) { y_ = y; }
private:
int x_, y_;
};
class BulletManager
{
public:
Bullet* create(int x, int y)
{
Bullet* bullet = new Bullet();
bullet->setX(x);
bullet->setY(y);
return bullet;
}
bool isOnScreen(Bullet& bullet)
{
return bullet.getX() >= 0 &&
bullet.getX() < SCREEN_WIDTH &&
bullet.getY() >= 0 &&
bullet.getY() < SCREEN_HEIGHT;
}
void move(Bullet& bullet)
{
bullet.setX(bullet.getX() + 5);
}
};
子弹需要管理器嘛
class Bullet
{
public:
Bullet(int x, int y) : x_(x), y_(y) {}
bool isOnScreen()
{
return x_ >= 0 && x_ < SCREEN_WIDTH &&
y_ >= 0 && y_ < SCREEN_HEIGHT;
}
void move() { x_ += 5; }
private:
int x_, y_;
};
这样直接就可以了
单例有时候会增加其他类的代码量,最好的是OOP(对象自己管理好自己)
所以,游戏中很多的声音管理器,特效管理器,模型管理器等等,可以都放到一个Game管理器中,通过这个game来获取每一个管理器下方法
class Game
{
public:
static Game& instance() { return instance_; }
// 设置log_, et. al. ……
Log& getLog() { return *log_; }
FileSystem& getFileSystem() { return *fileSystem_; }
AudioPlayer& getAudioPlayer() { return *audioPlayer_; }
private:
static Game instance_;
Log *log_;
FileSystem *fileSystem_;
AudioPlayer *audioPlayer_;
};
Game::instance().getAudioPlayer().play(VERY_LOUD_BANG);
观察者模式
观察者模式,也就mvc架构,C#将其嵌入了语法event
例如游戏中的成就系统,要是摸个环节达成成就 就调用成就 这样就太乱了
成就单独分隔开
//观察者 监听
class Observer
{
public:
virtual ~Observer() {}
virtual void onNotify(const Entity& entity, Event event) = 0;
};
//成就作为观察者处理消息
class Achievements : public Observer
{
public:
virtual void onNotify(const Entity& entity, Event event)
{
switch (event)
{
case EVENT_ENTITY_FELL:
if (entity.isHero() && heroIsOnBridge_)
{
unlock(ACHIEVEMENT_FELL_OFF_BRIDGE);
}
break;
// 处理其他事件,更新heroIsOnBridge_变量……
}
}
private:
void unlock(Achievement achievement)
{
// 如果还没有解锁,那就解锁成就……
}
bool heroIsOnBridge_;
};
此时还需要一个添加删除观察者的管理类 通知下发给每个注册的管理者
class Subject
{
protected:
void notify(const Entity& entity, Event event)
{
for (int i = 0; i < numObservers_; i++)
{
observers_[i]->onNotify(entity, event);
}
}
// 其他代码…………
};
享元模式
抽象出共有的属性 修改不同的属性
渲染一片森林,每棵树都有网格贴图位置颜色等,这样GPU消耗会大
class Tree
{
private:
Mesh mesh_;
Texture bark_;
Texture leaves_;
Vector position_;
double height_;
double thickness_;
Color barkTint_;
Color leafTint_;
};
一个老方法就是使用相同的网格和纹理,只改变不同树位置颜色信息
class TreeModel
{
private:
Mesh mesh_;
Texture bark_;
Texture leaves_;
};
class Tree
{
private:
TreeModel* model_;
Vector position_;
double height_;
double thickness_;
Color barkTint_;
Color leafTint_;
};
网友评论