怎样把做饭小游戏大全做的更有趣?

Cocos2D是一款功能强大的iphone游戏引擎,它可以很大程度上节约你的游戏开发时间。它包含sprite(精灵),绚丽的特效,animations(动画),物理引擎,声音引擎,以及其他一些相当实用的功能。
我也是刚接触Cocos2D,虽然目前市面上有很多cocos2d相关的教程,但我没能找到我想到的那种入门级别的教程-如何制作一款非常简单但是功能齐全的游戏。对于入门教程,这款游戏应当仅仅包含一些较为基础的功能,如animation(动画), collisions(碰撞)和声音。于是我自己制作了一款简单的游戏,并把过程中积累的点点滴滴制成了一篇3系列的教程,希望对广大刚刚接触Cocos2D的入门者有所裨益。
这一系列教程会带你逐步熟悉并学会制作一个简单iphone游戏的每一个步骤。你可以循序渐进的学习,或者干脆跳转到本教程的末尾下载示例工程,在那里,会有神奇的忍者等着你哟!
(跳转到全系列教程的&&或者&)
下载并安装Cocos2D
你可以从以下地址下载到最新的Cocos2D.
下载完成后,你需要安装实用的project templates(工程模板)。在mac下打开一个终端窗口,
进入到刚刚下载到的Cocos2D的目录并输入以下指令: ./install-templates.sh -f -u
注意,如果xcode没有安装在默认目录下,在这里你可以选择性的在指令后添加参数(如果你的机器曾经安装过多个版本的SDK的话,那么很可能之前你已经会用这种方法了)。
Hello, Cocos2D!
让我们从建立一个简单的Hello World程序开始吧!
启动Xcode,选择cocos2d Application template建立一个新工程。将其命名为 “Cocos2DSimpleGame”。
编译(Cmd+B)并运行(Cmd+R)之,如果一切顺利,你将看到如下图所示:
Cocos2D是以场景(scenes)组织的,对一个游戏来说,场景可以是关卡或者是屏幕。比如游戏一开始的主菜单场景,游戏中运行起来的场景,还有游戏结束game over的场景。在场景中,可以有很多的层layers(很像photoshop中的层),层中又可以包含很多节点nodes比如精灵sprite,文本labels,菜单menus和其他的。同时每个节点又可以包含其他的节点(例如一个sprite节点可以包含另一个sprite节点作为他的child)。
观察下Hello World示例工程,会发现里边只有一个层-HelloWorldLayer-我们准备在这儿实现我们主要的游戏逻辑。打开这个文件,会看到在init方法里边被加入了一个写着”Hello World”的label,现在删除掉它,我们以后将用一个sprite来替换它。
添加一个Sprite
在添加一个sprie之前,我们需要一些图片,你可以使用自己创建的,或者直接使用我(ray)可爱的妻子为这个项目制作的图片资源:&,&,
获得这些图片后,把它们从finder里拖拽进Xcode工程的resources文件夹下,确保”Copy items into destination group’s folder (if needed)是选中的。
好的,现在有了图片资源,下面要计算出该往哪里放置我们的主人公。需要注意的是在Cocos2D里,屏幕的左下角是(0,0)点,随着你往右上方向移动,x和y值会随之增加。因为本项目是landscape模式的(手机横向放置),所以这意味着右上角的坐标是(480,320)。
还需要注意的是,每当设置一个对象的坐标,默认情况下设置的是该对象自身中心的位置。所以如果想把主人公sprite放置到屏幕的横向左边缘,纵向屏幕一半的位置,需要执行以下两步:
x坐标,设置其为[player sprite's width]/2。
y坐标,设置其为[window height]/2。
这就试试看!打开Classes文件夹并点击HelloWorldLayer.m,用以下内容替换掉init方法:
-(id) init
if( (self=[super init] )) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *player = [CCSprite spriteWithFile:@&Player.png&
rect:CGRectMake(0, 0, 27, 40)];
player.position = ccp(player.contentSize.width/2, winSize.height/2);
[self addChild:player];
编译并运行,主人公sprite跃然屏幕之上,但注意背景默认是黑色的,白色看起来也许会更好点儿。使用CCLayerColor class可以简单的完成这一目标。打开HelloWorldLayer.h并修改其interface 声明部分:
@interface HelloWorldLayer : CCLayerColor
然后打开HelloWorldLayer.m,对init方法做一个轻微的修改:
if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {
背景就顺利变为了白色。
编译并运行,主人公出现在白色背景之上了,哈哈,我们的小忍者看起来跃跃欲试了!
移动靶子Moving Targets
接下来为了让我们的忍者不至于独孤求败,我们加入一些靶子,为了让游戏更有趣,可以让靶子移动起来-否则游戏将不会有很好的挑战性。将这些靶子稍微向右移出屏幕一点儿,并给他们设置一个向左移动的动作。
在init方法之前添加以下方法:
-(void)addTarget {
CCSprite *target = [CCSprite spriteWithFile:@&Target.png&
rect:CGRectMake(0, 0, 27, 40)];
// Determine where to spawn the target along the Y axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minY = target.contentSize.height/2;
int maxY = winSize.height - target.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
target.position = ccp(winSize.width + (target.contentSize.width/2), actualY);
[self addChild:target];
// Determine speed of the target
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minD
int actualDuration = (arc4random() % rangeDuration) + minD
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(-target.contentSize.width/2, actualY)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self
selector:@selector(spriteMoveFinished:)];
[target runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
为了让事情更容易理解,我使用了有点儿冗长的方式来讲解。这一部分其实就是和之前主人公sprite同样的方式来计算对象该放到哪儿,设置坐标并将其加入到场景中去。
唯一不同的是这里加入了actions(动作)。Cocos2D内部提供了许多极为便利的动作来给你的sprite动起来,例如move actions(移动),jump actions(跳跃),fade actions(渐隐渐现),animation actions(动画)等等,这里我们只用其中的三个action:
CCMoveTo:&使用CCMoveTo action来让对象从右侧屏幕外移动到屏幕左侧。注意可以通过指定duration参数控制这一过程需要多久,这里我们随机给他2-4秒的时间。
CCCallFuncN:&CCCallFuncN action 允许我们指定一个在动作执行完成后执行的回调函数。暂时写一个空的回调“spriteMoveFinished”,以后再填入内容。
CCSequence:&CCSequence action 允许将一系列动作按先后顺序组合成一个动作,一次执行,这里,让CCMoveTo首先执行,当它完成时,再执行CCCallFuncN动作。
接下来,添加上文提到的那个CCCallFuncN action中需要的回调函数,在addTarget:方法之前添加以下内容:
-(void)spriteMoveFinished:(id)sender {
CCSprite *sprite = (CCSprite *)
[self removeChild:sprite cleanup:YES];
此方法的目的是一旦sprite超出屏幕范围,就将其从屏幕上移除。随着靶子数量的不断增加,如果不及时清理之,将会有严重的内存泄漏问题出现。解决这个问题也可以使用另一种更为高端的手段-使用数组存储一系列可以重复使用的sprites对象,但对于这篇初学者教学来说,我们用目前这个基础的方法即可。
在继续前还有一件事儿要做。我们需要实际调用创建靶子的方法。为了让游戏更有趣,我们让靶子每隔一小段时间就出现。通过每隔一段时间就会被调用的schedule(调度)回调函数,就能完成这个目标。每隔一秒刷新一个靶子,在init方法里的return之前加入以下内容:
[self schedule:@selector(gameLogic:) interval:1.0];
接下来在回调函数里填入如下内容:
-(void)gameLogic:(ccTime)dt {
[self addTarget];
编译并运行,你会看到靶子们欢快地在屏幕上移动着:
射击Shooting Projectiles
到这里,主人公忍者多么渴望着被添加一个射击动作。虽然有很多方法可以实现射击,但是这个游戏里,我们希望每当用户触摸屏幕时,让主人公向着触摸的方向发射一个飞镖。
我使用CCMoveTo action来让所有逻辑尽量简单,但是使用它还是需要一丁点儿数学计算。CCMoveTo需要被指定一个目标点,我们不能直接使用用户触摸屏幕的点,因为这个点仅仅能表示主人公射击靶子的方向,实际上我们想让飞镖持续飞行到一直飞出屏幕为止。
这里是一个说明该问题的图片:
你可以看到,有一个由主人公起始点到触摸点组成的较小的三角,这个三角延伸到屏幕边缘组成的一个较大的三角,我们需要的就是这个大三角与屏幕边缘的交汇点。
回到代码部分,首先我们在层里启用触摸,在init方法中加入:
self.isTouchEnabled = YES;
由于启用了触摸,在层里会接收到相应的触摸回调函数。每当用户的手指从屏幕抬起,将会触发ccTouchesEnded方法,我们这就实现它:
- (void)ccTouchesEnded:( *)touches withEvent:(UIEvent *)event {
// Choose one of the touches to work with
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
// Set up initial location of projectile
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCSprite *projectile = [CCSprite spriteWithFile:@&Projectile.png&
rect:CGRectMake(0, 0, 20, 20)];
projectile.position = ccp(20, winSize.height/2);
// Determine offset of location to projectile
int offX = location.x - projectile.position.x;
int offY = location.y - projectile.position.y;
// Bail out if we are shooting down or backwards
if (offX &= 0) return;
// Ok to add now - we've double checked position
[self addChild:projectile];
// Determine where we wish to shoot the projectile to
int realX = winSize.width + (projectile.contentSize.width/2);
float ratio = (float) offY / (float) offX;
int realY = (realX * ratio) + projectile.position.y;
CGPoint realDest = ccp(realX, realY);
// Determine the length of how far we're shooting
int offRealX = realX - projectile.position.x;
int offRealY = realY - projectile.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/
// Move projectile to actual endpoint
[projectile runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:realMoveDuration position:realDest],
[CCCallFuncN actionWithTarget:self selector:@selector(spriteMoveFinished:)],
在第一部分里,我们从touches对象集合中选择一个,得到他在当前屏幕上的坐标,通过调用convertToGL来把此坐标转换为当前屏幕模式适应的,这一点很重要,因为我们使用的是landscape模式。
接下来加载飞镖sprite并像往常一样设置其初始坐标。根据之前讨论过的相似三角形算法,我们计算得到飞镖的终点。
注意这个算法并不完美。即使飞镖的Y坐标已经出了屏幕,它还是会被强制移动到X坐标移出屏幕为止。想解决这个有很多手段,包括检测射击点到屏幕边缘的最短距离,在游戏逻辑的回调里检测飞镖坐标是否在屏幕之外(比如visit),虽然这些方法都可以解决它,但简单起见,这篇初学者教程还是会使用之前的方式。
最后一件事儿是决定运动所需的时间。飞镖最好是能以固定的速率射出,所以我们还需要一丁点儿数学计算。使用&可以轻松地得到斜边的长度。
一旦有了距离,只需要将其除以一个固定的速率,便可得到时间。
剩余部分就像我们之前做的,给靶子设置上actions。编译并运行,哈哈,你的忍者能给予冲过来的鬼头靶子致命打击了!
碰撞检测Collision Detection
飞镖四处飞,但我们的小忍者并没有看到飞镖击倒鬼头靶子。是时候加入一些检测飞镖与靶子碰撞检测的代码了。
使用Cocos2D有很多途径解决这个,包括使用其中一个引擎包含的物理引擎:Box2D或者Chipmunk。为了有效说明问题的本质并使事情简单,我们将自己实现一个简单的碰撞检测。
首先,我们需要记录所有在当前场景里的靶子和飞镖对象。在HelloWorldLayer类的声明中加入:
并在init方法里加入初始化数组的代码:
_targets = [[ alloc] init];
_projectiles = [[ alloc] init];
在dealloc方法里边清理之:
[_targets release];
_targets = nil;
[_projectiles release];
_projectiles = nil;
现在,修改addTarget方法,在靶子数组中加入一个新靶子并设置其标识(tag)留待后用:
target.tag = 1;
[_targets addObject:target];
同样的,把在ccTouchesEnded里新建的飞镖加入到飞镖数组中并设置tag留待后用:
projectile.tag = 2;
[_projectiles addObject:projectile];
最后,修改spriteMoveFinished方法,根据tag分类把即将删除的对象从数组中也移除掉:
if (sprite.tag == 1) { // target
[_targets removeObject:sprite];
} else if (sprite.tag == 2) { // projectile
[_projectiles removeObject:sprite];
编译并运行,确保到目前为止一切都OK。虽然目前还看不到什么显著的变化,但我们已经有了做碰撞检测的基础了。
添加以下方法到HelloWorldLayer:
- (void)update:(ccTime)dt {
*projectilesToDelete = [[ alloc] init];
for (CCSprite *projectile in _projectiles) {
CGRect projectileRect = CGRectMake(
projectile.position.x - (projectile.contentSize.width/2),
projectile.position.y - (projectile.contentSize.height/2),
projectile.contentSize.width,
projectile.contentSize.height);
*targetsToDelete = [[ alloc] init];
for (CCSprite *target in _targets) {
CGRect targetRect = CGRectMake(
target.position.x - (target.contentSize.width/2),
target.position.y - (target.contentSize.height/2),
target.contentSize.width,
target.contentSize.height);
if (CGRectIntersectsRect(projectileRect, targetRect)) {
[targetsToDelete addObject:target];
for (CCSprite *target in targetsToDelete) {
[_targets removeObject:target];
[self removeChild:target cleanup:YES];
if (targetsToDelete.count & 0) {
[projectilesToDelete addObject:projectile];
[targetsToDelete release];
for (CCSprite *projectile in projectilesToDelete) {
[_projectiles removeObject:projectile];
[self removeChild:projectile cleanup:YES];
[projectilesToDelete release];
以上内容很清晰。我们遍历了一下飞镖和靶子数组,在遍历中得到每一个对象的bounding box(碰撞框),使用CGRectIntersectsRect来检测两个矩形是否相交。如果有相交,则将飞镖和靶子分别从场景和数组中移除。注意我们必须将这些对象加入到“toDelete”结尾的数组中,因为我们没法在当前循环中从数组中删掉它。还是一样,有很多更优的方法来解决这类问题,简单起见,我使用最简单的方法。
你仅仅需要一步就可以欢呼了,使用schedule调度这个方法,使其在每一帧都执行:
[self schedule:@selector(update:)];
编译并运行,所有和飞镖碰撞的靶子都会灰飞烟灭了!
完成触摸Finishing Touches
我们已经非常接近制作出一个成品(但很简单)的游戏了。只需要再加入一些音效和音乐(没有游戏不带声音的!)以及一些简单的游戏逻辑。
如果你阅读过我的这篇教程,你会非常欣喜地发现在Cocos2D中播放声音原来如此简单。
首先,把背景音乐和一个射击音效拖拽进你的工程的resources文件夹。你可以随意使用以下资源or my&, 或者制作你自己的。
接下来在HelloWorldLayer.m的一开头导入头文件:
#import &SimpleAudioEngine.h&
在init方法中,如下所示播放背景音乐:
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@&background-music-aac.caf&];
在ccTouchesEnded方法中播放音效:
[[SimpleAudioEngine sharedEngine] playEffect:@&pew-pew-lei.caf&];
现在,我们加入一个提示“You Win”或者“You Lose”的游戏结束场景。右键点击Classes文件夹,选择FileNew File,并选择Objective-C class,确保继承的类是NSObject。点击Next,在filename位置输入GameOverScene作为文件名,确保“Also create GameOverScene.h”是选中的。
用以下内容替换掉GameOverScene.h:
#import &cocos2d.h&
@interface GameOverLayer : CCLayerColor {
CCLabelTTF *_
@property (nonatomic, retain) CCLabelTTF *
@interface GameOverScene : CCScene {
GameOverLayer *_
@property (nonatomic, retain) GameOverLayer *
用以下内容替换掉GameOverScene.m:
#import &GameOverScene.h&
#import &HelloWorldLayer.h&
@implementation GameOverScene
@synthesize layer = _
- (id)init {
if ((self = [super init])) {
self.layer = [GameOverLayer node];
[self addChild:_layer];
- (void)dealloc {
[_layer release];
_layer = nil;
[super dealloc];
@implementation GameOverLayer
@synthesize label = _
-(id) init
if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
self.label = [CCLabelTTF labelWithString:@&& fontName:@&Arial& fontSize:32];
_label.color = ccc3(0,0,0);
_label.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:_label];
[self runAction:[CCSequence actions:
[CCDelayTime actionWithDuration:3],
[CCCallFunc actionWithTarget:self selector:@selector(gameOverDone)],
- (void)gameOverDone {
[[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
- (void)dealloc {
[_label release];
_label = nil;
[super dealloc];
注意这里有两个不同的对象:一个scene和一个layer。一个scene可以包含很多layer。不过目前这个只有一个,这个layer只是放置了一个label在屏幕中心,并schedule了一个3秒会自动返回Hello World场景的事件。
最后,加入一些极为简单的游戏逻辑进去。首先,记录一下被主人公的飞镖干掉的靶子。在HelloWorldLayer类中加入一个成员变量,在HelloWorldLayer.h中的@interface块儿加入如下:
int _projectilesD
在HelloWorldLayer.m里,导入GameOverScene类:
#import &GameOverScene.h&
在update方法中,增加飞镖摧毁靶子的数量并检测获得胜利的条件,在removeChild:target:之后加入:
_projectilesDestroyed++;
if (_projectilesDestroyed & 30) {
GameOverScene *gameOverScene = [GameOverScene node];
_projectilesDestroyed = 0;
[gameOverScene.layer.label setString:@&You Win!&];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
当有鬼头靶子越过了屏幕左侧,你就输了,修改spriteMoveFinished方法,在tag == 1 case中removeChild:sprite:方法之后加入:
GameOverScene *gameOverScene = [GameOverScene node];
[gameOverScene.layer.label setString:@&You Lose :[&];
[[CCDirector sharedDirector] replaceScene:gameOverScene];
编译并执行,现在你胜利或失败后会进入game over场景中,根据条件的不同会显示相应信息。
源码拿来!Gimme The Code!
就到这里!这是到目前为止所有的源码下载地址
何去何从?Where To Go From Here?
这个工程非常适合作为刚刚入门Cocos2D的程序员,你完全可以添加些新的功能进来。比如可以添加一个条形图表,用来指示在你获得胜利前一共击毁了多少靶子(参考Cocos2D的test工程里的drawPrimitivesTest),还可以为鬼头靶子加入一个很炫的死亡动画(参考ActionsTest,EffectsTest和EffectsAdvancedTest),也可以加入一些新的声音,素材或者游戏逻辑。尽情发挥你无边无际的想象力吧!
如果你想继续这个系列教程,请看第二篇&,或者第三篇&!
另外,如果你想学习更多有关Cocos2D的内容,请跟随我的其他系列教学,&, 或者&
我自己也是刚刚接触Cocos2D,同样也有很多需要学习的。如果你有更好的想法或点子,完全可以以此工程为基础添加内容。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:152850次
积分:2044
积分:2044
排名:第9797名
原创:27篇
转载:157篇
评论:15条您的当前位置: > 正文
COC玩家制作不一样的部落战这样更有趣,现在部落战的模式大家都满意么?如果觉得还是缺乏激情与战场厮杀的刺激的话,不妨来看看以下这位玩家的绝妙构思吧!
部落战,没有双方的对打怎么行!放学别走约个时间较量一番岂不是比你攻我守更好玩么!
情景模拟 双方各自兵出兵 狭路相逢勇者胜!
地图大致分为四部分,分别放置城堡、城墙和兵。有点类似足球的玩法。
为了保持一定的可玩性,甚至不能看到对方最末的布局,增加对战的变数
围墙5个一排可引导兵绕墙 增加策略性,你可以为你的阵地布置迷宫似的围墙。
对战场景概念图1
对战场景概念图2
对战场景概念图3
看完这篇文章有何感觉?已经有0人表态
文明上网,理性发言;请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的评论。如何设计优雅的移动游戏?
发表于 17:35|
作者Mike Lazer-Walker
摘要:对于开发者而言,关注游戏的复杂性在于,在获得新玩家的同时鼓励拿起就玩却不失深度或牺牲时间。优雅的设计不仅仅是理想状况,而是必要的特性,因此,认识到简单并不等于肤浅,是设计好的手机游戏所至关重要的。
设计移动游戏是一个非常有意思的想法,理论上,开发智能手机或平板电脑游戏与其他平台游戏设计没有根本的不同。移动游戏在传统系统属性上与其他类型以及平台极其相似,无论你想创造一个开心农场,使命召唤还是国际象棋。但实践中,想要创建一个成功的移动游戏完全是另一回事。有很多其他的顾虑,从市场饱和、难以被发现,到玩法定型及设备的尺寸因素等,由于这些原因,作为一个设计师来说创造一个优秀的手机游戏就像在玩“困难模式”。所有这些不同的因素集合到一起,意味着最成功的移动游戏倾向于优雅的规则集。也就是说,它们需要努力变得更深刻并有意义,但同时却需要从一组最小的简单规则中产生。肯定有更华丽的巴洛克式的游戏,但不管你衡量成功的标准是什么,确实很少有成功的手机游戏坚持华丽风格。那么,我们如何在游戏中实现这些优雅的设计?让我们来看看移动游戏的两大特征——游戏时长和交互方法,另外看下几种适用于移动平台的系统设计方法。游戏会话时长玩家玩手游相较于其他平台有很大不同。玩家需要在碎片化的时间内有游戏可玩,比如排队或者上厕所的时候,但是他们也希望游戏更加有意义,可以长期玩下去。研究表明iOS游戏会话时长大多介于一到两分钟之间,与此同时,大多数手机游戏实际在家里玩的时间要比路上更多。想要让你的游戏这两种情况下,在乐趣和奖励机制之间做到平衡是一个极有挑战性问题。为了帮我们思考设计这两种情况,把游戏想作一组反馈循环会很有帮助。在任一时间点上,你的游戏都有一个核心的认知模型。在这个基础上,你需要执行一些操作,让游戏给你反馈,这反过来又会影响这个来完善这个模型。关于这些反馈循环的关键一点是,它们是碎片化的;在任何时刻,可能有任意数量级嵌套的反馈循环。比如,让我们思考在玩愤怒的小鸟时发生了什么。让我们通过动作来开始,每一关中弹射小鸟穿过地图达成预计目标的同时,它也给了你相应的反馈:你是否破坏了你想要破坏的箱子或者小猪?小鸟的弹射轨道(轨道在鸟降落后依然可见)是否和你所想的一致?这些信息将影响你未来的弹射。退一步来说,这个游戏最小的度量单位是关卡。每个关卡还充当它自己的反馈和奖励的封闭系统: 通关让你获得一到三颗星星,鼓励你发展必要的技能来真正 '战胜' 它。总体来说,所有这些关卡本身也形成一个反馈循环和叙事模式,随着时间的推移你能清晰地知道整体的进程,另外它们让你知道相对于整体系统,你的技巧处于什么层级。我们可以继续延伸,但我认为基本概念是明确的。再次声明,这不仅仅是移动游戏才存在的理念。如果缺乏想时时刻刻的玩你的游戏的冲动或是看不到总体意义上的个人发展,那么可以说无论是在何种平台,你的游戏还有很大的改进余地。游戏会话的时长设计是相当重要的。它可以是一个即时反馈乐趣的游戏,同时还具有足够长的最小系统性循环,哪怕把玩几分钟,依然会让人觉得有趣。在玩愤怒的小鸟一两分钟内,你就可以体验游戏反馈循环的多个完整的迭代,即使是在如此短的会话时长内依然给人一种畅快感。同时更高级别的反馈循环的存在,意味着这些微瞬间的乐趣并不会破坏长期有意义的游戏体验。控制器难题电子游戏的平台——掌机、PC甚至商场柜机,它们相对于智能手机或平板电脑来说有大量的输入端。许多伟大的移动游戏找到独特的方式来使用多点触控或iPhone的加速器,而不是把大量的虚拟按钮显示在屏幕上,但iOS设备的输入方式仍然比其他形式的数字游戏少得多。这造成了一个艰难的设计挑战:怎么才能让有限输入的游戏系统更有趣,更有意义并更深入?这是游戏设计专业的学生相讨论很频繁的主题,对有抱负的设计师创建一个一键式的游戏更是永恒的课题,但iOS的限制,常常使其不仅是一个学术问题。归根结底,这是一个类似游戏会话时长的问题:你如何创造一个简单亲切的游戏系统,同时又不抛弃其他平台上的游戏的深度和游戏性。在游戏中构建交互的一个常用方法是将游戏的正式的要素减少为“名词”和“动词”。 让我们用《超级马里奥》来举例。马里奥包含两个“动词”——他可以跑和跳。马里奥的挑战来自于游戏引入并组织了一系列名词,用来给提供给动词发挥的空间。这些名词构成了不同的障碍物,你必须使用这两个动词的有趣并唯一的组合来克服这些障碍物。当然,马里奥如果只会跑或者跳那将非常无聊。但是即使只需要6个按键(4个方向键和跑跳键)就能玩转的马里奥这样的游戏,想在触屏上理想地实现也在很多方面非常复杂,这也就是为什么很少有 2D 平台类游戏能在 iOS平台上成功的原因。所以如何让游戏在有限的输入下更有内涵也更复杂?在这个名词和动词为框架的前提下,基本上有三种方式来增加游戏复杂性。我们可以添加一个新的输入,使用现有的输入添加一个新的动词或者我们可以把现有的动词赋给更多的名词,用新的意义来渲染动词。第一个选项是通常会增加我们所不希望看到的复杂性,但是其他两个处理恰当的话可以非常有效。让我们看看一些知名移动游戏的例子,使用这些方法后在没有改变核心游戏交互情况下增加了额外的深度。HundredsHundreds就是一个在不增加游戏动词复杂性下增加新的动词的很好的例子。最初,“触摸气泡使其增长”是唯一一个需要处理的动词,随着游戏的发展,介绍了新类型的对象:慢慢地随着时间时间推移而缩小的气泡,会刺穿触碰到的物体的齿轮,会将气泡冻结在原地的冰球等。这些东西很容易变得非常复杂,但至关重要的是,它们都没有打破“点击一个对象去做什么的规则”,尽管可能的动词数量会相当大,但它们通过简单的方式保持一致。它们之间的交互非常丰富,比如使用冰球冻结危险的齿轮,使其无害。这种交互令人满意,同时与系统交互的基本方法依然相当简单。Threes益智游戏Threes体现了另一种方法,不去改变任何你在游戏中能做的事情,但却在复杂度和策略层级上进行管理。在这个游戏中,它的规则保持不变。从开始到结束,唯一的动词是“滑动滑块”,除此之外没有任何变化。因为系统规则是以可预测的频率出现新的物体,所以游戏展现出的复杂度是随着进程而发生的自然结果。当游戏开始的时候屏幕上只有少量小数字的方块,做决定非常容易。当你开始平衡底层数字建立新的更高数字的时候,同样一个动词背后突然就有了更多意义和细微差别。这两个都是伟大的游戏,它们表面上提供了简单的玩法,但对在何处如何增加复杂度及动词的意义这点上,它们进行了极有深度的处理。两者之间的方法可能不同,但都做一个值得称赞的工作,那就是将一些复杂性从入门的关卡中转移出来,这使它们更容易上手。优雅现在我们已经通过两个不同的角度探索了设计游戏。思考你系统的反馈循环,以及管理相对长度的迭代,可以帮助设计不管是10秒钟还是1个小时都很有趣的东西。认识到你可以通过处理游戏里的动词来增加游戏复杂度,可以帮助你在不牺牲获取新玩家的同时,增加游戏的策略深度。最终,这两个概念展示了类似的结果:游戏的深度和系统性的复杂性,虽然相关,却不一定需要等价。关注在你的游戏的复杂性在于可以帮助使你的游戏尽可能多的获得新玩家,并鼓励游戏拿起就玩却不失深度或者牺牲长时间娱乐性。再次声明,这些概念在游戏设计世界并不是新东西。特别是,设计博客作者Dan Cook在他的文章 ""中谈到了很多嵌套反馈循环以及Anna Anthropy 和Naomi Clark的书""中深入探索了游戏的动词概念化背后意味着什么。但这些问题在移动平台更恶化了。在移动平台的背景下,保持尽可能简短并自我包含的游戏最低层级循环是非常重要的,但与此同时还不能丧失更大愿景的游戏深度。触摸屏控制的实用性使得在输入层级上增加的复杂性和微差别十分困难,因此在更高层级的系统上也能为富有经验的玩家提供高级的游戏体验比以往更加重要。手机游戏的严苛特性意味着优雅的设计不仅仅是理想状况,而是必要的特性。认识到简单并不等于肤浅,是设计好的手机游戏所至关重要的。英文文章来源:,译文出自:(责编/唐小引)
推荐阅读相关主题:
CSDN官方微信
扫描二维码,向CSDN吐槽
微信号:CSDNnews
相关热门文章

我要回帖

更多关于 做蛋糕小游戏大全 的文章

 

随机推荐