はじめに
Cocos2d-xおよびCocos Code IDEでLuaプロジェクト開発の基礎の基礎を終え、ゲームを作り始めると、数字の表示桁数を揃えたくなったり、時間を取得したくなったりします。これらを実現するのに便利なLua関数が存在します。ここでは、ゲーム開発に便利そうなLua関数をいくつか紹介します。
参照するコード
-- a0) 経過時間の表示桁数を5桁0詰めで定義
local FORMAT_TIME = "%05d"
local FORMAT_ANGLE = "%03d"
local GameScene = class("GameScene",function()
return cc.Scene:create()
end)
function GameScene.create()
local scene = GameScene.new()
scene:addChild(scene:createLayer())
return scene
end
function GameScene:ctor()
self.visibleSize = cc.Director:getInstance():getVisibleSize()
self.origin = cc.Director:getInstance():getVisibleOrigin()
self.schedulerID = nil
end
function GameScene:playBgMusic()
end
function GameScene:createLayer()
local layer = cc.Layer:create()
-- b1)起動時間を取得
local time0 = os.time()
-- 背景
local sprite_background = cc.Sprite:create("farm.jpg")
sprite_background:setPosition(self.visibleSize.width/2, self.visibleSize.height/2)
sprite_background:setScale(1.2)
layer:addChild(sprite_background)
-- 経過時間を表示するラベルを追加
local score = 0
-- a1)7桁0詰めで表示を作成
local label = cc.Label:createWithSystemFont(string.format(FORMAT_TIME,0), "Arial", 50)
label:setPosition(250,930)
layer:addChild(label)
-- 角度表示ラベルを追加
local label_angle = cc.Label:createWithSystemFont(string.format(FORMAT_ANGLE,0), "Arial", 50)
label_angle:setPosition(60,930)
layer:addChild(label_angle)
-- e1)ゲージを追加
local gauge = cc.ProgressTimer:create(cc.Sprite:create("menu2.png"))
gauge:setType(cc.PROGRESS_TIMER_TYPE_BAR)
gauge:setBarChangeRate(cc.p(1,0))
gauge:setMidpoint(cc.p(0,0))
gauge:setPosition(200,700)
layer:addChild(gauge)
-- e2)ゲージを満タン
local full = cc.ProgressTo:create(3,100)
gauge:runAction(full)
-- c1)点と線を描くための準備
local drawnode = cc.DrawNode:create()
layer:addChild(drawnode)
-- タッチ開始時に呼ばれる関数
local touchBeganLocation = nil
local function onTouchBegan(touch, event)
local location = touch:getLocation()
touchBeganLocation = location
-- c2)タッチされた地点に点を描く
drawnode:drawDot(touchBeganLocation, 10, cc.c4f(1, 1, 1, 0.4))
return true
end
-- タッチ中に呼ばれる関数
local function onTouchMoved(touch, event)
local location = touch:getLocation()
-- c3)タッチが動くたびにクリアして点と線を書く
drawnode:clear()
drawnode:drawDot(touchBeganLocation, 10, cc.c4f(1, 1, 1, 0.4))
drawnode:drawDot(location, 10, cc.c4f(1, 1, 1, 0.4))
drawnode:drawSegment(touchBeganLocation, location, 5, cc.c4f(1.0, 1.0, 1.0, 0.4))
-- d1) タッチ開始点と現在のタッチ点を結ぶ直線が水平方向となす角度を計算して表示
--print( (180/3.14)*math.atan2(location.y - touchBeganLocation.y, location.x - touchBeganLocation.x) )
local theta = (180/3.14)*math.atan2(location.y - touchBeganLocation.y, location.x - touchBeganLocation.x)
label_angle:setString(string.format(FORMAT_ANGLE,theta))
-- e3)ゲージを増減
local change = cc.ProgressTo:create(0.2,math.abs(theta)*100/180)
gauge:runAction(change)
end
-- タッチ終了時に呼ばれる関数
local function onTouchEnded(touch, event)
-- タッチが離れたら点と線を消し
drawnode:clear()
-- 角度表示を0にする
label_angle:setString(string.format(FORMAT_ANGLE,0))
-- ゲージを0にする
local change = cc.ProgressTo:create(0.3,0)
gauge:runAction(change)
end
-- タッチイベントで呼ばれる関数を登録し、このレイヤーでのタッチイベント取得を有効化
local listener = cc.EventListenerTouchOneByOne:create()
listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
listener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED )
listener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED )
local eventDispatcher = layer:getEventDispatcher()
eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer)
-- 定周期に呼び出される関数
local function func(dt)
-- b2)7桁0詰めで起動してからの経過時間(秒)を表示
label:setString(string.format(FORMAT_TIME,os.difftime(os.time(),time0)))
end
-- 定周期で呼び出す関数を登録する 関数名fun 周期1秒 また そのIDをself.schedulerIDに保存しておく
self.schedulerID = layer:getScheduler():scheduleScriptFunc(func, 1, false)
-- 他画面への遷移時に上記IDの定周期イベントを解除
local function onNodeEvent(event)
if "exit" == event then
if self.schedulerID then
cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.schedulerID)
end
end
end
-- 他画面への遷移イベントを有効化
layer:registerScriptHandler(onNodeEvent)
return layer
end
return GameScene
数字の表示桁数を揃える
a1)で表示桁数を0詰め5桁に指定しています。
string.format("%05d",0)
初期表示に指定している値は0一つですが、ラベル表示は00000となります。
時間を読み出す
b1)で現在の時間を秒数に直したものを取得しています。
os.time()
b2)で下記コードを使い、起動時の時間time0と現在の時間の差分を取得しています。
os.difftime(os.time(),time0))
線を引く
c1)で点と線を描画するための描画系を初期化し、
c2)でタッチ開始時の地点に点を描画し、
drawnode:drawDot(touchBeganLocation, 10, cc.c4f(1, 1, 1, 0.4))
c3)タッチ開始点と現在タッチしている点を結ぶ線を描画しています。
drawnode:drawSegment(touchBeganLocation, location, 5, cc.c4f(1.0, 1.0, 1.0, 0.4))
2点間を結ぶ直線と水平方向の角度を計算する
d1)にて、タッチ開始点と現在タッチしている点を結ぶ線が水平となす角度を三角関数のアークタンジェントを使い計算したあと、ラジアン(rad)を度(°)にしています。
(180/3.14)*math.atan2(location.y - touchBeganLocation.y, location.x - touchBeganLocation.x)
増減するゲージを表示する
e1)でゲージを初期化しています。ここではプロジェクト作成時に追加されたmenu2.pngの絵を使っていますが、色のついた細長い棒状の絵を使うのが一般的です。
e2)で一旦1秒かけて100%に
e3)でd1)の角度情報にあわせてゲージを増減しています。
今後の予定
特にありません。