반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형
$.mobile.loadPage (url, options) method



$.mobile.loadPage (url, options) method 는 $.mobile.changePage (toPage, options) method 에 의해 내부적으로(internally) 사용됩니다. 이것은 설정된 URL의 HTML 페이지를 수집(retrieves) 하고 메모리 내에 해당 윈도우를 load 합니다. 현재 보여지고 있는 윈도우는 바뀌지 않습니다. 그냥 다음 페이지를 내부적으로 다음 윈도우에 넣어서 메모리에 담아두고 있는거죠.


jQuery Mobile은 우리가 이 메소드를 사용하면 현재 display 되는 HTML 과 Load 되는 HTML 을 각각 분리할 수 있도록 처리해 줍니다. 이 메소드를 사용하면 예를 들어 pre-load 윈도우들의 경우 유저의 요구가 있었을 때 기다리는 시간 없이 즉시 표시해 줄 수 있도록 해 줍니다.  jQuery Mobile 은 data-prefetch attribute를 통해서 이런 작업을 합니다.


$.mobile.loadPage (url, options) method parameters


Parameter

Signification

url

Specifies the URL of the page you want to load into memory.

options.
pageContainer

jQuery class object indicating the element within which the new window will be displayed. Default $.mobile.pageContainer.

options.
data

The data option is an object or a string, corresponding to transmitted parameters.
- If using a string, it must be of the form name1=value1&name2=value2 etc., each name is the name of a parameter, and value the corresponding value encoded in UTF-8.
- If you use an object, jQuery Mobile itself encodes UTF-8 each value, and sends the server a string of the form name1=value1&name2=value2 etc.

options.
type

Method describing how to transmit parameters ("post" or "get"). The default is "get".

options.
reloadPage

If true, specifies to reload the window in the DOM, each viewing the page. Default false (the window is loaded into the DOM at the first display and is used as is).


Simulating the data-prefetch attribute using the $.mobile.loadPage ()


링크 내에 data-prefetch attribute 가 설정 되면 jQuery Mobile은 그 링크의 href attribute 에 해당하는 HTML 페이지를 백그라운드로 로딩합니다. 이 작업을 하기 위해 jQuery Mobile은 $.mobile.loadPage () method를 이용해서 메모리에 해당 윈도우를 저장하는 것이죠.


아래에 $.mobile.loadPage () method를 사용해서 윈도우를 preload 하는 예제를 보시겠습니다.



Preload a window with $.mobile.loadPage () method


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


</body>

</html>


<script>


$("#home").bind ("pagecreate", function ()

{

  $.mobile.loadPage ("index2.html");

});


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ("index2.html");

});


</script>



index2.html file containing the second window


<!DOCTYPE html>

<html> 

<head> 

  <meta http-equiv=Content-Type content=text/html;charset=iso-8859-1 />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=win2 data-add-back-btn=true data-dom-cache=true>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2</p>

  </div>

</div>


</body>

</html>


convention181.html


convention182.html



두번째 윈도우는 index2.html 파일을 포함하게 됩니다. 일단 첫번째 윈도우가 생성되면 (pagecreate event) 곧바로 두번째 윈도우가 DOM tree 에 include 되겠죠.




일단 두번째 윈도우가 로드되면 유저가 링크를 클릭하면 $.mobile.changePage () method를 사용해서 두번째 윈도우를 display 할 겁니다.

이 때 유저는 jQuery Mobile의 waiting message (Loading) 를 보지 않아도 됩니다. 왜냐하면 그 페이지가 이미 DOM 에 있으니까요. 두번째 윈도우에서 data-dom-cache=true attribute를 세팅해서 DOM 내에 두번째 윈도우가 계속 머물러 있게 됩니다. 그러면 첫번째 윈도우에서 링크를 클릭하면 곧바로 두번째 윈도우가 display 되는 겁니다.


반응형


반응형

$.mogile.changePage(toPage,options) method



이전 글에서 HTML 페이지내에서 링크를 거는 간단한 방법을 보여드렸습니다. 이 링크는 두개의 윈도우간의 transition을 가능하게 하죠. 그 윈도우가 같은 HTML 페이지 안에 있던 아니면 다른 HTML 안에 있던 상관없습니다.


이 두개의 윈도우간 transition을 좀 manage 하고 싶은 경우에 어떻게 할까요? jQuery Mobile 은  이를 위해 $.mobile.changePage (toPage, options)를 제공하고 있습니다. 이름에서 알 수 있듯이 이것은 $.mobile object 상에 정의된 changePage () 메소드 입니다.



toPage parameter (required)는 여러분이 display 하기를 원하는 윈도우나 페이지를 말하는 겁니다. options parameter (optional)는 이 윈도우를 display 하기 위해 사용되는 옵션들을 가리키는 객체입니다.


$.mobile.changePage (toPage, options) method parameters


Parameter

Signification

toPage

Indicates the window or the URL of the page you want displayed.
- For a window, it is a jQuery class object (eg $("#win2") to display the window with this id). In this case, the window must already exist in the DOM.
- For a URL, it is a string (eg "index2.html"). In this case, the first window in the file is displayed.

options.
transition

One of the values slide, slideup, slidedown, pop, fade or flip, corresponding to the transition effect between the two windows (slide by default). See details below.

options.
reverse

If true, specifies to reverse the direction of the transition effect. Default false.

options.
changeHash

Indicates whether the URL in the address bar should be changed to reflect the URL of the new page or window displayed (if changeHash is true, default), or must retain the old value (if changeHash is false).

options.
pageContainer

jQuery class object indicating the element within which the new window will be displayed. Default $.mobile.pageContainer.

options.
data

The data option is an object or a string, corresponding to transmitted parameters.
- If using a string, it must be of the form name1=value1&name2=value2 ..., each name is the name of a parameter, and value the corresponding value encoded in UTF-8.
- If you use an object, jQuery Mobile itself encodes UTF-8 each value, and sends the server a string of the form name1=value1&name2=value2 etc.

options.
type

Method describing how to transmit parameters ("post" or "get"). The default is "get".

options.
reloadPage

If true, specifies to reload the window in the DOM, each viewing the page. Default false (the window is loaded into the DOM at the first display and is used as is). This option is only used if the argument toPage refers to a URL (the window is loaded by jQuery Mobile with Ajax).

options.
showLoadMsg

Boolean indicating to display the message saying that an HTML page is being loaded. The message is described in $.mobile.loadingMessage ("loading" by default).


Possible values of the data-transition attribute


data-transition

Signification

slide

Moving from one window to another by a horizontal movement from right to left. This is the default.

slideup

The second window appears at the bottom, gradually covering the first.

slidedown

The second window appears at the top, gradually covering the first.

pop

The second window is the center of the first, widening to cover it.

fade

The first window disappears by reducing its opacity (from 1 to 0), while the second appears through an increase in opacity (from 0 to 1).

flip

The second window appears with a rotation effect on a vertical axis, and by removing the first window.


링크를 클릭했을 때 $.mobile.changePage ()과  jQuery Mobile 이 만든 href attribute 사이에는 어떤 일이 일어 날까요? 어떤게 더 우선일까요? 


헛갈릴 필요가 없는게요 jQuery Mobile은 자바스크립트 코드에서 어떤 일이 발생할 때는 <a> link의 href attribute에 "#" value를 할당하라고 하거든요. 링크 내의 href="#"는 jQuery Mobile에게 일반적인 프로세스로 진행하지 않을거라고 얘기하는 거거든요. (그러니까 이럴 경우에는 자바스크립트 내에 있는 우리의 코드가 우선으로 적용되게 되는 겁니다.)


$.mobile.changePage (toPage, options) method를 사용한 아래 샘플들을 보세요.


Display a window in the same HTML page


하나의 HTML 페이지에 두개의 윈도우가 있다고 가정하죠. 첫번째 윈도우에서 두번째 윈도우로 움직이고 싶구요 이것을 $.mobile.changePage () method를 사용해서 링크를 관리할 겁니다. (링크의 href attribute를 사용하는 대신에요.)


