var createScene = function () {
// Low Poly Character with Blender Tutorial of Grant Abbitt: https://www.youtube.com/user/mediagabbitt
// Character animations by Mixamo: https://www.mixamo.com/
engine.enableOfflineSupport = false
// Scene and Camera
var scene = new BABYLON.Scene(engine)
var camera1 = new BABYLON.ArcRotateCamera("camera1", Math.PI / 2, Math.PI / 4, 10, new BABYLON.Vector3(0, -5, 0), scene)
scene.activeCamera = camera1
scene.activeCamera.attachControl(canvas, true)
camera1.lowerRadiusLimit = 2
camera1.upperRadiusLimit = 10
camera1.wheelDeltaPercentage = 0.01
// Lights
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene)
light.intensity = 0.6
light.specular = BABYLON.Color3.Black()
var light2 = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -0.5, -1.0), scene)
light2.position = new BABYLON.Vector3(0, 5, 5)
// Skybox
var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", { size: 1000.0 }, scene)
var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene)
skyboxMaterial.backFaceCulling = false
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("textures/skybox2", scene)
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE
skyboxMaterial.diffuseColor = BABYLON.Color3.Black()
skyboxMaterial.specularColor = BABYLON.Color3.Black()
skybox.material = skyboxMaterial
// GUI
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI")
var instructions = new BABYLON.GUI.TextBlock()
instructions.text = "Move w/ WASD keys, B for Samba, look with the mouse"
instructions.color = "white"
instructions.fontSize = 16
instructions.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT
instructions.textVerticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM
advancedTexture.addControl(instructions)
// Ground
var ground = BABYLON.MeshBuilder.CreateGround("ground", { height: 50, width: 50, subdivisions: 4 }, scene)
var groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene)
groundMaterial.diffuseTexture = new BABYLON.Texture("textures/wood.jpg", scene)
groundMaterial.diffuseTexture.uScale = 30
groundMaterial.diffuseTexture.vScale = 30
groundMaterial.specularColor = new BABYLON.Color3(.1, .1, .1)
ground.material = groundMaterial
// Keyboard events
var inputMap = {}
scene.actionManager = new BABYLON.ActionManager(scene)
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyDownTrigger, function (evt) {
inputMap[evt.sourceEvent.key] = evt.sourceEvent.type == "keydown"
}))
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyUpTrigger, function (evt) {
inputMap[evt.sourceEvent.key] = evt.sourceEvent.type == "keydown"
}))
// 创建左侧摇杆
var leftJoystick = new BABYLON.VirtualJoystick(true)
BABYLON.VirtualJoystick.Canvas.style.zIndex = "4"
// Load hero character
BABYLON.SceneLoader.ImportMesh("", "https://assets.babylonjs.com/meshes/", "HVGirl.glb", scene, function (newMeshes, particleSystems, skeletons, animationGroups) {
var hero = newMeshes[0]
//Scale the model down
hero.scaling.scaleInPlace(0.1)
//Lock camera on the character
camera1.target = hero
//Hero character variables
var heroSpeed = 0.03
var heroSpeedBackwards = 0.01
var heroRotationSpeed = 0.1
var animating = true
const walkAnim = scene.getAnimationGroupByName("Walking")
const walkBackAnim = scene.getAnimationGroupByName("WalkingBack")
const idleAnim = scene.getAnimationGroupByName("Idle")
const sambaAnim = scene.getAnimationGroupByName("Samba")
//Rendering loop (executed for everyframe)
scene.onBeforeRenderObservable.add(() => {
if(leftJoystick.pressed){
// 计算要移动到的坐标
moveX = leftJoystick.deltaPosition.x * (engine.getDeltaTime()/1000) * -2
moveZ = leftJoystick.deltaPosition.y * (engine.getDeltaTime()/1000) * -2
// 再计算旋转方向
let angle = Math.atan2(leftJoystick.deltaPosition.x, leftJoystick.deltaPosition.y)
// 加上相机的偏转角度,这样观察的时候人物总是在正面?
angle += camera1.rotation.y
// 使用四元数代替弧度值,避免万向锥问题
let targ = BABYLON.Quaternion.FromEulerAngles(0, angle, 0)
hero.rotationQuaternion = BABYLON.Quaternion.Slerp(hero.rotationQuaternion, targ, 0.2)
hero.position.x+=moveX
hero.position.z+=moveZ
}
var keydown = false
//Manage the movements of the character (e.g. position, direction)
if (inputMap["w"]) {
hero.moveWithCollisions(hero.forward.scaleInPlace(heroSpeed))
keydown = true
}
if (inputMap["s"]) {
hero.moveWithCollisions(hero.forward.scaleInPlace(-heroSpeedBackwards))
keydown = true
}
if (inputMap["a"]) {
hero.rotate(BABYLON.Vector3.Up(), -heroRotationSpeed)
keydown = true
}
if (inputMap["d"]) {
hero.rotate(BABYLON.Vector3.Up(), heroRotationSpeed)
keydown = true
}
if (inputMap["b"]) {
keydown = true
}
//Manage animations to be played
if (keydown) {
if (!animating) {
animating = true
if (inputMap["s"]) {
//Walk backwards
walkBackAnim.start(true, 1.0, walkBackAnim.from, walkBackAnim.to, false)
}
else if
(inputMap["b"]) {
//Samba!
sambaAnim.start(true, 1.0, sambaAnim.from, sambaAnim.to, false)
}
else {
//Walk
walkAnim.start(true, 1.0, walkAnim.from, walkAnim.to, false)
}
}
}
else {
if (animating) {
//Default animation is idle when no key is down
idleAnim.start(true, 1.0, idleAnim.from, idleAnim.to, false)
//Stop all animations besides Idle Anim when no key is down
sambaAnim.stop()
walkAnim.stop()
walkBackAnim.stop()
//Ensure animation are played only once per rendering loop
animating = false
}
}
})
})
// Create button to toggle joystick overlay canvas
var btn = document.createElement("button")
btn.innerText = "Enable/Disable Joystick"
btn.style.zIndex = 10
btn.style.position = "absolute"
btn.style.bottom = "30px"
btn.style.right = "0px"
// btn.style.height = "100%"
// btn.style.width = "50%"
document.body.appendChild(btn)
// Button toggle logic
btn.onclick = ()=>{
if(BABYLON.VirtualJoystick.Canvas.style.zIndex == "-1"){
BABYLON.VirtualJoystick.Canvas.style.zIndex = "4"
}else{
BABYLON.VirtualJoystick.Canvas.style.zIndex = "-1"
}
}
// Dispose button on rerun
scene.onDisposeObservable.add(()=>{
BABYLON.VirtualJoystick.Canvas.style.zIndex = "-1"
document.body.removeChild(btn)
})
return scene
}