Wednesday, December 28, 2011

My Xmas Present

今年的boxing day, 3DS有折扣$30變成了$138, 因此3DS就成了我的耶誕節禮物啦. 本來遊戲考慮買Super Mario 3D Land的, 結果最後還是買了薩爾達時之笛.......

我不知道貢獻多少次錢給薩爾達時之笛這款遊戲了, 當年我的N64只有一張卡匣就是時之笛......, Game Cube也買了時之笛復刻版. 不過還是希望老任把風之指揮棒也重出在3DS上吧, 我會捧場的 :)

3DS內建的小遊戲比想像中有趣, AR的那個遊戲作的挺不錯的, 而且3D攝影的功能也蠻好玩的, 只是螢幕很小, 加上濾光片的角度有限, 玩的時候頭稍微亂動一下3D效果就跑掉了.... 而且打個十幾分鐘後再回來看電腦螢幕, 眼睛就會很不舒服. 不過整體而言, 還蠻不錯的, 尤其這個價格還算便宜, 感覺蠻划算的.




Saturday, December 10, 2011

在PC跟MAC間共用滑鼠/鍵盤

由於LynxEngine是一個跨平台的引擎, 所以我常常要在PC跟MAC上來回的工作. 目前我MAC的主要工作機器是MBP, 所以我都是外接螢幕再加上藍芽鍵盤/滑鼠來工作的, 每次都要來回切換輸入裝置實在很麻煩, 最沒效率的因為MAC鍵盤的配置跟PC鍵盤不同, 使用的時間又相對較少, 所以每次在MAC寫code時速度都會變慢很多.

這次回台灣渡假, 無意中發現台灣PC Home居然已經有賣這條j5 create JUC 400的線了, 而且還是24小時到貨, 二話不說買了一條. 目前使用了一個月, 非常的滿意, 在MAC上寫code的速度也增加了不少.這條線主要的功能就是讓使用者可以在PC跟PC或是PC跟MAC間共用鍵盤以及滑鼠, 同時還可以共用剪貼簿, 所以從PC上複製/移動資料夾到MAC也可以實現了! 另外附加的功能是還可以跟iPad/Android共用鍵盤/滑鼠喔.

非常推薦給同時有在開發PC跟MAC/iPhone遊戲的人.



Thursday, November 10, 2011

Vertex Shader Based Bokeh DOF for UE3

今年快結束了卻只po了三篇文章, 所以休假前po一篇來充充數吧 :)

最近半年都在幫UE3最佳化他們的DX11的部分還有增加一些AMD的新功能像是Eyefinity. 有一些更新已經被Epic整合進UE3了, 有一些則沒有. 今天剛丟出去的是原本只支援DX11的新功能-Bokeh DOF. 原本Epic是使用Geometry Shader來實作的, 但是因為輸出的point sprite數量很龐大, 很容易就超過了硬體能承受的頻寬而降低效能, 所以我將他移到了Vertex Shader來實現, 同時帶來另一個好處就是DX9的硬體也能使用這個特效了.

有UE3的授權的人請到這裡下載程式吧, 使用UDK的人就得等到Epic把他整合進去了, Epic是說他們之後會想整合進去, 至於何時就不清楚了......

Wednesday, August 03, 2011

LynxEngine Update : Web Player

前幾天為了JNI而上網找了一些資料, 意外發現其實透過JAWT可以輕易將native的東西render到browser上, 這樣透過JNI來橋接native code跟java, 就可以一次解決Android跟Web兩個平台了. 花了一個晚上試了一下, 結果出奇的容易. 然後寫了個java wrapper把輸入訊號送到native就大功告成了.

把之前的Script Game放上瀏覽器, 可以順利的運作, Lua跟Mono都可以正確執行無誤. 等再把JNI部分全部完成後, 應該移植到Android就沒甚麼大問題了.


Sunday, July 17, 2011

LynxEngine Update : Script System

很久一段時間都沒有新文章了, 因為前一陣子一直在忙著做iPhone的遊戲, 引擎也就很少進展了. 但是由於人力, 以及時間等等因素, 案子進展的的很不順利. 接著六月開始我又得一個人帶小孩, 上下學接送, 洗澡樣樣得自己來所以忙到連iPhone遊戲的案子都沒時間作了. 於是只能趁小孩睡覺後的一兩個小時, 試試引擎的script system. 其實引擎的script系統早就玩成了, 之前是使用Lua為主, 但是從來沒用script來做過任何遊戲demo, 所以這一兩個小時的時間就正好用來試試script系統以及補強一些功能.

