Contenu connexe Similaire à component based html5 game engine (20) component based html5 game engine2. About Me
唐博皞 Boyd Tang
@原木博皞
Startuper/原木游戏工作室 Co-Founder
独立游戏开发者
折腾Flash/HTML5游戏
高端骨灰级游戏玩家 (高玩, 恩=-=)
3. Outline
游戏编程的演变 – 从数据驱动的GameObject结构再
到Entity/Component架构
架构思路 - Entity/Component的实现特点
CraftyJS - HTML5中的Component Based游戏引擎
Demo/Practice – HTML5 CodeJam 48小时作品
4. 如果要做一个游戏,你会怎么写?
有一个Main函数
function main() {
while(/*游戏没结束*/){ /* 在循环里写游戏更新逻辑 */ }
/* 游戏结束出现游戏结果 */
}
更新逻辑是啥?一个player和一堆monster
player.update(); // player需要不断更新
for( var i = 0; i< MAX_MONS; i++){
monsters[i].update(); // 怪物也是
}
那如果Player和Monster有通用的功能呢?
5. GameObject – 经典的数据驱动结构
游戏世界中所有的物体都是
GameObject GameObject
角色,怪物,环境障碍,车
辆,子弹,摄像头,触发器,
Drawable Trigger
灯光
现在在Main函数中怎么写?
for( var i=0; Static Simulated
i<numGameObjects; i++)
gameObjects[i].update();
Player Monster
GameObject是什么呢?由
数据驱动,而非代码写死
6. 如果想在GameObject结构下添加功能呢?
我要这样? 还是这样?
GameObject GameObject
Drawable Trigger Drawable Trigger
Animated Static Simulated
Static Simulated Animated
Player Monster Player Monster
7. 更复杂的情况呢…
GameObject
Drawable Trigger
Static Simulated
Physics Animated
Player Monster
11. 现在的GameEntity结构
Player Monster Props Trigger
Drawable Drawable Drawable
Update
Update Animated
Animated Update
Position Position
Position
Physics Physics Physics
13. 一些关于Entity/Component的常见问题
一个GameEntity可以有多个相同的Component么?
是的,理论上是可以的。一般GameEntity的实现可以根据Component
的ClassName来进行hash,也可以通过给Component实例设置Name
进行hash。如果需要避免冲突,可以选择根据ClassName来实现。
传统的GameObject有个统一的update,GameEntity的
update呢,是一个Component嘛?
其实并不是这样的,GameEntity的update可以是interface,当
Component实现此interface后,即具备了update功能。也可以是事件
驱动下,Component监听发到GameEntity的update事件。
整个游戏世界中GameEntity是全都是同级的么?
GameEntity的实现时,可以增加GameEntityGroup的实现()。这样就
可以对其进行分组管理。
15. Crafty – 用JS将灱活发挥到极致
轻量的体积:14.5KB (Minified&Gzipped)
类似JQuery的选择器用于GameEntity的选择
同时支持Canvas或者DOM进行渲染
(不用Canvas渲染连IE6都能跑!)
事件驱动,有非常好用的Event系统
支持SpriteSheet,碰撞检测,声音等
16. Crafty的选择器
通过查询Component来进行选择
Crafty(“mycomp”);
Crafty(“hello 2D mycomp”);
Crafty(“hello, 2D, mycomp”);
第一个返回全部具有mycomp组件的GameEntity
第二个返回全部同时具有hello, 2D和mycomp组件的
GameEntity (AND操作)
第三个返回至少有这些组件之一的全部GameEntity
(OR操作)
17. Crafty的基本使用
创建GameEntity
var player = Crafty.e();
为GameEntity添加Component
player.addComponent(“2D, DOM”) //添加2D组件,使用DOM
渲染
也可以在创建GameEntity时添加 Crafty.e(“2D, DOM”);
为GameEntity设置属性
player.attr({ x:5, y:5, w:100, h:100}); //当具有2D组件时,
GameEntity即拥有了x,y,w,h等属性
级联操作
player.addComponent(“2D, color”)
.color(“red”).attr({ w:100, h:100});
18. 自定义你的Compoent
使用Crafty.c()方法进行自定义
Crafty.c(“mycomp”, { //为自定义组件命名
init: function() { //init函数在被组建被添加时调用
// 自定义组件函数中的this,均指向所属的Entity
this.requires(“2D, Color”); //requires方法可指定依赖组件
this.w = 32;
this.h = 32;
this.color(“red”);
//也可以这样写: this.attr({w:32, h:32 }).color(“red”);
},
myfunc: function() { /*我的方法实现*/ }
})
19. Crafty的事件系统
通常事件会在自定义组件的init中绑定
Init: function() {
this.requires(“2D, DOM, Mouse”);
//可以使用bind方法绑定事件
this.bind(“Enterframe”, function(e){ //Enterframe可任意监听
… // 即update 函数
});
this.bind(“Click”, function(e){ //当添加Mouse组件后可用
…// 当鼠标点击Entity时的处理函数
})
}
事件触发: this.trigger(“event”,data);
20. 属性与Setter方法、Change事件
属性获取、更改(若无setter, 首次使用即定义)
attr(name, value)或者attr({name:value})均更改属性
attr(name) 可获取属性
针对特定属性的处理:setter
Crafty.c(“mycomp”, {
_hp: 100,
init: function() {
this.setter(“hp”, function(v){ this._hp = v; /*一些判断
*/});
}
});
针对全部属性改变的事件:Change
this.bind(“Change”, function(){ /*一些判断*/ })
21. Crafty中的关卡场景定义
关卡场景定义
Crafty.scene(“sceneName”, function(){
…//执行一些函数,创建一堆Entity,设置背景,bhla bhla…
});
关卡场景调用
Crafty.scene(“sceneName”); // =_____= 没啥好说的…
关卡场景切换时发生了啥?
开始某关卡时,Stage当前所有具有2D组件的Entity都会被销毁
若希望保留某些Entity,给它添加Persist组件即可
关卡切换时SceneChange事件将触发
23. 使用SpriteSheet
使用Crafty.sprite函数创建Sprite组件
Crafty.sprite(16, 16, “spirte.png”, { // 定义每格长宽
grass1:[0,0], // 将此SpriteSheet的0,0格位置定义为grass1
grass2:[1,0], // 同上定义1, 0格为grass2
grass3:[2,0],
grass4:[3,0],
flower:[0,1], // flower定义在0,1格
bush:[0,2],
player:[0,3], // 玩家定义在0, 3格位置
});
定义Sprite组件后,创建GameEntity
Crafty.e(“2D, DOM, flower”);
//此时组件已定义,将渲染0,1 格的flower
24. 使用Sprite动画
添加SpriteAnimation组件即可使用Sprite动画
var player = Crafty.e(“2D, DOM, player, SpriteAnimation”)
.attr({ x:100, y: 100})
.animate(“left”, 6, 3, 8) // 定义left为x:6, y:3格开始到x:8格
.animate(“right”, 9, 3, 11)// 同上
.animate(“up”, 3, 3, 5)
.animate(“down”, 0, 3, 2);
播放动画
player.animate(“left”, 10); // 在10帧时间内播放left动画
其他函数
stop(), reset(), isPlaying(name)
26. Crafty中的键盘操控
基本组件:Keyboard组件
函数:isDown(key) //可以在Crafty.keys中找到映射
事件触发:KeyDown,KeyUp
高级组件:Multiway组件(依赖Keyboard)
函数:multiway([speed], {W: -90, S:90, D:0, A:180} );
事件触发:NewDirection(方向切换时), Moved(发生移动时)
便捷组件:Fourway, Twoway (依赖Multiway)
fourway // wasd四方向控制
twoway // ad 双方向,w跳可在Gravity组件中使用
27. Crafty中的鼠标操控
基本组件: Mouse 组件
函数:areaMap(polygon) //传入一个Crafy.Polygon作为检测区
事件触发: MouseOver, MouseOut, MouseUp, MouseDown,
Click
高级组件:Draggable组件(依赖Mouse组件)
函数: startDrag, stopDrag, enableDrag, disableDrag
事件触发: StartDrag, StopDrag
对于移动平台的Touch,同样使用Mouse组件
暂无对MultiTouch的支持