Use the $. Mobile.changePage () method to display a window in the same HTML page


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


<div data-role=page id=win2 data-add-back-btn=true>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2 </p>

  </div>

</div>


</body>

</html>


<script>


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ($("#win2"));

});


</script>



Window 2 에는 win2 라는 id 가 있습니다. 이것은 jQuery class 객체  $("#win2")로 다뤄질 수 있습니다. link attributes의 href="#" click event (instead of vclick)의 용도를 잘 생각해 보세요.  (이 이벤트는 link 에 position 돼 있어서 click 을 사용한 겁니다. 자세한 내용은 이전 글을 보세요.)






Display a window in another HTML page


이제는 두번째 윈도우가 다른 HTML 페이지에 있을 경우입니다. 두번째 윈도우를 보기위해 $.mobile.changePage () method를 사용합니다. 이 메소드의 첫번째 파라미터로 HTML 페이지의 URL 을 넣습니다.


Use the $.mobile.changePage () method to display a window in a new HTML page


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


<div data-role=page id=win2 data-add-back-btn=true>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2 </p>

  </div>

</div>


</body>

</html>


<script>


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ("index2.html");

});


</script>



Index2.html file


<!DOCTYPE html>

<html> 

<head> 

  <meta http-equiv=Content-Type content=text/html;charset=iso-8859-1 />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=win2 data-add-back-btn=true>

  <div data-role=header>

    <h1>Window 2</h1>

  </div>


  <div data-role=content>

    <p> Window content 2</p>

  </div>

</div>


</body>

</html>



결과는 이전 예제와 거의 같습니다. 첫번째 링크에서는 약간 다를겁니다. 왜냐하면 처음에는 그 HTML 페이지가 로드되지 않았을 것이기 때문에요. 아마 속도가 느리면 두번째 윈도우가 열릴 때까지  Loading 이라는 메세지가 뜰 겁니다.


만약 index2.html file안에 여러개의 윈도우가 있다면? 이럴 경우에는 첫번째 윈도우면 DOM 에 적재 됩니다. 다른 윈도우들은 접근하지 못하는 상황이 됩니다.


Transmit data when displaying the window


만약에 첫번째 윈도우가 두번째 윈도우에 어떤 정보를 전달해야 될 경우를 가정해 보죠. 이것은 $.mobile.changePage () call의 data option을 사용하게 됩니다. 이렇게 되면 두번째 윈도우에 파라미터를 전달할 수가 있습니다.


Use the $.mobile.changePage () method to transmit information


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


</body>

</html>


<script>


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ("action.php", 

  {

    data : { fname : "Eric", lname : "Sarrion" }

  });

});


</script>


Display the new window (action.php file)


<?
  $fname = $_REQUEST["fname"];
  $lname = $_REQUEST["lname"];
  $fname= utf8_decode ($fname);
  $lname= utf8_decode ($lname);
  
  $html = "";
  $html .= "<div data-role=page data-add-back-btn=true>";
  $html .=   "<div data-role=header>";
  $html .=     "<h1>Window 2</h1>";
  $html .=   "</div>";
  $html .=   "<div data-role=content>";
  $html .=   "<p>Window content 2</p>";
  $html .=   "<p>First name : $fname</p>";
  $html .=   "<p>Last name : $lname</p>";
  $html .=   "</div>";
  $html .= "</div>";
  echo utf8_encode ($html);
?>



아래 이미지를 보시면 두번째 윈도우에 파라미터가 display 되고 있습니다.




Modify the transition to display the window


지금 까지는 두 윈도우간 이동시 디폴트 transition 만 사용했습니다. jQuery Mobile은 $.mobile.changePage () call에서 transition option을 사용해서 특정 transition을 설정할 수 있는 기능을 제공합니다.


이전 예제에 transition option을 추가 하겠습니다.


Use slideup to transition between the two windows


$.mobile.changePage ("action.php",

{

  data : { fname : "Eric", lname : "Sarrion" },

  transition : "slideup"

});




두번째 윈도우가 나타날 때 이전과는 다르게 나타날 겁니다.


Create a window and then dynamically display when a click occurs


HTML 안에 이미 만들어진 윈도우를 display 하는 대신에 링크를 클릭하면 $.mobile.changePage () method로 dynamic 하게 새로운 윈도우를 만들어서 display 하고 싶습니다.


Creating window dynamically


<!DOCTYPE html>

<html> 

<head> 

  <meta name=viewport content="user-scalable=no,width=device-width" />

  <link rel=stylesheet href=jquery.mobile/jquery.mobile.css />

  <script src=jquery.js></script>

  <script src=jquery.mobile/jquery.mobile.js></script>

</head> 


<body> 


<div data-role=page id=home>

  <div data-role=header>

    <h1>Home</h1>

  </div>


  <div data-role=content>

    <p> Window content 1 </p>  

    <a href=# id=link1> Goto window 2 </a>

  </div>

</div>


</body>

</html>


<script>


var html = "";

html += "<div data-role=page id=win2 data-add-back-btn=true>";

html +=   "<div data-role=header>";

html +=     "<h1>Window 2</h1>";

html +=   "</div>"

html +=   "<div data-role=content>";

html +=     "<p> Window content 2 </p>";

html +=   "</div>";

html += "</div>";


$(html).insertAfter ("#home");


$("#link1").bind ("click", function (event)

{

  $.mobile.changePage ($("#win2"));

});


</script>



이럴 경우에 insertAfter (selector) jQuery method를 사용해서 표현하시면 됩니다. (DOM 안에 첫번째 윈도우에 이어서 만들어진 윈도우가 삽입되겠죠. 그 다음에 링크를 누르면 그 새로운 윈도우가 display 되는 겁니다.)


반응형


반응형
Posted on . Written by


iOS6의 landscape/Game Center orientation issue 와 관련 코로나에서 많은 개선을 했다는 것을 말씀 드리게 되서 기쁩니다. 이 개선된 사항들은 Corona daily build 930에서 사용하실 수 있습니다.