在修改了一些功能後, LnxEngine可以僅依靠Lua script完成整個遊戲的介面以及遊戲gameplay. 這次試作了一個橫向卷軸遊戲, 下面是遊戲的影片, 背景都是2D的sprite, 只有人物是3D的. 之後會繼續作作其他類型遊戲來試試看script system的能力.




之後上網看了一下Mono, 才發現Mono runtime 其實可以直接內嵌到應用程式中, 所以任何符合.Net 的bytecode, 就可以藉由Mono runtime來執行. 花了幾天時間上網查了一些資料, 發現整合Mono沒想像中的難, 不過原本的 C#+C++/CLI+Native的作法在Mono上卻行不通於是只好改用類似swig的作法來橋接Managed code跟Native code, 缺點是要花多一點時間來寫wrapper. 之後使用了C#來完成了之前用Lua作出的卷軸遊戲. 使用Mono最大的好處是, 任何能編譯成.Net bytecode的語言都可以用來作為引擎的script語言, C#, VB, JavaScript, Java都沒問題, 甚至Lua都有人作出bytecode編譯器, 所以彈性可以說是非常的高. 目前Lua與Mono是併存於LynxEngine中, 但將來應該會慢慢轉移到以Mono為主.


以下就列出C#以及Lua的code 作個比較, 相較起來Mono還是更有彈性.

C# script list



