本次尝试,模拟了一个小人物在场景中行走,使用简单模型建立了森林,图片纹理模拟草地,加载3D模型呈现人物,使用按键asdw模拟人物的行走,行走和站立时人物的切换等。

主要用到点:3D模型的加载,模型的动画(行走与站立)之间的切换。

不足之处:没有检测碰撞与边界。

需要注意的是,代码需要运行在服务器端,切记。

代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
</style>
<title>测试</title>
<script src="../js/three.js"></script>
<script src="../js/dat.gui.min.js"></script>
<script src="../js/OrbitControls.js"></script>
<script src="../js/util.js"></script>
<script src="../js/GLTFLoader.js"></script>
</head>
<body>
<script>
var scene, camera, renderer, controls, flag = 1;
var target;
var trees; // 荧光棒
var role; // 主角
var textPlane;
var stateList = {};
var actionMap = {
up: { direction: 'up', rotation: Math.PI, axes: 'z' },
down: { direction: 'down', rotation: 0, axes: 'z' },
left: { direction: 'left', rotation: - Math.PI / 2, axes: 'x' },
right: { direction: 'right', rotation: Math.PI / 2, axes: 'x' }
};
var nopeAction = { direction: null };
var nextAction = { direction: 'down', rotation: 0 };
var clock, mixer, currentAction, previousAction, lastkey;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 500);
camera.position.z = 20;
camera.lookAt(scene.position);
scene.add(camera);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.update();
clock = new THREE.Clock();
window.addEventListener('resize', onWindowResize, false);
var axesHelper = new THREE.AxesHelper(50);
scene.add(axesHelper);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
}
function run() {
init();
createRole(); //创建角色
createAmbientLight(); // 绘制环境光
// createSpotlist(new THREE.Vector3(50, 50, 50), role);
createPlane(); // 创建舞台平面
createTrees(20);
window.addEventListener('keydown', keyPressed, false);
window.addEventListener('keyup', keyUp, false)
render();
}
function render() {
var dt = clock.getDelta();
if (mixer) mixer.update(dt);
requestAnimationFrame(render);
controls.update();
handleRoleAction();
renderer.render(scene, camera);
}
run();
function createAmbientLight() {
var light = new THREE.AmbientLight(0xdddddd); // soft white light
scene.add(light);
}
function createPlane() {
//Create a plane that receives shadows (but does not cast them)
var planeGeometry = new THREE.PlaneBufferGeometry(1000, 1000);
var texture = new THREE.TextureLoader().load('../images/grasslight-big.jpg');
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(25, 25);
var planeMaterial = new THREE.MeshStandardMaterial({ map: texture, side: THREE.DoubleSide });
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
plane.position.y = -16;
plane.receiveShadow = true;
scene.add(plane);
}
function createSpotlist(Vector3, target) {
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(Vector3.x, Vector3.y, Vector3.z);
spotLight.castShadow = true;
spotLight.angle = Math.PI / 18;
spotLight.shadow.mapSize.width = 512;
spotLight.shadow.mapSize.height = 512;
spotLight.shadow.camera.near = 0.5;
spotLight.shadow.camera.far = 500;
spotLight.shadow.camera.fov = 30;
spotLight.target = target;
scene.add(spotLight);
// Create a helper for the spotlight
// var helper = new THREE.SpotLightHelper(spotLight);
// scene.add(helper);
// //Create a helper for the shadow camera (optional)
// var helper = new THREE.CameraHelper(spotLight.shadow.camera);
// scene.add(helper);
}
function createTrees(num) {
for (let i = 0; i < num; i++) {
let treeNode = new THREE.Object3D();
var treeTopGeo = new THREE.CylinderGeometry(0, 10, 20, 32);
var treeTopMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
var treeTop = new THREE.Mesh(treeTopGeo, treeTopMaterial);
treeTop.position.y = 4; // 树底部中心点高度是-11,底部的上边高度是-6,这样树顶部中心点高度默认是0的话,下边是-10,如果想让下边高度为-6,则中心点高度为4
var treeBottomGeo = new THREE.CylinderGeometry(5, 5, 10, 32);
var treeBottomMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
var treeBottom = new THREE.Mesh(treeBottomGeo, treeBottomMaterial);
treeBottom.position.y = -11; // 底面位置是-16,底部圆柱体中心点高度默认是0的话,底边高度是-5,所以将position.y设置为-11,这样下边高度是-16
treeNode.add(treeTop);
treeNode.add(treeBottom);
treeNode.position.set(util.createRandomPos(-250, 250), 0, util.createRandomPos(-250, 250));
scene.add(treeNode);
}
}
function createRole() {
// model
var loader = new THREE.GLTFLoader();
loader.load('../models/RobotExpressive.glb', function (gltf) {
role = gltf.scene;
role.position.y = -16;
mixer = new THREE.AnimationMixer(role);
stateList.Walking = mixer.clipAction(gltf.animations[10]);
stateList.Standing = mixer.clipAction(gltf.animations[8]);
// 设置下面两项主要是站着的时候,别抖了
stateList.Standing.clampWhenFinished = true;
stateList.Standing.loop = THREE.LoopOnce;
currentAction = stateList.Standing;
currentAction.play();
scene.add(role);
createSpotlist(new THREE.Vector3(50, 50, 50), role);
}, undefined, function (e) {
console.error(e);
});
}
function keyPressed(e) {
var key = event.keyCode;
if (lastkey != key) {
lastkey = key;
fadeToAction('Walking', 0.2);
}
switch (key) {
case 87:
/*w*/
nextAction = actionMap.up;
break;
case 65:
/*a*/
nextAction = actionMap.left;
break;
case 83:
/*s*/
nextAction = actionMap.down;
break;
case 68:
/*d*/
nextAction = actionMap.right;
break;
}
if (role) role.rotation.y = nextAction.rotation;
}
function keyUp() {
lastkey = null;
nextAction = nopeAction;
fadeToAction('Standing', 0.2);
}
function handleRoleAction() {
if (role) {
if (nextAction.direction == 'down' || nextAction.direction == "right") {
flag = 1;
} else if (nextAction.direction == 'up' || nextAction.direction == "left") {
flag = -1;
}
else {
flag = 0;
}
role.position[nextAction.axes] += 0.2 * flag;
}
}
function fadeToAction(name, duration) {
previousAction = currentAction;
currentAction = stateList[name];
if (previousAction !== currentAction) {
previousAction.fadeOut(duration);
}
if (currentAction) {
currentAction
.reset()
.setEffectiveTimeScale(1)
.setEffectiveWeight(1)
.fadeIn(duration)
.play();
}
}
</script>
</body>
</html>
附上github链接:https://github.com/liujiekun/threeJS记得在服务端启动,直接浏览器运行是看不到图片、纹理以及动画原型的。