처음 저희가 이 문제에 접근할 때 물리학자들이 자연의 forces들을 unify 하기 위한 접금 자세와 같은 자세였습니다. 최대한 일반적인 해결책을 찾으려고 애를 썼죠. 이 iOS6와 이슈와 관련한 해결책을 찾으면서 iOS5와 iOS 4.3 버전도 같이 동시에 테스트 해 가면서 일반적인 해결법을 찾으로겨 노력했습니다. 그래서 약간 stopgap 문제 같은게 생기기도 했었죠. ( #3 in last week’s FAQ)


개인적으로 그 stopgap 이 마음에 들지 않았습니다. 그래서 지난주에 팀에게 다른 방법을 찾아 보라고 부탁했고 좀 더 나은 방법을 찾아보자고 제안했습니다. 금요일 이전에 새롭게 전략을 만들었고 이대로 하면 훨씬 나아질 것이라고 생각했습니다.


이 새 전략은 거의 외과수술 수준의 작업을 해야 하는 작업입니다. 저희들이 무엇을 하는가 하면 이 workaround 가 오직 iOS 6 에서만 일어나도록 하는 겁니다. 이 현상은 iPhone 과 iPod Touch에서만 일어나거든요. -iPad에서는 이러한 현상이 일어나지 않습니다. -





저희들이 해야 할 일은 여러분의 info.plist에 special key 인 ‘CoronaUseIOS6LandscapeOnlyWorkaround’ 를 추가 하는 겁니다. 저희들이 이름을 조금 복잡하고 unfriendly하게  만들었는데요 애플이 다음버전에서는 이 버그를 해결하기를 바라는 마음에서 그렇게 지었습니다.


이 기능을 사용하시려면 build.settings 파일에  special ‘plist’ section을 추가하시면 됩니다.


settings =
{
orientation =
{
default = "landscapeRight",
supported =
{
"landscapeRight",
"landscapeLeft",
},
},
iphone =
{
plist =
{
CoronaUseIOS6LandscapeOnlyWorkaround = true,
},
}
}

 

(NOTE: 만약 이전의 workaround를 사용하신다면 여러분은 portrait 세팅을 remove 하셔야 합니다. 그리고 content key 도 remove 하셔야 됩니다. 그렇게 하지 않으시려면 그냥 위의 코드를 사용하시면 됩니다.)


이건 기본적으로 여러분 앱이 landscape 앱이라는 것을 코로나에 알려주는 겁니다. 그러면 이 special workaround를 activate 하고 싶다는 것을 얘기하는 것이죠. 이 workaround는 iOS 6 에서 돌아가는 iPhone 이나 iPod Touch 에서만 작동할 겁니다. iOS 5 에는 GameCenter bug 가 없습니다. 그러니까 거기서는 여러분의 landscape 앱이 제대로 잘 작동할 겁니다.


이제 마지막 문제가 있습니다. iOS 6 에서 돌아가는 iPad 의 photo picker 이슈 입니다. 만약에 여러분이 landscape 앱을 가지고 있다면 이 이슈가 발생할 겁니다. 이 부분은 다음 daily build 에서 해결책을 적용할 예정입니다.


반응형

Sprite Sheet 활용하기 (Advanced)

2012. 10. 12. 05:54 | Posted by 솔웅


반응형
Posted on . Written by


오늘의 게스트 Tutorial은 Omid Abourai 입니다. 인디 게임 개발자 이며 ArdenKid 라는 별명을 가지고 있습니다. 그는 2년여간 코로나 SDK 를 가지고 개발을 했으며 곧 그가 주도한 첫 게임인 "Balloon Bazooka"를 릴리즈 할 예정입니다. 그의 블로그는 www.ardentkid.com 입니다.  



Basic Sprite Sheets


만약 지난주의 를 animation tutorial 놓치셨다면 그것 부터 보세요. 이 튜토리얼은 지난주 튜토리얼의 basic sprite methods 의 연장선에 있는 겁니다.


Sprite sheet는 CPU 의 부담을 덜어준다는 면에서 아주 훌륭한 기술입니다. 그런데 그냥 vector animation 과 비교해서 단점이 있는 것도 사실입니다. 예를 들어 메모리를 많이 잡아먹는다든지 앱 크기가 커진다든지 하는 것들이요. (애플의 경우 20메가가 넘으면 wifi로 다운로드 받으라고 하는데 저희는 한 앱이 20메가를 넘지 않도록 작업을 하고 있습니다.)

그리고 예를 들어 한 캐릭터가 옷을 갈아입고 악세사리를 바꾸고 할 경우는 어떨까요? 우리의 캐릭터를 각 옷별로 또 악세사리별로 중복해서 만든다면 sprite sheet 를 쓰는 잇점이 줄어들겠죠. 이럴 경우 처음부터 부분 부분 별로 만들어서 활용한다면 적은 이미지 용량으로 훨씬 많은 효과를 낼 수 있을 겁니다.



이 튜토리얼은 그 이슈와 관련해서 가능한 해결법을 다룰 겁니다. 비밀은 코딩과 애니메이션 간에 좀 더 긴밀한 관계를 만드는 겁니다.

조만간 발매될 Balloon Bazooka 앱에서 사용했던 kid 관련 스프라이트 쉬트를 샘플로 시작해 보겠습니다.






이 sheet 는 코로나의 basic sprite animation에 맞게 디자인 됐습니다. 이미지를 로드한 다음 sequence들을 셋업하고 원하는 sequence들을 play 하는 방식이죠. 좀 더 진보된 테크닉을 원하신다면 아래 내용을 말씀해 드리고 싶습니다. 그런데 일단 우선은 이 basic methods가 익숙해지셔야 합니다.


Splitting the Animation Elements


우리는 화면에서 동시에 같은 sprite 표현을 사용하는 여러 kids 를 만들겁니다. 우리는 그들에게 다양한 옷과 살 색 등등을 적용할 겁니다. 다행히도 프로그램적으로 비쥬얼 property들을 tweening 함으로서 비슷한 애니메이션들을 만들 수 있습니다. 프로그램으로 scale, rotation, translation 등을 다야하게 적용할 수 있습니다. (우선 편의상 이번에는 팔은 가만히 있고 발만 움직이는 걸로 한번 만들어 보겠습니다.)


먼저 이 kid를 토막을 내겠습니다. color 별로 따로 만들고 나중에 이것들을 합칠께요. 이 작업을 하기 위한 새로운 image sheet 는 아래와 같을 겁니다.





이 new sheet 의 file size 가 225KB 에서 109KB로 줄어들었습니다. 그러면서도 다양하게 의상과 피부색을 조합할 수 있게 됐죠. 50%가 넘게 파일 사이즈를 줄였고 우리고 표현하고 싶은 다양한 kid 들을 표현할 수 있게 됐습니다.


이제 이 각각의 element들을 코드안에 individual sprite 로 정의 하겠습니다.


-- DECLARE CHARACTER SEQUENCES (MOST ARE JUST STATIC CHERRY-PICKED FRAMES!)
local sequenceData = {
  { name="beachboy_hat_yellow", frames={1} },
  { name="beachboy_body_dark", frames={34} },
  { name="beachboy_shorts_red", frames={42} },
  { name="beachboy_arm_dark", frames={ 5,12,15,19,23,26 }, loopDirection="bounce" },
  { name="beachboy_foot_dark", frames={47} }
}

-- CREATE A DISPLAY GROUP FOR THE CHARACTER
local beachboy = display.newGroup()

-- CREATE BODY PARTS AS SPRITES
local hat = display.newSprite( sheet, sequenceData )
      hat:setSequence( "beachboy_hat_yellow" )
local body = display.newSprite( sheet, sequenceData )
      body:setSequence( "beachboy_body_dark" )
local shorts = display.newSprite( sheet, sequenceData )
      shorts:setSequence( "beachboy_shorts_red" )
local rightArm = display.newSprite( sheet, sequenceData )
      rightArm:setSequence( "beachboy_arm_dark" )
local leftArm = display.newSprite( sheet, sequenceData )
      leftArm:setSequence( "beachboy_arm_dark" )
local rightFoot = display.newSprite( sheet, sequenceData )
      rightFoot:setSequence( "beachboy_foot_dark" )
local leftFoot = display.newSprite( sheet, sequenceData )
      leftFoot:setSequence( "beachboy_foot_dark" )

-- POSITION PARTS & ORIENT L/R SIDES WITH SCALING
shorts.x, shorts.y = 0, 15
leftArm.x, leftArm.y = -20, -18
leftArm.xScale = -1 --flip 'leftArm' horizontally
-- etc...

-- INSERT ELEMENTS INTO THE DISPLAY GROUP, ORDERED BOTTOM TO TOP
beachboy:insert(leftFoot)
beachboy:insert(rightFoot)
beachboy:insert(shorts)
-- etc...

-- STORE REFERENCES TO EACH ELEMENT
beachboy["feet"] = {leftFoot, rightFoot}
beachboy["shorts"] = shorts
beachboy["body"] = body
-- etc...



Animating the Elements


이 모든 element들이 제자리를 잡고 여러분의 캐릭터가 show up 하면 이제 그 캐릭터의 발 움직임을 줘서 애니메이션을 만들 수가 있습니다.


--WALK SEQUENCE
function beachboy:walk()

  local feet = self.feet

  --CLEAR EXISTING TRANSITIONS IF RUNNING
  if not ( self.currentTransitions ) then self.currentTransitions = {} end --add container table if not present
  local currTrans = self.currentTransitions
  local tot = #currTrans
  for i = tot,1,-1 do --loop backwards through transitions and clear each one
    if (currTrans[i]) then transition.cancel(currTrans[i]) ; currTrans[i] = nil end
  end

  local t = 500 --WALK CYCLE TIMING
  local dist = 160 --FOOT MOVEMENT DISTANCE
  local ease = easing.inOutQuad --FOR A NATURAL SWINGING MOTION

  --RECURSIVE ANIMATION FUNCTION
  local function anim()
    for i = 1,#feet do
      currTrans[i] = transition.to(feet[i], {y=dist, time=t, transition=ease, onComplete=function()
        currTrans[i] = transition.to(feet[i], {y=0, time=t, transition=ease, onComplete=function()
          anim()
        end})
      end})
    end
  end

  --START THE ANIMATION
  anim()

end


 

이제 우리만의 Runtime animation code 를 call 하고 있죠? 우리는 이 튜토리얼에서 계속 반복되는 transition들을 사용하고 있습니다. 여기서 팔도 발하고 같이 어울리게 애니메이션을 주고 싶다면 여기서 조금 더 작업을 해야 합니다. (이 부분은 따로 다루지는 않겠습니다.)

이제 같은 메모리로 여러 color들을 표현할 수 있게 됐습니다.


“Tinting” the Elements



여기서 각 파트별로 programatic tinting을 사용해서 color 까지도 코딩으로 넣을 수가 있습니다. 이것은 코로나의 setFillColor() method를 사용하면 됩니다. 우선 모든 부분을 흰색으로 만듭니다. 아래 샘플 이미지가 있습니다.







아래에 코딩으로 어떻게 sprite object들에 tint를 하는지에 대한 예제가 있습니다.

-- ACCESS EACH ELEMENT FROM THE CONTAINER TABLE BY INDEX NAME
beachboy.hat:setFillColor(252, 206, 0)
beachboy.body:setFillColor(126, 79, 33)
beachboy.shorts:setFillColor(220, 0, 0)
beachboy.feet[1]:setFillColor(126, 79, 33) --access 'leftFoot' by position within 'feet' table
beachboy.feet[2]:setFillColor(126, 79, 33) --access 'rightFoot' by position within 'feet' table
-- etc...

  

이제 원하는 색을 넣을 수도 있고 랜덤하게 색을 넣을 수도 있습니다. 여러분 마음대로 하시면 됩니다. 단지 다른 animation sequence 될 때마다 색을 넣어야 하는 작업을 해야 되겠죠. 그리고 캐릭터가 움직이면서 좀 더 CPU 를 잡아 먹을 겁니다. 그리고 한 객체에 한가지 색만 넣을 수 있겠죠. 줄무늬 옷이나 뭐 그런거는 좀 힘듭니다. 흰색과 회색을 사용해서 조금 sprite 한 느낌은 줄 수 있겠죠.


In Summary



해 보니까 이 방법은 요즘 대부분의 모바일 디바이스에서 사용하는 예외적인 방법이더라구요. 이 방법을 사용하면 texture memory를 훨씬 줄일 수 있습니다. 우리는 이 beachboy 캐릭터의 용량을 225 KB에서 109 KB로 줄였었습니다. 그리고 마지막 방법까지 하면 12KB 로 95%나 줄일 수 있었습니다.


그리고 또 다른 효과는 각 파트별로 다른 애니메이션 효과를 줄 수 있게 된 겁니다. 팔 하나만 움직이게 할 수도 있고 두 팔을 다 움직이게 할 수도 있구요 또 더 나아가서는 펀치나 킥하는 장면도 넣을 수 있겠죠.


그리고 각 character element 별로 tint/color 를 할 수가 있어서요 아주 다양한 캐릭터를 만들어 낼 수 있게 됐습니다.

이렇게 dynamically-optimized sprite sheet 를 사용하면 아주 다양하고 훌륭한 효과를 낼 수가 있습니다. 그리고 여러분의 코딩에 따라서 한정된 이미지로 개성있는 캐릭터를 계속 만들어 낼 수 있구요.


반응형


반응형
Posted on . Written by


화요일의 Tutorial이 다시 돌아왔습니다. 오늘의 튜토리얼은

Brent Sorrentino 가 작성한 건데요. Northern Colorado 에서 Corona Ambassador 로 활동하고 있습니다. Brent는 2년여 코로나 커뮤니팅서 활발히 활동하고 있습니다. 그는 프리랜서 여행사진작가이고 코로나 개발자이며 그래픽 디자이너 입니다. 그만의 앱을 개발하기 위해 코로나를 사용하고 있습니다. 또한 정기적으로 포럼에서 여러사람에게 도움을 주고 있고 여러 이슈들을 해결해 주고 있습니다 그의 웹사이트를 보시려면 여기를 클릭하세요.



오늘의 튜토리얼은 어떻게 animated sprite를 implement 할 것인가와 그와 관련된 API 들에 관한 겁니다. 아마 이전 튜토리얼에서 다룬 내용도 있을 겁니다. 올해 초 현재의 스프라이트 시스템이 소개 된 이후 몇가지 주요 개선사항이 있었습니다. 그리고 많은 개발자들이 아직도 코로나에서 어떻게 sprite를 implement 하는지에 대해 혼동을 하고 있습니다. 이 sprite를 사용하는 방법에는 두가지가 있습니다.


  1. The old (and now depreciated) sprite.* library.
  2. The current sprite APIs that work cohesively with image sheets and the display.* library.


이렇게 코로나의 스프라이트 라이브러리가 변화를 보였는데요. 그 중에서 현재 버전을 사용할 것을 강력히 추천합니다. 현재 방법을 사용하지 않았거나 코로나에서 스프라이트를 한번도 사용해 보지 않았다면 이 튜토리얼이 많이 도움이 될 겁니다.


코로나의 basic animation에 이미 익숙하신 분이라면 이 튜토리얼이 sprite event listeners에 대한 모든 정보를 제공하고 어떻게 implement 할 것인지를 가이드 해 드릴 겁니다.


Tutorial Contents

  1. Configuring a Basic Image Sheet or “Sprite Sheet”
  2. Defining Animation Sequences
  3. Declaring a Sprite Object
  4. Sprite Control Methods — managing playback and sequences
  5. Sprite Properties — accessing and setting various sprite properties
  6. Sprite Event Listeners — detecting sequence events such as “ended”, “loop”, and “next”
  7. Frame Trimming Support


Configuring a Basic Image Sheet or “Sprite Sheet”



정확히 image sheet 이 뭘까요? 한번 상상해 보세요. 여러분들의 animated object 들을 위해 각각 의 프레임들을 그린 한장의 종이가 있다고요. 코로나에서 다른 전문적인 용어로는 texture atlas, image map, or sprite sheet 라고 합니다. 이걸 그냥 간단히 image sheet라고 부를께요. 이것은 static 이든 animated object 이든지 상관없이 활용할 수 있습니다.

graphics.newImageSheet() API에 대한 자세한 사용법과 샘플들은 여기에 있습니다. 이 튜토리얼에서는  그중에서 어떻게 animated sprite를 위해 image sheets를 사용할지에 대해 다루겠습니다.



아래 그림은 running cat 을 표현하는 샘플 image sheet 입니다. 이 튜토리얼을 공부하면서 이 이미지를 사용하시려면 여기에 hi-resolution version 이미지가 있습니다. 이 sheet 에는 8개의 프레임이 순서대로 있습니다. 디폴트로 애니메이션은 top-left frame 부터 시작해서 오른쪽으로 진행하죠. 오른쪽 끝까지 가면 그 다음 줄로 갑니다. 그리고 전체 프레임을 다 돌면 중지합니다.






코로나에서 이 image sheet 을 어떻게 다루는지 보겠습니다. 우선 uniform-sized frame 인 basic image sheet 를 위해 indexed table을 setup 합니다.

local sheetData = {
  width = 512, --the width of each frame
  height = 256, --the height of each frame
  numFrames = 8, --the total number of frames on the sheet
  sheetContentWidth = 1024, --the total width of the image sheet (see note below)

  sheetContentHeight = 1024 --the total height of the image sheet (see note below)

}


IMPORTANT:  sheetContentWidthsheetContentHeightoverall 1:1 dimensions of the image sheet (전체 가로 세로)를 나타냅니다.1:1 content scale 은 여러분이 앱의 config.lua file에 set up 한 내용을 기준으로 합니다.  이렇게 하면 다른 디바이스별로 다른 이미지를 사용할 수 있도록 합니다. 예를 들어 @1 sheet는 original iPad 에 맞는 이미지를 사용하고 high-resolution @2 sheet 는 Retina iPad 에 맞는 이미지를 사용할 수 있습니다. 그러니까 1:1 sheet이 1024×1024 pixels 이라면 2:1 sheet 는 2048×2048 인 이미지가 되는거죠. image sheet setup에는 항상 1:1 dimensions를 사용하세요. config.lua file 세팅이 정확하다면 그 다음부터는 코로나가 알아서 처리할 겁니다.



이제 실제 image sheet 를 정의하세요. 괄호 안에 image file 과 위에 정의한 data table을 넣어주시면 됩니다. 아래처럼 파일이름만 넣으면 그 이미지 파일을 여러분 프로젝트 디렉토리의 root 에서 찾을 겁니다. 


local mySheet = graphics.newImageSheet( "runningcat.png", sheetData )


Defining Animation Sequences


여러분은 두가지 방법으로 animated frame 순서를 정하실 수 있습니다.

  • consecutively using a starting frame index and frame count
  • non-consecutively using a specific order of frames


이 두 가지 방법으로 코로나에서 sprite system 을 아주 flexible 하게 사용하실 수 있습니다. 하나의 image sheet 으로 여러 animation sequences를 사용해서 활용할 수가 있죠. 두 경우 모두 sub-table에서 comma-separated array 로 sequences를 define 하시면 됩니다.


Consecutive frames


local sequenceData = {
  { name = "normalRun", --name of animation sequence

    start = 1, --starting frame index

    count = 8, --total number of frames to animate consecutively before stopping or looping

    time = 800, --optional, in milliseconds; if not supplied, the sprite is frame-based

    loopCount = 0, --optional. 0 (default) repeats forever; a positive integer specifies the number of loops

    loopDirection = "forward" --optional, either "forward" (default) or "bounce" which will play forward then backwards through the sequence of frames

  } --if defining more sequences, place a comma here and proceed to the next sequence sub-table


}



Non-consecutive frames


local
sequenceData = {
  { name = "fastRun",
    frames = { 1,2,4,5,6,7 }, --specific order of frame indexes from the image sheet

    time = 250,
    loopCount = 0
  } --if defining more sequences, place a comma here and proceed to the next sequence sub-table

}

Mixed sequences (both consecutive and non-consecutive sequences)


local
sequenceData = {
{ name="normalRun", start=1, count=8, time=800 },
  { name="fastRun", frames={ 1,2,4,5,6,7 }, time=250, loopCount=0 }

}

 

Declaring the Sprite Object


현재의 sprite method를 사용하려면 display.newSprite() API 로 sprite를 선언하셔야 합니다. 신택스는 간단합니다.


display.newSprite( [parent,] imageSheet, sequenceData )
  • parent = The parent display group in which to insert the sprite (optional).
  • imageSheet = The image sheet which the sprite should utilize.
  • sequenceData = The array of animation sequences which you set up. The sprite will default to the first sequence in the array unless you specify otherwise (see Sprite Control Methods below).


이 튜토리얼에 나온 예제로 한다면 sprite 선언은 아래와 같을 겁니다.

local animation = display.newSprite( mySheet, sequenceData )


이제 이 sprite 는 display object가 됐습니다. 그냥 일반 static image, vector objects 같은 것들과 같게 됐죠. 이제 이 sprite 는 움직일 수도 있고 manipulated 될 수도 있고 physics body 를 입힐 수도 있고... 등등을 할 수 있습니다. 이 sprite object 를 remove 시키려면object:removeSelf()display.remove( object ) 를 사용하시면 됩니다. remove 한 다음에 nil로 세팅하는 것을 잊지 마세요.


Sprite Control Methods


이 스프라이트 시스템은 4가지 주요 control methods를 제공합니다. 여러분들은 이것으로 스프라이트의 playback과 sequence 를 control 하실 수 있습니다.


  • animation:play()
    Start the animation playing. Animations do not begin playing when you create them — you must start each animation manually using this command.
  • animation:pause()
    Pauses the animation. There is no “stop” control method; instead, pause the animation using this method.
  • animation:setFrame( frame )


    Immediately set or skip to the indicated frame index. If you want to “stop and reset” an animation sometime after you have started playing it, use the :pause() and :setFrame( frame ) commands consecutively, setting the frame back to the beginning of the sequence.
  • animation:setSequence( sequence )


    Set the sprite to a specific sequence that you declared in your sequence array. For example, if you want to change your cat animation from “normalRun” to “fastRun”, you would use animation:setSequence( “fastRun” ) and use animation:play() to begin playing it, since the animation will not play automatically after you change the sequence.


Putting It Together


전체 애니메이션을 함께 넣어보죠. 달리는 고양이를 normalRun 과 fastRun 두가지로 셋업할 겁니다. 아래 예제가 있습니다.

local sheetData = { width=512, height=256, numFrames=8,

sheetContentWidth=1024, sheetContentHeight=1024 }

local mySheet = graphics.newImageSheet( "runningcat.png", sheetData )

local sequenceData = {
  { name = "normalRun", start=1, count=8, time=800 },
  { name = "fastRun", frames={ 1,2,4,5,6,7 }, time=250 }
}



local animation = display.newSprite( mySheet, sequenceData )
animation.x = display.contentWidth/2 --center the sprite horizontally
animation.y = display.contentHeight/2 --center the sprite vertically

animation:play()





코로나 시뮬레이터로 테스트 해 보세요. 저 고양이가 화면 중앙에 나올겁니다. 그리고 normalRun sequence로 animating 되겠죠. (sequence를 따로 선언하지 않으면 위에 얘기했던 디폴트 순수대로 진행합니다.)
테스트를 위해 animation:play()앞에 animation:setSequence( “fastRun” )를 넣어 보세요.


Sprite Properties


Corona provides several properties which can yield information about existing sprites. You can even modify the timeScale (relative speed) of a particular sprite. These properties are as follows:

코로나에는 현재의 스프라이트에 적용할 수 있는 몇가지 프로퍼티들을 제공합니다. 특정 스프라이트의 timeScale (relative speed)를 modify 할 수도 있습니다. 아래 프로퍼티들을


  • object.frame
    A read-only property that represents the currently shown frame index of the loaded sequence. This does not set the frame — use the :setFrame() command to explicitly set an animation frame.
  • object.isPlaying
    Returns true if the animation is currently playing; false if it is not.
  • object.numFrames
    A read-only property that represents the number of frames in currently loaded sequence.
  • object.sequence
    A read-only property that returns the name of the currently playing sequence.
  • object.timeScale
    Gets or sets the scale to be applied to the animation time. This is used to control a sprite’s animation speed dynamically. For example, a time scale of 1.0 (default) runs the animation at normal speed. A time scale of 2.0 runs the animation twice as fast. A time scale of 0.5 runs the animation at half speed. The maximum allowed value is 20.0 and the minimum allowed value is 0.05. The value supports up to 2 decimal places.


Sprite Event Listeners


이제 basic sprite 선언과 두개의 sequences (“normalRun” , “fastRun”) 가 생겼습니다. 

이제 sprite event listener를 살펴보죠. 그리고 그것을 어떻게 implement 하는지에 대해 알아보겠습니다. sprite event listener 의 정의는 'sprite의 activity를 "listens" 하고 그 정보를 listener function에 전달하는 것' 입니다.


예를 들어 여러분의 달리는 고양이를 "normalRun" sequence로 4번(4 cycles)를 돌게 한 다음에 "fastRun" sequence로 바꿀 수 있습니다. 이것은 standard timer 로 표현하기에는 불가능한 효과죠. 그래서  그 대신에 sprite event listener를 implement 하는 겁니다.



예제를 보기 전에 sprite에서 사용 가능한 5가지 를 event phases보겠습니다.

이 phases 들은 최근의 코로나 Public Release 인 (2012.894) 버전 이후부터 사용하실 수 있습니다.


  • began = The sprite has started playing.
  • ended = The sprite has finished playing.
  • bounce = The sprite has bounced from forward to backward while playing.
  • loop = The sprite has looped to the beginning of the sequence.
  • next = The sprite has played a subsequent frame that’s not one of the above phases.


이 phases 를 어떻게 listen 할지에 대해 다루겠습니다. 근데 우선 달리는 고양이에 loopCount = 4를 추가해서 normalRun 의 sequence를 바꾸고 시작하도록 하죠. 이렇게 하면 4번의 loop가 끝나면 ended phase를 받을 수 있도록 해 줍니다.


local sequenceData = {
  { name = "normalRun", start=1, count=8, time=800, loopCount=4 }, --add loopCount=4

  { name = "fastRun", frames={ 1,2,4,5,6,7 }, time=250 }
}

 

Now, let’s write the listener function and add the actual event listener to the running cat. You can place this at the end of your sample code, after the sequences are declared and the sprite object placed on the screen.

이제 listener function을 만들어 봅시다. 그리고 달리는 고양이에 실제 event listener를 달아보죠. 아래 내용을 위 샘플 코드의 마지막 부분에 sequence 가 선언된 다음에 추가하시면 됩니다.


local function mySpriteListener( event )
if ( event.phase == "ended" ) then
    local thisSprite = event.target --"event.target" references the sprite
    thisSprite:setSequence( "fastRun" ) --switch to "fastRun" sequence
    thisSprite:play() --play the new sequence; it won't play automatically!
  end

end

animation:addEventListener( "sprite", mySpriteListener ) --add a sprite listener to your sprite

 
sprite listener 가 이제 모든 phases를 listener 함수에 전달하게 됩니다. if-then 구문을 사용해서 이 phases를 사용하는 것은 개발자가 코딩해야 할 부분입니다. 특정 시점에 우리는 ended phase를 listen 하게 됩니다. sequence의 loopCount parameter에 의해 4번의 루프가 끝나면 이 ended phase가 발생하도록 했죠. 이 ended phase 를 받으면 이 cat animation을 fastRun sequence로 바꾸고 play 하게 됩니다.

하나의 sprite listener를 모든 sprite 에 대해 사용하실 수 있습니다. listener 함수에서 event.target을 사용해서 원하는 스프라이트를 catch 해서 사용하실 수 있는겁니다.


Frame Trimming Supported



최근의 Public Build (2012.894) 에서는 frame trimming 도 지원합니다. 3rd-party sprite utilities 인 SpriteLoqTexturePacker 같은 곳에서 이 기능을 제공하고 있습니다. 그리고 코로나에서도 이 어플리케이션과 호환성 있게 이 기능을 사용할 수 있도록 하고 있습니다.

frame trimming 예제는 current sprite methods 를 사용하고 있는데 이것은 여러분 시스템의 코로나 어플리케이션에 있는 “HorseAnimation” sample project에서 확인 하실 수 있습니다.


CoronaSDK → SampleCode → Sprites → HorseAnimation



이와 관련해서는 다음 튜토리얼에서 다뤄지게 될 것 같습니다. 그동안 여러분은 샘플 프로젝트를 보셔도 되고 여기에서 imageSheet documentation를 보시면 많은 도움이 되실 겁니다.


In Summary


이 튜토리얼은 current sprite methods 의 대부분을 다뤘습니다. 여기에 basic image sheets, animation sequences 정의하기, sprite playback 다루기, 다양한 sprite property들 다루기 그리고 sprite event listener 사용하기 등을 추가로 다루고 있습니다. 모쪼록 이 튜토리얼이 개발자 여러분에게 스프라이트를 이용해서 앱을 만드는데 도움을 드릴 수 있기를 바라겠습니다. 특히 이전 버전의 sprite library 를 사용하시던 분들에게 새로 바뀐 sprite library 를 사용하시는데 도움이 되기를 바라구요.


반응형


반응형
Posted on . Written by


존 레논이 말했죠, life는 네가 다른 plan을 만들 때 일어난다고요. 그런 비슷한 일들이 최근 저희들에게 일어났었습니다. Kindle HD/NOOK HD 에 대해 관심을 많이 가진 이후로요. 이런 디바이스들에 대한 Corona’s support 를 하기 위해 Kindle HD에 대한 지원을 진행했고 NOOK HD 에 대한 지원도 많이 진행 됐습니다.


한가지 우리가 찾아낸 것은 여러분의 ‘build.settings’ file 에 어떤 Lua syntax 에러가 있으면 여러분의 APK는 NOOK pre-flight submission tests에 통과하지 못할 거라는 겁니다. 여러분의 편으를 위해서 저희들이 약간의 변화를 주려고 합니다. 그래서 그 파일에 에러가 있더라도 그 APK 가 제대로 동작할 수 있도록요.


이런 critical 한 이슈들에 대해 정리하는 동안 daily build 929 버전부터 가능하도록 한 이슈들이 몇가지 있습니다.



그 중 하나가 맵뷰를 로딩할 때 배경색을 흰색에서 회색으로 바꾼건데요. 이렇게 하면 activity indicator를 보는것이 훨씬 더 쉽습니다. 또한 native activity indicator 가 전체 스크린에 나오는 버그도 수정했습니다. 이 두 이슈는 NOOK HD 가 다른 안드로이드 디바이스와는 다르게 그들의 default를 세팅하지 않았기 때문에 일어나는 것 같습니다. 또한 NOOK HD 에서 맵뷰가 redrawing 하지 않는 버그도 찾아냈는데요. 운 좋게도 이와 관련된 작업을 standard와 custom android 디바이스에서 하고 있었거든요. 그래서 쉽게 고칠 수 있었습니다.

그리고 여러분 중에 인터페이스에 관심 있는 분들은 다음 내용이 흥미로울 겁니다. new NOOK HD 에서 제공되는 alert box의 default theme 이 별로 좋지가 않습니다. 그래서 이 것을 Jellybean(4.1) 의 디폴트 theme 인 (“Holo Dark”) 을 사용하기로 했습니다. 디폴트 인 왼쪽 이미지와 Jellybean theme 인 오른쪽 이미지를 비교해 보세요.






daily build 929 에서는 안드로이드 디바이스에는 이 4.1 theme을 적용할 겁니다. 이것은 standard Android (Google Play) 이든 custom Android devices 이든 (Kindle HD, NOOK HD) 모두에 적용 됩니다. 이렇게 함으로서 전체 안드로이드 스펙트럼에 걸쳐 여러분 앱의 일관성이 유지되도록 할 겁니다.


위 내용은 Android 3.x 이상의 디바이스에 적용 됩니다. 만약에 여러분 앱이 더 오래된 디바이스에서 run 된다면 alerts의 older look을 제공할 겁니다. (older Kindles와 NOOKs 도 마찬가지 입니다.)



아래 왼쪽은 old one 이고 오른쪽은 new one 입니다. 보시면 OK, Cancel 버튼의 위치가 바뀐것을 보실 수 있을 겁니다.




반응형


반응형

Posted on . Written by




Corona daily build 928에 적용될 내용을 공지합니다. 저희들은 스토리보드와 widget library들의 여러 버그들을 반견하고 수정했습니다. 또한 차세대 widgets 를 위한 기반작업으로 widget library에 여러 작업들을 진행하고 있습니다.



이 라이브러리에 대한 어떤 기능들이 퇴보하거나 한 사항들은 없음을 말씀 드리고 싶습니다. 예를 들어 한 버그를 없애기 위해 그 기능을 제한한다든가 하는 것들요. 그래서 이렇게 heads up  정보를 알려 드립니다.



아래가 저희들이 수정한 버그들의 리스트들입니다.

Storyboard

  • 15040 – Storyboard overlayEnded stack overflow when calling gotoScene
  • 17590 – Storyboard immediate scene transitions cause simulator to hang when using Runtime::addEventListener in enterScene.
  • 15384 – modal overlays let touch events through if x < 0
  • 15264 – Storyboard: overlayEnded being called infinitely
  • 15781 – Storyboard transition when using letterbox and universal app
  • 15257 – Memory Leak with storyboard.printMemUsage()
  • 16540 – enterScene called multiple times
  • 14794 – effect time in storyboard.hideOverlay()

Widget

  • 16094 – tableView methods scrollToY() not taking topPadding property into account, and scrollToIndex() not working.
  • 15293 – Inconsistent size property of Button widget’s label) – By adding method setLabelSize( newSize ) method
  • 17029 – tableViews/scrollView widgets scrolling does not stop on tap
  • 16605 – listener not working in newTableView




