MyException - 我的异常网
当前位置:我的异常网» 开源软件 » 开源轻量级HTML5游戏发动机gin简介(转)

开源轻量级HTML5游戏发动机gin简介(转)

www.MyException.Cn  网友分享于:2013-10-22  浏览:7次
开源轻量级HTML5游戏引擎gin简介(转)

HTML5 canvas 让程序员自由的绘制想要的图形和动画,使得纯粹基于HTML/Javascript/CSS的游戏铺平了道路。只不过canvas最初并非为游戏而设计,而且除了绘图以外,做游戏还有不少其他事情要考虑,例如鼠标键盘事件、图层、动画等。为了方便程序员开发游戏,游戏框架/引擎陆续被开发出来,gin 就是其中之一。

Project home: https://github.com/huandu/gin

Author: Huan Du (blog , twitter )
Samples: https://github.com/huandu/gin-samples
Live demo: simple sample mouse tracer shape breaker

gin是什么

gin是一个开源轻量级的HTML5游戏引擎,只专注于搭建一个简单可靠的游戏基础设施,让游戏能在网页中高效流畅的运转起来。

gin能做什么

gin提供了游戏开发中各种必须的基础设施,例如固定帧率渲染、鼠标键盘事件捕捉、图层、用户数据等,这些工具都是以最简单直接的方式提供出来,不要求OOP,没有预编译。

gin在设计之初就定位为一个“引擎”,而不是框架。就像汽车引擎不负责提供动力以外的事情一样,gin只专注于驱动游戏运转,不提供表现层的任何工具。

gin的特点

gin的特点是:简单、高效

使用gin只需要写如下的代码,十分简单:

view plain copy to clipboard print ?
  1. $G( 'your-game-container-id' , {}, {  
  2.     render: function (e) {  
  3.         // draw canvas with e.context   
  4.     }  
  5. });  
$G('your-game-container-id', {}, {
    render: function(e) {
        // draw canvas with e.context
    }
});

点击这里 可以看到一个完整而简单的使用gin的例子,源码看这里 。

相比其他现有的js游戏/绘图框架的设计思路,gin摈弃了传统的事件驱动模型,只提供固定帧率的回调接口,所有的鼠标键盘事件都由gin负责接收和缓存。gin的使用者可以在beforerender或render回调中集中处理所有缓存的事件,这样能最大化游戏性能,并提高整体游戏响应速度。

根据google chrome 8.0的profiling结果,在canvas绘图函数中数清除画布数据的clearRect()消耗CPU时间最多,画布越大性能消耗越明显,约是 stroke()一个相同大小的圆或长方形耗时的100倍甚至更多。如果采用传统的事件驱动模型,游戏会立即处理接收到的事件,执行绘图、逻辑判断等等,这样会不断的清除画布,浪费大量的CPU,而实际上只要达到30帧/s就能有流畅体验,在真正需要绘图的时候再绘图才更合理。

而且由于现在所有javascript引擎都是单线程的,脚本执行时无法响应任何DOM事件,浏览器也不会缓存这些事件,如果脚本较长时间占用CPU,还会造成事件丢失,最终影响用户体验。

由gin来缓存事件还有一个好处,这可以让键盘鼠标状态检测变得更简单。gin在beforerender和render回调中传入的事件对象带有 keyStates和buttonStates数组,分别对应键盘和鼠标的按键状态,可以支持多个键盘/鼠标按键同时按下的状态检测。

view plain copy to clipboard print ?
  1. $G( 'your-game-container-id' , {}, {  
  2.     render: function (e) {  
  3.         // check if 'blank' key pressed   
  4.         if  (e.keyStates[0x20]) {  
  5.             // do something   
  6.         }  
  7.   
  8.         // check if mouse L button pressed   
  9.         if  (e.buttonStates[0]) {  
  10.             // do something   
  11.         }  
  12.     }  
  13. });  
$G('your-game-container-id', {}, {
    render: function(e) {
        // check if 'blank' key pressed
        if (e.keyStates[0x20]) {
            // do something
        }

        // check if mouse L button pressed
        if (e.buttonStates[0]) {
            // do something
        }
    }
});

beforerender和render

gin将帧的回调函数分为两个,beforerender和render。这两个回调的唯一区别是beforerender参数e里面没有 canvas context,不能用于画图。这样做的好处是鼓励使用者将与绘图无关的逻辑放入beforerender,让每次脚本运行的时间更短,降低丢失消息的可能性。

遍历鼠标事件

gin缓存的鼠标事件并不能直接暴露出来,这是因为gin支持图层,在不同图层里面,鼠标事件的clientX和clientY都会因为图层的偏移量不同而不一样。如果为每一个图层事先计算好正确的clientX和clientY并且缓存起来,那会造成很大的性能损耗。gin的做法是提供遍历鼠标事件的接口,并在遍历中计算正确的坐标。

view plain copy to clipboard print ?
  1. $G( 'your-game-container-id' , {}, {  
  2.     render: function (e) {  
  3.         if  (e.buttonStates[0]) {  
  4.             // draw mouse move path   
  5.             var  ctx = e.context;  
  6.             ctx.strokeStyle = 'rgb(0,0,0)' ;  
  7.             ctx.beginPath();  
  8.   
  9.             e.traverseHistory(function (cur, prev) {  
  10.                 // the first point   
  11.                 if  (!prev) {  
  12.                     ctx.moveTo(cur.clientX, cur.clientY);  
  13.                 } else  {  
  14.                     ctx.lineTo(cur.clientX, cur.clientY);  
  15.                 }  
  16.             });  
  17.   
  18.             ctx.stroke();  
  19.         }  
  20.   
  21.         // cached mouse history must be cleared explicitly   
  22.         // history will not be really cleared until next beforerender/render is ready to call   
  23.         // so it's safe to clear history many times in one function or in other layer   
  24.         e.clearHistory();  
  25.     }  
  26. });  
