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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

드래그 하기 기초

2011. 11. 25. 01:23 | Posted by 솔웅


반응형

오늘은 Thanks Giving day라서 휴일입니다.

사무실에 안 가고 집에서 글을 쓰게 됐네요.
근데 여유있게 글을 쓸 상황은 아니군요.

점심 초대를 받아서 좀 있다 나가야 하거든요.

오늘은 간단하면서도 아주 자주 쓰이는 테크닉을 정리하겠습니다.

앱을 만들 때 특히 게임 같은 앱을 만들 때 드래깅 기술을 많이 사용하게 됩니다.
가장 기본적으로 알아 둬야 할것은 아래와 같습니다.
touch 이벤트 리스너를 사용하기
began에서 현재 위치 저장하기
moved에서 현재 위치 바꿔주기

이 정도만 확실하게 알아 두시면 됩니다.


스크린에 사각형을 그리고 저 사각형을 드래그 하는 앱입니다.
아래 소스코드 참조하세요.
-- create object
local myObject = display.newRect( 0, 0, 100, 100 )
myObject:setFillColor( 255 )

-- touch listener function
function myObject:touch( event )
    if event.phase == "began" then

        self.markX = self.x -- store x location of object
        self.markY = self.y -- store y location of object

    elseif event.phase == "moved" then

        local x = (event.x - event.xStart) + self.markX
        local y = (event.y - event.yStart) + self.markY
       
        self.x, self.y = x, y -- move object based on calculations above
    end
   
    return true
end

-- make 'myObject' listen for touch events
myObject:addEventListener( "touch", myObject )

우선 흰색 사각형을 그리구요.
그 다음 touch 이벤트 리스너에서 호출할 함수를 만듭니다.
맨 아래 부터 부시면 이 myObject라는 객체에 touch 이벤트 리스너를 달았다는 것을 잘 보세요.

이제 myObject라는 함수를 보겠습니다.

began 일 때 해당 객체(myObject)의 위치를 정합니다.
moved일 때 began일 때의 위치 event.xStart 를 현재 위치에서 빼고 그러니까 이동 거리를 구하고 객체의 위치 self.markX를 더해 줍니다.
그리고 그 위치값을  myObject 객체의 위치값으로 대입합니다.
그러면 이동하게 됩니다.

아주 간단합니다. 하지만 반드시 알고 있어야 하는 겁니다.

반응형


반응형

코로나 SDK (Corona SDK)에서는 화면 전환을 위해서 transition.to를 사용합니다.
이것만 사용해서도 아주 다이나믹한 효과를 낼 수 있는데요.

Ricardo Rauber Pereira라는 개발자가 아주 보기 좋은 화면 전환 클래스들을 구현해서 이를 공개했습니다.
director.lua라는 파일인데 구글에서 써핑하셔도 쉽게 찾으실 수 있습니다.

이 클래스에는 총 12개의 화면 전환 효과가 있습니다.
("moveFromRight","overFromRight","moveFromLeft","overFromLeft",
"moveFromTop","overFromTop","moveFromBottom",
"overFromBottom","crossfade","fade","flip","downFlip"
)

파일은 아래에 제가 압축해서 올린 샘플파일에 있습니다. 받아보세요.
제가 가지고 있는 건 버전 1.3 이네요.
 - Version: 1.3
 - Made by Ricardo Rauber Pereira @ 2010
 - Blog: http://rauberlabs.blogspot.com/
 - Mail: ricardorauber@gmail.com
이 파일을 보면 블로그와 이메일도 있으니까 참조하시구요.
저 블로그에 가 보니까 지금은 1.4 버전이 나왔네요.
이 개발자는 브라질 사람인가 봐요.

