Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4220863
  • 博文数量: 82
  • 博客积分: 671
  • 博客等级: 上尉
  • 技术积分: 24576
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-18 16:08
个人简介

www.kernel.org

文章分类

全部博文(82)

文章存档

2016年(1)

2015年(3)

2014年(12)

2013年(14)

2012年(52)

分类: 系统运维

2012-10-28 14:57:22

让角色动起来

   当键盘上特定的按键被按下时,为了让我们创建的角色同步地动起来,需要让Gamma来为我们改变对象水平、垂直方向的位置状态。在本章节,我们将实现如下功能:

·         键盘上向左的方向键控制角色往左移动

·         键盘上向右的方向键控制角色往右移动

·         键盘上的空格键控制角色跳跃

按键码

    首先我们得知道这三个按键(左键,右键和空格键)分别对应的键码(译者注:就是我们所说的按键所对应的ASCII)。通过查阅 我可以知道左键对应的ASCII码值是37,右键是39,空格是32

移动角色的函数

    然后,我们得弄清楚Gamma提供了哪些函数可以用于改变角色的位置状态。当游戏开始后,一旦我们给角色下达了向右移动的按键指令,那么角色就会以一个固定的速率动起来。本例中我们主要会用到Gamma提供的 两个API库函数。调用时为其传递参数实现角色向左移动的功能,同理,让角色向右移动时只要将函数的参数改为即可。调用 就可以实现角色的跳跃动作。函数都需要一个按键事件的对象作为其输入参数。

我们使用Gamma提供的 API为按键注册响应处理函数。响应处理函数被调用时系统会为其传递一个键盘事件,用于区分是按键被按下还是按键弹起。

gma.keyHandler.register(37, function (keyEvent) {

    manager.character.move(gma.constants.LEFT, keyEvent);

});

 

gma.keyHandler.register(39, function (keyEvent) {

    manager.character.move(gma.constants.RIGHT, keyEvent);

});

 

gma.keyHandler.register(32, manager.character.jump);

 

    为按键注册消息处理功能的API包含包里,所以在game.js开头的require函数里需要导入gma/events依赖包。

科里化/闭包

    上面的代码不是很优美,我们可以使用Javascript的科里化功能。科里化是一种根据输入参数返回函数的函数,是闭包最伟大的应用之一(译者注)。例如下面的(f1 f2)函数是等价的。创建f2时,根据其第一个输入参数对其进行科里化之后,就只需要一个按键事件作为其输入参数就可以了:

f1 = function (keyEvent) {

    manager.character.move(gma.constants.LEFT, keyEvent);

};

f2 = manager.character.move.curry(gma.constants.LEFT);

 

    所以,前面关于按键消息处理函数的注册代码可以简化成:

gma.keyHandler.register(37, manager.character.move.curry(gma.constants.LEFT);

gma.keyHandler.register(39, manager.character.move.curry(gma.constants.RIGHT);

gma.keyHandler.register(32, manager.character.jump);

 

最终示范代码

require([

    'gma/base',

    'gma/manager',

    'gma/entities/character',

    'gma/events'

],

    function(gma) {

        var manager = gma.manager({

            width : 600,

            height : 500

        });

        manager.character = gma.character({

            left     : 0,

            bottom   : 0,

            width    : 3,

            height   : 6,

            depth    : 3

        });

 

        var myLevel = {

            spawn : {

                main : [15, 24]

            },

            entities : [

                {top:0, left:0, width:30, height:3},

                {top:0, left:36, width:30, height:3}

            ]

        };

        manager.storeLevels(myLevel);

 

        gma.keyHandler.register(37, manager.character.move.curry(gma.constants.LEFT));

        gma.keyHandler.register(39, manager.character.move.curry(gma.constants.RIGHT));

        gma.keyHandler.register(32, manager.character.jump);

 

        manager.init();

    }

);

添加障碍

        Gamma也提供了一些用于定义障碍的对象,这些对象都有自己的行为方式。如果要在游戏关卡里添加障碍,必须将其放置在一个数组里。

    在本篇中,我们会用创建一个从一边移动到另一边的场景障碍,用创建一个在两点之间移动的巡逻障碍,以及用创建一些不断跳跃的障碍物:

entities : [

    gma.platformEnemy({bottom:0, left:45, width:3, height:6}),

    gma.patrolEnemy({bottom:0, left:6, width:3, height:6, limitLeft: 3, limitRight:12}),

    gma.jumpingEnemy ({bottom:0, left:7,  width:1, height:2}),

    gma.jumpingEnemy ({bottom:3, left:8,  width:1, height:2}),

    gma.jumpingEnemy ({bottom:6, left:9,  width:1, height:2})

]

    场景障碍和跳跃的障碍只需要限定其大小和位置即可,而巡逻障碍还需要设置它巡逻时的范围,即最大左右边界点limitLeft limitRight

类型

    如果以普通属性来创建游戏中的障碍物,可以将其设置成一个用户自定义类型。在创建障碍时来引用该类型以降低代码冗余。我们用来定义类型。例如:

manager.addCustomDefinitions({

    types : {

        jumpingJack: ['jumpingEnemy', {

            width    : 1,

            height   : 2

        }]

    }

});

    在定义障碍的类型时,需要将其放在数组里,且数组的第一个元素是类名,用它来实例化一个具体的对象,例如我们所要创建的跳跃障碍的对象;数组的第二个参数是一个对象,该对象里包含了一些属性值,这些属性会被应用到所有实例化的对象上面。

    下面我们通过引用上面定义的jumpingJack类型来重新创建跳跃障碍:

// 此时,引用自定义类型junpingJack

entities : [

    gma.platformEnemy({bottom:0, left:45, width:3, height:6}),

    gma.patrolEnemy({bottom:0, left:6, width:3, height:6, limitLeft: 3, limitRight:12}),

    {type:'jumpingJack', bottom:0, left:21},

    {type:'jumpingJack', bottom:3, left:24},

    {type:'jumpingJack', bottom:6, left:27}

]

提示

    后面我们不再显式的调用函数来创建跳跃障碍,而是通过设置其宽、高属性来定义它们。因为我们已经有了类型这个神奇的法宝(译者注)

模板

    默认情况下,所有被创建出来的障碍都是一个蓝色的方形柱体结构,这是由对象的模板属性决定的。对象的缺省模板是一个立方体,可以用下面的方法来设置其模板属性(虽然这一步操作显得多此一举)

manager.addCustomDefinitions({

    types : {

        jumpingJack: ['jumpingEnemy', {

            width    : 1,

            height   : 2

            template : 'cube'

        }

    }

});

    如果需要自定义障碍的外观,就必须通过创建模板来实现。下面的代码中,我们用模板助手创建了一个绿色的方柱体的模板:

manager.addCustomDefinitions({,

    templates : {

        greencube : ['meshTemplate', {

            mesh : gma.unitCubeInfo.mesh,

            material : {color : "#090"}   // 非常的绿

        }

    }

});

    让后将这个模板应用到前面定义的jumpingJack类型里:

manager.addCustomDefinitions({

    types : {

        jumpingJack: ['jumpingEnemy', {

            width    : 1,

            height   : 2

            template : 'greencube'

        }

    }

});

提示

    默认情况下,Gamma已经提供了蓝色红色模板,可以使我们很方便的就创建红色和蓝色立方体。在 章节的目录里,有模板对象类型的详细介绍,以及它们的用法。

    另外,Gamma中的游戏障碍缺省情况下都有一个默认的类型,使用蓝色模板定义的一个平台障碍

最终示范代码

require([

    'gma/base',

    'gma/manager',

    'gma/entities/character',

    'gma/events',

    'gma/entities/enemy'

], function(gma) {

        var manager = gma.manager({

            width : 600,

            height : 500

        });

        manager.character = gma.character({

            left     : 0,

            bottom   : 0,

            width    : 3,

            height   : 6,

            depth    : 3

        });

        manager.addCustomDefinitions({

            templates : {

                greencube : ['meshTemplate', {

                    mesh : gma.unitCubeInfo.mesh,

                    material : {color : "#090"}

                }]

            },

            types : {

                jumpingJack: ['jumpingEnemy', {

                    width    : 1,

                    height   : 2,

                    template : 'greencube'

                }]

            }

        });

        var myLevel = {

            spawn : {

                main : [15, 24]

            },

            entities : [

                {top:0, left:0, width:30, height:3},

                {top:0, left:39, width:30, height:3},

                gma.platformEnemy({bottom:0, left:45, width:3, height:6}),

                gma.patrolEnemy({bottom:0, left:6, width:3, height:6, limitLeft: 3, limitRight:12}),

                {type:'jumpingJack', bottom:0, left:21},

                {type:'jumpingJack', bottom:3, left:24},

                {type:'jumpingJack', bottom:6, left:27}

            ]

        };

        manager.storeLevels(myLevel);

        gma.keyHandler.register(37, manager.character.move.curry(gma.constants.LEFT));

        gma.keyHandler.register(39, manager.character.move.curry(gma.constants.RIGHT));

        gma.keyHandler.register(32, manager.character.jump);

        manager.init();

    }

);

自定义视角

        Gamma创建的默认视角是跟随角色一起移动的,位于角色前50个单位,z坐标也是50

    在关卡里我们可以在camera标签里设置其属性值来改变视角。在每个关卡里只需设置一个视角。注意:如果在你的关卡里提供了新视角,那么Gamma提供的默认视角将会被覆盖。

    下面这段代码的效果和缺省视角的效果是等效的:

var myLevel = {

     camera : {

         locZ : 50,

         attached : ['character']

     }

 };

 

    接下来,我们设置一个距离角色稍微远一点点,并且总是比角色只高那么一丁点的视角:

var myLevel = {

     camera : {

         locZ : 60,

         attached : ['character',0, 6]

     }

 };

 

阅读(3794) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~