using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Diagnostics;
using LynxEngine;
//----------------------------------------------
// 說明:
//----------------------------------------------
public class CBGLayer
{
public float ObjectWidth, ObjectHeight;
public uint ObjectInterval;
public float PosY;
public uint NumObjects;
public float ScrollingSpeed;
public CDynamicObj[] Objects = null;
public float[] Pos = null;

public CBGLayer()
{
}

public void CreateObjects(
CScene scene,
int n,
String name,
String filename,
CRenderableObj.DEPTHLAYERTYPE dl)
{
Objects = new CDynamicObj[n];
Pos = new float[n];
for (uint i=0; i < Objects.GetLength(0); i++)
{
Objects[i] =
scene.CreateDynamicEntity();
Objects[i].CreateSprite(
name,
filename,
ObjectWidth,
ObjectHeight);
Objects[i].UpdateTransform();
Objects[i].SetDepthLayer(dl);
scene.AddDynamicObj(Objects[i]);
}
}
}
//----------------------------------------------
// 說明:
//----------------------------------------------
class CPlayer : CDynamicObj
{
public enum STATE
{
RUN = 0,
JUMP,
ATTACK1
};

public class CState
{
public CSound Sound = null;
public CAnimation Animation = null;
}

public STATE State;
public CState [] States = null;

public CPlayer(IntPtr ptr)
: base(ptr)
{
}

public void SetState(STATE state)
{
States[(uint)State].Sound.Stop();

SetCurrentAnimation(
States[(uint)state].Animation);
States[(uint)state].Sound.Play();
State = state;
}
}
//----------------------------------------------
// 說明:
//----------------------------------------------
public class CScrollingGamePage : CUIPage
{
bool GameConsoleIsRunning = false;
CBGLayer[] BGLayers = new CBGLayer[4];
CPlayer Player;
CSound BGM;
CVector2 [] BackgroundUV = new CVector2 [2];
CScene Scene;

new public void OnCreate()
{
Scene = GlobalVar.SceneSystem.AddScene();
Scene.SetName("Scrolling Game Scene") ;

CCamera Camera = Scene.CreateCamera();
Camera.Create();
Scene.SetCurrentCamera(Camera);
CCameraContainer CameraContainer =
(CCameraContainer)Camera.GetContainer();

CVector3 CameraPos =
new CVector3(10, 10, -35);
CameraContainer.SetPosition(CameraPos);
CVector3 CameraLookPos =
new CVector3(10, 10, 0);
CameraContainer.LookAt(CameraLookPos);
CameraContainer.UpdateProjectionMatrix(
(float)(GlobalVar.GraphicsSystem.GetBackbufferWidth()) /
(float)(GlobalVar.GraphicsSystem.GetBackbufferHeight()));
CameraContainer.UpdateViewMatrix();

Scene.LoadBackgroundTexture(
"../texture/scene/map00/background0.tga");
BackgroundUV[0] = new CVector2();
BackgroundUV[1] = new CVector2();
BackgroundUV[0].x = 0.0f; BackgroundUV[0].y = 0.0f;
BackgroundUV[1].x = -0.5f; BackgroundUV[1].y = 0.0f;
Scene.SetBackgroundTextureUVOffset(
BackgroundUV[0].x, BackgroundUV[0].y,
BackgroundUV[1].x, BackgroundUV[1].y);

Player = new CPlayer(
Scene.CreateDynamicEntity().GetPtr());
Player.CreateModel(
"Player",
"../model/dynobj/boy/boy.mdl");

Player.SetDepthLayer(
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_3);
Player.Yaw(-90.0f, MATHORDER.LYNX_MATH_POST);
Scene.AddDynamicObj((CDynamicObj)Player);

Player.States = new CPlayer.CState[3];
Player.States[(uint)CPlayer.STATE.RUN] =
new CPlayer.CState();
Player.States[(uint)CPlayer.STATE.RUN].Animation =
Player.LoadAnimation("../model/dynobj/boy/run.ani");
Player.States[(uint)CPlayer.STATE.RUN].Sound =
GlobalVar.SoundSystem.LoadSound(
"Run",
"../sound/run.wav");
Player.States[(uint)CPlayer.STATE.RUN].Sound.SetLoops(-1);

Player.States[(uint)CPlayer.STATE.JUMP] =
new CPlayer.CState();
Player.States[(uint)CPlayer.STATE.JUMP].Animation =
Player.LoadAnimation("../model/dynobj/boy/jump.ani");
Player.States[(uint)CPlayer.STATE.JUMP].Sound =
GlobalVar.SoundSystem.LoadSound(
"Jump",
"../sound/jump.wav");

Player.States[(uint)CPlayer.STATE.ATTACK1] =
new CPlayer.CState();
Player.States[(uint)CPlayer.STATE.ATTACK1].Animation =
Player.LoadAnimation("../model/dynobj/boy/attack1.ani");
Player.States[(uint)CPlayer.STATE.ATTACK1].Sound =
GlobalVar.SoundSystem.LoadSound(
"Attack1",
"../sound/attack1.wav");

BGLayers[0] = new CBGLayer();
BGLayers[0].ObjectWidth = 160;
BGLayers[0].ObjectHeight = 320;
BGLayers[0].ObjectInterval = 110;
BGLayers[0].PosY = 320-35-320;
BGLayers[0].ScrollingSpeed = 1;
BGLayers[0].CreateObjects(
Scene, 6,
"Tree",
"../texture/scene/map00/tree_23.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_5);

BGLayers[1] = new CBGLayer();
BGLayers[1].ObjectWidth = 256;
BGLayers[1].ObjectHeight = 256;
BGLayers[1].ObjectInterval = 256;
BGLayers[1].PosY = 320-35-256;
BGLayers[1].ScrollingSpeed = 2.5f;
BGLayers[1].CreateObjects(
Scene, 3,
"Tree2",
"../texture/scene/map00/tree_01.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_4);

BGLayers[2] = new CBGLayer();
BGLayers[2].ObjectWidth = 128;
BGLayers[2].ObjectHeight = 64;
BGLayers[2].ObjectInterval = 110;
BGLayers[2].PosY = 320 - 22 - 64;
BGLayers[2].ScrollingSpeed = 6.0f;
BGLayers[2].CreateObjects(
Scene, 6,
"Bush",
"../texture/scene/map00/bush_08.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_3);

BGLayers[3] = new CBGLayer();
BGLayers[3].ObjectWidth = 64;
BGLayers[3].ObjectHeight = 64;
BGLayers[3].ObjectInterval = 64;
BGLayers[3].PosY = 320 - 40;
BGLayers[3].ScrollingSpeed = 6.0f;
BGLayers[3].CreateObjects(
Scene, 9,
"GroundTile",
"../texture/scene/map00/ground.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_2);

BGM = GlobalVar.SoundSystem.LoadSound(
"BGM",
"../sound/BGM.wav");
BGM.SetLoops(-1);

Scene.SetRenderMode(CScene.RENDERMODE.RENDER_SIMPLE);
Scene.SetSortMode(CScene.SORTMODE.SORT_BY_DEPTH_LAYER);
Scene.Setup();
}
//----------------------------------------------
// 說明:
//----------------------------------------------
new public void OnInit()
{
GlobalVar.SystemMouse =
(CMouse)(GlobalVar.InputSystem.FindDevice("System Mouse"));
GlobalVar.Engine.DeleteLastUIPage();
Player.SetState(CPlayer.STATE.RUN);

for (int i = 0; i < BGLayers.GetLength(0); i++)
{
for (int j=0; j < BGLayers[i].Objects.GetLength(0); j++)
{
BGLayers[i].Pos[j] = (int)(j*BGLayers[i].ObjectInterval);
}
}

BGM.SetVolume(0.6f);
BGM.Play();
}
//----------------------------------------------
// 說明:
//----------------------------------------------
void AnimationLoop()
{
if (GlobalVar.SystemMouse.ButtonStatus(CMouse.RBUTTON) &&
Player.State == CPlayer.STATE.RUN)
{
Player.SetState(CPlayer.STATE.JUMP);
}

if (GlobalVar.SystemMouse.ButtonStatus(CMouse.LBUTTON) &&
Player.State == CPlayer.STATE.RUN)
{
Player.SetState(CPlayer.STATE.ATTACK1);
}

if (Player.State != CPlayer.STATE.RUN)
{
if (Player.IsCurrentAnimationStopped())
{
Player.SetState(CPlayer.STATE.RUN);
}
}
}
//----------------------------------------------
// 說明:
//----------------------------------------------
new public void OnLoop(float step)
{
GlobalVar.SystemMouse.Poll();

if (GlobalVar.GameConsoleSystem.IsRunning())
{
GameConsoleIsRunning = true;
Player.States[(int)Player.State].Sound.Pause();
}
else
{
AnimationLoop();

if (GameConsoleIsRunning)
{
if (!Player.States[(int)Player.State].Sound.IsPlaying())
{
Player.States[(int)Player.State].Sound.Play();
}
GameConsoleIsRunning = false;
}

if (Player.State == CPlayer.STATE.RUN ||
Player.State == CPlayer.STATE.JUMP)
{
BackgroundUV[0].x += (step * 0.0003f);
BackgroundUV[1].x += (step * 0.0003f);
Scene.SetBackgroundTextureUVOffset(
BackgroundUV[0].x, BackgroundUV[0].y,
BackgroundUV[1].x, BackgroundUV[1].y);

for (int i = 0; i < BGLayers.GetLength(0); i++)
{
for (int j = 0;
j < BGLayers[i].Objects.GetLength(0); j++)
{
BGLayers[i].Pos[j] -=
(BGLayers[i].ScrollingSpeed * step);
if (BGLayers[i].Pos[j] < -BGLayers[i].ObjectWidth)
BGLayers[i].Pos[j] +=
(BGLayers[i].Objects.GetLength(0)*
BGLayers[i].ObjectInterval);

CVector3 Pos =
new CVector3(BGLayers[i].Pos[j],
BGLayers[i].PosY,
0);
BGLayers[i].Objects[j].SetPosition(Pos);
BGLayers[i].Objects[j].UpdateTransform();
}
}
}
}
}
//----------------------------------------------
// 說明:
//----------------------------------------------
new public void OnRender()
{
GlobalVar.Engine.Render();
}
//----------------------------------------------
// 說明:
//----------------------------------------------
new public void OnQuit()
{
base.OnQuit();
}
}


Lua script list


Player = {DynObj = 0, State = 0, States = {}}

Player.STATE = {}
Player.STATE.RUN = 0
Player.STATE.JUMP = 1
Player.STATE.ATTACK1 = 2

Scene = nil
BGLayer = {}
BackgroundUV = {u0 = 0.0, v0 = 0.0, u1 = -0.51, v1 = 0.0}
BGM = nil
GameConsoleIsRunning = false

------------------------------------------------
-- 說明:
------------------------------------------------
Player.SetState = function (state)
CSound_Cast(Player.States[Player.State].Sound):Stop()

CDynamicObj_Cast(Player.DynObj):SetCurrentAnimation(
Player.States[state].Animation)
CSound_Cast(Player.States[state].Sound):Play()
Player.State = state
end
------------------------------------------------
-- 說明:
------------------------------------------------
function BGLayer_Create (scene, layer, n, name, filename, depthlayer)
BGLayer[layer].NumObjects = n
for i=0,BGLayer[layer].NumObjects-1 do
DynamicObj = CDynamicObj_Cast(scene:CreateDynamicEntity())
DynamicObj:CreateSprite(
name,
filename,
BGLayer[layer].ObjectWidth,
BGLayer[layer].ObjectHeight)
DynamicObj:UpdateTransform()
DynamicObj:SetDepthLayer(depthlayer)
scene:AddDynamicObj(GetObjectPointer(DynamicObj))
BGLayer[layer][i] = {}
BGLayer[layer][i].DynObj = GetObjectPointer(DynamicObj)
BGLayer[layer][i].Pos = i*BGLayer[layer].ObjectWidth
end
end
------------------------------------------------
-- 說明:
------------------------------------------------
CScrollingGamePage.OnCreate = function ()
CSampleScriptGame:ComputeScreenRatio()

Scene = CScene_Cast(CSceneSystem:AddScene())
Scene:SetName(L"Scrolling Game Scene")

Camera = CCamera_Cast(Scene:CreateCamera())
Camera:Create()
Scene:SetCurrentCamera(GetObjectPointer(Camera))
CameraContainer = CCameraContainer_Cast(Camera:GetContainer())
CameraContainer:SetPosition(CVector3(10, 10, -35))
CameraContainer:LookAt(10, 10, 0)
CameraContainer:UpdateProjectionMatrix(
CGraphicsSystem:GetBackbufferWidth()/
CGraphicsSystem:GetBackbufferHeight())
CameraContainer:UpdateViewMatrix()

Scene:LoadBackgroundTexture(
L"../texture/scene/map00/background0.tga")
Scene:SetBackgroundTextureUVOffset(
BackgroundUV.u0, BackgroundUV.v0,
BackgroundUV.u1, BackgroundUV.v1)

DynamicObj = CDynamicObj_Cast(Scene:CreateDynamicEntity())
DynamicObj:CreateModel(L"Player", L"../model/dynobj/boy/boy.mdl")
DynamicObj:SetDepthLayer(CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_3)
DynamicObj:Yaw(-90.0, 1)
Scene:AddDynamicObj(GetObjectPointer(DynamicObj))

Player.States[Player.STATE.RUN] = {}
Player.States[Player.STATE.RUN].Animation =
DynamicObj:LoadAnimation(L"../model/dynobj/boy/run.ani")
Player.States[Player.STATE.RUN].Sound =
CSoundSystem:LoadSound(L"Run", L"../sound/run.wav")
CSound_Cast(Player.States[Player.STATE.RUN].Sound):SetLoops(-1)
Player.DynObj = GetObjectPointer(DynamicObj)

Player.States[Player.STATE.JUMP] = {}
Player.States[Player.STATE.JUMP].Animation =
DynamicObj:LoadAnimation(L"../model/dynobj/boy/jump.ani")
Player.States[Player.STATE.JUMP].Sound =
CSoundSystem:LoadSound(L"Jump", L"../sound/jump.wav")

Player.States[Player.STATE.ATTACK1] = {}
Player.States[Player.STATE.ATTACK1].Animation =
DynamicObj:LoadAnimation(L"../model/dynobj/boy/attack1.ani")
Player.States[Player.STATE.ATTACK1].Sound =
CSoundSystem:LoadSound(L"Attack1", L"../sound/attack1.wav")

BGLayer[0] = {}
BGLayer[0].ObjectWidth = 160
BGLayer[0].ObjectHeight = 320
BGLayer[0].ObjectInterval = 110
BGLayer[0].PosY = 320-35-320
BGLayer[0].ScrollingSpeed = 1
BGLayer_Create(
Scene, 0, 6,
L"Tree",
L"../texture/scene/map00/tree_23.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_5)

BGLayer[1] = {}
BGLayer[1].ObjectWidth = 256
BGLayer[1].ObjectHeight = 256
BGLayer[1].ObjectInterval = 256
BGLayer[1].PosY = 320-35-256
BGLayer[1].ScrollingSpeed = 2.5
BGLayer_Create(
Scene, 1, 3,
L"Tree2",
L"../texture/scene/map00/tree_01.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_4)

BGLayer[2] = {}
BGLayer[2].ObjectWidth = 128
BGLayer[2].ObjectHeight = 64
BGLayer[2].ObjectInterval = 110
BGLayer[2].PosY = 320-22-64
BGLayer[2].ScrollingSpeed = 6
BGLayer_Create(
Scene, 2, 6,
L"Bush",
L"../texture/scene/map00/bush_08.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_1)

BGLayer[3] = {}
BGLayer[3].ObjectWidth = 64
BGLayer[3].ObjectHeight = 64
BGLayer[3].ObjectInterval = 64
BGLayer[3].PosY = 320-40
BGLayer[3].ScrollingSpeed = 6
BGLayer_Create(
Scene, 3, 9,
L"GroundTile",
L"../texture/scene/map00/ground.tga",
CRenderableObj.DEPTHLAYERTYPE.DEPTH_LAYER_1)

BGM = (CSoundSystem:LoadSound(L"BGM", L"../sound/BGM.wav"))
CSound_Cast(BGM):SetLoops(-1)

Scene:SetRenderMode(CScene.RENDERMODE.RENDER_SIMPLE)
Scene:SetSortMode(CScene.SORTMODE.SORT_BY_DEPTH_LAYER)
Scene:Setup()
end
------------------------------------------------
-- 說明:
------------------------------------------------
CScrollingGamePage.OnInit = function ()
CEngine:DeleteLastUIPage()
Player.SetState(Player.STATE.RUN)

for i=0,3 do
for j=0, BGLayer[i].NumObjects-1 do
BGLayer[i][j].Pos = j*BGLayer[i].ObjectInterval
end
end

CSound_Cast(BGM):SetVolume(0.6)
CSound_Cast(BGM):Play()
end
------------------------------------------------
-- 說明:
------------------------------------------------
MouseDevice = CMouse_Cast(CInputSystem:FindDevice(L"System Mouse"))
------------------------------------------------
-- 說明:
------------------------------------------------
CScrollingGamePage.AnimationLoop = function ()
if (MouseDevice:ButtonStatus(RBUTTON) == TRUE and
Player.State == Player.STATE.RUN) then
Player.SetState(Player.STATE.JUMP)
end

if (MouseDevice:ButtonStatus(LBUTTON) == TRUE and
Player.State == Player.STATE.RUN) then
Player.SetState(Player.STATE.ATTACK1)
end

if (Player.State ~= Player.STATE.RUN) then
if (CDynamicObj_Cast(
Player.DynObj):IsCurrentAnimationStopped() == TRUE) then
Player.SetState(Player.STATE.RUN)
end
end
end
------------------------------------------------
-- 說明:
------------------------------------------------
CScrollingGamePage.OnLoop = function (step)
MouseDevice:Poll()

if (CGameConsoleSystem:IsRunning() == TRUE) then
GameConsoleIsRunning = true
CSound_Cast(Player.States[Player.State].Sound):Pause()
else
CScrollingGamePage:AnimationLoop()

if (GameConsoleIsRunning == true) then
if (CSound_Cast(
Player.States[Player.State].Sound):IsPlaying() == FALSE) then
CSound_Cast(Player.States[Player.State].Sound):Play()
end
GameConsoleIsRunning = false
end

if (Player.State == Player.STATE.RUN or
Player.State == Player.STATE.JUMP) then
BackgroundUV.u0 = BackgroundUV.u0 + (step * 0.0003)
BackgroundUV.u1 = BackgroundUV.u1 + (step * 0.0003)
Scene:SetBackgroundTextureUVOffset(
BackgroundUV.u0, BackgroundUV.v0,
BackgroundUV.u1, BackgroundUV.v1)

for i=0,3 do
for j=0, BGLayer[i].NumObjects-1 do
BGLayer[i][j].Pos =
BGLayer[i][j].Pos - BGLayer[i].ScrollingSpeed*step
if (BGLayer[i][j].Pos < -BGLayer[i].ObjectWidth) then
BGLayer[i][j].Pos =
BGLayer[i][j].Pos +
BGLayer[i].NumObjects*BGLayer[i].ObjectInterval
end
DynObj = CDynamicObj_Cast(BGLayer[i][j].DynObj)
DynObj:SetPosition(
CVector3(BGLayer[i][j].Pos, BGLayer[i].PosY, 0))
DynObj:UpdateTransform()
end
end
end
end
end
------------------------------------------------
-- 說明:
------------------------------------------------
CScrollingGamePage.OnRender = function ()
CEngine:Render()
end
------------------------------------------------
-- 說明:
------------------------------------------------
CScrollingGamePage.OnQuit = function ()
CUIPage:OnQuit();
end

Wednesday, January 26, 2011

LynxEngine update : iPhone Accelerometer Test

好久一段時間沒有更新了, 主要是因為這段時間都在忙iPhone的移植.

前一陣子終於註冊了Apple Developer的會員所以終於可以在iPhone上直接跑程式了.而模擬器上不能用的陀螺儀功能就成了第一個想測試的東西. 所以就結合了陀螺儀功能跟引擎做了一個類似裸視3D的功能, 實際跑起來還蠻有趣的. 不過由於我用的是iPod所以可視角度蠻差的, iPhone4的可視角度就好很多.