리카르도는 소스코드를 무료로 공개하는 대신 블로그에서 Donation을 받네요.
자신의 노력의 결과물을 나눠서 다른 사람이 쉽게 사용할 수 있도록 공개하는 개발자들에게는 성의 표시를 해줘도 좋겠죠? 여유가 있으면 Donation을 해도 좋고 블로그에 광고가 있으면 광고를 눌러줘도 되고 아니면 메일이나 트위터로 고맙다고 메세지 날려줘도 좋을 거예요.. :) 그리고 리카르도가 만든 앱을 다운받거나 구매하는 것도 ....


이 director.lua를 이용하는 방법은 아래와 같습니다.

http://www.youtube.com/watch?v=RAktnj7nwos

1. main.lua가 있는 폴더에 director.lua를  복사해 넣는다.
2. require 한다 (local director = require("director"))
3. 그룹을 만든다. local mainGroup = display.newGroup()
4. directorView를 그룹에 넣는다. mainGroup:insert(director.directorView)
5. 화면 전환 할 때 changeScene을 이용한다. director:changeScene("scene2","downFlip")
-> 첫번째 파라미터는 다음 화면을 보여줄 파일 이름입니다. 이 경우 scene2.lua가 되겠죠.
-> 두번째 파라미터는 화면 전환 효과 입니다. 아까 봤던 8가지 중에 아무거나 한가지를 넣으시면 됩니다.

그 다음은 전환될 화면 (scene2.lua)에서는 어떻게 해야 하는지 보겠습니다.
1. 모듈 선언을 한다. module(..., package.seeall) -> 이것은 Corona SDK에서 모듈 사용하는 규칙입니다.
2. localGroup이라는 그룹을 만든다. local localGroup = display.newGroup()
3. 함수 new()를 만든다. function new()    return localGroup end
4. 함수 new()는 localGroup을 return한다.
5. 다른 화면으로 전환하려면 마찬가지로 changeScene을 이용한다.
director:changeScene("nextfile","downFlip")

이것만 지켜주시면 됩니다.


우리의 리카르도가 공개한 샘플 입니다. 파일은 아래에 있습니다.


파일을 열어보니까 제가 못 봤던 book이라는 폴더가 있네요.
실행해 보니까 SlideView 관련된 클래스 인가봐요.
화면 전환 뿐만 아니라 Slideview 관련해서도 편리한 기능을 제공하나봅니다.

이건 제가 공부 좀 해서 다음 기회에 소개해 드릴께요.

오늘은 팁으로 제가 이 director.lua 클래스를 사용할 때 화면 전환 효과를 랜덤하게 처리하고 있는데요.

그 소스를 소개해 드릴께요.

일단 randomScreen.lua 파일을 아래처럼 만들어 놓습니다.
module(..., package.seeall)
function init()
    RandomScreen()
end

function RandomScreen() 
    changes = {"moveFromRight","overFromRight","moveFromLeft","overFromLeft",
                "moveFromTop","overFromTop","moveFromBottom",
                "overFromBottom","crossfade","fade","flip","downFlip"}
    selectScreen = math.random(1,12)
    screenChange = changes[selectScreen]
    return screenChange   
       
end


그리고 main.lua에서 이 파일을 require합니다.

local changeScreen = require("randomScreen")

그리고 화면전환 하기 직전에 이 랜덤한 화면전환 기능 값을 받습니다.

randomScreen = changeScreen.RandomScreen();

그리고 director.lua의 cangeScene을 이용할 때 이 값을 넣습니다.

director:changeScene("파일이름", randomScreen);

이렇게 하면 랜덤하게 화면 전환 효과들을 이용할 수 있습니다.
저는 앱을 만들 때 이렇게 처리하면 편하더라구요.

오늘의 팁이였구요.

director.lua에서 파라미터 넘기기나 팝업 기능 사용하기는 직접 소스 보면서 해 보세요.

그렇게 어렵지 않을 겁니다.

그럼...
반응형


반응형
오늘은 Sprite Sheet과 timer와 관련된 팁을 다루겠습니다.