three.js尝试(二)模拟游戏开发:3D人物在地图上行走的更多相关文章

  1. 喵的Unity游戏开发之路 - 在球体上行走

    很多童鞋没有系统的Unity3D游戏开发基础,也不知道从何开始学.为此我们精选了一套国外优秀的Unity3D游戏开发教程,翻译整理后放送给大家,教您从零开始一步一步掌握Unity3D游戏开发. 本文不 ...

  2. 拜托,使用Three.js让二维图片具有3D效果超酷的好吗 💥

    声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 背景 逛 sketchfab 网站的时候我看到有很多二维平面转 3D 的模型例子 ...

  3. [Unity3D]Unity3D游戏开发3D选择场景中的对象,并显示轮廓效果强化版

    大家好,我是秦培,欢迎关注我的博客,我的博客地址blog.csdn.net/qinyuanpei. 在上一篇文章中,我们通过自己定义着色器实现了一个简单的在3D游戏中选取.显示物体轮廓的实例. 在文章 ...

  4. 【游戏开发】小白学Lua(上)

    在很多游戏中,脚本语言是不可或缺的一部分,很多游戏都使用到了Lua,js,python一类的脚本,脚本语言可以在很多方面给开发进程带来帮助.脚本语言可以作为初始化文件读入变量和游戏数据的一个快速而方便 ...

  5. html5游戏开发--"动静"结合用地图块拼成大地图 & 初探lufyl

    一.前言   本次教程将向大家讲解如何用html5将小地图块拼成大地图,以及如何用现有的高级html5游戏开发库件lufylegend.js开发游戏.   首先让我们来了解了解如何用html5实现动画 ...

  6. Unity游戏开发--30s制作精美地图

    "君子生非异也.善假于物也"--<劝学>荀子 引用这句话的目的,是我觉得有时候.利用工具来提高游戏开发效率是很必要的. 利用工具,解放程序员双手. 今天想给大家介绍下. ...

  7. three.js尝试(一)模拟演唱会效果

    工作闲暇之余,偶然翻到了Three.js的官网,立刻被它酷炫的案例给惊艳到了,当即下定决心要试验摸索一番,于是看demo,尝试,踩坑,解决问题,终于搞定了,一个模拟演唱会场景. 主角围绕一个钢管在舞动 ...

  8. 游戏开发3D基础知识

    概念学习: 向量 向量简介 我们将所有彼此平行的向量进行平移,使其起点与坐标原点重合,当某一向量的起始端与坐标原点重合,我们成该向量处于标准位置.这样,我们就可用向量的终点坐标来描述一个处于标准位置的 ...

  9. 从一点儿不会开始——Unity3D游戏开发学习(一)

    一些废话 我是一个windows phone.windows 8的忠实粉丝,也是一个开发者,开发数个windows phone应用和两个windows 8应用.对开发游戏一直抱有强烈兴趣和愿望,但奈何 ...

