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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

함수 (function) 공부

2011. 10. 3. 02:05 | Posted by 솔웅


반응형
오늘은 글로벌, 로컬 함수 사용법에 대해 자세히 살펴 보겠습니다.

함수의 기본

local function main()
   print("Hello from CoronaSDK")
end
main()

아주 평범하고 간단한 함수 작성 및 함수 불러오기 예제입니다.
main()함수는 로컬로 선언 됐고 터미널에 Hello from CoronaSDK 를 출력합니다.
이 함수는 맨 아랫 줄 에서 call 했습니다. (main() )

local main
  local function init()
    main()
  end
  function main()
   print("Hello from CoronaSDK")
  end
  init()

이번엔 main 을 로컬로 미리 선언해 놓고 함수 선언 시 local 을 따로 표시하지 않았습니다.
프로그램을 실행하면 로컬 init() 함수를 부를 것이고 이 init() 함수는 main() 함수를 부를겁니다. 문제없이 작동됩니다.
그런데 여기서

local main
  local function init()
    main()
  end
  local function main()
   print("Hello from CoronaSDK")
  end
  init()
이렇게 main() 함수 작성할 때도 local로 또 선언을 하면 에러가 나게 됩니다.
바로 init() 함수 안에서 main()함수를 불러올 때 에러가 납니다.
왜냐하면 main()을 불러올 때는 main() 함수가 없었기 때문에 main 이 nil 이기 때문에 불러오지 못하겠다고 에러 메세지를 뿌리는 겁니다.

local main

  local function main()
   print("Hello from CoronaSDK")
  end
  local function init()
    main()
  end
  init()
위 소스는 어떨까요. init()안에서 main()을 불러올 때 이미 그 위에서 로컬 main() 함수가 구현 돼 있죠? 이 경우는 제대로 실행이 될 겁니다.

Encapsulated Function (함수 캡슐화)

local function main()
    print ("Hello from CoronaSDK")

    function insideMain()
      print("This is a function inside of main, not available to be called from any other")
    end

   insideMain()
  end
 
  main()

자 이렇게 함수 안에 함수가 있는 경우 제대로 실행 됩니다.

local function spawnObject()
   local resultingObject = display.newRect(10,10,100,100)
   local function onTouch(event)
     if "ended" == event.phase then
      print("touched rectangle")
     end
   end
   resultingObject:addEventListener("touch",onTouch)
   return resultingObject
  end

  local xTemp = spawnObject()

위 코드를 실행하면 어떻게 될까요?
우선 맨 밑에 로클 xTemp 변수에 spawnObject() 가 담기변서 spawnObject() 가 실행 됩니다.
spawnObject()에서는 처음에 resultingObject라는 사각형을 그리게 됩니다.
그리고 event를 받는 onTouch라는 함수를 만들구요.
여기서는 touch 이벤트가 끝날 때 터미널에 문자열을 출력합니다.
그 다음엔 아까 그린 사각형에 리스너를 답니다. touch 가 일어났을 경우 onTouch 함수롤 불러오도록 설정합니다.
그 다음에 이 사각형을 리턴합니다.
이제 화면에 있는 사각형을 클릭하면 터미널에 문자열이 찍히게 됩니다.

Member functions (멤버 함수들)

멤버함수들은 객체가 되는 방법이 일반 함수들과 조금 다릅니다. 바로 전 코드에다가 색을 바꾸는 함수도 한번 추가해 봅시다.
일단 사각형 색을 바꾸는 함수 부분을 아래와 같이 추가합니다.
local function spawnObject()
   local resultingObject = display.newRect(10,10,100,100)

   function changeColor(theColor)
     resultingObject:setFillColor(theColor[1],theColor[2],theColor[3])
   end

   local function onTouch(event)
     if "ended" == event.phase then
      print("touched rectangle")
     end
   end

   resultingObject:addEventListener("touch",onTouch)

   return resultingObject
  end

  local xTemp = spawnObject()

자.. 이제 저 함수에 theColor라는 파라미터를 넣어서 불러오는 것을 해야 하는데요.
이 함수는 local로 선언돼 있지 않지만 spawnObject() 함수 밖에서는 불러올 수 없습니다.
spawnObject() 함수 안에 이 함수가 있으니까요.
그럼 밖에서 불러올 수 있도록 살짝 바꿔 보겠습니다.

local function spawnObject()
   local resultingObject = display.newRect(10,10,100,100)

   function resultingObject.changeColor(theColor)
     resultingObject:setFillColor(theColor[1],theColor[2],theColor[3])
   end

   local function onTouch(event)
     if "ended" == event.phase then
      print("touched rectangle")
     end
   end

   resultingObject:addEventListener("touch",onTouch)

   return resultingObject
  end

  local xTemp = spawnObject()
  xTemp.changeColor({255,0,255})

