本内容接上题,上题的写法是写出一个求出logk(int n)的整数部分的template,结果如下:

#include <iostream>
using namespace std;
template <int n>
class static_log2N
{
    public:
        enum {value = static_log2N<n/2>::value+1 };
}    ;

template <>
class static_log2N<1>
{
    public:
        enum{value = 0};
};

int main()
{
    cout<<static_log2N<28>::value<<endl;
    cin.get();
}       

进一步扩展,可以写出一个求出底为k,求log(int k)(int N)的整数部分的程序来,如下:

#include <iostream>
using namespace std;
template <int base,int n>
class static_logxN
{
    public:
        enum {value = static_logxN<base,n/base>::value+1 };
}    ;

template <int base>
class static_logxN<base,1>
{
    public:
        enum{value = 0};
};

int main()
{
    cout<<static_logxN<3,28>::value<<endl;
    cin.get();
}       

   昨天去书店找关于此类编程的资料,在c++ templates一书中找到称其为metaprogamming, 呵呵,孤陋寡闻了, 这本书的中文版太贵了,而且网上评论说译的不是太好,于是上午就买了本影印版,看上去是有点费劲,不过可省了近20块大洋呢^_^  趁这几天有时间,抓紧看一下:)

June 19th, 2007Covariant return types

Covariant return types–翻译成中文的字面意思应该是协变返回类型, 它的意思可以概括为在面向对象的编程中, 子类在重写父类的方法时可以改变这个方法的返回值的类型. 一般来讲子类在重写(override)父类方法时, 要求这个方法在参数列表和返回值上都要和父类中的对应的方法保持相同的类型. 所以下面的代码是无法通过编译的:

class Base
{
public:
virtual int foo () {return 0;}
};

class Child : public Base
{
virtual long foo () {return 1;} //compile error, 'Child::foo': overridin
//virtual function return type differs
//and is not covariant from 'Base::foo'
};

也许大家还没有看到这个限制的不爽之处, 那么设想如下的情形, 你想为你的父类和子类都写一个clone ()方法, 返回一个clone出的对象的指针, 如果没有Covariant return type, 你需要写类似如下代码:

class Base
{
public:
Base* clone ();
};
class Child : public Base
{
public:
Base* clone ();
};

Child* bp = static_cast<child*>(child.clone ());</child*>

这里每个子类的clone方法都返回一个指向Base的指针, 如果想要转换成子类的指针还需要一次额外的类型转换, (当然也许你认为使用static_cast会在编译期间完成, 不会影响运行效率, 但显然代码不够优雅:) 如果使用Covariant return type, 我们就可以把每个子类的clone方法返回一个指向子类对象的指针类型了:

class Base
{
public:
Base* clone ();
};
class Child : public Base
{
public:
Child* clone ();
};
Child* bp = child.clone (); //no extra type cast needed.

实际上Covariant return type就是用来这种在子类重写父类方法, 并且它的返回值的类型和父类方法的返回类型具有一定的相关性(一般是其衍生类型即派生类). 在C++标准03版的10.3.5中对其covaraiant return type做了详细的描述. 大家有兴趣可以去翻一下.

March 25th, 2007cv-qualified type

常在bbs上看人讲cv-qualified type, 一直没搞明白这是个嘛东西, 今天google了一下, 居然没有找到答案, 于是想起google group,果然在里面搜到了, 这里有一个人问了个什么是cv-qualified type, 看了一下, 原来cv分别是const和voliate的简写…

  a cv-qualified type is the “const”, “volatile” or “const volatile”
version of a type. that is, a variable, function, etc. declared without
one of those is cv-unqualified, while the addition of one of those
specifies a cv-qualified type.

  翻开标准还真有这么一节专门讲它的…

March 24th, 2007WebGame的设计猜想 (1)

WebGame译成中文为网页游戏,

此类游戏不同于常见的游戏,

它是以网页为游戏界面,

Mud

有些类似,

但由于其结合了当今流行的ajax元素,

所以在界面及用户交互上比Mud很大提高.

WebGame由于是基于网页的,

所以它的平台相关性较小(只要有一个网页浏览器就差不多可以了.),

WebGame一般界面相对于通常游戏来说不够炫,

基本没有大家所常见的游戏特效,

它的界面一般就是显示一些玩家的数据和一些供玩家操作的按钮/链接.

不同于大家常见的

RPG游戏或是战略对抗游戏,

这些游戏通常要求玩家实时的操作游戏,

WebGame的时间进度相对来说较慢,

而正是由于WebGame

的游戏进度相当的慢,