오늘 다룰 소스는 Peach Pellen 이라는 개발자가 자기 친구가 앱을 개발한다는 얘기를듣고 도움이 될까 해서 만든 주사위놀이 샘플 코드입니다. 그리고 그 코드를 공개해서 다른 분들도 도움이 되길 바란다고 하네요.

아래 링크로 가시면 관련 글을 보실 수 있습니다.

http://techority.com/2011/11/22/rolling-the-dice/

저 싸이트로 가시면 샘플 코드를 다운 받으실 수 있구요.
아래 저도 그 코드를 올려 놓을 테니까 여기서 곧바로 다운 받으셔도 됩니다.

실행 화면은 아래와 같습니다.


오른쪽 위에 하얀 사각형을 누르면 주사위가 막 돌다가 멈춥니다.
그러면 터미널에 두 주사위의 합이 출력 됩니다.

그런데 이상한건 제가 집에서 이 소스코드를 실행 했을 때는 두 주사위가 항상 같은 숫자만 나왔거든요.

그래서 다른 숫자가 나오도록 소스를 좀 수정했습니다.
그리고 터미널뿐만 아니라 화면에도 합계가 텍스트로 표시 되도록 했구요.

그런데 회사와서 이 코드를 돌려보니까 두 주사위가 항상 같은 숫자가 나오는게 아니더라구요.

집에 있는 컴퓨터는 윈도우고 회사에 있는건 맥이라서 그런가?

하여간 아래 코드는 제가 조금 수정한 코드입니다. 다운 받은 파일에 있는 소스랑은 아주 조금 다를거예요.


--Hide the status bar => 스테이터스 바 감추기
display.setStatusBar(display.HiddenStatusBar)

--Require sprite => 스프라이트 require하기. 스프라이트는 director.lua나 movieclip.lua 처럼 별도의 파일로 제공되는게 아니라 corona sdk 에 내장된 클래스 입니다. 따로 파일을 구하실 필요가 없습니다.
require "sprite"

=> 스크린 너비와 높이 구해 놓기
_W = display.contentWidth;
_H = display.contentHeight;

--The background image => 배경화면 표시하고 합계를 표시할 텍스트 선언하고 위치 정해 줌
local bg = display.newImage( "bg.png" )
local total = display.newText("", _W/2, _H-(_H/7), native.systemFontBold, 30)

--Total sum of dice after a roll => 주사위 합계 담을 변수
local diceTotal = 0

--States whether or not the dice may be rolled => 주사위 돌리기 가능한 상태인지 아닌지 콘트롤 할 변수
local canRoll = true

--Sprite Setup => 스프라이트를 셋업 함
local diceSheet = sprite.newSpriteSheet( "dice.png", 64, 64)

주사위로 사용할 이미지는 이 이미지 입니다.
일단 이 이미지를 diceSheet이라는 이름으로 만듭니다. 이 프레임의 크기는 64X64 입니다.

local diceSet = sprite.newSpriteSet( diceSheet, 1, 6 )
sprite.add( diceSet, "dice", 1, 6, 195, 0)
sprite.add( diceSet, "dice2", 1, 6, 210, 0)

위 diceSheet를 diceSet이라는 스프라이트 세트에 담습니다. 시작하는 프레임은 1 이고 총 6개 프레임이 있습니다.
이 diceSet를 add합니다. 신택스는 아래와 같습니다.
sprite.add( spriteSet, sequenceName, startFrame, frameCount, time, [loopParam] )
첫번째는 diceSet를 dice라는 sequenceName으로 add를 하는데 시작 프레임 1이고 전체 프레임 count는 6 입니다. time은 195입니다. 이것은 195ms에 이 diceSet을 한번 돌린다는 겁니다.
두번째 줄은 dice2인데 dice와 모두 같고 이 time이 210 입니다.
두 주사위가 6개 프레임의 돌아가는 시간이 다르니까 각각 다른 프레임이 나오겠네요.
윈도우에서 항상 똑 같은 주사위 이미지가 나온게 제가 착각한 건가 본데요?
혹시 여러분 윈도우에서 한번 돌려보시구 어떻게 나오나 잘 살펴 보세요.
저도 집에 돌아간 다음에 다시 돌려 봐야 겠네요.