반응형

Kurogo Tutorial 24 - People Module -

2012. 10. 10. 21:23 | Posted by 솔웅


반응형

People Module



people 모듈은 directory 로 어떤 mobile access 기능을 제공하는 겁니다. 간단한 configuration으로 모바일 device 에서 유저에 대한 searching 과 detail 한 정보 보기 등을 가능하도록 할 수 있습니다. LDAP base directory와 database backed directories 모두 지원합니다.


Configuring the Server Connection



이 모듈의 configuration은 Administration Module 이나 SITE_DIR/config/people/feeds.ini file을 edit 하셔야 합니다. 여러분의 directory 시스템에 connect 하기 위해서는 여러 방법들이 사용될 수 있습니다.


  • RETRIEVER_CLASS allows you to determine the mechanism for retrieving the data. Current options include:
    • LDAPPeopleRetriever - uses a standard LDAP server. You can configure the various fields if your values differ from defaults
    • ADPeopleRetriever - a subclass of the LDAP retriever that has preconfigured mappings for Active Directory
    • DatabasePeopleRetriever - connects to an external database server. This controller assumes that people are mapped to a single row and that the various fields are stored in single (definable) columns
  • PERSON_CLASS allows you to set a different class name for the returned user objects when searching. This class must be a subclass of the Person class. This allows you to write custom behavior to handle the data in your directory service.