changeColor(theColor) 함수를 spawnObject()의 멤버인 resultingObject 의 멤버 함수로 선언했습니다.
이렇게 하면 spawnObject() 함수 밖에서 불러올 수 있습니다.
spawnObject() 를 xTemp 변수에 담았으니까. xTemp.changeColor({255,0,255}) 하게 되면 spawnObject()함수 안에 있는 changeColor를 불러오게 됩니다. 이 함수는 멤버인 사각형의 함수이니까요.

단순히 이 기능만 실행되게 하려면 여러 방법이 있습니다.
아래와 같이 해도 되구요.
local function spawnObject()
   local resultingObject = display.newRect(10,10,100,100)

   function changeColor(theColor)
     resultingObject:setFillColor(theColor[1],theColor[2],theColor[3])
   end

   local function onTouch(event)
     if "ended" == event.phase then
      print("touched rectangle")
     end
   end

   resultingObject:addEventListener("touch",onTouch)
    changeColor({255,0,255})
   return resultingObject
  end

  local xTemp = spawnObject()
  --xTemp.changeColor({255,0,255})

그런데 함수내 함수를 함수 바깥에서 부르기 위해서 멤버 변수를 사용한다는 예제를 배우는게 목적이니까 그걸 염두에 두고 보시면 될 거예요.

이 강좌의 원래 원본은 아래에 있습니다.
http://blog.anscamobile.com/2011/09/tutorial-scopes-for-functions/
코로나 SDK 만든 회사인 Ansca Mobile 에 있는 블로그에 있는 글입니다.

Cross calling

 다른 함수 안에 있는 함수 불러오는 방법 두번째 인데요. 이건 약간 복잡합니다.

local function spawnObject()
   local resultingObject = display.newRect(10,10,100,100)

   function resultingObject.changeColor(theColor)
     resultingObject:setFillColor(theColor[1],theColor[2],theColor[3])
   end

   local function onTouch(event)
     if "ended" == event.phase then
      print("touched rectangle")
     end
   end

  function wrap(event)
   if self.x < 25 then self.x = 25 end
   if self.x > 743 then self.x = 743 end
  end

   resultingObject:addEventListener("touch",onTouch)

   return resultingObject
  end

  local xTemp = spawnObject()
  Runtime:addEventListener("enterFrame", xTemp.wrap)

이 코드는 spawnObject() 안에 wrap(event) 함수를 만들고 spawnObject()
바깥에서 이 함수안의 wrap함수에 리스너를 답니다.

그런데 조금 이상하네요. 에러도 나구요. 아래 코드를 보겠습니다.

local function spawnObject() local resultingObject = display.newRect(10,10,100,100) function resultingObject.changeColor(theColor) resultingObject:setFillColor(theColor[1],theColor[2],theColor[3]) end local function onTouch(event) if "ended" == event.phase then print("touched rectangle") end end local function wrap(event)
print("in function wrap")
 if resultingObject.x < 25 then resultingObject.x = 25 end if resultingObject.x > 743 then resultingObject.x = 743 end end resultingObject:addEventListener("touch",onTouch) Runtime:addEventListener("enterFrame", wrap) return resultingObject end local xTemp = spawnObject()

이건 제대로 작동합니다.
spawnObject() 이 실행 됐을 때 이와 관련된 모든 함수들이 캡슐화 됐습니다.
이 코드의 목적은 이렇게 캡슐화 시키는 건가 봅니다.

Advanced Function

local hide = print
local print = math.random
local function main()
hide("What do you have to hide?")
hide( print(5) )
end

main()

루아는 위와 같이 함수를 변수에 담아서 편리하게 사용할 수 있습니다.

오늘은 함수와 관련된 좋은 아티클이 있길래 한번 공부해 봤습니다.
제가 100% 다 이해하지는 못한 것 같습니다.

저보다 더 프로그래밍 기초가 튼튼하신 분들은 좀 더 확실해 이해 하셨겠죠?
제가 잘못 이해했거나 부족한부분.... 덧 붙이고 싶으신 부분 있으면 언제든지 코멘트 해 주세요.

감사합니다.
반응형


반응형
accelerometer 는 가속도계라는 의미입니다.

이걸 적용하면 디바이스 기울기 이벤트에 따라 핸들링 할 수 있습니다.

어제 샘플로 드렸던 사람 인형 예제에 이 기능을 적용하도록 하겠습니다.

맨 밑줄에 아래 리스너를 다세요.

Runtime:addEventListener ("accelerometer", onAccelerate)

