반응형
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 (1) | 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 |