小地图的实现
1 .直接拿一个新的相机拍摄.这里试验下多镜头的操作吧
2 .直接拿数据进行渲染,反正我们想要的仅仅是一个图表,箭头,或者自己当前位置的信息
<!DOCTYPE html>
<!-- 添加小人,使用序列图 -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
<title>Babylon - Getting Started</title>
<!-- Link to the last version of BabylonJS -->
<script src="https://preview.babylonjs.com/babylon.js"></script>
<!-- Link to the last version of BabylonJS loaders to enable loading filetypes such as .gltf -->
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
<!-- Link to pep.js to ensure pointer events work consistently in all browsers -->
<script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
<script src="../handle/cannon.js"></script>
</head>
<body>
<canvas id="renderCanvas"></canvas>
</body>
</html>
As you can see, we inserted in the <body> a <canvas> element. This <canvas> element will be the place where we'll display the result of our 3D rendering. Insert some style in the <head>:
<style>
html, body {
overflow: hidden;
width : 100%;
height : 100%;
margin : 0;
padding : 0;
}
#renderCanvas {
width : 100%;
height : 100%;
touch-action: none;
}
</style>
Now some javascript code to run our project. To begin with, insert at the end of your <body>:
<script>
window.addEventListener('DOMContentLoaded', function() {
var canvas = document.getElementById('renderCanvas');
var engine = new BABYLON.Engine(canvas, true);
var scene = function(){
var scene = new BABYLON.Scene(engine)
scene.collesionEnabled=true
scene.enablePhysics(new BABYLON.Vector3(0,-9.81,0), new BABYLON.CannonJSPlugin())
// scene.enablePhysics()
// const camera=new BABYLON.ArcRotateCamera('player',0,0,20,BABYLON.Vector3.Zero(),scene)
const camera = new BABYLON.ArcRotateCamera('arcCamera1', -Math.PI/2, Math.PI/3, 30, BABYLON.Vector3.Zero(), scene)
camera.setPosition=(new BABYLON.Vector3(50,100,100))
camera.attachControl(canvas,false)
camera.checkCollisions=true
camera.applyGravity=true
// camera.allowUpsideDown=true
// 摄像机是否可以反转、
// 有了这俩属性,会在出场以原来的角度为基础做偏转。
// camera.inertialBetaOffset=0.01
// camera.inertialAlphaOffset=0.05
// camera.inertialPanningX=0.05
// camera.inertialPanningY=0.05
// camera.inertialRadiusOffset=0.01
camera.lowerRadiusLimit=4
// 最小缩放
camera.upperRadiusLimit=20
// 最大缩放
// 不知道值的尺度参考值要怎么选
camera.lowerBetaLimit=Math.PI/6
// 这个生效了,现在摄像机不能看到头顶了
camera.upperBetaLimit=Math.PI/2
// camera.paddingDistanceLimit=1000
// 定义相机平移的最大距离,确保相机一直在场景中
// camera.useInputToRestoreState=true
camera.zoomOnFactor=500
camera.angularSensibilityX=2000
// 这样是人站着左右旋转的速度不知道为啥是反着的:值还是越小越快
camera.keysLeft=[]
camera.keysRight=[]
camera.keysUp=[]
camera.keysDown=[]
// 这样也能屏蔽键盘事件
camera.viewport=new BABYLON.Viewport(0,0,1,1)
camera.layerMask=2
// 全屏:1号相机的视口
let speed=0.1
let camera2=new BABYLON.FreeCamera('minimap',new BABYLON.Vector3(0,200,0),scene)
// 小地图的相机:这是因为地图比较小,所以地图照的是全图,单是地图比较大的话,还是照不完,或者说这样也太费算力了,其实还是传坐标现实比较优雅,或者说比较简单,高效
// 而且相机也不能用这个,还是用跟随相机比较好
// 这种相机唯一的好处就是可以看到物体升起来的效果。
camera2.setTarget(new BABYLON.Vector3(0,0,0))
camera2.viewport=new BABYLON.Viewport(0,0,1,1)
camera2.layerMask=1
// 这个要在上面
// camera2.position=new BABYLON.Vector3(camera.position.x,camera2.position.y,camera.position.z)
camera2.rotation.y=0
// 原来0就是和原来的一样的。现在要做的就是调下他的位置了。
camera2.position.x=-120
camera2.position.z=-40
// 这里调的位置是相对位置,还是不知道屏幕有多大,所以不是最贴边的,他和横纵都是有比例限制的。需要做一下计算,什么宽高比位移什么数值,还要看相机的高度,这也太多因素了吧
// 宽:1500,高:900
// 这里先试验这个值
scene.activeCamera=camera
scene.activeCameras.push(camera)
scene.activeCameras.push(camera2)
var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(0, -1, -0.3), scene);
light.position=new BABYLON.Vector3(20,60,30)
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// 把这个放到外面,别的也可以操作
shadowGenerator.getShadowMap().refreshRate=60
shadowGenerator.usePoissonSampling=true
// 添加键盘事件,控制人物行动
const dsm=new BABYLON.DeviceSourceManager(engine)
// 添加检测事件
dsm.onDeviceConnectedObservable.add((device)=>{
console.log(device)
})
const ground = BABYLON.MeshBuilder.CreateGround("ground", {height: 100, width:100, subdivisions: 4},scene);
const player = BABYLON.Mesh.CreateBox('box', 2.0, scene)
player.checkCollisions = true
player.position.y=0
player.physicsImpostor = new BABYLON.PhysicsImpostor(player, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 2, friction: 0.0, restitution: 0 }, scene);
// 去掉地面的碰撞反弹力
ground.physicsImpostor = new BABYLON.PhysicsImpostor(ground, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 0.0, restitution: 0}, scene);
const Material = new BABYLON.StandardMaterial('material', scene)
Material.emissiveColor = new BABYLON.Color3(0, 0.58, 0.86)
player.material = Material
camera.setTarget(player)
let isJump=false
scene.registerBeforeRender(()=>{
let cameraForwardRayPosition=camera.getForwardRay().direction
let cameraForwardRayPositionWithoutY=new BABYLON.Vector3(cameraForwardRayPosition.x,0,cameraForwardRayPosition.z)
// 沿Y轴旋转的人的视角,如果脑袋还能转的话,这里的角度应该更加丰富。一般的fps游戏是可以低头捡底面的装备的,第一人称
player.lookAt(player.position.add(cameraForwardRayPositionWithoutY),0,0,0)
// 摄像机旋转,人先旋转,不管走不走吧。其实这里应该播个动画就好了
if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard)){
if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(65) == 1){
// 应该向左移动
player.locallyTranslate(new BABYLON.Vector3(-speed,0,0))
}else if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(32)==1){
// 按下space,跳.
// 碰撞到底面的时候可以再次响应按键
if(!isJump){
player.physicsImpostor.applyImpulse(new BABYLON.Vector3(0, 5, 0), player.getAbsolutePosition())
isJump=true
}
// player.locallyTranslate(new BABYLON.Vector3(0,speed,0))
// 这种效果实现跳也看起来挺自然的
}else if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(70)==1){
// f键
player.physicsImpostor.applyImpulse(new BABYLON.Vector3(0,0.17,0),player.getAbsolutePosition())
scene.getPhysicsEngine().setGravity(new BABYLON.Vector3(0,0,0))
let v2=BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(0,0.02,0),BABYLON.Matrix.RotationY(player.rotation.y))
player.position.addInPlace(v2)
// let v2=new BABYLON.Vector3(0,0.02,0)
// player.position.y+=1
// 这样是不行的,就算加到了,也会掉下来,一直按还会加速。。
// 自己在一直上升。为什么松开键还是会一直加呢?
}else if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(71)==1){
// G:点击下降
// 这个反应就贼慢,不知道为啥,明明是和他相反的操作啊
player.physicsImpostor.applyImpulse(new BABYLON.Vector3(0,-0.17,0),player.getAbsolutePosition())
scene.getPhysicsEngine().setGravity(new BABYLON.Vector3(0,-0.98,0))
let v2=BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(0,-0.02,0),BABYLON.Matrix.RotationY(player.rotation.y))
player.position.addInPlace(v2)
}else if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(87)==1){
// w键,前进
player.locallyTranslate(new BABYLON.Vector3(0,0,speed))
}else if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(83)==1){
// s:后退
player.locallyTranslate(new BABYLON.Vector3(0,0,-speed))
}else if(dsm.getDeviceSource(BABYLON.DeviceType.Keyboard).getInput(68)==1){
player.locallyTranslate(new BABYLON.Vector3(speed,0,0))
}
}
// 两个键一起按下怎么做检测呢。。
if(player.position.y>=5){
player.position.y=5
// 这里先简单做一个高度限制
}
})
// 需要一个键松开的参数:我这里想要的是松开就暂停。现在松开也是会一直上升的
player.onCollision=function(e){
console.log('click')
}
let groundMat=new BABYLON.StandardMaterial('groundMat',scene)
groundMat.diffuseTexture=new BABYLON.Texture('http://192.168.1.102:8080/source/image/ground.jpg')
groundMat.diffuseTexture.uScale=6
groundMat.diffuseTexture.vScale=6
groundMat.specularColor=new BABYLON.Color3(0,0,0)
groundMat.emissiveColor=new BABYLON.Color3(0.3,0.3,0.3,0.3)
ground.material=groundMat
ground.receiveShadows=true
ground.checkCollisions=true
ground.position.y=-2
ground.position.x = -28
return scene;
}()
engine.runRenderLoop(function() {
scene.render();
});
window.addEventListener('resize', function() {
engine.resize();
});
});
</script>