随机推荐

  1. RxJS 中的观察者和迭代器模式

    目录 前言 观察者模式 迭代器模式 RxJS 中两种模式的结合和实现 小结 参考 1. 前言 RxJS 是一个库,它通过使用observable(可观察对象)序列来编写异步和基于事件的程序.其结合了观 ...

  2. 测试面试题集锦(四)| Linux 与 Python 编程篇(附答案)

    本文为霍格沃兹测试学院学员学习笔记. 本系列文章总结归纳了一些软件测试工程师常见的面试题,主要来源于个人面试遇到的.网络搜集(完善).工作日常讨论等,分为以下十个部分,供大家参考.如有错误的地方,欢迎 ...

  3. C#设计模式之19-观察者模式

    观察者模式(Observer Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/423 访问. 观察者模式 ...

  4. Flutter 打包程序 build android apk

    Step-1 Java 路径 找到java路径, 可使用[flutter doctor -v] Step-2: 进入目录 找到路径后 C:\Program Files\Java\jre1.8.0_23 ...

  5. Azure Application Gateway(二)对后端 VM 进行负载均衡

    一,引言 上一节有讲到使用 Azure Application Gateway 为我们后端类型为 Web App 的 Demo 项目提供负载均衡,Azure Application Gateway 的 ...

  6. run as --> Maven clean 可以清除旧的jar包

    run as --> Maven clean 可以清除旧的jar包

  7. 下面POM插件的作用是转换包名,修改tomcat跳转端口

    <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat6-mave ...

  8. 《Java从入门到失业》第一章:计算机基础知识(三):程序语言简介

    1.3程序语言简介 我们经常会听到一些名词:低级语言.高级语言.编译型.解释型.面向过程.面向对象等.这些到底是啥意思呢?在正式进入Java世界前,笔者也尝试简单的聊一聊这块东西. 1.3.1低级语言 ...

  9. Wireshark中遇到的epoch time

    使用Wireshark分析DNS时遇到的Epoch time 首先看一下Wireshark分析DNS的情况(如下图): 这是协议树的第一项,第一项中的第五行出现了Epoch Time,查阅资料之后才知 ...

  10. 使用IDEA连接mysql后不显示表的解决方案

    使用idea连接mysql后显示如下: 没有显示我们要看的数据表.?????????? 解决方法: 点设置: 选择要看的数据库名称,保存后就OK了.