2015年3月23日 星期一

[Corona SDK] 如何加上註解

在C或Java裡,
如果我們要加上註解,
只要在前面加上"//"雙斜線即可,
那在Corona SDK裡呢?
很簡單,只要加上"--"雙減號即可,
那...如果是要將一個段落都變成註解呢?
只要用"--[["和"--]]"包起來即可,如:
--[[
print( 10 ) -- no action (comment)
--]]
print(10)雖然前面沒有"--",
但因為它在"--[["和"--]]"裡,
所以一樣沒有作用,算是註解的一部份,

那...如果我想將剛剛註解的段落變成有效呢?
就是取消註解的意思,
一個作法當然是將"--[["和"--]]"拿掉,
另一個簡單的作法,
尤其是你在開發階段,常常需要做測試時,
那就是在前面在加上"-"減號即可,如下:
---[[
print( 10 ) -- will print
--]]
上面的作法可立刻將來註解的段落變成有效的段落,
反過來,如果要再變註解的段落,把"-"減號拿掉即可,
如果你是用Sublime Text,而且有安裝Corona Editor,
如[Corona SDK] 好用的編輯器 - Sublime Text 2裡所提的,
那麼,你在上面測試註解comment的功能時,
你會發現那些註解部份的顏色會跟著改變

[Corona SDK] 好用的編輯器 - Sublime Text 2

Corona 沒有特定的編輯器,
你可以用記事本,UltraEdit或者官方推薦的Sublime Text,
今天就來介紹一下Sublime Text如何安裝,

步驟1:
請到Sublime Text去下載最新版本,
目前預設是Sublime Text 2,
當然,你也可以選擇Sublime Text 3來下載,
安裝好之後,打開Sublime Text

步驟2:
在安裝Corona套件之前,我們要先讓Sublime Text有支援套件安裝的功能,
請同時按下ctrl鍵和`鍵,後面的這個`鍵,就是鍵盤上數字1左邊那個鍵,
或者,你也可以從選單"View"/"Show Console"叫出console畫面來,

接著在console裡貼上下面的整段文字
import urllib2,os,hashlib; h = 'eb2297e1a458f27d836c04bb0cbaf282' + 'd0e7a3098092775ccb37ca9d6b2e4b7d'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by = urllib2.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by) if dh == h else None; print('Error validating download (got %s instead of %s), please try manual install' % (dh, h) if dh != h else 'Please restart Sublime Text to finish installation')
上面是從網址https://packagecontrol.io/installation#st2複製而來,
如果版本不是2.0.2,那建議到網址再複製一次,
另外,Sublime Text 3請到網址https://packagecontrol.io/installation#st3去複製,
貼上後按Enter讓它去執行,然後重開Sublime Text
如果重開Sublime Text後,有遇到它建議你再重開,就再重開

步驟3:
同時按下"Ctrl"+"Shift"+"P"三鍵,或者從選單"Tools/Command Palette"叫出Command palette的畫面
輸入"Package Control: Install Package"後按下Enter,
幾秒後會跑出可安裝的packages列表,
此時輸入"Corona Editor"
安裝它

步驟4:
如果安裝成功,你會發現選單最右邊多了一個"Corona SDK"選項
我們到"Snippets"下任選一個功能看看,
例如"Snippets/Display/Image",它會自動加入
display.newImage( [parent,], filename [,baseDir] [,x,y] [,isFullResolution] )
在程式裡

步驟5:
打開任何一個".lua"檔案看看,
然後到選單"Preferences/Color Scheme"裡選擇你要的編輯畫面文字配色

步驟6:
在打開".lua"檔案的情形下,
按"Ctrl"+"B"或者執行選單"Tools/Build",
此時就會呼叫"Corona Simulator",執行那個lua的結果,
在"Corona Simulator"畫面,如果想回到Sublime Text,
可以按下"Ctrl"+"Shift"+"B"或執行選單"File/Open in Editor"即可

2015年3月19日 星期四

[Corona SDK] display.contentWidth 和 display.viewableContentWidth 的差別是什麼?

