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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형
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에 대해 모두 훑어 봤습니다.


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

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

반응형

Physics Joint

2011. 9. 28. 22:53 | Posted by 솔웅


반응형
오늘은 Physics의 Joint 라는 개념에 대해 알아보겠습니다.
조인트는 여러 객체를 연결시키는 겁니다. 예를 들어 인형의 머리 몸통 팔 다리 이미지가 있을 때 이 이미지들을 joint로 연결해서 자연스럽게 움직이게 할 수 있습니다.
코로나 샘플을 보면 Bridge나 Chains에서 이 기술을 썼습니다.
























































보시면 다리를 구성하는 나무조각과 체인을 구성하는 각각의 체인들이 이 조인트로 연결 된 겁니다.
Joint를 사용하시려면 우선 객체를 만들어서 addBody를 하신 후에 그 객체에 Joint를 선언하시면 됩니다.

Joint 의 종류에는 총 8가지가 있습니다.
이 8가지에 대해 하나하나씩 알아가 보도록 하겠습니다.

오늘은 간략하게 각 조인트들을 적용해서 실행해 볼께요.
아래 코드를 가지고 여러 조인트들을 적용해 보겠습니다.
이 코드는 지난번에 충돌(Collision) 인가에서 썼던 코드일 겁니다.

local physics = require "physics"
physics.start()
system.activate( "multitouch" )
physics.setDrawMode( "hybrid" )

local ground = display.newImage( "ground.png" )
ground.x = display.contentWidth / 2
ground.y = 445
ground.myName = "ground"

physics.addBody( ground, "static", { friction=0.5, bounce=0.3 } )

local crate1 = display.newImage( "crate.png", 20, 70 )
physics.addBody( crate1, { density=3.0, friction=0.5, bounce=0.3 } )
crate1.myName = "first crate"
crate1.setGravity = 2
 
local crate2 = display.newImage( "crate.png", 100, 120 )
physics.addBody( crate2, { density=3.0, friction=0.5, bounce=0.3 } )
crate2.myName = "second crate"

-- A general function for dragging physics bodies
local function dragBody( event )
        local body = event.target
        local phase = event.phase
        local stage = display.getCurrentStage()
 
        if "began" == phase then
                stage:setFocus( body, event.id )
                body.isFocus = true
      -- Create a temporary touch joint and store it in the object for later reference
                body.tempJoint = physics.newJoint( "touch", body, event.x, event.y )
 
        elseif body.isFocus then
                if "moved" == phase then  
                        -- Update the joint to track the touch
                        body.tempJoint:setTarget( event.x, event.y )
                elseif "ended" == phase or "cancelled" == phase then
                        stage:setFocus( body, nil )
                        body.isFocus = false
                        -- Remove the joint when the touch ends                
                        body.tempJoint:removeSelf()
                end
        end
 
        -- Stop further propagation of touch event
        return true
end
 
-- Make object draggable
crate1:addEventListener( "touch", dragBody )
crate2:addEventListener( "touch", dragBody )

이미지는 아래 이미지들이 필요합니다.










잠깐 코드를 보면 처음에 physics를 import 해서 start 시켰구요.
멀티터치를 적용했네요. (이건 나중에 따로 살펴 볼 겁니다.)
그리고 draw mode는 hybrid로 해서 body가 적용된 사항을 볼 수가 있게 했구요.

그 다음에 ground.png를 그리고 여기에 static 으로 addBody를 했습니다.
다음은 crate.png로 두개의 객체를 만든 후 addBody를 했습니다.
dynamic이 디폴트니까 이게 적용 됐겠네요.

맨 밑에 보면 crate1, crate2에 touch에 반응하는 리스너를 달았고 touch 시 dragBody 함수를 불러오도록 했습니다.

dragBody에는 touch 조인트가 사용됐네요.
touch 해서 move 할 때는 touch 조인트가 적용되서 박스가 그럴듯 하게 움직일 겁니다. 그리고 touch 가 끝나면 조인트가 remove되서 박스는 떨어지겠네요.


이대로 실행해 보시구요.

시뮬레이터인 경우엔 마우스로 디바이스인 경우엔 손가락으로 박스를 옮겨 보세요.
그리고 막 돌려보시고 박스로 박스를 밀쳐보시고 한번 해 보세요.

그럼 Touch Joint 가 어떤식으로 적용 되는지 아실거예요.

Touch 조인트는 다른 조인트와 다르게 객체 하나에만 적용 됩니다.

