mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:23:54 +02:00
Bot.js NPCs wander around and make sounds
This commit is contained in:
parent
220f9fda76
commit
0a1e840d10
7 changed files with 108 additions and 39 deletions
|
@ -3,6 +3,7 @@
|
|||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/20/14.
|
||||
// Modified by Philip on 2/26/14
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// This is an example script that demonstrates an NPC avatar.
|
||||
|
@ -17,16 +18,53 @@ function getRandomInt (min, max) {
|
|||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
var CHANCE_OF_MOVING = 0.05;
|
||||
var CHANCE_OF_MOVING = 0.005;
|
||||
var CHANCE_OF_SOUND = 0.005;
|
||||
var CHANCE_OF_HEAD_TURNING = 0.05;
|
||||
var CHANCE_OF_BIG_MOVE = 0.1;
|
||||
|
||||
var isMoving = false;
|
||||
var isTurningHead = false;
|
||||
|
||||
var STARTING_RANGE = 18.0;
|
||||
var MOVE_RANGE = 1.0;
|
||||
var MAX_RANGE = 25.0;
|
||||
var MOVE_RANGE_SMALL = 0.5;
|
||||
var MOVE_RANGE_BIG = 5.0;
|
||||
var TURN_RANGE = 45.0;
|
||||
var STOP_TOLERANCE = 0.05;
|
||||
var MOVE_RATE = 0.10;
|
||||
var MOVE_RATE = 0.05;
|
||||
var TURN_RATE = 0.15;
|
||||
var PITCH_RATE = 0.20;
|
||||
var PITCH_RANGE = 30.0;
|
||||
|
||||
|
||||
var firstPosition = { x: getRandomFloat(0, STARTING_RANGE), y: 0, z: getRandomFloat(0, STARTING_RANGE) };
|
||||
var targetPosition = { x: 0, y: 0, z: 0 };
|
||||
|
||||
var targetDirection = { x: 0, y: 0, z: 0, w: 0 };
|
||||
var currentDirection = { x: 0, y: 0, z: 0, w: 0 };
|
||||
|
||||
var targetHeadPitch = 0.0;
|
||||
|
||||
var sounds = [];
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh1.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh2.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh3.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh4.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh5.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh6.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh7.raw"));
|
||||
sounds.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Vocals/sigh8.raw"));
|
||||
|
||||
// Play a random sound from a list of conversational audio clips
|
||||
function playRandomSound(position) {
|
||||
var whichSound = Math.floor((Math.random() * sounds.length) % sounds.length);
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
audioOptions.volume = 0.25 + (Math.random() * 0.75);
|
||||
audioOptions.position = position;
|
||||
Audio.playSound(sounds[whichSound], audioOptions);
|
||||
print("PlaySound " + whichSound);
|
||||
}
|
||||
|
||||
// change the avatar's position to the random one
|
||||
Avatar.position = firstPosition;
|
||||
|
@ -62,18 +100,40 @@ Avatar.billboardURL = "https://dl.dropboxusercontent.com/u/1864924/bot-billboard
|
|||
Agent.isAvatar = true;
|
||||
|
||||
function updateBehavior() {
|
||||
if (Math.random() < CHANCE_OF_SOUND) {
|
||||
playRandomSound(Avatar.position);
|
||||
}
|
||||
|
||||
if (!isTurningHead && (Math.random() < CHANCE_OF_HEAD_TURNING)) {
|
||||
targetHeadPitch = getRandomFloat(-PITCH_RANGE, PITCH_RANGE);
|
||||
isTurningHead = true;
|
||||
} else {
|
||||
Avatar.headPitch = Avatar.headPitch + (targetHeadPitch - Avatar.headPitch) * PITCH_RATE;
|
||||
if (Math.abs(Avatar.headPitch - targetHeadPitch) < STOP_TOLERANCE) {
|
||||
isTurningHead = false;
|
||||
}
|
||||
}
|
||||
if (!isMoving && (Math.random() < CHANCE_OF_MOVING)) {
|
||||
// Set new target location
|
||||
targetPosition = { x: Avatar.position.x + getRandomFloat(-MOVE_RANGE, MOVE_RANGE),
|
||||
y: Avatar.position.y,
|
||||
z: Avatar.position.z + getRandomFloat(-MOVE_RANGE, MOVE_RANGE) };
|
||||
targetDirection = Quat.multiply(Avatar.orientation, Quat.angleAxis(getRandomFloat(-TURN_RANGE, TURN_RANGE), { x:0, y:1, z:0 }));
|
||||
var front = Quat.getFront(targetDirection);
|
||||
if (Math.random() < CHANCE_OF_BIG_MOVE) {
|
||||
targetPosition = Vec3.sum(Avatar.position, Vec3.multiply(front, getRandomFloat(0.0, MOVE_RANGE_BIG)));
|
||||
} else {
|
||||
targetPosition = Vec3.sum(Avatar.position, Vec3.multiply(front, getRandomFloat(0.0, MOVE_RANGE_SMALL)));
|
||||
}
|
||||
isMoving = true;
|
||||
} else {
|
||||
|
||||
Avatar.position = Vec3.sum(Avatar.position, Vec3.multiply(Vec3.subtract(targetPosition, Avatar.position), MOVE_RATE));
|
||||
Avatar.orientation = Quat.mix(Avatar.orientation, targetDirection, TURN_RATE);
|
||||
if (Vec3.length(Vec3.subtract(Avatar.position, targetPosition)) < STOP_TOLERANCE) {
|
||||
isMoving = false;
|
||||
}
|
||||
}
|
||||
if (Vec3.length(Avatar.position) > MAX_RANGE) {
|
||||
// Don't let our happy little person get out of the cage
|
||||
isMoving = false;
|
||||
Avatar.position = { x: 0, y: 0, z: 0 };
|
||||
}
|
||||
}
|
||||
Script.willSendVisualDataCallback.connect(updateBehavior);
|
||||
|
|
|
@ -104,36 +104,7 @@ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2) {
|
|||
return glm::angleAxis(angle, axis);
|
||||
}
|
||||
|
||||
// Safe version of glm::mix; based on the code in Nick Bobick's article,
|
||||
// http://www.gamasutra.com/features/19980703/quaternions_01.htm (via Clyde,
|
||||
// https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java)
|
||||
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
|
||||
float cosa = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
|
||||
float ox = q2.x, oy = q2.y, oz = q2.z, ow = q2.w, s0, s1;
|
||||
|
||||
// adjust signs if necessary
|
||||
if (cosa < 0.0f) {
|
||||
cosa = -cosa;
|
||||
ox = -ox;
|
||||
oy = -oy;
|
||||
oz = -oz;
|
||||
ow = -ow;
|
||||
}
|
||||
|
||||
// calculate coefficients; if the angle is too close to zero, we must fall back
|
||||
// to linear interpolation
|
||||
if ((1.0f - cosa) > EPSILON) {
|
||||
float angle = acosf(cosa), sina = sinf(angle);
|
||||
s0 = sinf((1.0f - proportion) * angle) / sina;
|
||||
s1 = sinf(proportion * angle) / sina;
|
||||
|
||||
} else {
|
||||
s0 = 1.0f - proportion;
|
||||
s1 = proportion;
|
||||
}
|
||||
|
||||
return glm::normalize(glm::quat(s0 * q1.w + s1 * ow, s0 * q1.x + s1 * ox, s0 * q1.y + s1 * oy, s0 * q1.z + s1 * oz));
|
||||
}
|
||||
|
||||
glm::vec3 extractTranslation(const glm::mat4& matrix) {
|
||||
return glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]);
|
||||
|
|
|
@ -45,8 +45,6 @@ float angleBetween(const glm::vec3& v1, const glm::vec3& v2);
|
|||
|
||||
glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2);
|
||||
|
||||
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha);
|
||||
|
||||
glm::vec3 extractTranslation(const glm::mat4& matrix);
|
||||
|
||||
void setTranslation(glm::mat4& matrix, const glm::vec3& translation);
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
|
||||
#include <OctreeConstants.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <Util.h>
|
||||
#include "Quat.h"
|
||||
|
||||
|
||||
glm::quat Quat::multiply(const glm::quat& q1, const glm::quat& q2) {
|
||||
return q1 * q2;
|
||||
}
|
||||
|
@ -31,7 +33,6 @@ glm::quat Quat::inverse(const glm::quat& q) {
|
|||
return glm::inverse(q);
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 Quat::getFront(const glm::quat& orientation) {
|
||||
return orientation * IDENTITY_FRONT;
|
||||
}
|
||||
|
@ -52,3 +53,7 @@ glm::quat Quat::angleAxis(float angle, const glm::vec3& v) {
|
|||
return glm::angleAxis(angle, v);
|
||||
}
|
||||
|
||||
glm::quat Quat::mix(const glm::quat& q1, const glm::quat& q2, float alpha) {
|
||||
return safeMix(q1, q2, alpha);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ public slots:
|
|||
glm::vec3 getUp(const glm::quat& orientation);
|
||||
glm::vec3 safeEulerAngles(const glm::quat& orientation);
|
||||
glm::quat angleAxis(float angle, const glm::vec3& v);
|
||||
glm::quat mix(const glm::quat& q1, const glm::quat& q2, float alpha);
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Quat__) */
|
||||
|
|
|
@ -65,6 +65,38 @@ bool shouldDo(float desiredInterval, float deltaTime) {
|
|||
return randFloat() < deltaTime / desiredInterval;
|
||||
}
|
||||
|
||||
// Safe version of glm::mix; based on the code in Nick Bobick's article,
|
||||
// http://www.gamasutra.com/features/19980703/quaternions_01.htm (via Clyde,
|
||||
// https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java)
|
||||
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float proportion) {
|
||||
float cosa = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
|
||||
float ox = q2.x, oy = q2.y, oz = q2.z, ow = q2.w, s0, s1;
|
||||
|
||||
// adjust signs if necessary
|
||||
if (cosa < 0.0f) {
|
||||
cosa = -cosa;
|
||||
ox = -ox;
|
||||
oy = -oy;
|
||||
oz = -oz;
|
||||
ow = -ow;
|
||||
}
|
||||
|
||||
// calculate coefficients; if the angle is too close to zero, we must fall back
|
||||
// to linear interpolation
|
||||
if ((1.0f - cosa) > EPSILON) {
|
||||
float angle = acosf(cosa), sina = sinf(angle);
|
||||
s0 = sinf((1.0f - proportion) * angle) / sina;
|
||||
s1 = sinf(proportion * angle) / sina;
|
||||
|
||||
} else {
|
||||
s0 = 1.0f - proportion;
|
||||
s1 = proportion;
|
||||
}
|
||||
|
||||
return glm::normalize(glm::quat(s0 * q1.w + s1 * ow, s0 * q1.x + s1 * ox, s0 * q1.y + s1 * oy, s0 * q1.z + s1 * oz));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void outputBufferBits(const unsigned char* buffer, int length, QDebug* continuedDebug) {
|
||||
|
|
|
@ -75,6 +75,8 @@ float randFloatInRange (float min,float max);
|
|||
unsigned char randomColorValue(int minimum);
|
||||
bool randomBoolean();
|
||||
|
||||
glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha);
|
||||
|
||||
bool shouldDo(float desiredInterval, float deltaTime);
|
||||
|
||||
void outputBufferBits(const unsigned char* buffer, int length, QDebug* continuedDebug = NULL);
|
||||
|
|
Loading…
Reference in a new issue