我們常常會用到 display.contentWidth和display.contentHeight,
不管你是要放圖或顯示文字等等,
那...display.viewableContentWidth和display.viewableContentHeight又是幹嘛用的?
怎麼感覺這個好像比較是我們該用的參數?

如果你查了一下display.viewableContentWidth,

官網的解釋是:
A read-only property that contains the width of the viewable screen area in content coordinates.
看完了更加覺得它比display.contentWidth更適合我們在程式裡使用,
真的是這樣嗎?

因為config.lua裡的scale有四種選擇,
只有在scale = "zoomEven"時,它們才有差異,
所以,我們就設定scale = "zoomEven",
來看看它們有何不同...

我們將main.lua的程式改寫如下:
display.setStatusBar( display.HiddenStatusBar )

local xpos = display.contentWidth/2
local ypos = display.contentHeight/2
local background = display.newImage( "320x480.jpg", xpos, ypos )
local xpos = display.contentWidth
local ypos = display.contentHeight
local myText = display.newText( xpos .. "x" .. ypos, display.contentWidth/2, display.contentHeight/2-20, native.systemFont, 40 )
local xpos = display.viewableContentWidth
local ypos = display.viewableContentHeight
local myText = display.newText(  xpos .. "x" .. ypos, display.viewableContentWidth/2, display.viewableContentHeight/2+20, native.systemFont, 40 )
myText:setFillColor( 1, 110/255, 110/255 )
在模擬器跑跑看
View As 640 x 960
在View As "320x480"或"640x960"時,
二者值是一樣的,
在來試試其它解析度看看,例如1080x1920.
View As 1080 x 1920
數值不一樣了,
而且,文字的位置也相對移動了,
如果你仔細研讀的話,你會發現似曾相識,
用個圖來說明原因,

原來,display.ContentWidth=320是相當於一開始可用的畫布寛度(A點到F點),
display.viewableContentWidth=270是相當於要scale時會截取的有效畫布寛度(B點到E點),
截取的中心點還是160,然後往兩旁展開,
如果程式裡用display.ContentWidth ,  中心點是160(C點),
如果程式裡用display.viewableContentWidth ,中心點就會變成是135(G點),
display.newText()的動作會先發生,然後才scale,
在scale到真的解析度寬度1080後,結果就會和上圖的情形一樣,

如果是1920x1080呢?
Viewa As 1920 x 1080
上面的圖,程式其實有稍微修改,
不然,文字會跑出視窗外,看不到了
local xpos = display.contentWidth/2
local ypos = display.contentHeight/2
local background = display.newImage( "320x480.jpg", xpos, ypos )
local xpos = display.contentWidth
local ypos = display.contentHeight
local myText = display.newText( xpos .. "x" .. ypos, display.contentWidth/2, display.contentHeight/2-20, native.systemFont, 40 )
local xpos = display.viewableContentWidth
local ypos = display.viewableContentHeight
local myText = display.newText(  xpos .. "x" .. ypos, display.contentWidth/2, display.contentHeight/2+20, native.systemFont, 40 )
myText:setFillColor( 1, 110/255, 110/255 )
從上面的解說,你會發現如果不是"zoomEven" Mode,
那用一個都可以,
如果是"zoomEven" Mode,
那就是要display.contentWidth和display.contentHeight,
那...display.viewableContentWidth和display.viewableContentHeight要幹嘛?
它們可以讓你知道實際會出現的"有效"寬度和長度資訊,
就看你程式是不是有這樣的需求...

Note:理論上,在letterbox模式時,display.viewableContentWidth或display.viewableContentHeight應要比display.contentWidth或display.contentHeight來的大,
所以你會看到在letterbox mode時,上下或兩旁可能有黑邊現象,
但display.viewableContentWidth或display.viewableContentHeight看起來是指"有效的"寬度和長度資訊,而不是"可視的"寬度和長度資訊,所以它最大值會受限於display.contentWidth或display.contentHeight,
在letterbox mode,如果要取得包括黑邊的長度或寬度,應該是要用display.actualContentWidth和display.actualContentHeight,
這二個參數在zoomEven mode也適用,它們的值會和display.viewableContentWidth或display.viewableContentHeight一樣