그럼 이 소스를 기본으로 해서 다른 여러 joint들을 적용해 볼까요?

1. Pivot Joint
Pivot 은 중심, 축 이라는 뜻입니다. Box2D에서는 revolute Joint 라고 합니다.
코드 맨 밑에 아래 코드를 추가해 보세요.
myJoint = physics.newJoint( "pivot", crate1, crate2, 50,60 )

신택스는 아래와 같습니다.

physics.newJoint( jointType, object1, object2, anchorX, anchorY )

jointType은 "pivot"이고 object2, object2는 조인트 대상입니다.

anchorX-x 앵커 포인트, anchorY - y 앵커 포인트


실행해 보시고 박스를 막 움직여 보세요. 그러면 일정 거리만큼 객체들이 유지 될 거예요. 앵커 포인트가 객체 위치와 비교해서 어디로 설정 되느냐에 따라 두 객체의 연결 관계가 변합니다.


2. Distance Joint
pivot 조인트 부분을 주석처리하시고 아래 코드를 넣어보세요.
myJoint = physics.newJoint( "distance", crate1, crate2, crate1.x,crate1.y, crate2x,crate2.y )
Distance Joint는 두개의 객체 거리가 Fix돼 있게 만든 겁니다.

3. Piston Joint
피스톤 조인트는 아래 코드를 적용해 보세요.
myJoint = physics.newJoint( "piston", crate1, crate2, crate1.x,crate1.y, 50,80 )
이 조인트는 Box2D에서는 prismatic joint라고 불립니다.
이 조인트는 피스톤이나 자동차의 shock Observer같이 움직이는 조인트라고 합니다.
첫번째 객체의 앵커포인트를 기준으로 움직일 때 축을 기준으로 다른 객체가 움직입니다.
제 소스에서는 한 박스가 옆쪽으로 ground를 넘어서면 한 없이 떨어지고 다시 올리기가 힘든데요.
여러분은 상하좌우 wall을 만들고 이것에 addBody를 하셔서 한번 테스트 해 보시면 좋을 것 같네요.

4. Friction Joint
friction이 마찰, 저항이란 뜻인데요. pivot 조인트의 특별한 형태입니다.
움직일 때 약간 저항을 받는것 같네요. 코로나에서는 Sticky라고 표현했습니다.
myJoint = physics.newJoint( "friction", crate1, crate2, 10,30 )
위 코드로 테스트 해 봤는데... 전 정확히 어떤 특징이 있는지 모르겠네요.

5. Weld Joint
이 조인트는 확실히 알겠습니다.
Weld가 용접이란 뜻이니까 두 객체가 용접된 듯이 딱 붙어서 떨어지지 않는다는 얘기겠죠?
myJoint = physics.newJoint( "weld", crate1, crate2, 200,300 )
이렇게 하면 두 박스가 떨어져 있지만 용접한 것처럼 완전 고정돼 있습니다.
여러 객체를 붙일 때는 Weld 보다 여러 객체를 합한 body를 사용하는게 낫다고 코로나에서 그러네요.

6. Wheel Joint
Box2D에서는 line joint라고 합니다. piston과 pivot 조인트가 합쳐진 것이라고 하는데요. piston joint와 거의 같은데 다른 점은 축의 끝에서 로테이션이 가능하다고 합니다.
myJoint = physics.newJoint( "wheel", crate1, crate2, crate1.x,crate1.y, 50,80 )

7. Pulley Joint
myJoint = physics.newJoint( "pulley", crate1, crate2, 50,80, 200,120, crate1.x,crate1.y, crate2.x,crate2.y, 3.0 )
이 조인트를 사용했더니 두 박스가 대롱대롱 매달려있네요.
오른쪽 박스를 잡아 당기면 왼쪽 박스가 막 움직이구요.

8. Touch Joint
이 조인트는 이미 기본 소스에 적용 돼 있습니다.
Box2D에서는 mouse joint라고 한답니다. 객체가 마우스를 따라 다녀서 그런가요?

조인트를 없애려면 아래와 같이 합니다.
myJoint:removeSelf()

이렇게 Joint 까지 하고 나니 Box2D를 사용한 코로나의 Physics Engine에 대해 한번 다
훑어 봤습니다.

다음 토픽으로 넘어가기 전에 다음 시간엔 joint에 관한 샘플코드 몇가지를 살펴보고
넘어갈 까 합니다.

그럼 다음 시간에 뵐께요.



반응형