반응형
Emanuele Feronato의 블로그를 알게되서 가끔 들어가 보는데 아주 훌륭한 로직들을 많이 share하고 있네요.
눈내리는 효과, 물방울 올라가는 효과 두가지를 분석해 봤는데요.
여기 뱀 기어다니는 효과가 재밌어서 제 블로그에 정리해 둘까 합니다.
Emanuele는 String Avoider라고 이름을 붙였는데요. 제 눈에는 뱀 기어다니는걸로 보이더라구요.
아래 유튜브에도 올려놨는데 아주 간단한 코드로 이런 효과를 주고 있습니다.
아래 소스가 있습니다.
-- Declaring Variables
-- Stage Width and Height
local _W,_H = display.contentWidth,display.contentHeight
local tailLength = 5
local tailNodes = 200
local head = display.newCircle(_W/2,_H/2,10)
local nodes = {}
for i=1,tailNodes,1 do
nodes[i] = {}
nodes[i].x = head.x
nodes[i].y = head.y
end
-- Creating Display Groups
local tailGroup = display.newGroup()
local function startDrag(event)
-- Store the Target (the Head) in a variable
local t = event.target
if event.phase == "began" then
-- When the touch started, set the Focus on the Head
display.getCurrentStage():setFocus( t )
t.isFocus = true
-- Store initial Position of the Head
t.x0 = event.x - t.x
t.y0 = event.y - t.y
elseif t.isFocus then
if event.phase == "moved" then
-- While moving the head
-- remove every drawn line from the group
for i=tailGroup.numChildren,1,-1 do
tailGroup:remove(i)
end
-- Move the Head
t.x = event.x - t.x0
t.y = event.y - t.y0
-- Create starting line and insert it into the group
local line = display.newLine(head.x,head.y,nodes[1].x,nodes[1].y)
tailGroup:insert(line)
line.width = 20
nodes[1].x = head.x
nodes[1].y = head.y
-- Loop through every tailNode and save new positions in table
-- Note: LUA tables start with an index of 1 and not 0!
for i=2,tailNodes,1 do
local nodeAngle = math.atan2(nodes[i].y-nodes[i-1].y,nodes[i].x-nodes[i-1].x);
nodes[i].x = nodes[i-1].x+tailLength*math.cos(nodeAngle)
nodes[i].y = nodes[i-1].y+tailLength*math.sin(nodeAngle)
-- You could use
-- line:append(nodes[i].x,nodes[i].y)
-- but this wouldn't allow you to alter each segment (fading the color, reducing linewidth etc.)
-- Creating new line segments
local nLine = display.newLine(nodes[i-1].x,nodes[i-1].y,nodes[i].x,nodes[i].y)
-- c will store the colorvalue - starting from 255 and ending with 0 (white to black)
local c = 255-i/tailNodes*255
nLine:setColor(c)
-- width will start at 20 and fade out to 0
nLine.width = line.width-i/tailNodes*line.width
-- Important: insert the new Line segments into the table!
tailGroup:insert(nLine)
end
elseif event.phase == "ended" or event.phase == "cancelled" then
-- Remove the focus
display.getCurrentStage():setFocus( t, nil )
t.isFocus = false
end
end
end
-- Create touch Eventlistener
head:addEventListener("touch",startDrag)
한번 분석해 볼까요?
첫줄은 모바일 기기의 가로 세로 길이를 변수에 담았구요.
tailLength와 tailNodes 변수에 숫자를 대입했습니다.
그리고 head라는 변수에 원을 그려 넣었구요. nodes 라는 테이블 변수를 만들었습니다.
다음 for 문에서는 tailNodes 값 만큼 nodes에 head를 넣습니다. 총 200개가 되겠죠?
nodes 테이블에는 작은 원 200개가 들어있습니다. 이걸 가지고 효과를 만들겁니다.
다음에는 Display Group을 만들었습니다. tailGroup이라는 이름으로요.
그 다음으로는 맨 밑에 있는 리스너를 보죠.
head에 touch 리스너를 달았네요. 맨 처음 그려진 head에 Listener가 달립니다.
이 head를 touch 하면 startDrag함수가 실행되구요. 그러면 began, moved, ended phases 에 따라서 Control 할 수가 있습니다.
이제 startDrag 함수를 분석해 보죠.
처음 변수 t를 만들고 여기에 event.target 즉 head 를 넣습니다.
이제 control을 해 보죠.
began 단계에서는 t에 setFocus를 합니다.
setFocus는 해당 리스너에 Focus를 둔다는 의미인데요. 제 블로그에서 setFocus로 검색하시면 관련 글이 뜰 겁니다. 참고 하세요.
그리고 t.x0 에는 현재 이벤트가 일어나는 x포인트에서 t(head)의 x포인트를 뺀 값을 넣습니다. t.y0에도 현재 이벤트가 일어나는 y포인트에서 t의 y포인트를 뺀 값을 넣구요.
began에서는 여기까지 하구요. t.isFocus가 계속 유지되고 있으면 moved 일 때 로직을 실행합니다.
moved에서 처음 하는 일은 tailGroup의 모든 구성요소들을 지우는 겁니다. 이전 이미지가 그대로 남아 있으면 움직이는 효과가 아니라 선이 그려지는 효과가 날겁니다.
이 지우는 기능을 빼면 이런 효과가 납니다. 한번 해 보셔도 재밌을 거예요. 이 로직도 잘 이용하면 좋은 효과를 낼 수 있겠는데요.
그리고 t.x와 t.y를 이벤트가 일어난 좌표에서 began에서 구했던 t.x0와 t.y0를 뺀 값을 넣습니다. 그러면 head가 움직이게 됩니다.
그리고 head의 x,y좌표에서 그 다음 node에 선을 긋습니다. (뱀의 몸이 이어지도록 보이겠죠?)
그리고 이 라인을 그룹에 insert하구요. 그 width를 20으로 설정합니다.
그리고 이 node 1을 head 위치로 옮깁니다.
다음에는 for문을 돌려서 모든 tailNode를 새로운 위치로 옮겨서 뱀 몸체가 기어가는 효과가 나도록 합니다.
우선 현재의 node와 이전 node 사이의 각도를 구해서 nodeAngle에 넣습니다.
두 점의 좌표를 가지고 각도를 구하는 공식은 math.atan2(y,x) 함수를 이용하시면 됩니다.
그리고 이 각도를 이용해서 각 node의 x,y좌표값을 얻습니다.
x는 math.cos(x) 함수를 이용하시고 y는 math.sin(x)를 이용하시면 됩니다.
이제 뱀 머리를 움직이면 이전 이미지들은 지워지고 이전 node 이미지들이 계속 따라오면서 움직이는 효과가 날 겁니다.
그런데 아직까지는 짧은 선이 계속 따라 올 거구요. 긴 뱀 꼬리가 따라오도록 하는 건 아래 로직에서 처리 해 줍니다.
아까는 head와 첫번째 node사이에 line을 그려 줬는데요. 이제는 node와 node들 사이에 라인을 그려 줍니다.
그리고 나서 색이 점점 검은색에 가까와 지도록 계산을 해서 이 새 라인의 색을 set 해 줍니다.
그러면 꼬리로 갈 수록 점점 색이 여리게 나올 겁니다.
여기까지 하면 이런 효과가 납니다.
아직 width를 설정해 주지 않아서 그렇습니다.
이 모양은 정자가 움직이는 모양 같네요.
이 node들 사이의 line의 두께는 뒤로 갈 수록 점점 줄어들도록 하는 공식을 넣습니다.
그리고 이 라인을 tailGroup에 insert합니다.
여기까지 하면 모든 움직이는 로직은 완료 됩니다.
마지막으로 유저가 손을 떼어서 이벤트가 완료 되면 setFocus를 해제합니다.
이러면 저 위에 유튜브 영상에서 보는 것처럼 뱀이 기어다니는 효과를 주실 수 있습니다.
이 소스에서는 math 함수 3개에 대해서 익숙해 지도록 연습하라고 권해 드리고 싶네요.
그러면 정말 아주 다양한 효과들을 낼 수 있습니다.
즐코딩 하시구요. ~~~~ ~~~~ 추천 추천 부탁 드려요...
눈내리는 효과, 물방울 올라가는 효과 두가지를 분석해 봤는데요.
여기 뱀 기어다니는 효과가 재밌어서 제 블로그에 정리해 둘까 합니다.
Emanuele는 String Avoider라고 이름을 붙였는데요. 제 눈에는 뱀 기어다니는걸로 보이더라구요.
아래 유튜브에도 올려놨는데 아주 간단한 코드로 이런 효과를 주고 있습니다.
아래 소스가 있습니다.
-- Declaring Variables
-- Stage Width and Height
local _W,_H = display.contentWidth,display.contentHeight
local tailLength = 5
local tailNodes = 200
local head = display.newCircle(_W/2,_H/2,10)
local nodes = {}
for i=1,tailNodes,1 do
nodes[i] = {}
nodes[i].x = head.x
nodes[i].y = head.y
end
-- Creating Display Groups
local tailGroup = display.newGroup()
local function startDrag(event)
-- Store the Target (the Head) in a variable
local t = event.target
if event.phase == "began" then
-- When the touch started, set the Focus on the Head
display.getCurrentStage():setFocus( t )
t.isFocus = true
-- Store initial Position of the Head
t.x0 = event.x - t.x
t.y0 = event.y - t.y
elseif t.isFocus then
if event.phase == "moved" then
-- While moving the head
-- remove every drawn line from the group
for i=tailGroup.numChildren,1,-1 do
tailGroup:remove(i)
end
-- Move the Head
t.x = event.x - t.x0
t.y = event.y - t.y0
-- Create starting line and insert it into the group
local line = display.newLine(head.x,head.y,nodes[1].x,nodes[1].y)
tailGroup:insert(line)
line.width = 20
nodes[1].x = head.x
nodes[1].y = head.y
-- Loop through every tailNode and save new positions in table
-- Note: LUA tables start with an index of 1 and not 0!
for i=2,tailNodes,1 do
local nodeAngle = math.atan2(nodes[i].y-nodes[i-1].y,nodes[i].x-nodes[i-1].x);
nodes[i].x = nodes[i-1].x+tailLength*math.cos(nodeAngle)
nodes[i].y = nodes[i-1].y+tailLength*math.sin(nodeAngle)
-- You could use
-- line:append(nodes[i].x,nodes[i].y)
-- but this wouldn't allow you to alter each segment (fading the color, reducing linewidth etc.)
-- Creating new line segments
local nLine = display.newLine(nodes[i-1].x,nodes[i-1].y,nodes[i].x,nodes[i].y)
-- c will store the colorvalue - starting from 255 and ending with 0 (white to black)
local c = 255-i/tailNodes*255
nLine:setColor(c)
-- width will start at 20 and fade out to 0
nLine.width = line.width-i/tailNodes*line.width
-- Important: insert the new Line segments into the table!
tailGroup:insert(nLine)
end
elseif event.phase == "ended" or event.phase == "cancelled" then
-- Remove the focus
display.getCurrentStage():setFocus( t, nil )
t.isFocus = false
end
end
end
-- Create touch Eventlistener
head:addEventListener("touch",startDrag)
한번 분석해 볼까요?
첫줄은 모바일 기기의 가로 세로 길이를 변수에 담았구요.
tailLength와 tailNodes 변수에 숫자를 대입했습니다.
그리고 head라는 변수에 원을 그려 넣었구요. nodes 라는 테이블 변수를 만들었습니다.
다음 for 문에서는 tailNodes 값 만큼 nodes에 head를 넣습니다. 총 200개가 되겠죠?
nodes 테이블에는 작은 원 200개가 들어있습니다. 이걸 가지고 효과를 만들겁니다.
다음에는 Display Group을 만들었습니다. tailGroup이라는 이름으로요.
그 다음으로는 맨 밑에 있는 리스너를 보죠.
head에 touch 리스너를 달았네요. 맨 처음 그려진 head에 Listener가 달립니다.
이 head를 touch 하면 startDrag함수가 실행되구요. 그러면 began, moved, ended phases 에 따라서 Control 할 수가 있습니다.
이제 startDrag 함수를 분석해 보죠.
처음 변수 t를 만들고 여기에 event.target 즉 head 를 넣습니다.
이제 control을 해 보죠.
began 단계에서는 t에 setFocus를 합니다.
setFocus는 해당 리스너에 Focus를 둔다는 의미인데요. 제 블로그에서 setFocus로 검색하시면 관련 글이 뜰 겁니다. 참고 하세요.
그리고 t.x0 에는 현재 이벤트가 일어나는 x포인트에서 t(head)의 x포인트를 뺀 값을 넣습니다. t.y0에도 현재 이벤트가 일어나는 y포인트에서 t의 y포인트를 뺀 값을 넣구요.
began에서는 여기까지 하구요. t.isFocus가 계속 유지되고 있으면 moved 일 때 로직을 실행합니다.
moved에서 처음 하는 일은 tailGroup의 모든 구성요소들을 지우는 겁니다. 이전 이미지가 그대로 남아 있으면 움직이는 효과가 아니라 선이 그려지는 효과가 날겁니다.
이 지우는 기능을 빼면 이런 효과가 납니다. 한번 해 보셔도 재밌을 거예요. 이 로직도 잘 이용하면 좋은 효과를 낼 수 있겠는데요.
그리고 t.x와 t.y를 이벤트가 일어난 좌표에서 began에서 구했던 t.x0와 t.y0를 뺀 값을 넣습니다. 그러면 head가 움직이게 됩니다.
그리고 head의 x,y좌표에서 그 다음 node에 선을 긋습니다. (뱀의 몸이 이어지도록 보이겠죠?)
그리고 이 라인을 그룹에 insert하구요. 그 width를 20으로 설정합니다.
그리고 이 node 1을 head 위치로 옮깁니다.
다음에는 for문을 돌려서 모든 tailNode를 새로운 위치로 옮겨서 뱀 몸체가 기어가는 효과가 나도록 합니다.
우선 현재의 node와 이전 node 사이의 각도를 구해서 nodeAngle에 넣습니다.
두 점의 좌표를 가지고 각도를 구하는 공식은 math.atan2(y,x) 함수를 이용하시면 됩니다.
그리고 이 각도를 이용해서 각 node의 x,y좌표값을 얻습니다.
x는 math.cos(x) 함수를 이용하시고 y는 math.sin(x)를 이용하시면 됩니다.
이제 뱀 머리를 움직이면 이전 이미지들은 지워지고 이전 node 이미지들이 계속 따라오면서 움직이는 효과가 날 겁니다.
그런데 아직까지는 짧은 선이 계속 따라 올 거구요. 긴 뱀 꼬리가 따라오도록 하는 건 아래 로직에서 처리 해 줍니다.
아까는 head와 첫번째 node사이에 line을 그려 줬는데요. 이제는 node와 node들 사이에 라인을 그려 줍니다.
그리고 나서 색이 점점 검은색에 가까와 지도록 계산을 해서 이 새 라인의 색을 set 해 줍니다.
그러면 꼬리로 갈 수록 점점 색이 여리게 나올 겁니다.
여기까지 하면 이런 효과가 납니다.
아직 width를 설정해 주지 않아서 그렇습니다.
이 모양은 정자가 움직이는 모양 같네요.
이 node들 사이의 line의 두께는 뒤로 갈 수록 점점 줄어들도록 하는 공식을 넣습니다.
그리고 이 라인을 tailGroup에 insert합니다.
여기까지 하면 모든 움직이는 로직은 완료 됩니다.
마지막으로 유저가 손을 떼어서 이벤트가 완료 되면 setFocus를 해제합니다.
이러면 저 위에 유튜브 영상에서 보는 것처럼 뱀이 기어다니는 효과를 주실 수 있습니다.
이 소스에서는 math 함수 3개에 대해서 익숙해 지도록 연습하라고 권해 드리고 싶네요.
그러면 정말 아주 다양한 효과들을 낼 수 있습니다.
반응형
'Corona SDK > 샘플 코드 분석' 카테고리의 다른 글
animation chain 소스 분석 해 보기 03 (0) | 2013.08.11 |
---|---|
animation chain 소스 분석 해 보기 02 (0) | 2013.07.22 |
animation chain 소스 분석 해 보기 01 (0) | 2013.07.15 |
간단하게 눈발 흩날리는 느낌 주기 (2) | 2012.02.16 |
돈 넣고 돈 먹기(야바위) 모바일 게임 만들기 2 (11) | 2012.01.04 |
돈 넣고 돈 먹기(야바위) 모바일 게임 만들기 1 (2) | 2012.01.03 |
내가 그린 선으로 떨어지는 공 받아내기 (2) | 2011.12.31 |
Corona SDK 화면전환 API (Story Board) (4) | 2011.12.23 |
Level 별 Lock 기능 걸고 푸는 법 (0) | 2011.12.15 |
벽돌 깨기 게임 만들기 -3 (1) | 2011.12.01 |