Options for LDAPPeopleRetriever and ADPeopleRetriever


  • HOST - should match the address of your server. Keep in mind that this server must be accessible from the web server the framework is hosted on. Managing network and firewall settings is the responsibility of your network administrator.
  • SEARCH_BASE - should manage the LDAP search base of your directory. You can get this value from the administrator of your LDAP directory. Examples would include “dc=example,dc=com”
  • PORT - Optional (Default 389) The port to connect. Use 636 for SSL connections (recommended if available)
  • ADMIN_DN - Some servers do not permit anonymous queries. If necessary you will need to provide a full distinguished name for an account that has access to the directory. For security this account should only have read access and be limited to the search bases to which it needs to access.
  • ADMIN_PASSWORD - The password for the ADMIN_DN account.





다음 값들은 controller에게 searching 할 때 어떤 attributes들을 사용할 것인지를 알려 줍니다. 이 값들은 디폴트값고 다를 경우 사용할 필요가 있을 겁니다.


  • LDAP_USERID_FIELD (uid, samaccountname for AD)- Stores the unique user name for this user. Do not choose an attribute that is sensitive as they are easily viewed by users
  • LDAP_EMAIL_FIELD (mail) - The attribute of the user’s email address
  • LDAP_FIRSTNAME_FIELD (givenname) - The attribute of the user’s first name
  • LDAP_LASTNAME_FIELD (sn) - The attribute of the user’s last name
  • LDAP_FULLNAME_FIELD (blank) - If you wish to use a single field for name (like cn), include this here.
  • LDAP_PHONE_FIELD (telephonenumber) - The attribute of the user’s phone number

