GLshader

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  75 随笔 :: 0 文章 :: 46 评论 :: 0 引用

公告

置顶随笔 #

摘要: 2012年, 时间表.阅读全文
posted @ 2012-01-20 17:10 glshader 阅读(87) 评论(0) 编辑

2012年4月21日 #

深度优先搜索 --- stack

广度优先搜索 --- queue

Dijkstra --- priority queue 

Dijkstra(A*)  --- weighted priority queue

posted @ 2012-04-21 11:51 glshader 阅读(16) 评论(0) 编辑

2012年3月19日 #

最近在工作中遇到一个小问题:设计一个小型的事件队列,用来解决技能释放,物品打造,采矿等事件执行时的延迟, 类似魔兽世界中法师放魔法前的读秒操作。 最开始, 我打算用一组抽象来解决这个问题:

class Event    // 事件基类
{
public:
Event(int nInterval)
: m_nInterval(nInterval)
{}
virtual ~Event() {}
virtual void Execute(Actor* pActor) {}

int m_nInterval; // m_nInterval毫秒过后, 执行事件
};

以此为基类, 创建如下两个真正执行操作的类:

class CastSpellEvent    // 释放魔法
: public Event
{
public:
CastSpellEvent(int nInterval, int nTarget, int nSpell)
: Event(nInterval)
, m_nTarget(nTarget)
, m_nSpell(nSpell)
{}

virtual void Execute(Actor* pActor)
{
    pActor->CastSpell(m_nSpell, m_nTarget);
    }

int m_nTarget; // 目标ID
int m_nSpell; // 魔法ID
};

class ForgeEvent // 物品打造
: public Event
{
public:
ForgeEvent(int nInterval, int nFormula)
: Event(nInterval)
, m_nFormula(nFormula)
{}

virtual void Execute(Actor* pActor)
{
int nItem, nNum; // 公式中的物品和物品数量
pActor->RemoveItem(nItem, nNum);
}

int m_nFormula; // 公式ID
};

基本工作搞定了, 但是还有一些小问题, 比如:如何获得这两个类的实例?如何销毁这些类的实例? 我是否需要用一个事件工厂来生产和销毁这些类的实例? 这会不会增加项目的复杂度? 其他人容易接受吗? 这些代码容易调试吗? 可扩展性高吗? 需要扩展性吗?............有些时候,程序员没有太多时间纠结完这些小问题, 那么让我们先看看如何使用这些类吧:

class EventQueue    // 事件队列
{
public:
typedef std::vector<Event*> EventContainer;

public:
EventQueue(Actor* pActor)
: m_pOwner(pActor)
{}

public:
void Add(Event* pEvt) // 添加事件, 意味着玩家想搞点事情做。
{
if (pEvt)
m_Events.push_back(pEvt);
}

void Update(int nDelta)
{
// 更新,如果时间到了调用Execute
for ( ... )
{
m_Events[i]->Execute(m_pOwner);
// 后续处理
}
}

private:
EventContainer m_Events; // 事件队列
Actor* m_pOwner; // 事件队列的拥有者
};

class Actor // 我们的玩家
{
public:
Actor()
: m_EventQueue(this)
{}
public:
int CastSpell(int nSpell, int nTarget);
int RemoveItem(int nItemID, int num);
EventQueue& GetEventQueue() { return m_EventQueue; }
int Update(int nDelta)
{
m_EventQueue.Update(nDelta); // 每帧更新
}

private:
EventQueue m_EventQueue; // 只要给的起钱, 他(她,它)当然会得到一个事件队列。
};

int main() // 伟大的main函数
{
// 这些当然是随手乱写的,事件工厂什么的我懒得写了,你懂的。

Actor a;

Event* evt0 = new CastSpellEvent(10, 1, 1);
Event* evt1 = new ForgeEvent(100, 1);
a.GetEventQueue().Add(evt0);
a.GetEventQueue().Add(evt1);

a.Update(100);

return 0;
}

采用抽象的方式, 必然导致new的存在, 这可能并不一定正确, 但我在大部分情况下都会编写出类似代码。  依然有一些小问题需要考虑, 比如: 这样做效率高吗? 会对内存池造成压力吗? 会产生内存碎片吗? 容易调试吗? 其他人容易接受吗? 会增加复杂度吗? ...........纠结完这些问题后, 工作告一段落。

不过事情到这里还没有完, 因为我并不认为这是一个非常不错的解决方案, 除了上面提出的各种问题外, 还因为这里有设计模式存在, 对于这样一个简单的问题, 设计模式显得太过臃肿, 对于内存池来说, 内存分配过于频繁。 从成本的角度考虑, 这样的做法代价有些高了。 那么有没有其他解决方案? 让我想想................

 

(这些代码都是实际项目代码的简化版, 真正的代码要复杂的多, 复杂到让人一夜之间白发三千丈。)