[Corona SDK] 為什麼 display.newImage() 的位置怪怪的? - anchor的用法

如果我們想要在畫面放上一張圖片:
local background = display.newImage( "320x480.jpg",0,0)
很簡單,只要一行,
用模擬器看一下...
anchorX=0.5, anchorY=0.5
耶?奇怪了,怎麼照片位置好像不太對,
原來,每個物件都有所謂的anchorX和anchorY,
anchor就是物件做任何操作的中心點,
不管你是移動,放大縮小,旋轉等等
上面的圖是從coronalabs官網的說明抓下來的,
anchorX/anchorY是從物件的左上角(0, 0)到右下角(1, 1),
預設值是(0.5, 0.5),也就是物件的中心點,
(anchor的數字是和物件大小相比的比例值)
也就是說,display.newImage( "320x480.jpg",0,0)是把圖片的中心點放到(0, 0)的位置,
當然就會看到第一張圖的樣子,
那要怎麼調回來讓圖位置正確呢?



local background = display.newImage( "320x480.jpg",0,0)
background.anchorX=0
background.anchorY=0
只要將anchor調到0就可以了
anchorX = 0, anchorY = 0
不過,你會發現demo的程式裡,好像都不是這樣做的,
沒錯,通常我們不會去改anchor預設值,除非有需要,
因為位置是相對的,
所以你可以用以下的做法:
local xpos = display.contentCenterX
local ypos = display.contentCenterY
local background = display.newImage( "320x480.jpg", xpos, ypos )
或者有人是這樣用
local xpos = display.contentWidth/2
local ypos = display.contentHeight/2
local background = display.newImage( "320x480.jpg", xpos, ypos )
意思都是一樣,因為anchor預設是在圖片中央, 將圖片中央放在畫面中央,當然就會是對的...

2015年3月18日 星期三

[Android] 如何藉由JNI來呼叫底層Native的C/C++程式 - part I

基本上,Android提供的API已足夠一般寫程式的需求,
不過,有時候我們仍然會需要直接呼叫底層Native的C/C++程式,
有時是因為效能,有時是因為Android提供的功能不足...

如果你也是使用Eclipse,
那麼,你必須先安裝CDT和NDK,
之後,在你想要增加JNI介面的project按右鍵,
執行"Android Tools"/"Add Native Support"後,
你會發現project下面多了一個"jni"目錄,
目錄底下還有一個"x.cpp"和"Android.mk",
到這邊,你已經完全了第一步了...

接下來,Java要如何呼JNI的函式呢?

package myTest.com;
 
import android.app.Activity;
import android.os.Bundle;
 
public class MainActivity extends Activity { 
 private native String hello(String s); 
 
 static {
  System.loadLibrary("NativeMyTest");
 } 
}
"NativeMyTest"是你剛剛產生jni目錄時,輸入的名稱,
也就是說,待會會產生NativeMyTest.so檔,
 hello(String s)則是定義在JNI裡的函式,
 那JNI這邊呢?
#include <jni.h>
#include <stdio.h>

 #define LOG_TAG "MainActivity"
#define LOGI(...) __android_log_print(4, LOG_TAG, __VA_ARGS__);

JNIEXPORT void hello(JNIEnv* env, jobject obj, jstring str){ 
 LOGI("hello: %s", str);
}