$G('your-game-container-id', {}, {
    render: function(e) {
        if (e.buttonStates[0]) {
            // draw mouse move path
            var ctx = e.context;
            ctx.strokeStyle = 'rgb(0,0,0)';
            ctx.beginPath();

            e.traverseHistory(function(cur, prev) {
                // the first point
                if (!prev) {
                    ctx.moveTo(cur.clientX, cur.clientY);
                } else {
                    ctx.lineTo(cur.clientX, cur.clientY);
                }
            });

            ctx.stroke();
        }

        // cached mouse history must be cleared explicitly
        // history will not be really cleared until next beforerender/render is ready to call
        // so it's safe to clear history many times in one function or in other layer
        e.clearHistory();
    }
});

图层

gin虽然并没有把图层的内部类(GinLayer)暴露出来,但它无处不在,例如,所有的回调函数的this都是当前layer的实例。

gin默认会创建一个图层作为所有图层的基础,使用者可以在图层上创建无数的子图层,子图层可以继续嵌套更多子图层。每个子图层有自己的beforerender和render,可以独立的渲染。

图层可以用stop()方法来停止渲染,stop的图层和它的子图层的beforerender/render都不会被调用,直到调用play()让它们继续渲染。

view plain copy to clipboard print ?
  1. $G( 'your-game-container-id' , {}, {  
  2.     start: function () {  
  3.         this .layers( 'sample' , {  
  4.             left: 0,  
  5.             top: 20,  
  6.             width: 100,  
  7.             height: 200  
  8.         }, {  
  9.             render: function (e) {  
  10.                 // your code   
  11.             }  
  12.         })  
  13.         .layers('sample_again' , {}, {  
  14.             play: function () {  
  15.                 // this function will be called once the layer starts to play   
  16.                 this .layers( 'sub_sample' , {});  
  17.             }  
  18.         });  
  19.     },  
  20.     render: function (e) {  
  21.         // it's how to find layer, or even sub-layer   
  22.         var  sample =  this .layers('sample '),  
  23.             sub = this.layers([' sample_again ', ' sub_sample']);  
  24.   
  25.         // do something   
  26.     }  
  27. });  
$G('your-game-container-id', {}, {
    start: function() {
        this.layers('sample', {
            left: 0,
            top: 20,
            width: 100,
            height: 200
        }, {
            render: function(e) {
                // your code
            }
        })
        .layers('sample_again', {}, {
            play: function() {
                // this function will be called once the layer starts to play
                this.layers('sub_sample', {});
            }
        });
    },
    render: function(e) {
        // it's how to find layer, or even sub-layer
        var sample = this.layers('sample'),
            sub = this.layers(['sample_again', 'sub_sample']);

        // do something
    }
});

gin的未来

gin刚刚发布了1.0.0版 ,是一个just work的版本,并且发布了三个例子,放在gin-samples 项目中。

gin未来将首先考虑支持更多的浏览器和平台,特别是移动设备上的支持。对于简单高效的引擎而言,最适合应用的环境就是性能相对较差的移动设备。

其次需要考虑的是实现更强大的图层(layers),现在的图层已经实现了类似于flash MovieClip的各种基本功能,还差key frame没有实现,未来会增加支持。

FAQ

Q: gin的api文档呢?
A: 暂时还没有,有问题请直接联系我(github ,twitter )

Q: gin支持哪些浏览器?
A: 测试过的是Firefox 3.6、Chrome 8.0/10.0,理论上Opera、Safari也会支持。IE就别想了,等IE9支持了canvas再说吧。

Q: gin-samples里面的例子不能正常运行是什么原因?
A: 如果是下载源码运行,需要手动将gin.js拷贝到sample目录里面才能运行。此外,需要保证电脑可以访问网络,因为有些例子使用了jQuery,用的是google dns。如果还不行,请检查一下浏览器是否是gin所支持的浏览器,gin自己没有做任何浏览器检测。

附录

我在开发过程中了解过的游戏/绘图框架包括The Render Engine 、GameJS 、cakejs 、cocos2d ,它们都是非常好的框架,gin从某种程度上说是针对它们的不足而设计的。 :P

gin最开始是我心血来潮写的一个小框架,还未完成就在“给力HTML5 —— 2011 Google HTML5训练营” 第一期活动 中使用,非常意外且幸运的用它实现了第一个可玩的HTML5游戏Raiden 5 (Chrome only) ,在这里 可以围观最原始的gin。

 

文章评论

程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
老程序员的下场
老程序员的下场
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
中美印日四国程序员比较
中美印日四国程序员比较
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
旅行,写作,编程
旅行,写作,编程
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序员和编码员之间的区别
程序员和编码员之间的区别
编程语言是女人
编程语言是女人
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
如何成为一名黑客
如何成为一名黑客
每天工作4小时的程序员
每天工作4小时的程序员
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
漫画:程序员的工作
漫画:程序员的工作
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
10个调试和排错的小建议
10个调试和排错的小建议
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
我是如何打败拖延症的
我是如何打败拖延症的
一个程序员的时间管理
一个程序员的时间管理
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员必看的十大电影
程序员必看的十大电影
那些争议最大的编程观点
那些争议最大的编程观点
程序员的鄙视链
程序员的鄙视链
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
代码女神横空出世
代码女神横空出世
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序员都该阅读的书
程序员都该阅读的书
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
鲜为人知的编程真相
鲜为人知的编程真相
程序员应该关注的一些事儿
程序员应该关注的一些事儿
我的丈夫是个程序员
我的丈夫是个程序员
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有