Options for DatabasePeopleRetriever


DatabasePeopleRetriever 에는 사용할 수 있는 여러 configuration value들이 있습니다. 모두 optional 이죠. 데이터베이스 connection에 대한 configuration에 대해 자세히 알고 싶으시면 Database Access를 보세요.

만약 이중에 어떤 value 라도 생략되면은 디폴트를 세팅할 겁니다. (Configuring Database Connections)

아래 value는 데이터가 있는 테이블의 위치를 controller에게 알려 줍니다.


  • DB_USER_TABLE - (users) The name of the table that stores the user records. This table should at least have fields for userID, name and email. Each row should contain a single user entry.


아래 값들은 controller 에게 주요 field 에 대한 정보를 줍니다. 이 값들은 디폴트값과 그 값이 다를 경우에 적용되게 됩니다.


  • DB_USERID_FIELD (userID)- stores the userID in the user table. You can use any unique column for the userID field. Do not use sensitive values as they are easily viewed by users.
  • DB_EMAIL_FIELD (email) - stores the email in the user table
  • DB_FIRSTNAME_FIELD (firstname) - stores the first name of user.
  • DB_LASTNAME_FIELD (firstname) - stores the last name of user.
  • DB_PHONE_FIELD (no default) - stores the user’s phone number. If empty then the search will not use the phone number


