Controlling Character Movement from SideViewRectTileMap

# Course Introduction

Because DefaultPlayer includes RigidbodyComponent, KinematicbodyComponent, and SideviewbodyComponent, the subject of movement control will vary depending on the mode the map was produced with. Among them, a map produced with SideViewRectTile mode controls the character's movement with SideviewbodyComponent. Today let us learn about SideviewbodyComponent and look at the use methods with a simple example.

##### API Reference

[SideviewbodyComponent](/apiReference/Components/SideviewbodyComponent)

> Learn more Please refer to [Creating Maps with SideViewRectTile Mode](/docs/?postId=758) for the details of SideViewRectTile.

# About SideviewbodyComponent

SideviewbodyComponent is used to control character movement in a side-scrolling system in SideviewRectTile maps. [png](move) SideviewbodyComponent.

[png](165871206539396a3c85df20c4f439e76b91157a57a82)

[{"Property":"ApplyClimbableRotation","Description":"When true, the character on the rotating or slanted ladder will be affected by the shape of the ladder. When false, the character is not affected by the slant or rotation of the ladder."},{"Property":"EnableDownJump","Description":"Turns Jump Down on or off."},{"Property":"DownJumpSpeed","Description":"Controls the speed of the bounce back up when jumping down. The greater the value, the higher the bounce."},{"Property":"JumpDrag","Description":"Controls the rate of the jump speed. The greater the value, the faster the fall."},{"Property":"JumpSpeed","Description":"Controls the speed of the bounce when jumping. The greater the value, the higher the bounce."},{"Property":"Enable","Description":"If it is True, it enables SideviewbodyComponent."}]

# SideviewbodyComponent Use

Let's learn how to utilize SideviewbodyComponent. We recommend referring to [Create Map with SideViewRectTile Mode](/docs/?postId=758) first and creating a map below, and then doing the example in this guide. [gif](1658478611789db5a20547f4f40a5bec1c0b961ad97a7)

## Creating a Double Jump

