闲话周末,游戏人生

这世上也许有玩不起游戏的人,但不会有离的开游戏的人 – 除非,你真的以为游戏只是网吧里的少年在虚拟世界中的厮杀,或是商场游戏厅中那一个个挥汗如雨惊声尖叫疯狂的背影。

游戏,本质其实很简单。国外的游戏制作者用“Core Loop”(核心循环 – 或理解为核心玩法)来诠释,我非常认可。比如风靡全球的社交游戏《City Ville》,它的核心就是:玩家用金币购买种子,播种,一段时间后收获“作物”,“作物”可以供给城市里的商业机构,居民进入这些机构消费,玩家获得金币。这种循环周而复始,不觉得枯燥,是因为它会给你带来成就感。它让你浑然不觉。

现实生活中,人生的基本规则也是如此:日复一日,年复一年,吃饭,睡觉。大千世界,也不过是一些周而复始的迭加,但各种成就和目标让你觉得,每一天都不一样。

游戏需要“平衡”(Balancing),或是“公平”、“制衡”。在ARPG泰斗《Diablo I》中,玩家如果选择武士,会有更好的盔甲和近战本领,但他只能学会非常简单、低档的魔法;玩家如果选择魔法师,则是在控制一个几乎没有近身防御能力的肉身,还要因生命力极低而提心吊胆随时死亡,但他利用魔法进行远程攻击和群体攻击会对敌人制造毁灭性的打击。遗憾的是,《Diablo I》的魔法盾设计让魔法师在魔法药水补给充足的情况下几乎无敌。因此,如果是以通关为目的,武士这个角色我从来不会使用。

在多人游戏中,平衡更加重要。比如星际争霸的第一个内部测试版本基于《魔兽争霸II》的源码框架在1996年就完成了,可直到1998年3月31日,这款游戏才正式问世。期间经过了无数的测试和打磨。以至于十多年过去了,我和周围的许多朋友依然能为这款游戏疯狂。

社会生活也是如此。努力学习,可以有更好的工作;努力工作,可以有更多的晋升空间;努力维持社会关系,可以有更多的朋友和机会;恪守承诺和坚持,可以得到来自周围人的认可和信任。破坏平衡,比如违反法律,就会受到惩罚。

然而,外挂和作弊让游戏失去平衡,会让快乐驱动变成单纯的快感驱动,加速游戏的死亡。光说国内,死于外挂的游戏,知名的,或是不知名的,不计其数。

这又让我想到一个网络上流传已久的有趣比喻:人生如游戏,在投胎的时候,会让你选择难度。选择简单模式,出生点是发达国家;选择困难模式,出生点是发展中国家;选择噩梦模式,会出生在一个神奇的国家,因为这里有一部分“玩家”是开了外挂的,他们并不需要遵守游戏规则,可以在特定的甚至任意的时候随意践踏你的生命和信仰。不过,乐趣在于,在这个服务器里面玩,能升到满级活到最后的,都是神一样的角色。从游戏平衡的角度来思考,我常常被这种潜在可以获得的成就感驱动得充满能量。

生活是不是一场游戏不是重点,重点是,你是不是用玩游戏的心态感受生活。作为一个童年有着“256种颜色和30万个像素的梦想”的人,我很庆幸自己是如此思考的。

很久不写博客了,上微博更多:@awguoweibo.com/awguo),顺便再次强行插入一则广告:我的公司制作社交游戏,正在招游戏设计师和策划,有兴趣者可以在微博上给我发私信。

Advertisements

状态机-简单、重要、高可应用性的思想

转载请注明:http://www.awflasher.com/blog/archives/534