다른 필드들은 아래 configuring the detail fields 에서 설명됩니다.


Configuring the Detail Fields


서버 세팅이 끝났으면 여러분 서버와 detail view 와의 field mapping을 해야 합니다. 디폴트로는 LDAP으로 세팅 돼 있습니다. 만약에 nonstandard directory를 사용하신다면 혹은 자체 필드들을 가지고 있는 데이터베이스와 연결하신다면 이것들이 어떻게 display 될지에 대해 customize 하셔야 합니다.

이 필드들은 SITE_DIR/config/people/page-detail.ini file 에 configured 됩니다. 각 필드는 섹션별로 configured 됩니다. (섹션 이름은 unique 해야 합니다.) 섹션의 순서는 detail view의 순서와 같습니다. 각 섹션안에는 어떻게 display 될지에 대해 설정할 수 있는 여러 value들을 넣을 수 있습니다.


  • label - (required) A text label for the field. Can include HTML tags.
  • attributes - (required) Array of fields to put in the contents (should map the the field names in your backend system)
  • format - (optional) A string for vsprintf to format the attributes. Only needed if more than one attribute is provided.
  • type - (optional) One of “email” or “phone”. Used to format and generate links.
  • module - (optional) Creates a link to a another module and uses that module’s linkForValue method to format the result. See the section on Module Interaction for more details.
  • section - (optional) If this field belongs to a section, the name of that section
  • parse - (optional) A function which will be run on the value before display. Generated with create_function. Gets the argument “$value” and returns the formatted output.


Configuring Display Options


아래 있는 옵션들은 people 모듈을 appearence 하는데 관련된 것들입니다.

  • BOOKMARKS_ENABLED - (optional) If set to true, a link to bookmarked entries will appear. Note that if you have not bookmarked any entries, this link will not appear until an entry is bookmarked. Defaults to true.
  • CONTACTS_SUBTITLE_NEWLINE - (optional) Set to true to display contacts subtitles on a new line. Defaults to false.
  • SEARCH_TIP - (optional) A string to be shown near the search bar providing a tip about searching. By default this string is empty, and not shown.


Configuring the Fixed Entries


이 모듈은 모듈 인덱스 페이지에서 directory entry들의 리스트를 보이게 할 수 있습니다. 그리고 SITE_DIR/config/people/contacts.ini를 수정함으로서 이 리스트의 content를 update 하실 수 있습니다. 각 entry는 섹션의 0-indexed 형식으로 숫자화 되서 다뤄집니다. 각 섹션은 4개의 value들이 있습니다. 이것들은 listItem template 과 매핑돼 있죠. 이것들은 URL 리스트를 표시하기 때문에 phone number 를 가지지 못합니다. 다만 어떤 URL 이라도 올 수 있습니다.


  • title - The Name of the entry as it’s shown to the user
  • subtitle - The subtitle, typically the phone number for phone entries.
  • url - The link it should point to, use tel:XXXXXXXX links for phone numbers
  • class - The CSS class of the item, such as phone, map, email


