Vehicle template: /player.lua — code sample - Stingray Lua API Reference

Vehicle template: /player.lua — code sample

Code

require 'core/appkit/lua/class'
require 'core/appkit/lua/app'
local SimpleProject = require 'core/appkit/lua/simple_project'
local CameraWrapper = require 'core/appkit/lua/camera_wrapper'
local UnitController = require 'core/appkit/lua/unit_controller'
local ComponentManager = require 'core/appkit/lua/component_manager'
local UnitLink = require 'core/appkit/lua/unit_link'
local PlayerHud = require 'script/lua/player_hud'
local Project = require 'script/lua/project'
local VehicleFollowCam = require 'script/lua/vehicle_follow_cam'
local VehicleUnitController = require 'script/lua/vehicle_unit_controller'
local Util = require 'core/appkit/lua/util'

-- On touch devices we will override the input_mapper in Appkit to use the Hud Controls.
if scaleform and Util.use_touch() then
    function Appkit.input_mapper:get_motion_input()
        return PlayerHud:get_motion_input()
    end
end

Project.Player = Appkit.class(Project.Player)
local Player = Project.Player

-- Cache off for readability and speed
local Keyboard = stingray.Keyboard
local Vector3 = stingray.Vector3
local Matrix4x4 = stingray.Matrix4x4
local Matrix4x4Box = stingray.Matrix4x4Box
local Quaternion = stingray.Quaternion
local World = stingray.World
local Unit = stingray.Unit

local free_cam_move_speed = stingray.Vector3Box(Vector3(3.8,3.8,3.8))
local free_cam_yaw_speed = 0.085
local free_cam_pitch_speed = 0.075
local follow_camera_name = "camera"
local follow_cam_offset = stingray.Vector3Box(Vector3(0,9.0,1.8))
local follow_rotational_speed = 4.0
local follow_behind_latency = 0.07

function Player:init()
    -- Vehicle Unit
    self.vehicle_unit = nil
    self.vehicle = nil

    -- Camera
    self.camera_unit = nil
    self.is_freecam_mode = false

    -- Free Camera Mode behavior
    self.saved_freecam_pose = Matrix4x4Box(Matrix4x4.identity())
    self.save_freecam_pose_exists = false
end

local function play_spawn_sound()
    if s3d.Wwise then
        s3d.Wwise.load_bank("content/audio/default") -- temporarily necessary for autoload mode to work
        local wwise_world = s3d.Wwise.wwise_world(SimpleProject.world)
        s3d.WwiseWorld.trigger_event(wwise_world, "sfx_amb_lightwind")
    end
end

local function init_camera(self, view_position, view_rotation)
    -- Spawn camera unit
    local world = SimpleProject.world
    local camera_unit = SimpleProject.camera_unit
    self.camera_unit = camera_unit

    -- Use Appkit Camera Convenience wrapper
    local camera_wrapper = Appkit.CameraWrapper(self, camera_unit, 1)
    -- Set position and enable
    camera_wrapper:set_local_position(view_position)
    camera_wrapper:set_local_rotation(view_rotation)
    camera_wrapper:enable()

    -- Set up follow camera behavior
    local vehicle = self.vehicle
    local follow_cam = VehicleFollowCam(self, world, self.vehicle, camera_unit, follow_camera_name, follow_cam_offset:unbox(), follow_rotational_speed, follow_behind_latency)

    local level = SimpleProject.level
    local unit_link = UnitLink(self, level, camera_unit, 1, self.vehicle_unit, 3, true)

    self.is_freecam_mode = false
end

local function init_controllers(self)
    -- Add freecam unit controller, starts disabled
    input_mapper = Appkit.input_mapper
    local freecam_controller = UnitController(self, self.camera_unit, input_mapper)
    freecam_controller:set_move_speed(free_cam_move_speed:unbox())
    freecam_controller:set_yaw_speed(free_cam_yaw_speed)
    freecam_controller:set_pitch_speed(free_cam_pitch_speed)
    freecam_controller:set_enabled(false)

    -- Add vehicle controller
    local vehicle_controller = VehicleUnitController(self, SimpleProject.level, self.vehicle, self.vehicle_unit, PlayerHud)