앱이 실행중에 이 리스너를 단다는 얘기예요. accelerometer 가 일어 날 때 onAccelerate 함수를 실행 하라는 의미구요.

그럼 저 리스너 위에 onAccelerate 함수를 만들어 넣을까요?

local function onAccelerate( event )
physics.setGravity( 10 * event.xGravity, -10 * event.yGravity )
end

이 함수는 중력을 세팅해주는 함수입니다.
기울기를 구해서 그것에 맞게 중력을 주는 겁니다.

아주 간단하죠?

이건 시뮬레이터에서는 못하구요. 직접 디바이스에 인스톨 하신 후에 테스트 할 수 있어요.

참고로 리스너 다는 방법은 아래와 같습니다.

object:addEventListener( eventName, listener )

eventName 에 들어갈 수 있는 것들은 touch, enterFrame, tap, accelerometer , collisiion, sprite 등 여러가지가 있습니다.

API 의 events 부분을 참고하세요.



반응형

Physics Joints 예제 코드

2011. 9. 29. 22:54 | Posted by 솔웅


반응형
Physics Joints 예제를 살펴 보겠습니다.

-살펴보기 전에 여러분들이 댓글로 힘을 주시면 고맙겠습니다. 댓글 꼭 남겨 주세요. -



위 코드를 살펴 보겠습니다.
자동차 몸체와 바퀴가 조인트로 연결 돼 있고 앱을 시작하면 위에서 밑으로 떨어집니다.
다 떨어지면 언덕에서 아래로 구르게 됩니다.

display.setStatusBar( display.HiddenStatusBar )

require "physics"
physics.start()
physics.setDrawMode("hybrid")

--Determine Device Size
local disw = display.contentWidth
local dish = display.contentHeight

local car = display.newGroup()

여기 까지는 따로 설명이 필요 없구요. (newGroup()에 대해서는 나중에 살펴 볼 겁니다.)

--Create The Car
local car_body = display.newRect(0, 0, 102, 20)
car_body:setFillColor(100,75,75)
local car_rear_wheel = display.newCircle( 10, 30, 15 )
local car_front_wheel = display.newCircle( 80,30,15 )
car_rear_wheel:setFillColor(25,128,25)
car_front_wheel:setFillColor(25,25,200)

여긴 자동차를 만드는 부분입니다.몸통을 newRect로 만들고 색을 정해 주고 앞바퀴와 뒷바퀴를 newCircle()을 이용해서 만듭니다.

여기까지 하면 이렇게 나옵니다.

자동차 몸통이 있고 그 아래에 파랗고 녹색인 바퀴 두개가 있습니다.



















































그 다음은 바닥과 왼쪽 오른쪽 벽 그리고 경사도를 아래와 같이 만듭니다.
--Add An Environment
local floor = display.newRect(0, dish-10, disw,dish )
local lwall = display.newRect(0, 0, 0,dish )
local rwall = display.newRect(disw,0,disw,dish)
local ramp = display.newLine(0,dish-40,disw,dish-10)
local rshape = {0,0,disw,30}
ramp.width = 3


여기 까지 하면 위와 같이 나옵니다.

rshape는 나중에 ramp에 addBody할 때 사용할 겁니다.


한번 볼까요?


--Apply The Physics
physics.addBody(floor,"static", {friction=0.5})
physics.addBody(lwall,"static", {friction=0.5})
physics.addBody(rwall,"static", {friction=0.5})
physics.addBody(ramp,"static",{friction=1,shape=rshape})
physics.addBody(car_body,{density=0,friction=0,bounce=0})
physics.addBody(car_rear_wheel,{density=2,friction=3,bounce=0,radius=15})
physics.addBody(car_front_wheel,{density=2,friction=3,bounce=0,radius=15})


지금까지 만든 객체들에 addBody를 해 줍니다.

자동차 몸체와 바퀴만 빼 놓고 나머지는 static으로 해 줍니다. 움직이지 않게 하겠다는 뜻이죠?

몸체와 바퀴는 표시를 안 했으니 디폴트 값인 dynamic이 적용 됩니다.

그러면 디폴트 중력인 9.8의 중력을 받아서 밑으로 떨어지게 될 겁니다.



이 상태로 실행하면 dynamic이 적용된 몸체와 바퀴가 떨어져서 경사면에서 아래로 미끄러지거나 구르게 됩니다.


그런데 아직 서로간의 관계를 joint를 써서 사용하지 않았기 때문에 따로따로 떨어져서 움직이게 됩니다.


이제 Joint를 사용하겠습니다.