posted @ 2012-03-19 23:43 glshader 阅读(28) 评论(0) 编辑

2012年2月13日 #

这可能是我辈必经之路吧......

 

添加一条ctags命令: ctags.exe -R --extra=+fq --sort=yes --fields=+afiKSs --c++-kinds=+px

posted @ 2012-02-13 19:50 glshader 阅读(66) 评论(0) 编辑

2012年1月30日 #

http://www.math.uri.edu/~bkaskosz/flashmo/graph3d/

 

手写函数, 自动生成latex

http://webdemo.visionobjects.com/equation.html?locale=zh_CN

posted @ 2012-01-30 21:56 glshader 阅读(53) 评论(0) 编辑

2012年1月22日 #

  很长时间没有再看过lua,最近快过年了,我终于有机会再写一些lua的心得体会。大约半年前,一个同窗好友看了我的lua学习笔记,跟我道谢,表示学到了不少东西。我赶紧跟他解释,这些学习笔记都是我自学时乱写的,有很多错误的用法,应当用来当作前车之鉴,而不是学习材料。

  最开始学习lua的时候,我太执着于将C++的一些东西强加给lua,比如将C++类的成员函数导出给lua,以及让C++可以透明的操作lua中的table,metatable等。现在想想,这些东西是完全没有必要的。

  lua不是C++,C++也不是lua,他们的编程思想有很大差别,使用方式也有很多区别。C++和lua的交集体现在函数调用上,比如C++调用lua编写的某个函数,lua调用C++编写的某个全局函数。这里要注意的是,lua调用的是C++的全局函数,或者说就是纯C函数,更具体一些就是形如int callback(luastate*)的函数,而且只能调用这种签名的函数。只有将函数地址保存为callback函数的upvalue,才能将成员函数注册进去,当lua调用C++的callback函数时,再将upvalue解析出来。这种做法比单纯的全局函数注册复杂,而且不见得实用,如果对某个实例调用其类的成员函数,不如从lua中传入一个userdata或者lightuserdata到C++中,再进行调用。那么lua是怎么得到这个userdata的呢?可以有很多种方式,比如C++调用lua函数的时候传入userdata等。

  lua的表操作也不适合放在C++中进行,例如设置metatable这样的操作,最好的办法是把这些操作放到lua脚本文件中。虽然在C++中做和在lua中做本质是一样的,但是C++很不擅长做这些琐碎的事情,比如构建一个非常复杂的table,其中还有table的嵌套,各种metatable的设置等。在C++中过多的编写对lua自身特性的操作,会让程序变得复杂且难以调试。当然,C++可以利用table保存一些必要的信息,比如调试需要用的调用栈信息等等,不过最好不要有复杂的操作。

  总的来讲,应当尽量简化C++和lua之间的调用操作,并降低两者之间对对方特性的依赖,同时,让C++和lua做自己最擅长的事情,从而达到事半功倍的效果。

 

祝大家新年快乐!!!

posted @ 2012-01-22 10:05 glshader 阅读(2049) 评论(3) 编辑

2012年1月20日 #

摘要: 2012年, 时间表.阅读全文
posted @ 2012-01-20 17:10 glshader 阅读(87) 评论(0) 编辑

2012年1月4日 #

摘要: 有一些事情要暂时忘记, 有一些事情要牢牢记住.有一些人要悄然离去, 有一些人要紧紧拥吻.有一束花我要献给他人, 有一颗心我要好好珍藏.有一双手为我擦干眼泪, 另一双手为我抚平创伤.有一双炽翼带我傲游天际, 有一双铁鞋伴我脚踏实地.火热的阳光会蒸发我的灵魂, 但那一股清风时不时在我耳边轻语:"我的时间不多了."阅读全文
posted @ 2012-01-04 14:18 glshader 阅读(57) 评论(1) 编辑

2011年12月24日 #

摘要: merry merry christmas lonely lonely christmas阅读全文
posted @ 2011-12-24 11:14 glshader 阅读(27) 评论(0) 编辑

2011年12月16日 #

摘要: template<unsigned SIZE>class SlotArray{public: SlotArray() { memset(m_Data, 0, sizeof(m_Data)); memset(m_SlotMask, 0, sizeof(m_SlotMask)); }public: bool AllocSlot(unsigned& slot) { unsigned i = 0; for (i = 0; i < s_SlotMaskSize && (m_SlotMask[i] == 0xFFFFF...阅读全文
posted @ 2011-12-16 13:00 glshader 阅读(27) 评论(0) 编辑

2011年12月15日 #

摘要: 爱惜自己的身体, 早点睡觉, 别熬夜。阅读全文
posted @ 2011-12-15 22:42 glshader 阅读(83) 评论(2) 编辑

仅列出标题  下一页