172 lines
6.5 KiB
JavaScript
172 lines
6.5 KiB
JavaScript
//
|
|
// golfClub.js
|
|
//
|
|
// Created by Philip Rosedale on April 11, 2016.
|
|
// Some modifications by Thijs Wenker on Octobre 14, 2016
|
|
// Copyright 2016 High Fidelity, Inc.
|
|
//
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
// A simple golf club. If you have equipped it, and pull trigger, it will either make
|
|
// you a new golf ball, or take you to your ball if one is not made.
|
|
|
|
(function() {
|
|
var ball = null;
|
|
var collisionSoundURL = "http://hifi-production.s3.amazonaws.com/tutorials/golfClub/collision1.wav";
|
|
var triggerState = false;
|
|
var BALL_GRAVITY = -9.8;
|
|
var BALL_START_VELOCITY = 0.1;
|
|
var BALL_MAX_RANGE = 10;
|
|
var BALL_DROP_DISTANCE = 0.6;
|
|
var BALL_DIAMETER = 0.07;
|
|
var BALL_LIFETIME = 3600;
|
|
var MAX_BRAKING_SPEED = 0.2;
|
|
var BALL_BRAKING_RATE = 0.5;
|
|
var CLIENT_ONLY_BALL = false;
|
|
|
|
var TRIGGER_CONTROLS = [
|
|
Controller.Standard.LT,
|
|
Controller.Standard.RT,
|
|
];
|
|
|
|
function lowercaseFirstLetter(capitalizedString) {
|
|
return capitalizedString.charAt(0).toLowerCase() + capitalizedString.slice(1);
|
|
}
|
|
|
|
// http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
|
|
function hexToRgb(hex) {
|
|
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
|
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
|
|
return r + r + g + g + b + b;
|
|
});
|
|
|
|
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
return result ? {
|
|
red: parseInt(result[1], 16),
|
|
green: parseInt(result[2], 16),
|
|
blue: parseInt(result[3], 16)
|
|
} : null;
|
|
}
|
|
|
|
function triggerPulled(hand) {
|
|
// Return true if the trigger has just been pulled
|
|
var triggerValue = Controller.getValue(TRIGGER_CONTROLS[hand]);
|
|
var oldTriggerState = triggerState;
|
|
var TRIGGER_PULL_THRESHOLD = 0.5;
|
|
var TRIGGER_RELEASE_THRESHOLD = 0.4;
|
|
if (triggerValue > TRIGGER_PULL_THRESHOLD) {
|
|
triggerState = true;
|
|
} else if (triggerValue < TRIGGER_RELEASE_THRESHOLD) {
|
|
triggerState = false;
|
|
}
|
|
return (triggerState && (oldTriggerState != triggerState));
|
|
}
|
|
|
|
function ballPosition(ball) {
|
|
// return the position of this entity
|
|
var properties = Entities.getEntityProperties(ball, ['position']);
|
|
if (!properties) {
|
|
return null;
|
|
} else {
|
|
return properties.position;
|
|
}
|
|
}
|
|
|
|
function ballModel(clubID) {
|
|
try {
|
|
return JSON.parse(Entities.getEntityProperties(clubID, ['userData']).userData).ballModel;
|
|
} catch (e) { }
|
|
return null;
|
|
}
|
|
|
|
function inFrontOfMe() {
|
|
return Vec3.sum(MyAvatar.position, Vec3.multiply(BALL_DROP_DISTANCE, Quat.getFront(MyAvatar.orientation)));
|
|
}
|
|
|
|
function avatarHalfHeight() {
|
|
return MyAvatar.getDefaultEyePosition().y - MyAvatar.position.y;
|
|
}
|
|
|
|
function brakeBall(ball) {
|
|
// Check the ball's velocity and slow it down if beyond a threshold
|
|
var properties = Entities.getEntityProperties(ball, ['velocity']);
|
|
if (properties) {
|
|
var velocity = Vec3.length(properties.velocity);
|
|
if ((velocity > 0) && (velocity < MAX_BRAKING_SPEED)) {
|
|
Entities.editEntity(ball, {
|
|
velocity: Vec3.multiply(BALL_BRAKING_RATE, properties.velocity)
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function makeBall(position, color) {
|
|
var firstLowerCaseColor = lowercaseFirstLetter(color);
|
|
// Create a new sphere entity
|
|
ball = Entities.addEntity({
|
|
type: 'Model',
|
|
position: position,
|
|
name: 'Ball - ' + color,
|
|
dimensions: {
|
|
x: BALL_DIAMETER,
|
|
y: BALL_DIAMETER,
|
|
z: BALL_DIAMETER
|
|
},
|
|
gravity: {
|
|
x: 0,
|
|
y: BALL_GRAVITY,
|
|
z: 0
|
|
},
|
|
velocity: {
|
|
x: 0,
|
|
y: BALL_START_VELOCITY,
|
|
z: 0
|
|
},
|
|
friction: 0.5,
|
|
restitution: 0.5,
|
|
shapeType: 'sphere',
|
|
dynamic: true,
|
|
lifetime: BALL_LIFETIME,
|
|
collisionsWillMove: true,
|
|
modelURL: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/minigolf%20course/putters/newBall.fbx',
|
|
textures: JSON.stringify({
|
|
file4: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/minigolf course/putters/ball_' + firstLowerCaseColor + '.png',
|
|
file5: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/minigolf course/putters/newBall.fbx/C:/Users/User/Documents/Substance Painter 2/export/lambert1_Normal_OpenGL.png',
|
|
file6: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/minigolf course/putters/newBall.fbx/C:/Users/User/Documents/Substance Painter 2/export/lambert1_Metallic.png',
|
|
file7: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/minigolf course/putters/newBall.fbx/C:/Users/User/Documents/Substance Painter 2/export/lambert1_Roughness.png',
|
|
file8: 'http://hifi-content.s3.amazonaws.com/caitlyn/production/minigolf course/putters/newBall.fbx/C:/Users/User/Documents/Substance Painter 2/export/lambert1_Ambient_occlusion.png'
|
|
}),
|
|
collisionSoundURL: collisionSoundURL
|
|
}, CLIENT_ONLY_BALL);
|
|
}
|
|
|
|
function checkClub(clubID, params) {
|
|
var hand = params[0] == "left" ? 0 : 1;
|
|
var makeNewBall = false;
|
|
if (triggerPulled(hand)) {
|
|
// If trigger just pulled, either drop new ball
|
|
if (ball !== null) {
|
|
Entities.deleteEntity(ball);
|
|
}
|
|
makeBall(inFrontOfMe(), ballModel(clubID));
|
|
}
|
|
brakeBall(ball);
|
|
}
|
|
|
|
this.continueEquip = function(id, params) {
|
|
// While holding the club, continuously check for trigger pull and brake ball if moving.
|
|
checkClub(id, params);
|
|
}
|
|
|
|
this.startEquip = function(id, params) {
|
|
var hand = params[0];
|
|
Messages.sendLocalMessage('Hifi-Teleport-Disabler', hand);
|
|
}
|
|
|
|
this.release = function() {
|
|
Messages.sendLocalMessage('Hifi-Teleport-Disabler', 'none');
|
|
}
|
|
});
|