introduction to corona sdk
DESCRIPTION
TRANSCRIPT
Introduction to Corona SDKCooper Maa
2013/9
Who am I?
• 本名:馬萬圳 (Cooper Maa)
• 現任於 :
• 擅長 Arduino 、嵌入式系統韌體研發、物聯網及網路通訊協定
Downloading Examples
https://github.com/coopermaa/Corona_SDK_Intro
Agenda
• Corona SDK Overview
• Quick Start
• Corona SDK Framework
– Text, Shapes, Images, Audio
– Events and Listeners
– Physics
– Storyboard
– Widget
Corona SDK Overview
What is Corona SDK?
• 程式語言很簡單 (Lua)• 很快就可以上手• 開發跨平台 Apps (iPhone, iPad, Android)
A piece of cake
好比剪貼勞作用 Corona SDK 寫 Game 就這麼簡單
Cross Platform Development
xcode + Objective-C
之前兩套都要學,而且都不容易學
eclipse + Java
Notepad++ and Corona SDK
現在只要會 Lua ,既簡單又輕鬆
有 Free 版可用 (Starter)
誰在用 Corona SDK ?
and more…
High Performance
30 fps: 預設每秒 30 個 frames
不只可以寫遊戲
What is Lua?
• Scripting Language• Small and Simple• Extensible• Portable
Lua v.s Othe Languages
if not carMoving then -- do somethingelseif noGas then -- do something elseend
for i = 1,10 do print(i)end
for j = 100,1,-1 do print(j)end
if (!carMoving) { // do something} else if (noGas) { // do something else}
for (i=1; i<=10; i++) { print(i);}
for (j=100; j>0; j++) { print(j);}
Lua objects are Tables
array = { "a", "b", 100, "hello" }dictionary = { x=5, y=7, name="Coopermaa" }
t = {} -- empty tablet[1] = "a" -- numerical indext["x"] = 5 -- key indext.x = 5 -- equivalent property access key = "x"t[key] = 5 -- any type can be a key
t["printCooper"] = function print("Cooper") end
Object methods
-- create empty tablelocal o = {}
-- add methodfunction o:saySomething(something) print(something)end
-- output 'hi'o:saySomwthing("hi")
The ':' is syntactic sugar
-- create empty tablelocal o = {}
-- add methodfunction f(self, something) print(something)endo.saySomething = f
-- output 'hi'o.saySomething(o, "hi")
Arrays are 1-based-- Lua: index begins with 1local array = {'a', 'b', 'c'}
for i=1,#array do print(array[i])end
// Other languages: index begins with 0array = ['a', 'b', 'c'];for (var i=0; i<arr.length; i++) { console.log(array[i]);}
Features of Corona SDK• OpenGL graphics• OpenAL audio• Box2D Physics• Texture atlases, sprites• Networking• GPS, multi-touch, accelerometer, camera, video• Widgets library and native web views, textfields• Services: ads, analytics, IAP• Game networks: Game Center (iOS) and Google Play Game Services
for achievements, leaderboards, real-time multiplayer games• Corona Cloud (shutdown) : multiplayer support, leaderboards, chat,
push notification, game analytics
Community• http://www.coronalabs.com/community/ - 官方社群• http://docs.coronalabs.com/ - 官方文件• http://www.youtube.com/user/CoronaLabs - 官方 Youtube• https://github.com/coronalabs - 官方 github• http://www.youtube.com/user/CoronaGeek
Quick Start
下載 Free 版 Corona SDK
注意! Windows 版只能 Build Android App
安裝 Corona SDK
按照慣例,都是按 [Next] 一路到底即可
安裝 XCODE (Mac only)
https://developer.apple.com/xcode/裝了 XCODE 才能 Build 出 iOS App
安裝 JDK 6 (32-bit)
http://bit.ly/nYenCt裝了 JDK 才能 Build 出 Android App (.apk 檔 )
打開 Corona Simulator
點按 [Corona SDK > Corona Simulator]
啟動 ( 激活 ) Corona SDK
第一次開 Corona Simulator 要先輸入帳號啟動軟體
Corona Simulator
之後都是用 Corona Simulator 來跑程式
Corona Simulator Output 視窗
這個視窗提供偵錯用的訊息
Sample Apps
點按 Corona Simulator 的 [Sample Apps]裏面有很多分類好的範例,都有程式碼可供學習
Step-by-step example
點按 [Demo] 有幾個一步步教學
Playing Corona Demos
Demo: Images & Text
Demo: Touch & Sound
Demo: Physics
Text Editor
TextMate for MacNotepad++ for Windows
Project Structure• Project_Folder (top-level)– images (folder)– audio (folder)– videos (folder)– data (folder, read-olny files, e.g. json and xml, fonts)– scripts (folder, other Lua files, apart from main.lua)– main.lua (every project must contain a main.lua)– config.lua (Configuration settings for an app)– build.settings (Build-time settings for an app)– Icon-hdpi.png, Icon-mdpi.png, Icon-ldpi.png
一定要有 main.lua ,其它檔案可有可無
實作: Hello World
體驗活動
HelloWorld
進行流程
建立 HelloWorld 資料夾1
編輯 main.lua2
用 Corona Simulator 載入 main.lua
3
Build 出 Android .apk 檔4
編輯 main.lua
-- print 會把字串印到 Corona Simulator Output 視窗print("Hello World")
-- 建立 "Hello World" 文字-- 語法 : display.newText([parentGroup], string, left, top, font, size)local myText = display.newText("Hello World!", 50, 50, "Arial", 60)
-- 設定文字顏色為紅色-- 語法 : [object]:setTextColor(R, G, B)myText:setTextColor(255, 0, 0)
本例會在畫面上產生一個 Hello World 的文字也會在 Corona Simulator Output 視窗印出 Hello World
2
用 Corona Simulator 載入 main.lua3
Build Android .apk
點按 [File > Build for Android (Ctrl + B)]在 [Save to Folder] 欄位輸入存放 .apk 檔的資料夾
4
在手機上安裝並執行 App
Text, Shapes, Images, Audio
Text and Image
local background = display.newImage( "world.jpg" )
local myText = display.newText( "Hello, World!", 0, 0, native.systemFont, 40 )myText.x = display.contentWidth / 2myText.y = display.contentWidth / 4myText:setTextColor( 255,110,110 )
點按 [Sample Apps > Getting Started > HelloWorld]注意! myText 的 x, y 是自己的中心點,不是 left 和 top
座標系統
(x, y): x 是水平位置, y 是垂直位置左上角的座標是 (0, 0)
iPad768x1024
iPhon4640x960
Galaxy SIII720x1280
Nexus One480x800
解析度百百種
自動縮放
TIDA
Content Area
-- config.luaapplication = {
content = {
width = 320,height = 480, scale = "letterbox"
}}
在 config.lua 裏定義 Content Area 的寬和高在不同的裝置上, Corona 會自動縮放 Text, Image, Vector
Scale methods
模式 說明
letterbox 等比例縮放。整個 Content Area 都會在 Screen 裏,但是設備的畫面比例如果跟 Content Area 不一樣,畫面可能會產生黑邊。黑邊還是可以利用,只要把視覺元素放到 Content Area 外即可。
zoomEven 等比例縮放。但設備畫面比例如果跟 Content Area
不一樣,部份內容可能會被犧牲掉 ( 被裁減掉 ) 。
zoomStrech 填滿整個 Screen 。預設的 method 。畫面會撐開導致內容變形。因為會扭曲 Content Area ,所以不建議用這種模式。
實作:認識 Scaling
體驗活動
Fishes - 水族箱
點按 [Sample Apps > Graphics > Fishes] 開啟範例點按 [ViewAs > iPhone 5] 模擬 iPhone 5
Droid
開啟 config.lua
-- config.luaapplication = {
content = {
width = 320,height = 480, scale = "letterbox"
}}
點按 [File > Show Project Files ] 打開專案資料夾然後用編輯器打開 config.lua ,原始內容如上
刪除 Content Area 的設定
-- config.luaapplication = {}
Content Area 解析度會變成 iPhone 5 的 640 x 1136因為水族箱沒有等比例縮放,所以魚跑出去了
letterbox 模式
letterbox 會等比例縮放但因為 iPhone 5 畫面比例不一樣,所以上下有黑邊
-- config.luaapplication = {
content = {
width = 320,height = 480, scale =
"letterbox"}
}
zoomEven zoomStrech
zoomEven: 等比例縮放,但內容被切掉了一部份zoomStrech: 填滿整個 Screen ,不過內容變形了
Shapes
display.newline() - 線display.newRect() - 矩形display.newRoundedRect() - 有圓角的矩形display.newCircle() - 圓形
實作:認識 Shapes
體驗活動
Shapes
建立 config.lua
-- config.luaapplication = {
content = {
width = 320,height = 480, scale = "letterbox"
}}
輸入上列內容以設定 Content Area 與 Scaling
畫出三角形
_W = display.contentWidth_H = display.contentHeight
-- 利用 newLine() 畫出三角形 , 框線寬度為 3 ,框線顏色為白色-- 語法 : display.newLine([parentGroup], x1, y1, x2, y2)local l = display.newLine(_W/2, 0, 0, _H/4)l.width = 3l:setColor(255, 255, 255)
-- 畫出三角形另外兩條邊-- 語法 : lineObject:append(x, y, [x2, y2...])l:append(_W, _H/4, _W/2, 0)
建立 main.lua ,然後輸入上列程式碼以畫出三角形
畫出矩形
-- 利用 newRect() 畫出矩形,填充顏色為黃色,-- 白色筆刷,寬度為 3-- 語法 : display.newRect([parentGroup], left, top, width, height)local r = display.newRect(0, _H/4, _W, _H*3/4)r:setFillColor(255, 255, 0)r.strokeWidth = 3r:setStrokeColor(255, 255, 255)
畫出圓形
-- 利用 newCircle() 畫圓,半徑為 80 ,-- 填充色為綠色,黑色筆刷,寬度為 4-- 語法 : display.newCircle([parentGroup,] xCenter, yCenter, radius)local c = display.newCircle(_W/2, _H*3/5, 80)c:setFillColor(0, 255, 0)c.strokeWidth = 4c:setStrokeColor(0, 0, 0)
實作:翻滾吧!小魚
體驗活動
HelloTransition
簡易動畫說明
讓魚游到右上角1
移動時魚要翻滾2
載入背景及魚的圖檔1
-- 載入水族箱背景local background = display.newImage("bkg.jpg")-- 載入魚的圖檔local fish = display.newImage("fish.png", 30, 220)
加上簡單的動畫2
-- 載入水族箱背景local background = display.newImage("bkg.jpg")-- 載入魚的圖檔local fish = display.newImage("fish.png", 30, 220)
function listener(object)print("I am here!!!")
end
-- 讓魚花 3.5 秒鐘的時間移動到右上角-- 移動時要翻滾 360 度 , 快要到達時減速-- 完成移動後就呼叫 listener()transition.to(fish, {time=3500, x=250, y=80,
rotation=360, transition=easing.outExpo, onComplete=listener})
移動完成時, Output 視窗會印出 "I am here!!!"
transition.to()在指定時間內轉換 display object 的狀態,例如移動位置 (x and y)、透明度 (alpha)、大小(width and height)、縮放比例 (xScale, yScale) 等
功能說明
transition.to( target, params )語法
Control Property 說明time 指定轉換的時間,預設是 500 ( 單位: milliseconds)delay 指定轉換前的延遲時間,即多久後開始轉換,預設是 0delta false 表示 target property 為指定值, true 為變動值。
例如 y=100 , false 時會移動到 100 , true 是往下移動 100 單位
transition 設定轉換的 easing function ,見下頁說明onStart 轉換開始會呼叫的 listener function , target 會傳給
listeneronComplete 轉換完畢會呼叫的 listener function , target 會傳給
listener
Easing Functions
Easing Functions 是緩和用的函式,可以讓動畫變得比較平滑緩和一點功能說明
Easing Function 說明easing.inExpo() 開始速度為 0 ,然後才加速。內插值算法為指數函數easing.inOutExpo() 開始速度為 0 ,接著加速,然後再放慢速度。內插值算
法為指數函數easing.inOutQuad() 開始速度為 0 ,接才加速,然後再放慢速度。內插值算
法為二次函數easing.inQuad() 開始速度為 0 ,然後才加速。內插值算法為二次函數easing.linear() 使用線性函數計算內插值,預設的 easing functioneasing.outExpo() 開始速度很快,快到達時減速。內插值算法為指數函數easing.outQuad() 開始速度很快,快到達時減速。內插值算法為二次函數
Easing Functions 的比較
點按 [Sample Apps > Graphics > Easing Examples] 打開範例
認識 Display Group
體驗活動
HelloDisplayGroup
Display Group
Display Group 可以包含其它 display objects ,方便管理一群 display objects ,例如一起移動一群 (組 )物件。
Display Group 很類似 Photoshop 圖層的概念
遊戲載入後titleScreen 會往上移然後開始進行遊戲
遊戲流程
往上移動 titleScreen 1
移動完成後開始遊戲讓小魚進行翻滾
2
載入背景及魚的圖檔1
-- 載入水族箱背景local background = display.newImage("bkg.jpg")-- 載入魚的圖檔local fish = display.newImage("fish.png", 30, 220)-- 載入音效檔local bubble = audio.loadSound("bubble.wav")
-- 開始進行遊戲function startGame() -- 讓魚花 3.5 秒鐘的時間移動到右上角 -- 移動時要翻滾 360 度 , 快要到達時減速 transition.to(fish, {time=3500, x=250, y=80, rotation=360, transition=easing.outExpo})
audio.play(bubble)end
顯示 titleScreen2
-- 顯示 titleScreen Display Groupfunction showTitleScreen() -- 建立 titleScreen Display Group local titleScreen = display.newGroup()
-- 產生兩個 display objects 並放入 titleScreen display.newText(titleScreen, " 開心水族箱 ", 20, 110, "Arial", 50) display.newText(titleScreen, "Start", 120, 280, "Arial", 40)
-- 花 1.2 秒把 titleScreen 往上移, 1 秒後開始動作 -- 移動完成時呼叫 startGame() transition.to(titleScreen, {time=1200, delay=1000, y=-480, onComplete=startGame})end
showTitleScreen()
這就是所謂的場景轉換,使用 storyboard 來管理會更簡單
Current Stage
Current Stage 是最上層的 Display Group可利用 display.getCurrentStage() 取得
往上移動1移回原位2
移動畫面-- 載入背景圖display.newImage( "world.jpg" )
-- 顯示 "Hello World"local myText = display.newText("Hello, World!", 0, 0, nil, 40)myText.x = display.contentWidth / 2myText.y = display.contentWidth / 4myText:setTextColor( 255,110,110 )
-- current stage 是最上層的 Display Groupstage = display.getCurrentStage()
-- 花 1.2 秒把 stage 往上移, 1 秒後開始動作transition.to(stage, {time=1200, delay=1000, y=-480})-- 花 1.2 秒把 stage 移回原位, 2.5 秒後開始動作transition.to(stage, {time=1200, delay=2500, y=0})
HelloTransition2
Events and Listeners
Events
• System• Timers• Buttons• Collision• Audio
Event Types• Runtime Events
– enterFrame - occurs at fps interval (30 or 60)– system - such as app suspend or exit– orientation - changes from portrait to landscape or vice-versa
• Local events, such as:– touch (hit) - user touches the device screen / display objects– collision - two physics object collide– timer - a running timer completes its duration– audio - an audio file finishes playing– networkRequest - network requests phase/status/response– location (GPS) - generated by the GPS hardware
enterFrame Event
-- 載入齒輪 gear 於畫面中央local gear = display.newImage("gear.png")gear.x = display.contentWidth / 2gear.y = display.contentHeight / 2
-- 讓齒輪每一個 Frame 旋轉 1 度local function animate(event) gear.rotation = gear.rotation + 1end
Runtime:addEventListener("enterFrame", animate)
-- 可以利用 xScale, yScale 調整齒輪的縮放比例gear.xScale, gear.yScale = 0.8, 0.8
利用 enterFrame 事件讓齒輪產生旋轉的效果
GearRotaion
Touch Event
使用 addEventListener() 註冊 Listener 使用 removeEventListener() 移除 Listener
_RADIUS = 20local tapSound = audio.loadSound("beep.mp3")
-- 在 touch 的位置畫出一顆黃色的球local function onTouch(e) -- 有 began, moved, ended 和 cancelled -- 四種 touch events -- 這裏只處理 began event if e.phase == "began" then local circle = display.newCircle(e.x, e.y, _RADIUS) circle:setFillColor(255, 255, 0) audio.play(tapSound) return true endend
Runtime:addEventListener("touch", onTouch)
HelloTouch
HelloTimer - function listener
畫面上的數字會從 0 數到 20 ,然後再從 1 數到 20…
local timeDelay = 500 -- Timer delay 時間local iterations = 20 -- 重複次數
-- 畫出白色的 Texttext = display.newText("0", 115, 105, "Arial", 160)text:setTextColor(255, 255, 255)
-- 定義 function listenerfunction listener(event) local count = event.count text.text = count if count >= iterations then timer.performWithDelay(timeDelay, listener, iterations) endend
-- 在 timer up 時呼叫 listener ,重複指定次數timerID = timer.performWithDelay(timeDelay, listener, iterations)
HelloTimer
HelloTimer2 - table listener
畫面上的數字會從 0 數到 20 ,然後再從 1 數到 20…
local timeDelay = 500 -- Timer delay 時間local iterations = 20 -- 重複次數
-- 畫出白色的 Texttext = display.newText("0", 115, 105, "Arial", 160)text:setTextColor(255, 255, 255)
-- 定義 table listenerfunction text:timer(event) local count = event.count self.text = count
if count >= iterations then timer.performWithDelay(timeDelay, text, iterations) endend
-- 在 timer up 時呼叫 listener ,重複指定次數timer.performWithDelay(timeDelay, text, iterations)
HelloTimer2
實作: Hello Animation
體驗活動
HelloAnimation
跑來跑去的球
定義球半徑、球速與方向1
在畫面中央畫出黃色的球2
加上動畫讓球移動碰到邊邊時切換方向
3
定義 Content Area
-- config.luaapplication = {
content = {
width = 320,height = 480, scale = "letterbox"
}}
輸入上列內容以設定 Content Area 與 Scaling
定義球半徑、球速與方向
_W = display.contentWidth_H = display.contentHeight
-- 定義球半徑、球速與預設方向local radius = 20local xspeed = 7.5local yspeed = 6.4local xdirection = 1local ydirection = 1
xdirection = 1 往正向移動 ( 右 ) , -1 則反向移動 ( 左 )ydirection = 1 往正向移動 ( 下 ) , -1 則反向移動 ( 上 )
1
在畫面中央畫出黃色的球
-- 在畫面中央畫出一顆黃色的球local ball = display.newCircle( _W/2, _H/2, radius)ball:setFillColor(255, 255, 0)
2
設定畫面四邊的位置
-- 設定畫面四邊的位置-- 這邊是 letterbox 的算法, zoomEven 算法不一樣local screenTop = 0local screenBottom = _Hlocal screenLeft = 0local screenRight = _W
待會球會移動,碰到邊邊時要讓球切換方向
加上動畫讓球移動3
-- 加上動畫讓球移動,碰到邊邊時切換方向function animate(eveent) local dx = xspeed * xdirection local dy = yspeed * ydirection local xNew, yNew = ball.x + dx, ball.y + dy
if xNew > screenRight - radius or xNew < screenLeft + radius then xdirection = -xdirection end if yNew > screenBottom - radius or yNew < screenTop + radius then ydirection = -ydirection end
ball:translate(dx, dy)end
Runtime:addEventListener("enterFrame", animate)
動畫的播放預設是 30 fps ,每秒 30 格
zoomEven 模式下螢幕四邊的算法(0, 0)
(display.screenOriginX, display.screenOriginY)
display.viewableContentHeight
display.viewableContentWidth
所以,四邊位置為…
local d = display -- 變數別名,簡化程式碼local screenTop = d.screenOriginYlocal screenBottom = d.viewableContentHeight + d.screenOriginYlocal screenLeft = d.screenOriginXlocal screenRight = d.viewableContentWidth + d.screenOriginX
display.screenOriginX 與 display.screenOriginY 在 zoomEven 模式下,原點通常不是 (0, 0)
如果很多顆球怎麼辦?
定義一個畫球的 function1
把畫出來的球放進集合2
針對集合裏的每一顆球加上動畫讓球移動
一樣碰到邊邊時切換方向
3
HelloAnimation2
定義球的各項參數
-- 定義三顆球的參數 ( 半徑、球速、顏色等 )local params = { { radius=20, xdir=1, ydir=1, xspeed=2.8, yspeed=6.1, r=255, g=0, b=0 }, { radius=12, xdir=1, ydir=1, xspeed=3.8, yspeed=4.2, r=255, g=255, b=0 }, { radius=15, xdir=1, ydir=-1, xspeed=5.8, yspeed=5.5, r=255, g=0, b=255 },}
定義一個畫球的 function1
-- 定義畫球的 function ,新球都會在畫面中央出現local function newBall(params) local xpos = display.contentWidth*0.5 local ypos = display.contentHeight*0.5 local circle = display.newCircle(xpos, ypos, params.radius) circle:setFillColor(params.r, params.g, params.b) circle.xdir = params.xdir circle.ydir = params.ydir circle.xspeed = params.xspeed circle.yspeed = params.yspeed circle.radius = params.radius
return circleend
把畫出來的球放進集合2
local collection = {}
-- 畫出三顆球,並把球放進 collection 集合for i=1,#params do
local ball = newBall(params[i])collection[#collection + 1] = ball
end
設定畫面四邊的位置-- 設定畫面四邊的位置 , 這邊是 zoomEven 的算法local d = display -- 變數別名,簡化程式碼local screenTop = d.screenOriginYlocal screenBottom = d.viewableContentHeight + d.screenOriginYlocal screenLeft = d.screenOriginXlocal screenRight = d.viewableContentWidth + d.screenOriginX
-- config.luaapplication = {
content = {
width = 320,height = 480, scale = "zoomEven"
}}
加上動畫讓球移動3
-- 加上動畫讓球移動,碰到邊邊時切換方向function animate(event) for _,ball in pairs(collection) do local dx = ball.xspeed * ball.xdir local dy = ball.yspeed * ball.ydir local xNew, yNew = ball.x + dx, ball.y + dy
local radius = ball.radius if xNew > screenRight - radius or xNew < screenLeft + radius then ball.xdir = -ball.xdir end if yNew > screenBottom - radius or yNew < screenTop + radius then ball.ydir = -ball.ydir end
ball:translate(dx, dy) endend
Runtime:addEventListener("enterFrame", animate)
Physics
物理效果入門
啟動物理引挈後,木箱就會變成自由落體掉到地面上
HelloPhysics
載入背景、地面與木箱
local sky = display.newImage("bkg_clouds.png")sky.x = 160; sky.y = 195
local ground = display.newImage("ground.png")ground.x = 160; ground.y = 445
local crate = display.newImage("crate.png")crate.x = 180; crate.y = 50crate.rotation = 5
(x, y) 指的是物體自己的中心點rotation 指的是旋轉角度
啟動物理引挈並放入物體local physics = require("physics")physics.start()
local sky = display.newImage("bkg_clouds.png")sky.x = 160; sky.y = 195
local ground = display.newImage("ground.png")ground.x = 160; ground.y = 445
physics.addBody(ground, "static")
local crate = display.newImage("crate.png")crate.x = 180; crate.y = 50; crate.rotation = 5
physics.addBody(crate)
ground 是靜止的物體 (static body) ,不受重力影響
影片欣賞
Youtube 影片教學 : http://bit.ly/17MQkgn
實作: HelloPhysics2
體驗活動
HelloPhysics2
從天而降大量的箱子
程式流程
定義一個產生箱子物體的 function1
利用 timer.performWithDelay() 每 0.5 秒跑一次 newCrate() 產生箱子
2
定義產生箱子的 function1
-- 定義產生箱子的 functionfunction newCrate()
local crate = display.newImage("crate.png")crate.x = math.random(320)crate.y = -50; crate.rotation = 5
physics.addBody(crate)end
x 座標由亂數產生y 座標設成負的,感覺就像從螢幕外面放入箱子
利用 timer 每 0.5 秒產生一個箱子2
-- 每 0.5 秒跑一次 newCrate() 產生箱子-- 設定 timer 執行 50 次,設成 0 表示無窮timer.performWithDelay(500, newCrate, 50)
按 [Ctrl + R] 重新載入,即可看到完成的結果
比較 density, bounce 的差別
點按 [Sample Apps > Physics > ManyCrates]會發現:大箱子比較重,最小的箱子比較會彈跳
實作:拍氣球
體驗活動
ImpulseBallon
拍氣球
當使用者拍氣球時,就對氣球施力讓它往上飛
進行流程
載入背景、地面與氣球1
啟動物理引挈並放入物體2
加入觸控事件處理並讓氣球往上飛
3
載入背景、地面與氣球
因為要從天而降,所以氣球 (ballon) 的 y 座標是負的氣球圖檔可在 [Sample Apps > Physics > CollisonFilter] 找到
1
local sky = display.newImage("bkg_clouds.png")sky.x = 160; sky.y = 195
local ground = display.newImage("ground.png")ground.x = 160; ground.y = 445
local balloon = display.newImage("red_balloon.png")balloon.x = 180; balloon.y = -50
啟動物理引挈並放入物體2
local physics = require("physics")physics.start()
local sky = display.newImage("bkg_clouds.png")sky.x = 160; sky.y = 195
local ground = display.newImage("ground.png")ground.x = 160; ground.y = 445
physics.addBody(ground, "static")
local balloon = display.newImage("balloon.png")balloon.x = 180; balloon.y = -50
physics.addBody(balloon)
加入觸控事件處理
applyLinearImpulse() 會產生一個推動力第一和第二個參數分別是 x 和 y 方向的推動力
y 是負的,所以氣球會往上飛
3
-- 使用者拍氣球時,就推動一下氣球讓它往上飛function balloon:tap(e) balloon:applyLinearImpulse(0, -0.8, balloon.x, balloon.y)end
balloon:addEventListener("tap", balloon)
物理引挈 - 進階用法一覽
橋 (Bridge)
中間是木板連結起來的橋,左右各連結一根竹竿範例路徑: [Sample Apps > Physics > Bridge]
鍊條 (Chains)
畫面右半部是連結在一起的鍊條範例路徑: [Sample Apps >
Physics > Chains]
玩偶 (RagDoll)
玩偶是多個 Shapes 鏈結起來的物體,可以用繩子操控玩偶範例路徑: [Sample Apps >
Physics > RagDoll]
物理連結 (Physics Joints)
Joint Types 說明Pivot Joint 樞紐連結。最常用的連結,舉凡輪胎、馬達、齒輪、轉
盤、關節等都可以用 Pivot Joint 完成。在 Box2D 稱為 revolute joint 。
Distance Joint 距離連結,以固定距離連結物體Piston Joint 活塞連結。在 Box2D 稱為 prismatic jointFriction Joint 摩擦連結Weld Joint 焊接連結。這種連結方式不會移動或旋轉。Wheel Joint 結合了 piston 與 pivot 兩種 joints 。在 Box2D 稱為
line joint 。Pulley Joint 滑輪連結。把繩索連結兩個物體,繩索長度是常數,如
果一物體被往下拉,另一個物體就會往上拉Touch Joint 觸控連結。把物體連結到目前觸控的位置
Storyboard
Concepts of Storyboard
Storyboard 的用途是場景管理 (Scene Management)1
使用 storyboard.newScene() 建立新場景2
使用 storyboard.gotoScene() 切換場景3
每個 Scene 物件都有個 view property ,也就是其內部的 display group
4
在 Scene 生命中的每個階段都有對應的事件5
storyboard 範例
點按 [Sample Apps > Interface > Storyboard] 打開範例觸控後會呼叫 storyboard.gotoScene() 切換到下一個場景
切換場景切換到指定的場景功能說明
storyboard.gotoScene( sceneName [, options] )語法
option 說明effect 設定場景轉換的效果,例如 fade, zoomOutIn,
zoomOutInFade, flip, flipFadeOutIn, ZoomOutInRotate, zoomInOutRotate, fromRight, fromLeft, fromTop, fromButtom, slideLeft, slideRight, slideDown, slideUp, crossFade 等
time 轉換效果的持續時間,預設是 500 millisecondsparams (optional) 傳遞給下一個場景的自訂資料。資料會透過 event
listeners 傳遞,可從 createScene, willEnterScene 與 enterScene 這幾個事件的 event.params 取得
storyboard.gotoScene( "scene1", {effect = "fade"})範例
建立新場景-- scene1.lua
local storyboard = require "storyboard"local scene = storyboard.newScene()
function scene:createScene( event ) -- object creation code hereend
function scene:enterScene( event ) -- scene logic goes hereendscene:addEventListener( "createScene" )scene:addEventListener( "enterScene" )
return scene
使用 storyboard.newScene() 建立新場景記得要用 addEventListener() 註冊每個階段的 event listener
場景的事件event 說明createScene 當場景的 view 不存在時會呼叫。通常會在這階段建立
display objects 並加到 self.view 裏willEnterScene 發生於場景轉換開始前enterScene 發生於場景移到螢幕上時 ( 即場景轉換完畢時 ) 。通常會
在這個階段 start timers, load audio, start listeners 等exitScene 發生於場景即將移開螢幕時。通常會在這個階段 stop
timers, unload audio, stop listeners 等didExitScene 發生於場景移開螢幕時 ( 即場景轉換完畢時 )destroyScene 發生於場景被清除 (purge) 或被移除時 (remove) 。通常
會在這個階段 remove listeners, widgets 等
一般來說, willEneterScene 和 didExitScene 比較少用
清除與移除場景的差別-- Called immediately after scene has moved onscreen:function scene:enterScene( event ) print( "1: enterScene event" ) -- remove previous scene's view storyboard.purgeScene( storyboard.getPrevious() ) --[[ INSERT code here (e.g. start timers, load audio, start listeners, etc.) ]] end
Mobile Devices 記憶體很珍貴,不用時要「節能減碳」purgeScene() 是清除 display objects ,場景將來還可以再 re-
load removeScene() 是把整個模組 unload
Scene Template
點按 [Sample Apps > Interface > Storyboard] 打開範例點按 [File > Show Project Files] 即可找到 scenetemplate.lua
---------------------------------------------------------- scenetemplate.lua ( 節錄 )-------------------------------------------------------
local storyboard = require( "storyboard" )local scene = storyboard.newScene()
-- Called when the scene's view does not exist:function scene:createScene( event )
local group = self.viewend
-- Called immediately after scene has moved onscreen:function scene:enterScene( event )
local group = self.viewend
Hello Storyboard( 重寫 HelloDisplayGroup)
體驗活動
HelloStoryboard
遊戲流程
顯示 titleScreen 場景1
切換到 gameScreen2
讓小魚進行翻滾到指定地點
3
main.lua1
local storyboard = require( "storyboard" )
-- 切換到 titleScreen 場景storyboard.gotoScene("titleScreen", {effect = "fade", time=300})
titleScreen.lua2
-- titleScreen.lualocal storyboard = require( "storyboard" )local scene = storyboard.newScene()
function scene:createScene( event ) local group = self.view
display.newText(group, " 開心水族箱 ", 20, 110, "Arial", 50) display.newText(group, "Start", 120, 280, "Arial", 40)end
function scene:enterScene(event) local function showGameScreen() -- 切換場景,花 1.2 秒把 titleScreen 往上移 storyboard.gotoScene("gameScreen", "slideUp", 1200) end
timer.performWithDelay(1000, showGameScreen, 1)end
scene:addEventListener("createScene", scene)scene:addEventListener("enterScene", scene)
return scene
gameScreen.lua3
-- gameScreen.lualocal storyboard = require( "storyboard" )local scene = storyboard.newScene()
local fish = nillocal bubble = audio.loadSound("bubble.wav")
function scene:createScene( event ) local group = self.view
display.newImage(group, "bkg.jpg") fish = display.newImage(group, "fish.png", 30, 220)end
function scene:enterScene(event) -- 讓魚花 3.5 秒鐘的時間移動到右上角 -- 移動時要翻滾 360 度 , 快要到達時減速 transition.to(fish, {time=3500, x=250, y=80,
rotation=360, transition=easing.outExpo}) audio.play(bubble)end
scene:addEventListener("createScene", scene)scene:addEventListener("enterScene", scene)
return scene
Widget
Widgets• button• switch• segmented
control• slider• stepper• spinner• table view
(list view)• scroll view• tab bar• picker wheel• progress view
點按 [Sample Apps > Interface > WidgetDemo] 看示範
ButtonEvents
1. 示範 Button widget2. 使用影像檔製作 button 3. 處理 onPress, onRelease 與
onEvent 事件
點按 [Sample Apps > Interface > ButtonEvents] 看示範
Widget 建立步驟
載入 widget library:
local widget = require("widget")
1
使用 widget.newXXXX() 產生 widget2
建立按鈕
local widget = require( "widget" )
local function btnClicked(event) print(event.target.id .. ": Hello World")end
-- Create a simple buttonwidget.newButton{
id = "simple button",left = 60,top = 120,label = "Say Hello",onRelease=btnClicked
}
HelloWidgets
建立切換鈕
local function onOffSwitchListener(event)
print("On/Off Switch\nIs on?: " .. tostring(event.target.isOn))end
-- Create a default on/off switchlocal onOffSwitch = widget.newSwitch{ left = 100, top = 230, initialSwitchState = true, onPress = onOffSwitchListener}
Corona Simulator Output
點按 Button 或 Switch 時,在 Output 視窗裏看見的訊息
工具箱 (3rd Party Tools)
Koneki LDT
Lua Devepment Tools (LDT) 是 Eclipse-based 的 Lua IDE
Outlaw IDE
有免費版 : Outlaw Lite version ,可建立專案的數量有限
有 syntax highlighting 與 auto complete 功能
用來產生 Sprite sheet 圖檔
TexturePacker
用來設定 Physics Parameters 以建立 Collision shapes
Gumbo - Corona Level Designer
Gumbo 可以自動產生 UI 的 Lua Code ,有 Web 與 PC 版
LevelHelper
用拖曳 (Drag and drop) 的方式建立關卡 (level)
Cutting EngineJoints
Custom ShapesPath Movement
tiled map editor
Lime 2D Tile Engine
Lime 可以使用 Tiled 產生的 Map
Feature Demo: http://bit.ly/17jGVMr
補充資料
App Icons for iOSFile Size (w x h) Purpose
Icon.png 57 x 57 Icon - iPhone
[email protected] 114 x 114 Icon - Retina iPhone
Icon-72 72 x 72 Icon - iPad
[email protected] 144 x 144 Icon - Retina iPad
Icon-Small-50.png 50 x 50 Search - iPad
[email protected] 100 x 100 Search - Retina iPad
Icon-Small.png 29 x 29 Search - iPhone
[email protected] 58 x 58 Search - Retina iPhone
App Icons for Android
File Size (w x h)
Icon-xhdpi.png 96 x 96
Icon-hdpi.png 72 x 72
Icon-mdpi.png 48 x 48
Icon-ldpi.png 36 x 36
Android Manifest Permissions-- build.settingssettings{ android = { versionCode = "11", -- App 版本號碼 version 1.1 usesPermissions = {
"android.permission.INTERNET","android.permission.VIBRATE",
"android.permission.ACCESS_FINE_LOCATION","android.permission.CAMERA","android.permission.REBOOT",
}, },}
在專案資料夾下建立 build.settings上列這些設定代表需要 :
「存取網路、設備震動、 GPS、 Camera 以及重開機」等權限
HelloVibrate
安裝時會要求「控制震動」的權限點按 App 的 [Vibrate] 按鈕就會產生震動
HelloVibrate
build.settings
-- build.settingssettings ={
android ={
usesPermissions ={
"android.permission.VIBRATE",}
}}
main.lualocal widget = require( "widget" )
local function btnClicked(event)-- 讓設備震動system.vibrate()
end
-- Create a simple buttonwidget.newButton{
left = 60,top = 120,label = "Vibrate",onRelease=btnClicked
}
只要 system.vibrate() 一行程式碼就可以讓設備震動一下
如何發 Email 與簡訊
native.showPopup()顯示系統預設的 popup window可用來發 Email, SMS 簡訊 , twitter 訊息等
功能說明
native.showPopup( name, options )語法
點按 [Sample Apps > Netwokring > ComposeEmailSMS] 打開範例
發 HTML Email-- 發一封 HTML email 給兩位收件人local options ={ to = { "[email protected]",
"[email protected]" }, cc = { "[email protected]",
"[email protected]" }, subject = "My High Score", isBodyHtml = true, body = "<html><body>I scored over <b>9000</b>!!!"
"Can you do better?</body></html>", attachment = {
{ baseDir=system.ResourceDirectory, filename="email.png", type="image" },
{ baseDir=system.ResourceDirectory, filename="coronalogo.png", type="image" },
},}native.showPopup("mail", options)
執行結果
發 SMS 簡訊
-- 發一則 SMS 簡訊 ( 不支援夾檔 )local options ={ to = { "1234567890", "9876543210" }, body = "I scored over 9000!!! " ..
"Can you do better?"}native.showPopup("sms", options)
保存 Game Settings
到這裏 http://bit.ly/1f1lh3O 下載 loadsave.lua loadsave.lua 可以把 Lua table 存成 json 檔,也可以反 過來把 json 檔轉成 Lua table
1
以 saveTable(tableName, filename) 保存設定2
以 tableName = loadTable(filename) 載入設定3
保存設定
local loadsave = require("loadsave")
appSetings = {
musicOn = true,score = 80,lives = 1
}
loadsave.saveTable(appSettings, "appSettings.json")
appSettings.json 會被儲存到 system.DocumentsDirectory如 /data/data/com.coopermaa.helloworld/appSettings.json
載入設定
local loadsave = require("loadsave")
appSettings = loadsave.loadTable("appSetings.json")
if appSettings == nil thenappSettings = { musicOn = true, score = 0, lives = 3}loadsave.saveTable(appSettings, "appSetings.json")
end
若找不到檔案, loadTable() 會回傳 nil可判斷回傳值以決定是否使用預設值
使用自訂字型(Load Custom Fonts)
CustomFont
不喜歡系統預設字型嗎?
-- 使用系統預設字型顯示 Textdisplay.newText("12345", 30, 60, native.systemFont, 90)display.newText("24680", 30, 180, native.systemFont, 90)
安裝自訂字型 - iOS-- build.settingssettings ={
iphone ={
plist ={
UIAppFonts ={
"fonts/DS-DIGI.ttf"},UIApplicationExitsOnSuspend =
true}
}}
以 DS-Digital 字型為例 : http://bit.ly/7dqQ7G把字型檔 DS-DIGI.ttf 放到一個資料夾下 (e.g. fonts)
安裝自訂字型 - Mac, Windows, Android
注意事項: 1. Windows 裝好字型後,必須重開 Corona Simulator 才能載入字型 3. 在 Android 上,字型檔名大小寫有別,而且副檔名一定要用小寫
Mac: 在字型檔上點按兩下以安裝
Windows: 在字型檔按右鍵,然後選 [ 安裝 ]
Android: 把字型檔放到專案資料夾裏
在 Windows 7 上安裝字型
使用自訂字型
-- 使用自訂字型 DS-Digital 顯示 Textdisplay.newText("12345", 30, 60, "DS-Digital", 100)display.newText("24680", 30, 180, "DS-Digital", 100)
在 Mac 與 Windows 上,字型名稱可能會不一樣在 Android 上,檔案名稱 ( 不加副檔名 ) 就是字型名稱
讓程式跨平台-- 同一套字型,在不同平台下名稱可能會不一樣-- 底下會根據平台調整字型的名稱local platform = system.getInfo("platformName")local font = "DS-Digital"
if platform == "Win" thenfont = "DS-Digital"
elseif platform == "Android" then-- filename with no extension, case sensitivefont = "fonts/DS-DIGI"
else-- Mac and iOSfont = "DS-DIGI"
end
-- 使用自訂字型 DS-Digital 顯示 Textdisplay.newText("12345", 30, 60, font, 100)display.newText("24680", 30, 180, font, 100)
在 App 中置入廣告
廣告目的
Corona SDK 支援的廣告網路
置入 Google AdMob 廣告的步驟
申請 AdMob 帳號1
到 AdMob 網站新增應用程式2
整合 AdMob 廣告到你的 App 裏3
申請 AdMob 帳號1
連到 http://www.google.com.tw/ads/admob/點按 [申請 AdMob]
直接用 Google 帳號登入
點按右上角的 [登入 ] 直接用 Google 帳號登入或是填寫表單申請新的 Google 帳號也可以
輸入 Google 帳密
填寫個人資料後按 [ 提交 ]
添加第一個應用程式
這是第一次新增 App 的畫面以後要從 AdMob 首頁進入以新增 App (見下頁 )
新增網站 /應用程式
以後新增 App 要從這個位置進入
輸入稅務資料
在使用 AdMob 前,要先輸入收款的稅務資料付款詳細資料建議用 PayPal ,屆時可轉帳到指定銀行帳
號
到 AdMob 網站新增應用程式2
點按 [網站與應用程式 > 新增網站 /應用程式 ] 並點按 [Android 應用程式 ]
填寫應用程式資料
有關 Android 套裝 URL 請見下頁說明
Android 套裝 URL
把 App 在 Google Play 上的網址 ( 上圖紅框處 ) 填入 Android 套裝 URL 欄位。這只是方便讓使用者移至 App 詳細資料頁面,
輸入個人網站也可以,不寫也沒關係
下載 AdMob Android SDK (Java User only)
用 Corona SDK 寫 App 的不需下載
收益報告
點按 [網站與應用程式 >網站與應用程式 ] 即可看到收益報告
管理設定
在收益報告頁面上點 App 的 [管理設定 ]
取得發佈商 ID
之後 App 要用發佈商 ID 跟 AdMob 整合
整合 AdMob 廣告到你的 App 裏3
-- build.settingssettings ={ plugins = { -- key is the name passed to Lua's 'require()' ["CoronaProvider.ads.admob"] = { -- required publisherId = "com.coronalabs", }, }, }
在 build.settings 檔中加入上列設定其它廣告網站請參考 http://bit.ly/1eofiHE
在程式裏加入顯示廣告的程式碼-- main.lua-- 載入 'ads' library ( 在 Simualtor 下無法使用廣告 )local ads = require "ads"-- 發佈商 IDlocal appID = "a152396ea402f78"
myText = display.newText( "Hello AdMob", 50, 50, "Arial", 32 )
local function adListener(event)-- 收不到廣告時,印出錯誤訊息if event.isError then
print(event.response)end
end -- 設定廣告 appIDads.init( "admob", appID, adListener )-- 在指定位置顯示廣告,每 60 秒更新一次ads.show( "banner", { x=0, y=250, interval=60 } )
手機上執行的結果
HelloAdMob
參考資料• AdMob 帳號申請• 申請 AdMob 並設定付款資料• Android 教學之 AdMob與AdSense行動廣告• 如何領取 Google AdMob 手機廣告收入• https://github.com/coronalabs/plugins-sample-ads-admob• 如何申請 PayPal 帳戶
申請 PayPal 帳號
申請 PayPal
• eBay 子公司• 線上金流• 可用來線上付款• 也可以線上收款,包括收取 AdMob 的款項
• 網站 : https://www.paypal.com/tw
註冊帳號
到 PayPal 網站點右上角的 [ 立即註冊 ]
選擇 [ 個人 ] PayPal 帳號
[ 個人 ] 不能接受別人信用卡付款, [特選 ] 可以,但是要手續費,適合網拍賣家, [商業 ] 適合公司行號
填寫個人資料
可以用中文填寫。日後用 email 登入 PayPay
設定密碼提示
輸入信用卡卡號
輸入信用卡卡號才可以用 PayPal 線上購物刷卡若不需要線上購物付款,例如只是用來收 AdMob 款項
者可跳過與信用卡相關的步驟
確認電子郵件啟用帳號
完成電子郵件確認
輸入 PayPay 登入密碼後即完成電子郵件確認
確認信用卡郵件
等收到信用卡月結單時,上面會有 NTD 70 的費用要找一下 4 位數代碼
信用卡認證
點按 [獲得認證 ] 。 PayPal 會從信用卡帳戶扣除 NTD 70 ,目的是確認此信用卡是否為您所有
輸入 4 位數代碼
完成認證
會看到「感謝您!我們會在 24小時內退還所有費用。」
帳戶變成 [已認證 ]
之後便可以用 PayPal 線上付款
使用 PayPal 領取 AdMob 廣告收入
收到 AdMob 付款通知
登入 PayPal
登入後,前往我的帳戶
會看到 AdMob 的付款資訊
點按 [接受 ]
接受付款
提領
在 [我的帳戶 ] 底下點按 [ 提領 ]
選擇提領交易款項的方式
點按 [ 提領交易款項到你的銀行帳戶 ]
輸入銀行帳戶資料
核對資料
輸入交易款項金額
最後按下 [ 提交 ]
完成交易
會收到轉帳通知郵件
等轉帳完成,就可以在你的銀行帳號看到入帳囉