jint JNI_OnLoad(JavaVM* pVm, void* reserved) {
  JNIEnv* env;
  if ((*pVm)->GetEnv(pVm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {
  return -1;
  }
 
  JNINativeMethod nm[2];
  nm[0].name = "hello";
  nm[0].signature = "(Ljava/lang/String)V";
  nm[0].fnPtr = (void*)hello;

  jclass cls = (*env)->FindClass(env, "myTest/com/MainActivity");
  (*env)->RegisterNatives(env, cls, nm, 1);
  gJavaVM = pVm;
  return JNI_VERSION_1_6;
}
JNI_OnLoad()是用來載入那些會被Java程式所呼叫的函式,
FindClass()傳入的參數必須和Java程式的package和class名稱一樣,
執行時,看看是載入NativeMyTest.so有問題,還是沒有發現hello函式,
再來決定是那裡有問題...

[Corona SDK] config.lua中的scale - 實例演練

在[Corona SDK] config.lua中的scale怎麼設定呢?裡,
我們看到了config.lua中scale的意義,
現在就來實際演練一下,
實際操作時,不只width,height,scale要注意,
原圖的大小也有關係,
Simulator裡"View As"所選的手機解析度也會影響,
假設原圖是一張320x480大小:

1. 如果我們config.lua的設定如下:

width = 320,
height = 480,
scale = "none"
View As 320 x 480
View As 640 x 960
View As 1080 x 1920
View As 1920 x 1080
那麼,因為圖和原始畫布比例一樣,
所以不管用什麼解析度的手機來看都是完整的,雖然有的可能會變形

2. 如果將scale改成letterbox呢?

width = 320,
height = 480,
scale = "letterbox"
View As 320 x 480
View As 640 x 960
View As 1080 x 1920
View As 1920 x 1080
在320x480以及640x960的解析度,畫面都是滿框不變形,因為它們比例一樣,
在1080x1920的解析度,上下有黑邊,因為它的長寛比和320x480不同,所以scale後,相當於320x480的圖畫在320x568左右的畫布上,
在1920x1080的解析度,左右有黑邊,因為它的長寛比和320x480不同,所以scale後,相當於320x480的圖畫在853x480左右的畫布上,

3. 如果將scale改成zoomEven呢?
width = 320,
height = 480,
scale = "zoomEven"
View As 320 x 480
View As 640 x 960
View As 1080 x 1920
View As 1920 x 1080


一樣,320x480以及640x960的解析度,畫面都是滿框不變形,因為它們比例一樣,
在1080x1920的解析度,左右被截掉了,因為它的長寛比和320x480不同,所以scale後,相當於320x480的圖畫在270x480左右的畫布上,
在1920x1080的解析度,上下被截掉了,因為它的長寛比和320x480不同,所以scale後,相當於320x480的圖畫在320x180左右的畫布上,

4. 如果將scale改成zoomStretch呢?
width = 320,
height = 480,
scale = "zoomStretch"
View As 320 x 480
View As 640 x 960
View As 1080 x 1920
View As 1920 x 1080
在320x480以及640x960的解析度,畫面都是滿框不變形,因為它們比例一樣,
在1080x1920和1920x1080的解析度,畫面是滿框,但會變形

如果原圖不是320x480呢?
也就是說,如果原圖長寬比和config.lua裡的長寬比不同呢?
那就必須同時考慮原圖,config.lua裡width/height設定,再配合scale的參數,觀念是類似的...
基本上,如果你的原圖只是當背景用,比例不重要的話,那scale就設成zoomStretch,
如果比例很重要,但是可以接受截圖,那scale就設成zoomEven,
如果比例很重要,但是可以接受黑邊,那scale就設成letterbox,
如果比例很重要,不能接受截圖和黑邊,那...你就必須準備多張不同解析度的圖囉

[Corona SDK] config.lua中的scale怎麼設定呢?

各家手機解析度都不同,
為了解決這個問題,
Corona SDK利用config.lua來設定,
裡面的width和height,你可以想成是初始的畫布大小,
最終的畫布大小和你所用的手機解析度來決定,
scale呢?初始的畫布長寬比和手機解析度長寬比如果不同時,
怎麼處理放大縮小的原則就是由這個參數決定,
有幾種模式可選:
"none":就是不作用
"letterbox":會盡量將所有內容全部在畫面中顯現,而且會維持原來的比例,但因為這樣,所以有時會有黑邊出現
letterbox

"zoomEven":會將內容全部塞滿畫面,而且會維持原來的比例,換句話說,內容可能會跑出面,也就是被截掉了
zoomEven

"zoomStretch":會將內容全部塞滿畫面,但不會維持原來的比例,換句話說,內容可能會變形
zoomStretch