end

-- Main Player Spawn function.
-- Player starts in vehicle follow cam mode, and can toggle to free cam mode and back
function Player.spawn_player(level, view_position, view_rotation)
    if not level then
        print "ERROR: No current level - cannot spawn"
        return
    end

    local player = Player()
    PlayerHud:init_hud()

    local vehicle_unit = World.spawn_unit(SimpleProject.world, "content/models/4wheel/4wheel", Vector3(-3,0,0))
    player.vehicle_unit = vehicle_unit
    player.vehicle = stingray.Unit.vehicle(vehicle_unit)

    init_camera(player, view_position, view_rotation)
    init_controllers(player)

    play_spawn_sound()

    Appkit.manage_level_object(level, Player, player)
end

local function despawn_player(self)
    ComponentManager.remove_components(self)
    self.camera_unit = nil -- do not need to destroy it as it is the default SimpleProject.camera_unit
    local vehicle_unit = self.vehicle_unit
    if vehicle_unit then
        World.destroy_unit(SimpleProject.world, vehicle_unit)
        self.vehicle_unit = nil
    end
end

function Player.shutdown(object, level)
    PlayerHud:shutdown(level)
    despawn_player(object)
end

local function enable_drive_mode(self)
    -- save off freecam camera position
    local camera_wrapper = CameraWrapper.manager:get(self)
    self.saved_freecam_pose:store(camera_wrapper:local_pose())
    self.save_freecam_pose_exists = true

    -- disable freecam movement
    local freecam_controller = UnitController.manager:get(self)
    freecam_controller:set_enabled(false)

    -- enable vehicle follow cam movement
    local followcam_controller = VehicleFollowCam.manager:get(self)
    followcam_controller:set_enabled(true)

    -- enable vehicle movement
    local vehicle_controller = VehicleUnitController.manager:get(self)
    vehicle_controller:set_enabled(true)

    -- attach camera to vehicle
    local unit_link = UnitLink.manager:get(self)
    unit_link:set_parent(self.vehicle_unit, 2)
    unit_link:link()    
end

local function enable_free_mode(self)
    -- detach camera from vehicle
    local unit_link = UnitLink.manager:get(self)
    unit_link:unlink()

    -- disable vehicle movement
    local vehicle_controller = VehicleUnitController.manager:get(self)
    vehicle_controller:set_enabled(false)

    -- disable vehicle follow cam movement
    local followcam_controller = VehicleFollowCam.manager:get(self)
    followcam_controller:set_enabled(false)

    -- enable freecam movement
    local freecam_controller = UnitController.manager:get(self)
    freecam_controller:set_enabled(true)

    -- set freecam to saved off camera position
    local camera_wrapper = CameraWrapper.manager:get(self)
    if self.save_freecam_pose_exists then
        camera_wrapper:set_local_pose(self.saved_freecam_pose:unbox())
    end
end

local function toggle_camera_mode(self)
    -- freecam toggle input
    local index = Keyboard.button_id("")
    if (index and Keyboard.pressed(index)) or PlayerHud:check_toggle_camera() then
        if self.is_freecam_mode then
            enable_drive_mode(self)
        else
            enable_free_mode(self)
        end
        self.is_freecam_mode = not self.is_freecam_mode
    end
end

local function check_exit_level(self)
-- level exit input
    if Appkit.is_standalone() then
        local index = Keyboard.button_id("f5")
        local b1_pressed = index and Keyboard.pressed(index) 
        local index = Keyboard.button_id("esc")
        local b2_pressed = index and Keyboard.pressed(index) 
        if b1_pressed or b2_pressed or PlayerHud:exit_level() then
            SimpleProject.change_level(Project.level_names.menu)
        end
    end
end

function Player.update(self, dt)
    PlayerHud:update(dt)
    toggle_camera_mode(self)
    check_exit_level(self)
end

return Player