2015년 6월 20일 토요일

corona sdk 에서 tiled 사용하기 09 – Controlling a Platformer Character’s Jump



https://github.com/anthonymoralez/lime-tutorials/tree/master/tutorial-09


NOTE: This tutorial is copied from the original at OutlawGameTools.com

09 – Controlling a Platformer Character’s Jump (플랫폼 캐릭터 점프 제어하기)

Difficulty: Beginner
Duration: 30 minutes 헐 30분이나 걸린다네요.
Description:
In this tutorial you will see how easy it is to make a sprite jump via physics. This is not the only way this can be achieved, this is just the way I am showing here, if you have a better way please email me.

Step 1: Getting your map (맵 불러오기)

To keep things simple we are going to use an already created map that was built using concepts learned in previous tutorials. The map is a single screen map that you will recognise.
You can download the map here.
The map has the physical terrain already set up as well as a positioned object which we will use to create our player.
맵데이터는 앞에서 사용한 것 사용해도되고 여기있는 데이터를 다운해서 사용하면 됩니다.

Step 2: Creating our player (플레이어 만들기)

To create our player we will use the Object Listener features, in your main.lua file before you call lime.createVisual() place the following code snippet:
플레이어를 만들기전에 object listener를 만들어야 합니다. 화면에 map을 만들기전 즉 lime.createVisual()하기전에 아래 코드가 들어가야 합니다.
이해가 안되면 앞의 예제중 플레이어 캐릭터를 나오게 하는 예제에 보면 됩니다.
이번 예제에서는 Player layer가 있어야 하는데 만약 개인적으로 만든 맵이라면, object layer 말고 일반 tile layer를 하나만들어 Player layer로 이름을 변경해야 합니다.
local onPlayerSpawnObject = function(object)
    local layer = map:getTileLayer("Player")
    player = display.newImage(layer.group, "guy.png")
    player.x = object.x
    player.y = object.y
end
map:addObjectListener("PlayerSpawn", onPlayerSpawnObject)
All this code does is first get a layer called "Player" in our map, then create an image object at the position of our spawn object making sure to add it to the layer group.
If you ran your game now you would get your little player image loaded up in the map and nothing else interesting happening.
실행시키면 아래와 같은 화면이 나옵니다.
Player In Game

Step 3: Making him jump (점프 시키기)

To make our player jump using physics we first must make him physical, to do so you will need to initially start up the physics engine by placing the following code somewhere at the top of your main.lua file:
점프 하려면 물리엔진을 시작 시켜야 합니다. 제일 앞에 아래 코드를 넣습니다.
require("physics")
physics.start()
With that done you will now need to make your physics body, this is done by adding one line of code to our object listener, just after you have set the players position:
그리고 리스너에에 아래 코드를 넣도록 합니다. 
physics.addBody(player, { density = 1.0, friction = 0.3, bounce = 0.2 })
위치는 앞에 코드 마지막에 넣습니다.
local onPlayerSpawnObject = function(object)
    local layer = map:getTileLayer("Player")
    player = display.newImage(layer.group, "img/guy.png")
    player.x = object.x
    player.y = object.y
    physics.addBody(player, { density = 1.0, friction = 0.3, bounce = 0.2 })
end
Physics In Game
Now if you run the game your player will fall gracefully to the ground landing nicely in front of the little plant, this is because of layering.
이렇게 해서 실행하면 캐릭터가 아래로 떨어집니다.
The next step is to make him jump, in this tutorial I will simply add this function to a "tap" event however you may wish to activate it some other way such as when your player taps a jump button or tilts the device.
To do this simply create a "touch" event listener and then apply an impulse to the player, like so:
터치를 하면 player가 위로 올라갔다가 떨어지게 만들건데 디바이스의 이벤트 핸들러 touch에 리스너를 등록합니다.
local onTouch = function(event)
    player:applyLinearImpulse(0, -5, player.x, player.y)
end
Runtime:addEventListener("touch", onTouch)
Nice and simple really, just apply a small impulse to our player everytime the user taps the screen. Run the game and test it out, you will notice that your player is able to jump in mid-air simply by tapping multiple times, we will now fix that.
이렇게 해놓으면 누를때 마다 하늘위로 올라갑니다. 물체가 있더라도 하늘로 올라가죠. 아래에 점프를 제한하는 방법이 나옵니다.

Step 4: Limiting the jump (점프의 제한)

In order to limit the jump we must first decide how we want to limit it, for the purposes of this tutorial we will say that we only want our player to be able to jump if he is currently on the ground.
위와 같은 동작을 막자면 점프를 땅에서만 되도록 하는 방법입니다.
Now that we have decided our limitation we need to think about the implementation, we could either go about this by saying our player can only jump when touching a ground object or that he can’t jump when in the air. I have decided to go down the former route simply so that I can show the use of collision events, you may wish to go another way in your games.
To start off with we will put a simple check around our jump function to make sure that the player can only jump when we allow him to do so:

아래 소스를 이용하면 player.canJump를 만들어서 특정한 위치에서만 점프가 되도록 작업하였습니다. 하지만 player.canJump 는 항상 false 가 됩니다. 어디에서도 true를 안했으니까요.
local onTouch = function(event)
    if player.canJump then
        player:applyLinearImpulse(0, -5, player.x, player.y)
    end
