Corona で スマートフォン アプリ開発をしよう。開発編
海賊王をめざす男 マツです。こんにちは。
Corona で、タップするとその位置に画像が追加され、地面に落下するアプリをつくってみます。
local screenW, screenH = display.contentWidth, display.contentHeight local physics = require("physics") physics.start() display.setStatusBar( display.HiddenStatusBar ) local ground = display.newImage( "ground.png" ) ground.x = 160; ground.y = 445 physics.addBody( ground, "static", { friction=0.5, bounce=0.3 } ) local scaleFactor = 1.0 local physicsData = (require "matsu").physicsData(scaleFactor) local matsuShape = display.newImage("matsu.png") physics.addBody( matsuShape, physicsData:get("matsu") ) matsuShape.x = screenW / 2; matsuShape.y = matsuShape.height / 2; local xyText = display.newText( "xy", 0, 0, native.systemFont, 24 ) xyText.x = display.contentWidth / 2 xyText.y = 0 xyText:setTextColor( 255,110,110 ) local idText = display.newText( "id", 0, 0, native.systemFont, 24 ) idText.x = display.contentWidth / 2 idText.y = 30 idText:setTextColor( 255,110,110 ) system.activate( "multitouch" ) -- Display the Event info on the screen local function showEvent( event ) xyText.text = "(" .. event.x .. "," .. event.y .. ")" idText.text = "Id: " .. tostring( event.id ) end local function onTouch( event ) local t = event.target showEvent( event ) local phase = event.phase -- タッチ 開始 if "began" == phase then display.getCurrentStage():setFocus( t ) t.isFocus = true -- 最初の位置を保存 t.x0 = event.x - t.x t.y0 = event.y - t.y -- タッチ フォーカス中 elseif t.isFocus then -- 動かしたとき if "moved" == phase then -- オブジェクトのタッチした場所を適応 t.x = event.x - t.x0 t.y = event.y - t.y0 -- 終了したとき elseif "ended" == phase or "cancelled" == phase then display.getCurrentStage():setFocus( nil ) t.isFocus = false end end return true end local function otherTouch( event ) print( "otherTouch: event(" .. event.phase .. ") ("..event.x..","..event.y..")" .. tostring(event.id) ) local s = display.getCurrentStage() if "began" == event.phase then showEvent( event ) local scaleFactor = 1.0 local physicsData = (require "matsu").physicsData(scaleFactor) local matsuMiniShape = display.newImage("matsu_mini.png") physics.addBody( matsuMiniShape, physicsData:get("matsu_mini") ) matsuMiniShape.x = event.x; matsuMiniShape.y = event.y; matsuMiniShape.isFocus = true matsuMiniShape.id = event.id matsuMiniShape:addEventListener( "touch", onTouch ) --event.target = matsuMiniShape end end Runtime:addEventListener( "touch", otherTouch ) matsuShape:addEventListener( "touch", onTouch )
ここで注目するのは、physicsData に外部 matsu.lua ファイルを使用しているところ。
local physicsData = (require "matsu").physicsData(scaleFactor)
matsu.lua
-- This file is for use with Corona Game Edition -- -- This file is automatically generated with PhysicsEdtior (http://physicseditor.de). Do not edit -- -- Usage example: -- local scaleFactor = 1.0 -- local physicsData = (require "shapedefs").physicsData(scaleFactor) -- local shape = display.newImage("objectname.png") -- physics.addBody( shape, physicsData:get("objectname") ) -- -- copy needed functions to local scope local unpack = unpack local pairs = pairs local ipairs = ipairs module(...) function physicsData(scale) local physics = { data = { ["matsu"] = { { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 33, 29.5 , 49.5, 21 , 53.5, 45 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 49.5, 21 , 61.5, 8 , 65.5, 34 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -40.5, 28 , -30, 31.5 , -33.5, 39 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -43.5, 62 , -36, 48.5 , -24.5, 44 , 29, 30.5 , 30, 48.5 , -40.5, 72 , -45.5, 68 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -24.5, 44 , -36, 48.5 , -30, 42.5 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 71, 14.5 , 65, 5.5 , 71.5, 3 , 76.5, 17 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -73.5, 3 , -66, 5.5 , -73.5, 16 , -77.5, 16 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 34.5, 72 , -42, 89.5 , -40.5, 72 , 30, 48.5 , 39.5, 68 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -42, 89.5 , 34.5, 72 , 36, 89.5 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 65, 5.5 , -55, -70.5 , -39, -81.5 , 15, -89.5 , 33, -82.5 , 67.5, -43 , 71.5, -25 , 71.5, 3 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 67.5, -43 , 33, -82.5 , 56.5, -64 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -73.5, -35 , -64.5, -59 , -66, 5.5 , -73.5, 3 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 15, -89.5 , -39, -81.5 , -13, -90.5 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 33, 29.5 , 29, 30.5 , 61.5, 8 , 49.5, 21 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -64.5, -59 , -55, -70.5 , 65, 5.5 , 29, 30.5 , -30, 31.5 , -40.5, 28 , -55, 18.5 , -66, 5.5 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -21.5, 38 , 29, 30.5 , -24.5, 44 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -30, 31.5 , 29, 30.5 , -21.5, 38 } } , { density = 2, friction = 0.3, bounce = 0.3, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 29, 30.5 , 65, 5.5 , 61.5, 8 } } } , ["matsu_mini"] = { { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 11.5, 12.5 , 20, 10 , 20, 18 } } , { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 20, 10 , 23.5, 4.5 , 25.5, 12.5 } } , { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -12.5, 16.5 , 14.5, 34.5 , -16, 35 , -18.5, 25.5 } } , { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -30.5, -9.5 , -26.5, -23.5 , -26, 3 , -30.5, 6.5 } } , { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 11.5, 12.5 , -19, -31 , -8, -36 , 6, -36 , 18, -30 , 26.5, -17.5 , 23.5, 4.5 , 20, 10 } } , { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { -26.5, -23.5 , -19, -31 , 11.5, 12.5 , 15.5, 26.5 , 14.5, 34.5 , -12.5, 16.5 , -26, 3 } } , { density = 2, friction = 0.5, bounce = 0.5, filter = { categoryBits = 1, maskBits = 65535 }, shape = { 23.5, 4.5 , 26.5, -17.5 , 29.5, 6.5 } } } } } -- apply scale factor local s = scale or 1.0 for bi,body in pairs(physics.data) do for fi,fixture in ipairs(body) do for ci,coordinate in ipairs(fixture.shape) do fixture.shape[ci] = s * coordinate end end end function physics:get(name) return unpack(self.data[name]) end return physics; end
これは、サードパーティ製の PhysicsEditor というソフトからビルドしたファイルです。
PhysicsEditor
PhysicsEditor | Edit your box2d and chipmunk shapes with ease
http://www.physicseditor.de/
透過 png のアウトラインパスを解析して .lua ファイルに書き出すソフトです。
これで、物理演算などのオブジェクトの形状衝突に利用できます。
実行すると画面をタップした場所にオブジェクトが追加され、地面に向かって落下するアプリが実行できました。
Corona をつかってみて
Flash をやってきた方にはとてもとっつきやすい感じです。
心配なこととして、
Corona SDK は、Android 2.1以下のサポートをしない方向で動いているみたいです。
http://developer.anscamobile.com/forum/2011/03/01/android-update-please-read
現状 Corona は、ビルドの際に Ansca 社(Corona 開発元)のサーバーを見に行くようです。
なので、Ansca 社のサーバーがなんらかの理由(メンテナンスなど)で利用できないことがあるとビルドができないということになります。
Corona のバージョンアップは、サーバーのバージョンアップと同義なので、過去に Corona でつくったものがビルドできないということになりかねないです。
ビルド時に旧バージョンのものも選択できるように、日本コロナの会のみなさんが積極的に Ansca 社に働きかけているので解決できるといいですね。
日本コロナの会
https://groups.google.com/group/coronaja?hl=ja
Corona は魅力あるソフトなのでこれからもその動向を追ってみます!