The character's movement is controlled `MoveVelocity`. Let us make a simple double jump feature through `MoveVelocity`.   


  1. Under MyDesk , create a new script component  called DoubleJump, and then add it to DefaultPlayer .

  2. As shown below, add the `IsDoubleJumping` Property and `TryDoubleJump` Function to DoubleJump .
         
         @Component
         script DoubleJumpAbility extends Component
         property boolean IsDoubleJumping = false
         
         @ExecSpace("ClientOnly")
         method void TryDoubleJump()
         local sb = self.Entity.SideviewbodyComponent
         
         -- If the character has not performed the double jump yet but is still in the air, you should change the Y-axis value of the speed.
         if self.IsDoubleJumping == false and sb:IsOnGround() == false then
             local jumpSpeed = sb.JumpSpeed
             local vel = sb.MoveVelocity
         
             vel.y = jumpSpeed
             sb.MoveVelocity = vel
         
             -- Once the character performs the double jump, it changes IsDoubleJumping to true.
             self.IsDoubleJumping = true
         end
         end
         end
         



    
    
         If the character has not performed the double jump yet but is still in the air, you should change the Y-axis value of the speed.
        IsDoubleJumping Property is a state variable to be changed to true when the double jump is performed and to be false again when landing.
    
    3. In addition, add the `OnUpdate` Function as below.
        ```lua
    @Component
    script DoubleJumpResetter extends Component
        @ExecSpace("ClientOnly")
        method void OnUpdate(number delta)
        local sb = self.Entity.SideviewbodyComponent
    
        -- Once the character lands, it changes IsDoubleJumping to false.
        if sb:IsOnGround() then
            self.IsDoubleJumping = false
        end
        end
    end
    

  4. As shown below, KeyDownEvent  should be added, too. 
         
         @Component
         script DoubleJumpInputHandler extends Component
         @EventSender("Service", "InputService")
         handler HandleKeyDownEvent(KeyDownEvent event)
         -- Parameters
         local key = event.key
         --------------------------------------------------------
         
         if key == KeyboardKey.LeftAlt or key == KeyboardKey.Space then
             self:TryDoubleJump()
         end
         end
         end
         



    
    
       
    5. Click **[Play]**   and test. If you input LeftAlt or Space key, a double jump is available.
    [gif](165872170517526609c30a97c4a2e9a175212254925b8)
    
    ## Creating Slippery Tiles
    If you apply `MoveVelocity`, you can make the character's movement meet the game concept that the creator intends. In this example, let us create the movement as walking on a slippery road by adding acceleration and frictional force concepts to meet the field concept full of snow and ice.
      
    
    1.  Under MyDesk , create a new script component  called CustomPlayerController, and then add it to DefaultPlayer .
       
    2. Add Property as below after opening CustomPlayerController .
        ```lua
    @Component
    script PlayerMovementInput extends Component
        property Vector2 InputDirection = Vector2(0,0)
        property boolean IsJumpKeyPressed = false
        property boolean IsCrouchKeyPressed = false
    end
    

  3. To add the `OnBeginPlay` Function and handle the user input directly, you should enable PlayerControllerComponent. 
         
         @Component
         script PlayerControllerDisabler extends Component
         @ExecSpace("ClientOnly")
         method void OnBeginPlay()
         -- To handle the user input directly, you should disable PlayerControllerComponent.
         local controller = self.Entity.PlayerControllerComponent
         controller.Enable = false
         end
         end
         



    
    
        
    4. KeyDownEvent  and KeyUpEvent  should be added to record the key input state.
        ```lua
    @Component
    script PlayerInputHandler extends Component
        @EventSender("Service", "InputService")
        handler HandleKeyDownEvent(KeyDownEvent event)
        -- Parameters
        local key = event.key
        --------------------------------------------------------
    
        if key == KeyboardKey.RightArrow then
            self.InputDirection.x = self.InputDirection.x + 1
        end
        if key == KeyboardKey.LeftArrow then
            self.InputDirection.x = self.InputDirection.x - 1
        end
        if key == KeyboardKey.UpArrow then
            self.InputDirection.y = self.InputDirection.y + 1
        end
        if key == KeyboardKey.DownArrow then
            self.InputDirection.y = self.InputDirection.y - 1
            self.IsCrouchKeyPressed = true
        end
        if key == KeyboardKey.LeftAlt or key == KeyboardKey.Space then
            self.IsJumpKeyPressed = true
        end
        end
    
        @EventSender("Service", "InputService")
        handler HandleKeyUpEvent(KeyUpEvent event)
        -- Parameters
        local key = event.key
        --------------------------------------------------------
    
        if key == KeyboardKey.RightArrow then
            self.InputDirection.x = self.InputDirection.x - 1
        end
        if key == KeyboardKey.LeftArrow then
            self.InputDirection.x = self.InputDirection.x + 1
        end
        if key == KeyboardKey.UpArrow then
            self.InputDirection.y = self.InputDirection.y - 1
        end
        if key == KeyboardKey.DownArrow then
            self.InputDirection.y = self.InputDirection.y + 1
            self.IsCrouchKeyPressed = false
        end
        if key == KeyboardKey.LeftAlt or key == KeyboardKey.Space then
            self.IsJumpKeyPressed = false
        end
        end
    end
    
    
    
    

  5. Let us calculate the character's movement based on acceleration and frictional force. First, add properties as follows. 
         
         @Component
         script MovementProperties extends Component
         property number MaxSpeed = 4 -- Maximum speed
         property number Accel = 10 -- Acceleration
         property number Drag = 8 -- Frictional force
         property number AirAccel = 6 -- Aerial acceleration
         property number AirDrag = 4 -- Aerial frictional force
         end
         



    
    
        
    6. For better handling, let us apply the acceleration and frictional force values differently in the air. 
    Add the `GetAccel` and `GetDrag` Functions as below.
        ```lua
    @Component
    script GroundAirMovementAttributes extends Component
        method number GetAccel()
        local body = self.Entity.SideviewbodyComponent
    
        if body:IsOnGround() then
            return self.Accel
        else
            return self.AirAccel
        end
        end
    
        method number GetDrag()
        local body = self.Entity.SideviewbodyComponent
    
        if body:IsOnGround() then
            return self.Drag
        else
            return self.AirDrag
        end
        end
    end
    

  7. Set it as decelerating when there is no key input from the user and accelerating when there is. Add `UpdateVelocity` and `SignOf` Functions as below. 
         
         @Component
         script MovementVelocityController extends Component
         method number SignOf(number value)
         if value >= 0 then
             return 1
         else
             return -1
         end
         end
         
         method void UpdateVelocity(number delta)
         local body = self.Entity.SideviewbodyComponent
         local vel = body.MoveVelocity
         
         if self.InputDirection.x == 0 then
             -- Decelerate when there is no input.
             if vel.x ~= 0 then
                 local sign = self:SignOf(vel.x)
                 local drag = self:GetDrag()
                 vel.x = vel.x - drag * sign * delta
         
                 if self:SignOf(vel.x) ~= sign then
                     vel.x = 0
                 end
             end
         else
             -- Accelerate when there is input.
             local sign = self:SignOf(vel.x)
             local accel = self:GetAccel()
             vel.x = vel.x + self.InputDirection.x * accel * delta
             vel.x = math.min(vel.x * sign, self.MaxSpeed) * sign
         end
         
         -- Apply the final calculation result.
         body.MoveVelocity = vel
         end
         end
         



    
    
        
    8. Make the `OnUpdate` function call `UpdateVelocity`.
        ```lua
    @Component
    script SpeedController extends Component
        @ExecSpace("ClientOnly")
        method void OnUpdate(number delta)
        -- Speed control
        self:UpdateVelocity(delta)
        end
    end
    

  9. Click [Play]   and test. You can see that the movement to the left and the right is smooth and slipping. [gif](1658730031714e5dd719655354d66878ba051e490182e) However, since PlayerControllerComponent is inactive, the character's jump motion or movement animation does not work yet. You need to add a function to control the motion and animation for normal operation.

  10. Open  CustomPlayerController again and then add the `UpdateAction` function that controls the motions of characters.
         
         @Component
         script PlayerActionHandler extends Component
         method void UpdateAction()
         local controller = self.Entity.PlayerControllerComponent
         local body = self.Entity.SideviewbodyComponent
         
         -- Prone
         if self.IsCrouchKeyPressed and body:IsOnGround() then
             controller:ActionCrouch()
         end
         
         -- Jump and Down Jump
         if self.IsJumpKeyPressed and body:IsOnGround() then
             if self.IsCrouchKeyPressed then
                 controller:ActionDownJump()
             else
                 controller:ActionJump()
             end
         end
         end
         end
         



    
    
        
    11. Also add the `UpdateAnimationState` function that controls the animations of characters.
        ```lua
    @Component
    script AnimationStateController extends Component
        method void UpdateAnimationState()
        local body = self.Entity.SideviewbodyComponent
        local state = self.Entity.StateComponent
    
        if body:IsOnGround() then
            if self.InputDirection.x ~= 0 then
                -- Walking animation
                state:ChangeState("MOVE")
            elseif self.IsCrouchKeyPressed then
                -- Prone animation
                state:ChangeState("CROUCH")
            else
                -- Standing animation
                state:ChangeState("IDLE")
            end
        else
            -- Floating animation
            state:ChangeState("FALL")
        end
        end
    end
    

  12. You also should add the `UpdateLookDirection` function that controls the character's left and right gaze. 
         
         @Component
         script PlayerLookController extends Component
         method void UpdateLookDirection()
         local controller = self.Entity.PlayerControllerComponent
         
         -- The Direction the player faces
         if self.InputDirection.x ~= 0 then
             if self:SignOf(self.InputDirection.x) < 0 then
                 -- It looks toward the left side.
                 controller.LookDirectionX = -1
             else
                 -- It looks toward the right side.
                 controller.LookDirectionX = 1
             end
         end
         end
         end
         



    
    
        
    13. Let us make the `OnUpdate` function call `UpdateAction`, `UpdateAnimationState`, and `UpdateLookDirection`.
        ```lua
    @Component
    script CharacterController extends Component
        method void OnUpdate(number delta)
        -- Speed control
        self:UpdateVelocity(delta)
    
        -- Addition: Motion control
        self:UpdateAction()
    
        -- Addition: Animation control
        self:UpdateAnimationState()
    
        -- Addition: Left and right gaze control
        self:UpdateLookDirection()
        end
    end
    

  14. [png](move) SideviewbodyComponent checks `EnableDownJump`. Enter 3.3 for the `DownJumpSpeed` value. [png](1658731157148bf72bff0378b464f9addc47a64839d56)

  15. Click [Play]   and test. Check if the character's motion, animation, and gaze controls work normally. [gif](1658731907252ed230a57a59f4b899f347a4ba97f0ebf)




## Creating More Slippery Tiles

If you use the `GetUnderfootTile` function, you can find out what tile the character is currently stepping on. Let us create an even more slippery feature by reducing the frictional force when stepping on an icy tile.

  1. Under MyDesk , create a new script component  called IceTileChecker, and then add it to DefaultPlayer .

  2. Add Property as below after opening IceTileChecker .
         
         @Component
         script DragSettings extends Component
         property number IceDrag = 2
         property number DefaultDrag = 0
         end
         



    
    
    3. Add the `OnBeginPlay` function and compose its content as follows.
        ```lua
    @Component
    script DefaultDragInitializer extends Component
        @ExecSpace("ClientOnly")
        method void OnBeginPlay()
        self.DefaultDrag = self.Entity.CustomPlayerController.Drag
        end
    end
    

  4. Let us add the `OnUpdate` function and make the tile the character steps on much more slippery if the tile is "Ice" by using the `GetUnderfootTile` function. 
         
         @Component
         script SurfaceDragHandler extends Component
         @ExecSpace("ClientOnly")
         method void OnUpdate(number delta)
         local customController = self.Entity.CustomPlayerController
         local body = self.Entity.SideviewbodyComponent
         local underfootTile = body:GetUnderfootTile()
         
         customController.Drag = self.DefaultDrag
         
         if underfootTile == nil then
            return
         end
         
         if underfootTile.Name == "Ice" then
             customController.Drag = self.IceDrag
         end
         end
         end
         



    
    
    5. Click **[Play]**   and test. You see that it is much more slippery on an icy tile rather than a snow tile.
    [gif](16587333763832e690f96aaf64196b8a4bd6dfef571cd)