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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

지난번 튜토리얼이 길어서 11번에 나눠서 다 올렸습니다.

그거 올리느라고 다른 글들이 많이 밀렸네요.

공부할 것이 많아서 좋습니다. :)

오늘 다룰 글은 1월 29일에 Coronasdk 홈페이지에 올라온 튜토리얼입니다.

모양 맞추기 게임을 아주 쉽게 잘 가르쳐 주고 있네요.


Posted on . Written by



오늘의 guest tutorial 은 Greg Pugh 의 무료 강좌 입니다. 그는 MC Strategies 에서 플래시 및 앱 디벨로퍼로 일하고 있고 펜실베니아 Nanticoke 에 있는 independent studio인 GP Animations의 owner 이기도 합니다.  Greg이 개발한 앱들은 그의 블로그에서보실 수 있습니다. 또한 그는 RayWenderlich.comKwiksher.com에 Corona tutorial을 연재하고 있습니다. 또한 그는 최근 Corona Ambassador 로서 Corona SDK 의 세계로 새로 진입하는 개발자들을 위한 iBook 을 집필하고 있습니다.


Preface


애들이 있다 보니까 저의 iPad는 아이들이 주로 독서하거나 게임할 때 그리고 앱들을 가지고 노는데 사용합니다. 바로 지금 제 딸이 두 책에 끌리는가 봅니다. 제가 쓴 책 (http://www.ColinTurtle.com)과  약간 괴상한 "Game For Cats" 라는 책에요. 조만간 제 딸은 자기 외모와 색깔들과 알파벳 뭐 이런것들을 배울 나이가 되겠죠. 그리고 다른 앱들을 가지고 놀게 될 겁니다. 오늘 저는 아이들이 모양을 드래그 and 드롭해서 같은 모양의 틀에 맞추는 아주 기초적인 아이들용 앱을 만드는 방법으로 보여드리려고 합니다.

우선 실제 이 앱이 동작하는 것을 이 비디오를 통해서 먼저 보셨으면 합니다.

보시다시피 두개의 모양을 동시에 drag 할 수 있게 만들 겁니다. 왜냐하면 아이들은 smart device들을 가지고 놀 때 두손을 모두 사용하려고 하는 경향이 있거든요. 이 기능을 구현하기 위해 David McCuskey 가 만든 dmc_multitouch 를 사용할 겁니다. (관련 모듈이 들어 있는 파일들은 프로젝트에 포함돼 있습니다. 그러니 따로 다운 받으실 필요는 없구요. 그냥 이 프로젝트만 다운 받으시면 됩니다.) 이 글을 쓰는 지금 시점에는 코로나 시뮬레이터에서 멀티터치를 지원하지 않고 있습니다. 테스트를 하시려면 publish 를 해서 디바이스에 인스톨 하신 다음에 멀티터치를 테스트 하셔야 할 겁니다.



프로젝트 파일은 여기에서 다운 받으실 수 있습니다. 일단 SnapShapes 폴더의 압축을 풀면 그 안에 두개의 폴더가 있을 겁니다. SnapShapes_FINAL 에는 완성된 main.lua file 가 있습니다. 그리고 SnapShapes_START 폴더에는 단순한 artwork 와 supporting files 들만 있습니다.


Project Code


시작하시려면 우선 여러분이 사용하시는 텍스트 에디터를 여시고 create a new file 을 선택하신 다음에 그 파일 이름을 main.lua 로 하고 SnapShapes_START 폴더 안에 저장하세요. 첫번째로 할 작업은 dmc_multitouch.lua 파일을 import 하는 겁니다. 아래 코드를 카피해서 main.lua 에 붙여넣기 하세요.


-- Require dmc_multitouch
MultiTouch = require("dmc_multitouch");


다음으로는 status bar 를 감출겁니다. 아이들은 상태바에 나오는 시간이나 여러분 phone 에 어떤 서비스들이 있는지 등은 관심이 없거든요.


-- Hide status bar
display.setStatusBar(display.HiddenStatusBar);


이제 제공된 이미지들을 여러분의 images 폴더에 넣으세요. 그리고 아래 코드를 복사해서 main.lua  파일에 붙여 넣고 저장하세요.


-- Background image
local background = display.newImageRect("images/background.png", 640, 960);
background.x = display.contentCenterX;
background.y = display.contentCenterY;
-- Square outline
local sqLine = display.newImageRect("images/sqLine.png", 228, 228);
sqLine.x = 473;
sqLine.y = 181;
-- Square
local square = display.newImageRect("images/square.png", 188, 188);
square.x = 144;
square.y = 778;
-- Circle outline
local circLine = display.newImageRect("images/circLine.png", 245, 245);
circLine.x = 181;
circLine.y = 180;
-- circle positioning
local circle = display.newImageRect("images/circle.png", 200, 200);
circle.x = 473;
circle.y = 778;
-- myText positioning
local myText = display.newImageRect("images/myText.png", 508, 78);
myText.x = 311;
myText.y = 475;


Corona SDK Simulator 를 여신 후 File > Open 을 선택하세요. 그리고 SnapShapes_START  폴더에 있는 main.lua 를 여세요. phone 종류는 iPhone으로 선택하시기 바랍니다. 이제 여러분 시뮬레이터는 아래 이미지처럼 보일 겁니다.




이제 여러분은 화면에 display 해야할 모든 것을 다 display 했습니다. 이제 기능들을 추가할 차례입니다.
우선 파란 원에 적용될 코드를 만들겁니다. 그 다음에는 단지 변수 이름 등만 수정해서 빨란 사각형에 적용하면 됩니다. 이 때 이 원에 대해 멀티터치가 가능하도록 하고 initial positioning variables 들을 0으로 세팅하세요. 아래 코드를 복사해서 여러분이 만든 main.lua 파일에 붙여 넣으세요.


-- Circle
MultiTouch.activate(circle, "move", "single");
-- Set initial variables to 0
local circlePosX = 0;
local circlePosY = 0;


원을 드래그 하면 이 원은 touch event의 target 이 될 겁니다. moved 와 ended 같은 phases 들을 이용해서 기능을 구현할 수 있게 되는 거죠. 이 원이 위에 있는 동그란 점선 중앙에 50픽셀 이내로 접근했다면 그 원은 그 동그란 점선 안으로 snap 될 겁니다. 그 외의 경우에는 원은 그냥 드래그한 장소에 있게 됩니다.
아래 코드를 추가해 주세요.


-- User drag interaction on blue circle
local function circleDrag (event)
local t = event.target
-- If user touches & drags circle, follow the user's touch
if event.phase == "moved" then
   circlePosX = circle.x - circLine.x; 
   circlePosY = circle.y - circLine.y;
   if (circlePosX < 0) then circlePosX = circlePosX * -1; end
   if (circlePosY < 0) then circlePosY = circlePosY * -1; end
   -- If user drags circle within 50 pixels of center of outline, snap into middle
   if (circlePosX <= 50) and (circlePosY <= 50) then
      circle.x = circLine.x;
      circle.y = circLine.y;
   end


이 원이 동그란 점선 안으로 snap 됐고 유저가 드래그 하는 것을 멈췄다면 그 원은 동그란 점선 안에 제대로 안착돼 있을 갑니다. 


아래 코드를 추가하세요.


-- When the stops dragging circle within 50 pixels of center of outline, snap into middle, and...
elseif event.phase == "ended" then
   if (circlePosX <= 50) and (circlePosY <= 50) then
      circle.x = circLine.x;
      circle.y = circLine.y;
     -- ...lock circle into place where it cannot be moved.
     MultiTouch.deactivate(circle);
   end
end
return true;
end


마지막으로 circleDrag 함수에 이벤트 리스너를 추가하세요. 그리고 저장하시구요.


circle:addEventListener(MultiTouch.MULTITOUCH_EVENT, circleDrag);


시뮬레이터를 refresh 하면 화면에서 파란 원을 드래그 하실 수 있으실 겁니다. 그리고 동그란 점선 중앙에서 50 픽셀 이내로 접근하면 동그란 점선 중앙에 원이 곧바로 snap 될 겁니다. 더이상 드래그를 하지 않으면 그 원은 동그란 점선 안에 제대로 위치해 있을 겁니다.

이제 같은 코드를 빨간 사각형에 적용해 보죠.
그냥 변수 이름들만 바꾸시면 됩니다.


-- Same actions for the square as the circle
MultiTouch.activate(square, "move", "single");
local squarePosX = 0;
local squarePosY = 0;
local function squareDrag (event)
local t = event.target
if event.phase == "moved" then
   squarePosX = square.x - sqLine.x;
   squarePosY = square.y - sqLine.y;
   if (squarePosX < 0) then squarePosX = squarePosX * -1; end
   if (squarePosY < 0) then squarePosY = squarePosY * -1; end
   if (squarePosX <= 50) and (squarePosY <= 50) then
      square.x = sqLine.x;
      square.y = sqLine.y;
   end
elseif event.phase == "ended" then
   if (squarePosX <= 50) and (squarePosY <= 50) then
      square.x = sqLine.x;
      square.y = sqLine.y;
      -- If you'd like to be able to move the square again, comment out the line below
      MultiTouch.deactivate(square);
   end
end
return true;
end
square:addEventListener(MultiTouch.MULTITOUCH_EVENT, squareDrag);


사각형이 점선안에 제대로 자리 잡은 후에도 계속 드래그할 수 있도록 하시려면 코드의 deactivate 라인을 주석처리해 주세요.
이제 유저가 두 모양을 모두 제자리에 놓았다면 유저에게 잘 했다고 축하 해 주시면 되겠네요.

여기까지 입니다. 아이들이 가지고 놀 수 있는 앱을 아주 쉽고 빠르고 만들었습니다.




The Next Step?


위에 구현된 기본적은 기능을 확장해서 좀 더 큰 아이나 어른들을 위한 앱으로 발전 시킬 수도 있겠죠.



    이 코드를 활용해서 아이들이 인형에게 옷을 입히는 앱을 만들 수도 있겠죠?
    여러 조각의 퍼즐을 맞추는 게임을 만들수도 있을 겁니다. 위에 있는 함수들을 여러 조각들에 적용해서 구현하면 될 겁니다.
    adventure game 에 puzzle challenge 를 만들 수도 있을 겁니다.



모바일 혁명이 계속된다면 교육용 앱도 지금 보다 많이 대중성을 가질 겁니다. multitouch 모양 맞추기 기능의 기본을 이해하고 있으면 집에서만이 아니라 학교에서도 사용할 수 있는 아주 좋은 앱을 확장해서 개발할 수도 있겠죠?

반응형

Pinch Zoom Rotate 구현하기 - 11/11 -

2013. 2. 14. 23:41 | Posted by 솔웅


반응형
Posted on . Written by



And Finally…


지금까지의 코드는 single display object 에 대한 내용이었습니다. 실제로는 여러 object 에 이것이 적용 될 수도 있을 겁니다. object 들의 그룹에 pinch-zoome 이 일어날 수도 있겠죠. 더 중요한 것은 이 기능을 re-use 할 수 있도록 하려면 어떻게 해야 할까요?

:touch() 함수를 re-use 하려면 이 기능이 어떤 display object(이미지이든 그룹이든)에도 쉽게 적용 될 수 있도록 해야겠죠. 사용하고 있는 reference 들을 간단하게 change 할 수도 있어야 되겠구요. 이 기느응ㄹ 구현하기 위해 여러 object 들을 포함한 display group 을 하나 만듭시다. 그리고 touch listener 를 붙이고 그 그룹에 function 도 적용해 보죠.


sample11.lua
local group = display.newGroup() -- create display group to listen for new touches
-- populate display group with objects
local rect1 = display.newRect( group, 200, 200, 200, 100 )
rect1:setFillColor( 0, 0, 255 )
 
local rect2 = display.newRect( group, 300, 300, 200, 100 )
rect2:setFillColor( 0, 255 ,0 )
 
local rect3 = display.newRect( group, 100, 400, 200, 100 )
rect3:setFillColor( 255, 0, 0 )
 
group.dots = {} -- keep a list of the tracking dots
 
-- advanced multi-touch event listener
function touch(self, e)
local target = e.target -- get the object which received the touch event
local rect = self -- get reference to self object
if (e.phase == "began") then -- handle began phase of the touch event life cycle...
-- ...
 
end
 
group.touch = touch -- attach pinch zoom touch listener
group:addEventListener("touch") -- listen for touches starting on the touch object
 



In Summary


이제 모두 완료 됐습니다. 이제 touch listener module 은 어떤 display object 나 그룹에도 적용될 수 있습니다. 즉 쉽게 multitouch pinch-zoom-rotation 을 구현할 수 있게 된거죠.


아직 전체 project 를 다운받지 못하신 분들은 여기에서 다운받아서 실행해 보세요.


질문이나 의견이 있으시면 언제든지 댓글에 달아 주세요.

반응형

Pinch Zoom Rotate 구현하기 - 10/11 -

2013. 2. 14. 23:23 | Posted by 솔웅


반응형
Posted on . Written by



Pinch Centre Translation


이전 글에서 만들었던 sample9.lua 코드를 실행해 보세요. tracking dot 들이 rotate,scale, move 할 때 display object 가 약간씩 이동하는 걸 보실 수 있을 겁니다. 이렇게 하면 정확하게 그 midpoint 를 얻을 수가 없는 상황이거든요.


이 문제를 해결하려면 translation, scaling, rotation 을 적용하는데 단순히 basic 만 사용하면 안됩니다. 여기에 display object 의 center point location 도 같이 적용해야 합니다.

    Scaling 은 midpoint 와 “rect” centre 사이의 거리도 참고해서 적용되어야 합니다.
    Rotation 은 “rect” centre 에 적용 되야 합니다. tracking dot midpoint 주위를 회전해야 합니다.
    translation 은 이미 적용됐기 때문에 따로 고려를 하지 않아도 됩니다.


이제 어떤 standard library 수학 함수를 우리가 사용해야 할까요? point 를 회전시켜야 하는데 그 회전은 다른 포인트 주변을 돌아야 합니다. 그러니까 우리는 math helper 들을 사용할 필요가 있습니다. 또한 moved phase 에도 작업을 해 줘야 합니다.



sample10.lua


-- rotates a point around the (0,0) point by degrees
-- returns new point object
function rotatePoint( point, degrees )
local x, y = point.x, point.y
local theta = math.rad( degrees )
local pt = {
x = x * math.cos(theta) - y * math.sin(theta),
y = x * math.sin(theta) + y * math.cos(theta)
}
return pt
end
 
-- rotates point around the centre by degrees
-- rounds the returned coordinates using math.round() if round == true
-- returns new coordinates object
function rotateAboutPoint( point, centre, degrees, round )
 
local pt = { x=point.x - centre.x, y=point.y - centre.y }
pt = rotatePoint( pt, degrees )
pt.x, pt.y = pt.x + centre.x, pt.y + centre.y
if (round) then
pt.x = math.round(pt.x)
pt.y = math.round(pt.y)
end
return pt
end
 
 
-- changes to 'moved' phase
 
-- ...
-- apply rotation and scaling to rect
rect.rotation = rect.rotation + rotate
rect.xScale, rect.yScale = rect.xScale * scale, rect.yScale * scale
end
local pt = {} -- declare working point for the rect location
-- translation relative to centre point move
pt.x = rect.x + (centre.x - rect.prevCentre.x)
pt.y = rect.y + (centre.y - rect.prevCentre.y)
-- scale around the average centre of the pinch (centre of tracking dots, not rect centre)
pt.x = centre.x + ((pt.x - centre.x) * scale)
pt.y = centre.y + ((pt.y - centre.y) * scale)
-- rotate the rect centre around the pinch centre (same rotation as the rect is rotated!)
pt = rotateAboutPoint( pt, centre, rotate, false )
-- apply pinch translation, scaling and rotation to the rect centre
rect.x, rect.y = pt.x, pt.y
-- store the centre of all touch points
rect.prevCentre = centre
 
else -- "ended" and "cancelled" phases

main.lua

sample10.lua


moved phase 에 여러 기능들이 추가 됐습니다.


    pt 는 display 객체의 포지션 에 대한 working space 를 사용하기 위해 정의됩니다.
    midpoint translation은 working object 에 적용됩니다.
    midpoint 와 display object 중심사이의 거리가 scale 됩니다.
    display object 의 중심은 midpoint 주위를 회전합니다.


이제 코드를 실행해 보세요. 여러분 손가락이 어디에 있던 touch (tracking dot) 은 display object 에서 시작되고 touch point 에 따라 pinch-zoom 이 일어날 겁니다.


이 효과는 손가락 두개를 사용할 때 제대로 나타날 겁니다. 이전에는 tracking point들이 display object 에서의 그들의 시작지점의 영향을 받았었는데 이제는 약간 달라졌거든요. 결과는 거의 같긴 하지만 터치 포인트들간의 평균이 조금 더 정확해 졌습니다.



반응형