Vehicle template: /player.lua code sample - Stingray Lua API Reference
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