The PlayerManager Component
The PlayerManager component is responsible for the following aspects of the game
- Creating the player character by loading and configuring appropriate assets
- Placing the player in the initial location
- Move the player in the scene in response to user inputs such as keyboard or controllers
- Handle player related commands from the user using a set of actions.
The basic PlayerManager class provides a set of actions which can be used to perform simple operations like walking, moving the player around, picking up items etc. Developer can add additional actions to make the player character perform more actions. Actions can be configured to be executed in response to user inputs from a keyboard or a controller.
Creating Player Character
During initialization, the PlayerManager component creates a Player object which, in turn, loads the assets for the player character and places the character in its original location on that level. The PlayerManager loads and passes a PlayerConfig object to initialize the player object as follows:
import { playerConfig } from "./configs/player/player-config";export class PlayerManager1 {....init(){this.player = new Player( playerConfig, this.scene, this.canvas);this.player.init( () =>{.....});}}
Note how the configuration data for the player is loaded from the file /configs/player/player-config and is passed to the Player object. You can change the content of this file to load the mesh of your choice and also can customize the scaling, rotation and position of the mesh. A sample player configuration file is shown below:
export const playerConfig: PlayerConfiguration = {assetInfo: {filePath: "/assets/player/",fileName: "josh.gltf"},playerMeshIndex: 0,playerMeshScaling:3.2,playerPosition: new Vector3(-33, 0, 142 ),lookAt: new Vector3(-0.996, 0, 0.0811),checkCollisions: true,forwardSpeed: 0.05,backwardSpeed: 0.003,lateralSpeed: 0.02,rotationSpeed: 0.02,arcRotateCameraConfig: {wheelPrecision: 50,checkCollisions: true,alpha: 2.295,beta: 1.337468,radius: 30,lowerRadiusLimit: 5,upperRadiusLimit: 300,},}
Handling input from different devices
Kheljs provides a set of classes to manage input from keyboard and other controllers. You simply instantiate and use these classes from PlayerManager to enable that input device. The default application generated by Kheljs uses the KeyboardInputManager class to handle inputs. You can use any of the following input managers:
- KeyboardInputManager - for managing input from a keyboard
- DualShockPadInputManager - for managing input from playstation controllers
- XBoxControllerInputManager - for managing input from xbox controllers
export class PlayerManager implements IPlayerManager {...player: Player;kbdInputMgr: PlayerKeyboardInputManager;...init(): void {this.player = new Player(playerConfig, this.level.scene, this.level.canvas);this.player.init(() => {this.animator = new PlayerAnimator(this.player, this.level.scene);// This creates a keyboard input manager and registers keyboard actionsthis.registerkeyboardActions();....});}...}
Performing actions by the player character in response to keyboard input
The PlayerManager class is responsible for listening to player related commands from the user. Player related commands are commands entered from an input device like keyboard or controller that allows the user to interact and control the player character. Examples of such commands are:
- Move forward,
- Move Backward
- Raise hand
- Crouch to go under a narrow passage
- Hide against a wall
- Jump to climb over a wall.
- Switch weapon
- Fire gun
- Reload gun
Each of these actions performed by the player character is implemented as PlayerAction objects which just performs the revelvant action independent of the input device. These actions are then mapped from user input from an device by using a input configuration file. For example, in the default application generated by kheljs, the actions performed by the player charcater in response to keyboard input are defined in a file named player-keyboard-actions.ts. A section of this file is shown below. Note how actions and animations has been set up for single key and multiple key combination.
export const keyboardActions: PlayerKeyboardAction [] = [{ keys: ["ArrowLeft"], animation: "Walk", action: new TurnLeft() },{ keys: ["ArrowRight"], animation: "Walk", action: new TurnRight() },{ keys: ["ArrowUp"], animation: "Walk", action: new MoveForward() },{ keys: ["ArrowDown"], animation: "Walk", action: new MoveBackward() },{ keys: ["a"], animation: "Walk_Strafe_Left", action: new MoveLeft() },{ keys: ["d"], animation: "Walk_Strafe_Right", action: new MoveRight() },{ keys: ["x"], animation: "Rifle_Aim_Idle" },{ keys: ["f"], animation: "Rifle_Fire_Standing", action: new FireRifle() },{ keys: ["p"], action: new PickupInventory() },{ keys: ["w"], action: new WeildGun() },{ keys: ["ArrowLeft", "ArrowUp"], animation: "Walk", actions:[ new TurnLeft(), new MoveForward()] },{ keys: ["ArrowRight", "ArrowUp"], animation: "Walk", actions:[ new TurnRight(), new MoveForward()] },{ keys: ["x", "ArrowLeft"], animation: "Rife_Aim_Strafe_Left"},{ keys: ["x", "ArrowRight"], animation: "Rife_Aim_Strafe_Right" },{ keys: ["x", "ArrowUp"], animation: "Rifle_Aim_Walking" },{ keys: ["x", "ArrowDown"], animation: "Rifle_Aim_Walking" },....}
To add more functionality to a player character, simply add more actions and map those actions using the player-keyboard-actions.ts file.
Performing actions by the player character in response to dualshock pad input
For dualshock pad you have to create a configuration file with the name player-dualshockpad-actions.ts and load the content this file to register the dualshock pad actions. The generated game already contains support for dualshock pad. A part of the dualshock pad actions file is shown below:
export const dualshockPadActions: PlayerDualShockPadAction [] = [{ status: ["ls_pressed"], animation: "Walk", action: new MoveInDirection() },{ status: ["rs_left"], action: new RotateCameraLeft() },{ status: ["rs_right"], action: new RotateCameraRight() },// Firing + other actions{ status: ["rt_pressed"], animation: "Rifle_Fire_Standing", action: new FireGun() },{ status: ["rt_pressed", "ls_pressed"], animation: "Rifle_Fire_Walking", actions: [new MoveInDirection(),new FireGun()]},{ status: ["rt_pressed", "ls_pressed", "lt_pressed" ], animation: "Rifle_Fire_Walking", actions: [new FireGun()]},// Aiming + other actions{ status: ["lt_pressed"], animation: "Rifle_Aim_Idle", action: new AimGun() },{ status: ["lt_pressed", "ls_pressed"], animation: "Rifle_Aim_Walking", actions: [new AimGun(),new MoveInDirection()]},{ status: ["lt_pressed", "rt_pressed"], animation: "Rifle_Fire_Standing", action: new FireGun() },{ status: ["ls_pressed", "rs_left"], animation: "Walk", actions: [ new RotateCameraLeft(), new MoveInDirection() ] },{ status: ["ls_pressed", "rs_right"], animation: "Walk", actions: [ new RotateCameraRight(), new MoveInDirection() ] },{ status: [ "Cross"], action: new PickupInventory(), actionType: "callback" },{ status: [ "Triangle"], action: new WeildActiveGun(), actionType: "callback" },{ status: [ "Circle"], action: new UnweildGun(), actionType: "callback" },]