--Add The Wheel Joints and Let The Problems Begin
local rear_wheel_joint = physics.newJoint("wheel",car_body,car_rear_wheel,10,10,0,10)
local front_wheel_joint = physics.newJoint("wheel",car_body,car_front_wheel,80,10,0,10)


앞바퀴와 뒷바퀴를 각각 자동차 몸체에 wheel joint를 사용해서 연결했습니다.



몸체랑 바퀴랑 연결되긴 했는데 뭔가가 조금 이상하죠?

일단 바퀴끼리 막 서로 가까워지기도 하고 그러니까 이 거리를 항상 유지해 보죠.


--Keep The Wheels Separated                                         
local wheel_distance_joint = physics.newJoint("distance",car_rear_wheel, car_front_wheel, car_rear_wheel.x, car_rear_wheel.y, car_front_wheel.x, car_front_wheel.y)

distance joint를 써서 두 바퀴의 거리를 항상 유지하도록 했습니다.


돌려 보시면 아까보다는 조금 나아 졌는데 아직 완벽하지는 않습니다.


나머지는 여러분들이 weld, pivot 조인트 등을 사용하셔서 한번 적용해 보세요.


현재까지의 전체 소스는 아래와 같습니다.

display.setStatusBar( display.HiddenStatusBar )

require "physics"
physics.start()
physics.setDrawMode("hybrid")

--Determine Device Size
local disw = display.contentWidth
local dish = display.contentHeight

local car = display.newGroup()

--Create The Car
local car_body = display.newRect(0, 0, 102, 20)
car_body:setFillColor(100,75,75)
local car_rear_wheel = display.newCircle( 10, 30, 15 )
local car_front_wheel = display.newCircle( 80,30,15 )
car_rear_wheel:setFillColor(25,128,25)
car_front_wheel:setFillColor(25,25,200)

--Add An Environment
local floor = display.newRect(0, dish-10, disw,dish )
local lwall = display.newRect(0, 0, 0,dish )
local rwall = display.newRect(disw,0,disw,dish)
local ramp = display.newLine(0,dish-40,disw,dish-10)
local rshape = {0,0,disw,30}
ramp.width = 3

--Apply The Physics
physics.addBody(floor,"static", {friction=0.5})
physics.addBody(lwall,"static", {friction=0.5})
physics.addBody(rwall,"static", {friction=0.5})
physics.addBody(ramp,"static",{friction=1,shape=rshape})
physics.addBody(car_body,{density=0,friction=0,bounce=0})
physics.addBody(car_rear_wheel,{density=2,friction=3,bounce=0,radius=15})
physics.addBody(car_front_wheel,{density=2,friction=3,bounce=0,radius=15})

--Add The Wheel Joints and Let The Problems Begin
local rear_wheel_joint = physics.newJoint("wheel",car_body,car_rear_wheel,10,10,0,10)
local front_wheel_joint = physics.newJoint("wheel",car_body,car_front_wheel,80,10,0,10)

--Keep The Wheels Separated                                         
local wheel_distance_joint = physics.newJoint("distance",car_rear_wheel, car_front_wheel, car_rear_wheel.x, car_rear_wheel.y, car_front_wheel.x, car_front_wheel.y)

--Populate The Scene
car:insert(lwall)
car:insert(rwall)
car:insert(floor)
car:insert(ramp)
car:insert(car_body)
car:insert(car_rear_wheel)
car:insert(car_front_wheel)

return car


끝에 insert는 처음에 설정했던 car라는 그룹에 각 객체들을 넣는다는 겁니다.

나중에 화면전환 같은 거 할 때 유용하게 사용 됩니다.

이 부분은 그 때 자세히 살펴 보도록 하겠습니다.


소스 하나만 더 소개시켜 드릴까요?



저 인형이 하늘에서 떨어져서 쓰러지는 건데요.

목, 팔, 다리,몸통 관절들이 제법 사실적으로 움직입니다.


이 샘플은 pivot 조인트만 이용해서 만들었습니다.

그리고 RotationLimits를 이용해서 팔관절, 다리 관절등이 반대로 꺾이지 않게 했구요


그리고 머리, 팔, 다리를 끌고 드래그 하면 그에 따라 움직이는데요.

이건 물론 touch 조인트를 이용해서 만들었구요.


샘플 코드를 압축해서 올려 놓습니다.

소스 분석은 직접 한번 해 보세요.



그리고 참고로 Box2D의 개발자 매뉴얼도 올려 놓습니다.


조인트에 대한 부분도 나와있으니까 한번 살펴 보세요.

이로서 Corona SDK의 Physics Engine에 대해 모두 훑어 봤습니다.


다음 시간부터는 어떤 주제로 할까요?

여하튼 다음에 뵈요....

반응형