Creating groups of contacts

  • NOTE - Creation of contact groups is not supported in the admin console at this time.


만약에 여러 contacts 를 카테고리로 묶어야 한다면 여러분들은 그것을 group으로 묶어야 합니다. contact group들을 만드시려면 아래와 같이 하시면 됩니다.


  1. If it does not exist, create a file named SITE_DIR/config/people/contacts-groups.ini
  2. Add a section to contacts-groups.ini with a short name of your group. This should be a lowercase alpha numeric value without spaces or special characters
  3. This section should contain a “title” option that represents the title of the group. Optionally you can include a description value that will show at the top of the contacts list for the group
  4. Create a file named SITE_DIR/config/people/contacts-groupname.ini where groupname is the short name of the group you created in contacts-groups.ini. This file should be formatted like contacts.ini with each entry being a numerically indexed section
  5. To use this group, assign it to a entry in contacts.ini. Do not include a url, but rather add a value group with a value of the short name of the group. You can optionally add a title that will be used instead of the group title indicated in contacts-groups.ini


아래는 SITE_DIR/config/people/contacts-groups.ini의 예제입니다. 각 그룹은 섹션으로 표현되는데 그 안에는 title 이 있고 옵션으로 description 이 있습니다. 여러분이 원하는 만큼의 그룹을 만드실 수 있습니다.


[admissions]
title = "Admissions"


SITE_DIR/config/people/contacts-admissions.ini. 아래는 admissions group의 예제입니다. contacts.ini file과 같은 형식입니다.


[0]
title    = "Admissions Main Number"
subtitle = "(617-555-0001)"
url      = "tel:6175550001"
class    = "phone"

[1]
title    = "Admissions Hotline"
subtitle = "(617-555-0002)"
url      = "tel:6175550002"
class    = "phone"


SITE_DIR/config/people/contacts.ini. 그룹을 보이기 위해 group value가 있습니다. url value는 없습니다.


[0]
title    = "Static Entry 1"
subtitle = "(617-555-0001)"
url      = "tel:6175550001"
class    = "phone"

[1]
title    = "Admissions"
group    = "admissions"


반응형

Kurogo Tutorial 23 - Links Module -

2012. 10. 10. 03:43 | Posted by 솔웅


반응형



========= o ============ o ========== o ========== o ================


이 부분은 Tutorial 이 잘 못 되었네요.


Links 모듈 설명하다가 갑자기 People 모듈로 건너 뛰었습니다.

저 위에 이미지 다음 부터는 people 모듈 관련 내용입니다.


Kurogo 쪽에 얘기해야겠어요... ^^;

반응형

Kurogo Tutorial 22 - Content Module -

2012. 10. 10. 01:44 | Posted by 솔웅


반응형

Content Module


content module은 다른 소스로부터 자유롭게 content를 모으고 display 할 목적으로 만들어 졌습니다. Content Module은 다른 HTML site 나 RSS feed 로부터 display 된 곳으로부터 content를 모아서 display 할 수 있습니다. 또한 configuration file이나 administration module을 사용해서 static content configured 를 display 하도록 할 수 있습니다.

디폴트로 content 모듈은 리스트에 그 feed 를 display 합니다. 그리고 나서 유저가 feed를 선택하면 그 feed 의 content가 보여지게 되는 겁니다. 만약에 feed 가 1개만 있다면 리스트 대신 그 feed 가 보여집니다. 옵션으로 group화 할 수 있습니다.


Configuring Content Feeds


SITE_DIR/config/MODULE/feeds.ini file에 원하는 만큼의 feed 를 정의 하세요. 각 feed 는 section에 의해 표현됩니다. 그 섹션의 이름은 모듈의 page를 의미합니다. 이곳에는 configure 할 몇가지 property들이 있습니다.


  • TITLE - The title of the feed. This is shown in the list and in the navigation bar
  • CONTENT_TYPE - the type of content. Values include:
    • html - Static html text that is included in the CONTENT_HTML property
    • html_url - Fetch HTML content from the BASE_URL property.
    • rss - Fetch RSS content from the BASE_URL property. Will retrieve the content from the first item in the feed. Good for CMS’s that expose their content via RSS. Ensure that this feed contains the full content and not just a link



Creating Groups of Content


  • NOTE - Creation of content groups is not supported in the admin console at this time.

You can create groups of content in order to organize similar content into categories. Creating content groups involves the following steps:

유사한 콘텐트를 하나의 카테고리에 묶기 위해 콘텐트의 group을 만들 수 있습니다. 아래와 같이 group을 생성하시면 됩니다.

  1. SITE_DIR/config/MODULE/feedgroups.ini 파일을 생성한다.
  2. 그룹 이름을 feedgroups.ini 의 section 안에 넣는다. 스페이스나 특수문자가 없는 alpha numeric 소문자이어야 한다.
  3. 섹션에는 TITLE option이 있어야 한다. 이것은 그룹의 title을 나타낸다. 옵션으로 DESCRIPTION value를 넣을 수 있다. 이것은 그룹의 리스트 top에 보여질 내용이다.
  4.  SITE_DIR/config/MODULE/feeds-groupname.ini  파일을 만든다. groupname is the short name of the group you created in feedgroups.ini. This file should be formatted like feeds.ini with each entry being a uniquely indexed section.
  5. 이 그룹을 사용하기 위해 eeds.ini. 안에 entry를 할당한다. 그룹의 short name 값으로 GROUP 값을 넣는다. 옵션으로 TITLE을 넣을 수 있다. 이것은 eedgroups.ini 안에서 group title 대신에 쓰이게 된다.

feeds.ini file에는 groups와 content entry 들이 있을 겁니다. 이것들은 section의 순서대로 display 될 겁니다. 만약 1개의 그룹만이 있다면 그 그룹이 display 될 겁니다.

아래는 SITE_DIR/config/MODULE/feedgroups.ini 예제입니다. 각 그룹은 TITLE이 있는 section 입니다. 여러분이 원하는 만큼의 그룹을 만들 수 있습니다.


[applying]
TITLE = "Applying to Universitas"
DESCRIPTION = ""

[visiting]
TITLE = "Visiting"
DESCRIPTION = ""


SITE_DIR/config/MODULE/feeds-applying.ini.  아래는 applying group 예제입니다. feeds.ini file처럼 format 됐습니다.


[admissions]
TITLE = "Admissions"
SUBTITLE = ""
SHOW_TITLE = 0
CONTENT_TYPE = "html_url"
BASE_URL = "http://universitas.modolabs.com/admissions"
HTML_ID = "node-2"


SITE_DIR/config/MODULE/feeds.ini


[applying]
TITLE = "Applying to Universitas"
GROUP = "applying"

[visiting]
TITLE = "Visiting"
GROUP = "visiting"

[othercontent]
TITLE = "Other Content"
SUBTITLE = ""
SHOW_TITLE = 0
CONTENT_TYPE = "html_url"
BASE_URL = "http://www.example.com/othercontent"
HTML_ID = "html-id"


Options for HTML Content


HTML document에서 data를 추출하기 위해서는 몇가지 옵션이 추가로 있습니다. 대부분의 경우 HTML, HEAD 태그 같은 것들은 건너뛰고 header와 footer 들도 remove 할 겁니다. 그리고 그 HTML 문서의 일부분만 사용하길 원하겠죠. 어떤 content 를 포함 시킬것인지 결정하는 방법에는 두가지가 있습니다.

  • HTML_ID - Use this option to include only a single element (and its child elements) based on its HTML id attribute. This is the simplest, and most recommended option if it is available. The value for this option is case sensitive.
  • HTML_TAG - Use this to include all elements of a certain tag. For instance set it to “table” to include all table elements or “p” to include all paragraph elements. Do not include the surrounding brackets (<, >)


만약 이 옵션을 사용하지 않으면 body tag 전체가 추출될 겁니다.


반응형