--First Die
local dice = sprite.newSprite( diceSet )
dice.x = 120
dice.y = 200
dice:prepare("dice")

첫번째 sprite를 dice라는 변수에 담고 화면의 위치를 정해 줍니다.
스프라이트 쉬트 사용하는 순서가 이렇게 되네요.
sprite.newSpriteSheet => sprite.newSpriteSet => sprite.add => sprite.newSprite => spriteInstance:prepare => spriteInstance:play => spriteInstance:pause
따로 정리해서 외워도 좋겠는데요.

--Second Die
local dice2 = sprite.newSprite( diceSet )
dice2.x = 200
dice2.y = 300
dice2:prepare("dice2")

두번째 스프라이트 dice2를 선언합니다.

--Roll button
local rollBtn = display.newImage("die.png")
rollBtn.x = 280
rollBtn.y = 40

=> 버튼 이미지를 표시합니다.

--End Roll Function
local function endRoll()
    dice:pause()
    showTotal();
end

첫번째 주사위 play를 중지시키고 showTotal함수를 실행합니다.

local function endRoll2()
    dice2:pause()
    showTotal();
end

두번째 주사위 play를 중지시키고 showTotal함수를 실행합니다.

function showTotal()
    diceTotal = dice.currentFrame + dice2.currentFrame
    print(diceTotal) --Print the result in the terminal
    total.text="Total : " .. diceTotal;
    canRoll = true --Allow the dice to be rolled again
end

현재 프레임 = 주사위 눈 입니다. dice와 dice2의 현재 프레임을 구해서 더하면 주사위 두 눈의 합이 됩니다.
이것을 터미널에 print하고 스크린에도 표시합니다.
canRoll은 true로 세팅해서 버튼을 누르면 주사위가 돌아갈 수 있도록 합니다.

--Roll function
local function rollDice()
    if canRoll == true then
        canRoll = false --Prevent dice from being rolled again before the current role is over
        dice:play()
        dice2:play()
        randomTime = math.random(1500, 3500)
        timer.performWithDelay(randomTime, endRoll, 1)
        randomTime2 = math.random(1500, 3500)
        timer.performWithDelay(randomTime2, endRoll2, 1)
    end
end
canRoll을 false로 해서 버튼을 눌러도 주사위가 새로 돌지 않도록 막아 놓습니다.
dice와 dice2를 play시킵니다.
랜덤값 (1.5초 ~ 3.5초)를 구해서 timer를 사용해서 그 시간만큼만 돌고 dice를 멈추게 합니다. 다음줄은 dice2를 멈추게 합니다.

rollBtn:addEventListener("tap", rollDice)

버튼에 이벤트 리스너를 달아서 누르면 rollDice가 실행 되도록 합니다.



이렇게 하면 위 그림처럼 화면에 주사위 눈의 합이 출력 됩니다.

원래 소스가 두 주사위의 눈이 각각 다르게 표시되도록 하는 거였다면 제가 수정한 코드는 괜히 수정한 거네요. 이미 원래 소스에 이런 경우를 생각해서 스프라이트에서 프레임 플레이 시간을 각각 다르게 해 준건데......

어쨌든 남의 소스를 보고 나름대로 고쳐보는게 프로그래밍 배우는데 아주 큰 도움이 됩니다.

여러분들도 이 코드를 이용해서 이것저것 고치거나 기능을 덧붙이거나 하면 빨리 실력이 늘고 이 코드도 진짜로 여러분의 코드가 되고 여러분의 자산이 될 거예요.

그럼 다음 시간에 뵐께요......
반응형