玩家基本上不需要花费太多时间耗在游戏上面就行了,

可以作为一款休闲娱乐的游戏玩,

大家可以见到的WebGame

ogame,

travian, 战神世界等等(还有很多,

不一一列举了).

   由于最近在试玩一个新的游戏(混沌战争,

http://alpha.chaoswar.cn:8080),

所以有些便对其的设计产生了兴趣.

把自己的粗略的想法写出来,

希望能看到大家更好的想法~

  本文中着重讨论WebGame对于数据流程的处理.

   WebGame要处理两类事情:

1. 维护玩家数据

2. 处理用户对数据的查询/更新请求.

   玩家数据又可再分为三类:

固定的数据(

此类数据一般一经设定就不会改变,

例如用户名称,及其他.),

主动更新的数据(

此类数据会依照系统设定的某个公式以与时间成正比的方式增长,

例如用户的资源),

被动更新的数据(此类数据不会主动发生改变

, 但它会受主动更新数据/用户行为的影响而改变,

例如战斗积分)

   用户的行为大致会有以下几点:

1. 对资源生产单位的升级(

增加生产力),

2. 建造高级建筑/生产消耗单位(主要是具有战斗力的士兵/

具有生产力的农民,

这两种情况类似)

3. 攻击别的玩家,

获得/失去战斗单位,

资源.

4. 玩家系统内部的交流(如内部邮件).

5. 玩家之间的交易,

    一般而言,

一个游戏系统都是设定在一系列的公式基础上的,

这样用户资源的计算才能有章可循,

并且游戏中应当有其对时间和系统最小时间片的定义(最小时间片为系统的最小计时单位,

一般为1).

但是如何计算这些资源,

如何能够保证返回给用户的信息总是实时并准确的呢? 通过实时的演算系统各个玩家的状态是不合理的, 因为当玩家数量巨大的时候被次演算都将是一个耗时的过程. 对于玩家数据的计算我们引入事件这一概念.

 

所谓事件是由用户交互而产生的影响玩家数据变化默认轨迹的过程. 假设如果一个系统没有用户的交互,

那么我们可以说系统的每时每个用户的数据都是可以通过运算求出的, 因为我们有一系列的公式来计算这些状态.

但正是由于游戏系统会接收大量的用户交互而产生大量的事件才导致了玩家数据的变化脱离系统计算轨迹. 那么我们可以得出,

在一个系统的有事件发生之前, 系统的状态是可以通过公式计算出来的, 同样, 在一个事件之后, 下一个事件发生之前,

这之间的系统状态同样可以通过相关的公式计算得出. 那么我们可以继而得出, 假如系统现在同时有n个事件在队列中的话,

系统在第n个事件发生后的状态可以由 第一个事件发生前的状态(公式计算) -> 第一个事件发生后的状态(事件处理) ->

第二个事件发生前的状态(公式计算)->第二事件发生后….. -> 第n个事件发生前(公式计算)->

第n个事件发生后的状态逐步推导而出.

  今天写到这… 被别的事耽搁了..

March 24th, 2007WebGame的设计猜想 (2)

于事件系统的设定,

我们定义系统中只有事件才会导致资源改变脱离原系统的计算轨迹, 同样如果一个过程会引起资源变化轨迹的改变那么它一定是一个事件.

为了便于处理我们再次约束一个事件最多有两个当事人, 假如一个过程会有多个当事人参与, 那么我们可以把此过程分解成若干个同时发生的子事件.
   我们再考虑一下事件体系的并行计算的可行性:
  

并行性 ==> 假如一个事件结束时会衍生出其他事件, 那么由其衍生的事件一定要晚于这个事件发生(不可能同时发生,

就是说衍生事件的时间至少要晚于父亲事件一个最小计时单位), 假如处理到系统事件队列中的第n刻的事件, 如果有m个同时发生的事件,

如果一个事件满足下面的条件, 那们我们可以说这个事件可以并行处理:  在此事件之前的发生在n刻的m-1个事件的关系双方没有此事件中的双方当事人.因为我们在系统中已经假设如果一个事件能衍生出另一个事件, 那么新产生的事件一定要晚于此事件,

所以这个衍生出的事件必然也会晚于和父亲事件同时发生的事件.   所以本系统在事件的级别上可以做到一些并行的处理.
    这几天忙别的… 没写太多…

March 24th, 2007WebGame的设计猜想 (3)

们假设有这么一个游戏设定,

玩家之间可以通过派遣军队来攻打对方的城市 (军队由各种级别的士兵组成), 另外, 当一个玩家的军队路过某玩家城市附近的时候, 则在一定条件下经过城市的玩家会得到一个警告信息.

事件过程模拟:
  我们已经讲过只有事件才会影响玩家资源变化的轨迹,

所以在每次处理事件之前都会有一次隐含的计算事件当事玩家资源的过程.
  现在我们假设玩家
A要出兵攻打玩家B的城市(在从出发到B城市的路上会经过玩家C的城市的附近), 这里的事件处理是如何的呢è首先系统会通过距离及速度的公式得出A到达C城市附近的时间, 并产生一个经过C城市的事件

  这时产生一个事件
E1 A==>C   type=pass

by    src=A  dest=B 

startTime=400   Endtime=800

   于是到达系统的时间800的时候, 系统根据事件EC1的类型调用相关的事件处理例程处理此事件,于是在处理完EC1的时候, 会产生下一个事件,

EC2为到达B城市的事件
E2 A==>B  

type=fight    src=A  dest=B 

startTime=400   Endtime=1000

  于是到系统的1000时间点时, 系统根据事件类型, 调用战斗事件的处理例程,

并得到结果, 此时可能会再产生一个新的返回事件, 放入系统的事件队列.

   以上是一个简单的事件, 让我们再多一点思考:

假如由于城市C升级了相关科技, 它能够监测到有玩家军队经过的范围扩大了,

那我们要怎么做呢? 我们说, 一个城市如果升级科技,

系统会为其建立一个科技升级的事件:
E-Upgrade 

type=upgrade  src=C dest=NULL  startTime =500 EndTime=600

   这个事件的开始时间为其开始升级科技的时间,

结束时间为科技升级完成的时间, 于是当系统到时间600的刻, 开始调用升级科技相关的例程来处理此事件,

由于此事件增加了城市的监测范围, 它会更新所以dest=C type=pass by的事件(根据相关公式计算相关时间), 如果此时军队已经进入更新科技后的监测范围而没进入原来的监测范围,

那么我们说它会把原来的E1 AèC   type=pass by    src=A 

dest=B  startTime=400   Endtime=800事件更新并把它放到比它晚一个系统时间最小单位的事件队列中去 (这个新的事件相当于一个衍生时间, 根据我们前面的假定,

衍生事件是要晚于源事件的)
E1-up  A==>C   type=pass by    src=A 

dest=B  startTime=400   Endtime=601

   另外再举一个例子就是如果玩家取消了这个军队的行程呢?

这时我们会删除此事件, 并创建一个返回事件(如果途中经过其他城市会先创建一个新的pass

by的事件).

  以上大概是对事件模型的应用的一些解释. 这里我们还有一个问题, 如果模拟多方城市参与的军团作战呢?

这里的作战单位应该是多对多了似乎需要再对这个机制进行一下扩充

  最后再讨论一下事件的处理机制:
  个人认为事件的处理可以有两种方式: 查询时处理/定时处理.

  查询时处理: 我们知道,

事件是自用户交互而产生的, 假如没有用户交互, 就不会有事件的产生,

而我们处理事件也是为了让用户得到有效和及时的数据. 查询时处理的原则就是只有在用户请求更新数据的时候我们才处理在此系统时间点之前的所有事件(在没有用户处理前对于事件的处理是毫无意义的 (同样对于事件的处理只要我们能够按照顺序和把握时间点那么所有的结果都会是正确的),

查询时处理的好处就是可以保证系统负荷在没有用户请求的时候会很低.

它的特点是对于用户来说它看的信息是即时和正确的, 但是事件的处理可能不是实时的.

  但查询时处理有一个致命的弱点就是虽然用户得到的信息可以说是即时和正确的, 但是这只限于通过系统内部的查询机制来获取数据, 由于事件的处理的不实时性, 这可能会导致一些需要无法很好的完成: 发生某个事件时发送email通知玩家, 这一点就不好完成. 另外一个缺点可能是如果系统积累了太多事件等待处理,

可能处理第一个用户的请求时所需的时间相对较长.

  于是我们引入了定时处理的机制, 定时处理来说就是以系统时间的最小单位为一个时间片来对系统的事件进行处理,

这种好处是能够保证事件的发生始终是实时而准确的. 保证了实时通知的需要可以很好的完成.

另外考虑以下几种常见的情况:

  系统停机维护==> 停止资源增长,

这个其实还算简单, 主要是更新一些事件的发生时间和玩家资源计算的最后时间就ok

  基本到这里了, 关于事件机制就写到这吧, 其实一个webgame取胜的关键还是创意… 其他的都是小问题…  


© 2007 pangwa's Blog | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress