海賊王をめざす男 マツです。こんにちは。

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 は魅力あるソフトなのでこれからもその動向を追ってみます!

HTML5飯