IvanK 库介绍

本文介绍一种IvanK JavaScript库,以及在Tizen上如何使用它。

简介

IvanK库是一个开源的JavaScript图形库。 它小,简单且很轻。 它使用WebGL渲染图形,并且在浏览器(也在移动设备)中运行,且支持WebGL。

要在你的Tizen Web应用程序中使用IvanK库: 

或者 

  • 直接链接你的应用程序到最新的版本:
<script type="text/javascript" src="js/ivank.js"></script>

用IvanK些演示和工程。 其中的两个用于创建本文中的Tizen Web示例应用程序。

你可以在这个向导中找到很用的关于IvanK库的信息。 API文档可以在这里找到。

示例应用程序

从这篇文章中,我们使用IvanK主页上的演示源代("Box2D" 和 "Pseudo 3D"),创建两个Tizen Web示例应用程序(IvanKBox2D 和 IvanKPsuedo3D)。

该示例应用程序使用完全Tizen 视图(720x1280),并且在Tizen SDK 2.2.1上测试过。

如何用IvanK库工作

这节描述些关于用IvanK库工作的基本问题。 请参考IvanK Lib主页以获取更多信息。

关于IvanK的座标系统如下所示:

图1 IvanK 的座标系统

这个是以像素为单位。

IvanKPseudo3D

首先,我们集关注IvanKPseudo3D示例应用程序。 如何创建这样的一个应用程序呢?

第一步就是在你的DOM结构中创建一个<canvas>元素。

<canvas id="c" width="720" height="1280"></canvas>

正如你所看见的,canvas 适合HD(720x1280)分辨率。 canvas id 属性用来创建一个Stage对象,这个对象是为了IvanK作显示树的根源(请看IvanK向导的类层次一节)。

stage = new Stage("c");

当我们有Stage的时候,我们就可以创建其他对象。 我们将他们作为Stage的后代来显示他们。 我们创建一个新的Sprite,且设置它的座标:

s = new Sprite();
s.x = stage.stageWidth/2;
s.y = stage.stageHeight/2;

我们也可以如下设置它的旋转和大小:

s.rotation = Math.random()*360;
s.scaleX = s.scaleY = 0.5 + Math.random();

我们将新创建的对象添加到Stage中:

stage.addChild(s);

然而,在IvanKPseudo3D示例应用程序中,它看起来更复杂一点,这是因为我们的地球应用有一个特别的形状。 下面的代码片断用于给出在我们的地球工程上的形状和3D效果:

vrt = []; ind = []; uvt = [];
var lat, lon, x, y, z, p;

for (var i=0; i<=n; i++)        // rows
    for (var j=0; j<=n; j++)    // cols
    {
        lat = -Math.PI/2 + i*Math.PI/n;
        lon =  Math.PI   + j*Math.PI/n;
        x = Math.cos(lat) * Math.cos(lon);
        y = Math.sin(lat);
        z = Math.cos(lat) * Math.sin(lon);
        p = 9/(8+z);            // perspective
        vrt.push(p*x, p*y);
        uvt.push(0.5*j/n, i/n);
        if(i<n && j<n)          // 6 indices for 2 triangles
           ind.push(nn*i+j, nn*i+j+1, nn*(i+1)+j, nn*i+j+1, nn*(i+1)+j, nn*(i+1)+j+1);
    }

vrt, ind, uvt 分别是 vertices, indices 和 coordinates,它们应用在纹理映射上。 

意:本文不会去解释上面的代码片断是如何工作的。 如果你想要知道更多,看这篇文章。 它描述了你可以在ActionScript(IvanK库是基于Flash API)中如何为了3D效果来使用三角形。

现在我们可以使用已计算的数据(vrt, ind, uvt)来描绘一个合适的形状,以及以期望的方式来画一个位图(见图4):

// static shading layer
var sh = new Sprite();  s.addChild(sh);
sh.graphics.beginBitmapFill(new BitmapData("images/shade.png"));
sh.graphics.drawTriangles(vrt, ind, uvt);

上面的代码片断用来为我们的地球对象画一个遮蔽层。

图2:shade.png 位图

图3: earth.jpg 位图

 

我们以相似的方式用一个地球位图来填充Sprite:

s.graphics.beginBitmapFill(bd);
s.graphics.drawTriangles(vrt, ind, uvt);

上面的代码片断是onEF()函数的一部分,该函数通过 Event.ENTER_FRAME 事件触发:

stage.addEventListener(Event.ENTER_FRAME, onEF);

完整的 onEF() 函数如下所示:

function onEF(e)
{
    s.scaleX = s.scaleY = zoom = (3*zoom + 50 + stage.mouseY)*0.25;
    var vel = 0.00005*(stage.mouseX - s.x);
    for(var i=0; i<uvt.length; i+=2) uvt[i] += vel;  // shifting X coordinate
    
    s.graphics.clear();
    s.graphics.beginBitmapFill(bd);
    s.graphics.drawTriangles(vrt, ind, uvt);
}

它用于放大和旋转地球对象。 stage.mouseX 和 stage.mouseY 表示触摸座标。

图4 IvanKPseudo3D 示例应用程序截图(设备)

 

意:这个应用程序在设备和模拟器上面看起来不同。 在设备上背景是白色的,在模拟器上是黑色。 这是因为IvanK的背景是透明的,因此它和父背景(在设备和模拟器上不同)一样。

IvankBox2D

IvankBox2D 示例应用程序使用IvanK 库和Box2dWeb(2.1a.3版本)的物理引擎。 Box2dWeb 物理引擎可执行所有的仿真程序。 IvanK库展示其結果。

意:更多的关于Box2dWeb物理引擎的信息都可以在 Box2dWeb 主页上找到,或者在 developer.tizen.org 上发表的两篇文章中找到:"Box2DWeb 在 Cocos2D-HTML5 游戏中"("Box2dWeb" 章节) 和 "在Tizen 上的 Custom 3D 图形“ ("物理引擎 - Box2dWeb" 章节)。

学习Box2dWeb物理引擎的基本知识也不是本文的讨论范围。 我们建议你在阅读本节之前先看前面的文章,以理解Box2dWeb物理引擎。

var bodies = [];    // instances of b2Body (from Box2D)
var actors = [];    // instances of Bitmap (from IvanK)

"bodies" 和 "actors" 表格保存Box2D 和 IvanK 对象的实例,用以允许简单地访问他们。 如前所述,我们创建一个画面元素和一个Stage对象(请看前面章节)。 下面我们需要为我们的应用程序创建一个背景:

// background
var bg = new Bitmap( new BitmapData("images/winter2.jpg") );
bg.scaleX = bg.scaleY = stage.stageHeight/512;
stage.addChild(bg);

我们用box 和 ball 对象来创建一个Box2D世界,这些对象相互之间可能会冲突。 我们可以定义他们的形状,位置,大小等。

当你有了所有已创建的Box2D对象,你就可以使用IvanK库来画他们。 你需要创建一个新的Sprite对象(演员),设置位图到该对象,对它作刻度,并且将其作为Stage对象的后来进行添加。

// both images are 200 x 200 px
var bxBD = new BitmapData("images/box.jpg");
var blBD = new BitmapData("images/bigball.png");

(...)
var bm = new Bitmap(i<15 ? bxBD : blBD);  bm.x = bm.y = -100;
var actor = new Sprite();  actor.addChild(bm);
if(i<15) { actor.scaleX = hw;  actor.scaleY = hh; }
else     { actor.scaleX = actor.scaleY = hw;      }

actor.addEventListener(MouseEvent.MOUSE_MOVE, Jump);
stage.addChild(actor);
actors.push(actor);

"hw"和"hh"分别表示Box2D实体的半宽和半高。 

另外,我们在Sprite对象上添加一个事件监听器。 MouseEvent.MOUSE_MOVE 事件触发 Jump()函数:

up = new b2Vec2(0, -5);

(...)

function Jump(e)
{
    var a = e.currentTarget;    // current actor
    var i = actors.indexOf(a);
    //  cursor might be over ball bitmap, but not over a real ball
    if(i>=15 && Math.sqrt(a.mouseX*a.mouseX + a.mouseY*a.mouseY) > 100) return;
    bodies[i].ApplyImpulse(up, bodies[i].GetWorldCenter());
}

Jump()函数负责对运动物体产生一个波。 

如前所述,我们需要如下所示的onEF()函数:

function onEF(e)
{
    world.Step(1 / 60,  3,  3);
    world.ClearForces();
    
    for(var i=0; i<actors.length; i++)
    {
        var body  = bodies[i];
        var actor = actors [i];
        var p = body.GetPosition();
        actor.x = p.x *100; // updating actor
        actor.y = p.y *100;
        actor.rotation = body.GetAngle()*180/Math.PI;
    }
}

已经完成的 IvanKBox2D 示例应用程序:

图5 IvanKBox2D 示例应用程序截图 

 

总结

我们希望本文向你展示了,如何在你的Tizen Web 应用程序中使用 IvanK 图形库。 用它来创建不可思议的游戏和应用程序吧!