end
Runtime:addEventListener("touch", onTouch)
If you ran your game now all we have done is broken the jump function as player.canJump will always be false, to fix this we need to make our collision event listener:
그래서 플레이어가 충돌이 충돌여부에 따라 해당 값을 변경해 주어야 합니다. 그게 collision 이벤트를 등록하면 해당 처리를 할 수 있습니다. 아래코드는 미완성 코드인데... 좀 더 아래를 보면 됩니다.
local function onCollision(self, event )
    if ( event.phase == "began" ) then

    elseif ( event.phase == "ended" ) then

    end
end
player.collision = onCollision
player:addEventListener( "collision", player )
What we have here is an empty collision event handler that checks the phase of the collision but does nothing. We could simply have it so that on collision began it sets player.canJump to true and on collision ended set it back to false again, but what happens when our player bumps into other things that we don’t want to allow him jumping on like water or glue? Simple, we specifiy which object is actually a ground object which we can do this through the use of properties in Tiled.
In the map that I have provided I have already set up the properties how we need them but just so we are all clear, all I have done is given each physics object (making sure to include each of the control points for the centre terrain) an "IsGround" property, they don’t need a value as all we care about is the existence of the property itself but you could be fancy here and change it to "GroundType" to enable different jump powers on different surfaces.
With these properties set up it is just a simple addition to the collision event to enable and disable jumping, the updated code is below:
아래 코드가 완벽한 코드입니다. 주의 해야할점은 tiled에서 맵에 수정을 좀 해줘야합니다. canJump가 true가 되려면 IsGround가 true가 되어야 하는데 그럴려면 땅과 충돌이 일어나야 합니다. object layer나 tile셋의 property에 IsGround를 넣어 주도록 합니다.
즉 object layer에 넣으려면 Object Type Body, IsGround, BodyType=static 이 되도록 해주고, 타일에 넣어주려면 HasBody, IsGround, bodyType=static 이 되도록 해줍니다.
Lua스크립트에서 중요한가지가 있습니다. 순서가 중요한것입니다. 리스너 등록시 함수를 넘겨주는데 정의하기전에 넘겨주면 동작하지 않습니다. 물론 에러도 발생하지 않습니다.
GroundType을 이용해서 매질이 다른곳에서 다른 형태의 점프가 되도록 작업할 수도 있습니다.
local function onCollision(self, event )
    if ( event.phase == "began" ) then
        if event.other.IsGround then
            player.canJump = true
        end
    elseif ( event.phase == "ended" ) then
        if event.other.IsGround then
            player.canJump = false
        end
    end
end
player.collision = onCollision
player:addEventListener( "collision", player )
The new code is highlighted and fairly easy to understand, the important thing to realise here is that event.other is not a Tiled Object but in fact a Corona physics body. Lime has handily copied over all the properties that you may have set on the Tiled Object (including our "IsGround" property) to make things simpler for us.

Step 5: Run your game (게임 실행하세요)

If you run your game now your player will now be limited to jumping only when he is on the ground.
지금까지 작업한걸 테스트해보면 객체가 땅바닥에 닿을때 Jump가 됩니다.
Resources:
Completed Project: git clone https://github.com/anthonymoralez/lime-tutorials


꼭 알아두세요.
1. lime은 프로젝트 최상위 폴더에 lime폴더 통째로 복사해서 넣습니다.
2. Layer는 높은쪽이 위쪽 레이어입니다.
3. Tiled에서 tileset의 프로퍼티는 이름과 값으로 구성됩니다.
4. 화면에 보이게한뒤 물리 설정을 해야합니다. local visual = lime.createVisual(map) => local physical = lime.buildPhysical(map)
5. 타일셋에 물리 객체는 HasBody로 합니다.
6. 타일셋 import/export로 현재 저장된 프로퍼티를 다른 맵파일(tmx)과 쉽게 공유할 수 있습니다.
7. 타일을 간단하게 애니메이션 시키는 방법,IsAnimated, frameCount=?,frameTime 이 있지만 오류 발생합니다. 사용 하려면 코드 수정해야 합니다.
8. 타일 에니메이션 또다른 방법은 IsAnimated tile.sprite:setSequence("animation1") 이걸 이용하세요
9. PlayerSpawn 만들기 : object layer사용 tool을 이용하여 위치 설정 Type을 PlayerSpawn 프로퍼티 playerImage=? 추가 후 코드 추가 map:addObjectListener("PlayerSpawn", onObject)
10. 물리세계를 만들려면 object layer 에 객체를 추가한뒤 type Body로 하면됩니다. 프로퍼티 bodyType=static 추가
11. 물리세계 정보를 런타임에 디버깅 Map>>Map Properties : Physics:DrawMode=hybrid?debug?normal 선택함
12. 물리세계 원형으로 처리하려면 프로퍼티 radius=? 추가함
13. Jump동작을 넣으려면 Groud일때만 점프 되도록 코드 추가하고 map에 Ground처리 해야함 object layer에 넣으려면 Object Type Body, IsGround, BodyType=static 이 되도록 해주고, 타일에 넣어주려면 HasBody, IsGround, bodyType=static 이 되도록 해줍니다.

댓글 없음:

댓글 쓰기