其实在数字电路中就已经介绍过这种模型,包括后续的“信息论”、“随机过程”等课程中,也介绍到了这个模型中的一些基本概念。可是平时在课堂上学过了,没有实际应用确实难以记住。这次在师弟Xophiix(http://www.xophiix.com.cn)处看到状态机一文,发现确实能将这一概念运用到Flash的交互开发中。Xophiix虽然仅仅是大二的学弟,但是有着非常强烈的创新欲望和实践经验。所谓三人行必有我师,这次这个“状态机”,确实帮了我那个挫的不能再挫的“是男人就下100层”的大忙。

言归正传,来介绍如何使用状态机模型进行开发。

首先,要明确什么叫做状态(Status)。我不想引用什么字典里的解释,那样只会将这里的问题复杂化。举例说明最方便。就拿我这个游戏来说,玩家所扮演的小人,就存在三种状态:小人跑动(move)、小人站立静止(stand)、小人在空中坠落(falling)。为了配合下面的代码实例,我简记为move, stand, falling,下同。图中分别用橘黄标示为A,B,C。

状态的一大特性就是转化。状态不是孤立的,换句话说,状态是变化的,是会互相转化的,比如,move可以转化到falling;falling可以转化到stand。
值得一提的是,转化有两条原则:
·转化本身的逻辑性 – 并非所有的状态之间都可以任意转化,这里stand就不能变化为falling,因为小人不可能站在挡板上不动自己掉下;而falling也不能转化为move,因为小人掉下的途中不可能跑动(脚踩空),而必须通过一次stand,再跑动。

转化的外界因素 – 转化的时候需要一个外因,这里四种转化,我用数字表示为1,2,3,4,意义分别是
1、移动出了挡板,从空中坠落
2、坠落途中掉在挡板上,站立
3、用户按左、右键,或者掉在了有“方向履带”的挡板上,小人跑动起来
4、用户停止按键并且小人站在非“方向履带”的挡板上,小人站立

这两条原则总结完了之后,就好设计程序了。但是在设计程序之前,一定要把这几个状态以及转换原则疏理清晰,如果你连一共有几种状态都分不清楚就开始写代码,那肯定有更多的麻烦等着你。

while-switch的方法可能是VC程序员最熟悉的了,前文提到的Xophiix的blog中可以看到。不过在Flash中,还是onEnterFrame-switch比较方便。毕竟Flash是按frame渲染的,用onEnterFrame的循环在资源消耗上有着很大的优势。代码如下,保留了整个小人的Action,状态机核心在中间加粗部分:

getPlayer.onEnterFrame = function()
{

if (this.isTowardLeft == undefined)
{
// 是否站在履带上
xinc = 0;
}
else if (this.isTowardLeft)
{
// 左旋转履带
xinc = -1;
}
else
{
// 右旋转履带
xinc = 1;
}
if(Key.isDown(Key.LEFT))
{
//按下左件
xinc -= spd;
}
if(Key.isDown(Key.RIGHT))
{
//按下右件
xinc += spd;
}    switch( statusNow )
{
case “stand”://站立状态
if( xinc != 0 )
{
//如果x轴向增量不为零,代表人应该移动了
this.gotoAndPlay( “move” );
statusNow = “move”;
//跳转到移动状态
break;
}
break;
case “move”://移动状态
if( !this.isOnLand)
{
//如果人不在挡板上,则坠落
this.gotoAndStop( “falling” );
statusNow = “falling”;
}
else if( xinc == 0 )
{
//如果x轴向增量为0,则站住
this.gotoAndStop( “stand” );
statusNow = “stand”;
break;
}
break;
case “falling”://坠落状态
if( this.isOnLand )
{
//如果人掉在挡板上,则转化为站立
this.gotoAndStop( “stand” );
statusNow = “stand”;
break;
}
break;
default:break;
}

//简单物理模型的建立,参考了ox_darkness师兄@Flash8
if( statusNow == “stand” )
{
yinc = 0;
this._y = this.receiveTarget._y;
}
if( statusNow == “move” )
{
yinc = 0;
this._y = this.receiveTarget._y;
if( xinc > 0 )
{
this._xscale = -Math.abs( this._xscale );
}
else if ( xinc < 0 )
{
this._xscale = Math.abs( this._xscale );
}
if( xinc != 0 )
{
this._x += xinc;
}
if( statusNow == “falling” )
{
this._y += yinc;
}
}
if( statusNow == “falling” )
{
yinc+=0.15;
this._y += yinc;
if( xinc > 0 )
{
this._xscale = -Math.abs( this._xscale );
}
else if ( xinc < 0 )
{
this._xscale = Math.abs( this._xscale );
}
if( xinc != 0 )
{
this._x += xinc;
}
}
if (this._y > sceneh || this._y < -5)
{
gameOver();
}
}