From 61f4009b22ba9687d11b95595336fe897deaf006 Mon Sep 17 00:00:00 2001 From: PhilipRosedale Date: Thu, 7 Apr 2016 18:03:45 -0700 Subject: [PATCH 1/2] Simple golfclub that makes and jumps to balls --- examples/golfclub/golfClub.js | 133 ++++++++++++++++++++++++++++++++ examples/golfclub/golfClub.json | 36 +++++++++ 2 files changed, 169 insertions(+) create mode 100644 examples/golfclub/golfClub.js create mode 100644 examples/golfclub/golfClub.json diff --git a/examples/golfclub/golfClub.js b/examples/golfclub/golfClub.js new file mode 100644 index 0000000000..f034398d90 --- /dev/null +++ b/examples/golfclub/golfClub.js @@ -0,0 +1,133 @@ +// +// golfClub.js +// +// Created by Philip Rosedale on 11/11/15. +// Copyright 2015 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 HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + var collisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/Collisions-ballhitsandcatches/billiards/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 TRIGGER_CONTROLS = [ + Controller.Standard.LT, + Controller.Standard.RT, + ]; + +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); + if (!properties) { + return null; + } else { + return properties.position; + } +} + +function gotoPointOnGround(position, away) { + // Position yourself facing in the direction you were originally facing, but with a + // point on the ground *away* meters from *position* and in front of you. + + var offset = Quat.getFront(MyAvatar.orientation); + offset.y = 0.0; + offset = Vec3.multiply(-away, Vec3.normalize(offset)); + var newAvatarPosition = Vec3.sum(position, offset); + + // Assuming position is on ground, put me distance from eyes to hips higher, plus a 50% adjust for longer legs. + // TODO: Need avatar callback for exact foot-to-hips height. + + var halfHeight = avatarHalfHeight(); + print("Height = " + halfHeight); + newAvatarPosition.y += (halfHeight * 1.5); + MyAvatar.position = newAvatarPosition; +} + +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); + 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) { + // Create a new sphere entity + ball = Entities.addEntity({ + type: "Sphere", + position: position, + color: { red: 255, green: 255, blue: 255 }, + 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, + collisionSoundURL: collisionSoundURL + }); +} + +function checkClub(params) { + var hand = params[0] == "left" ? 0 : 1; + var makeNewBall = false; + if (triggerPulled(hand)) { + // If trigger just pulled, either drop new ball or go to existing one + var position = ballPosition(ball); + if (position && (Vec3.distance(MyAvatar.position, position) < BALL_MAX_RANGE)) { + gotoPointOnGround(position, BALL_DROP_DISTANCE); + } else { + Entities.deleteEntity(ball); + makeBall(inFrontOfMe()); + } + } + brakeBall(ball); +} + +this.continueEquip = function(id, params) { + // While holding the club, continuously check for trigger pull and brake ball if moving. + checkClub(params); +} + +}); diff --git a/examples/golfclub/golfClub.json b/examples/golfclub/golfClub.json new file mode 100644 index 0000000000..b6096dd698 --- /dev/null +++ b/examples/golfclub/golfClub.json @@ -0,0 +1,36 @@ +{ + "Entities": [ + { + "collisionsWillMove": 1, + "compoundShapeURL": "http://hifi-content.s3.amazonaws.com/caitlyn/dev/Tutorials/Putter_phys.obj", + "created": "2016-04-07T23:19:30Z", + "description": "Spawns ball or jumps to ball with trigger", + "dimensions": { + "x": 0.043093059211969376, + "y": 1.1488667726516724, + "z": 0.42455694079399109 + }, + "dynamic": 1, + "id": "{266a9bc2-cff5-4128-b347-5eab519d8209}", + "modelURL": "http://hifi-content.s3.amazonaws.com/caitlyn/dev/Tutorials/putter_VR.fbx", + "name": "Golf Putter", + "queryAACube": { + "scale": 1.2255613803863525, + "x": -0.61278069019317627, + "y": -0.61278069019317627, + "z": -0.61278069019317627 + }, + "rotation": { + "w": 0.41972994804382324, + "x": 0.78570234775543213, + "y": -0.41875332593917847, + "z": 0.17653167247772217 + }, + "script": "https://s3.amazonaws.com/hifi-public/philip/golfClub.js", + "shapeType": "compound", + "type": "Model", + "userData": "{\"wearable\":{\"joints\":{\"LeftHand\":[{\"x\":-0.1631782054901123,\"y\":0.44648152589797974,\"z\":0.10100018978118896},{\"x\":-0.9181621670722961,\"y\":-0.0772884339094162,\"z\":-0.3870723247528076,\"w\":-0.0343472845852375}],\"RightHand\":[{\"x\":0.16826771199703217,\"y\":0.4757269620895386,\"z\":0.07139724493026733},{\"x\":-0.7976328134536743,\"y\":-0.0011603273451328278,\"z\":0.6030101776123047,\"w\":-0.012610925361514091}]}}}" + } + ], + "Version": 57 +} From aab93d8a267824928f34dba969ea3a750130d192 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 11 Apr 2016 10:46:22 -0700 Subject: [PATCH 2/2] fixes per code review --- examples/golfclub/golfClub.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/golfclub/golfClub.js b/examples/golfclub/golfClub.js index f034398d90..eecca891a4 100644 --- a/examples/golfclub/golfClub.js +++ b/examples/golfclub/golfClub.js @@ -1,7 +1,7 @@ // // golfClub.js // -// Created by Philip Rosedale on 11/11/15. +// Created by Philip Rosedale on April 11, 2016. // Copyright 2015 High Fidelity, Inc. // // @@ -46,7 +46,7 @@ function triggerPulled(hand) { function ballPosition(ball) { // return the position of this entity - var properties = Entities.getEntityProperties(ball); + var properties = Entities.getEntityProperties(ball, ['position']); if (!properties) { return null; } else { @@ -82,7 +82,7 @@ function avatarHalfHeight() { function brakeBall(ball) { // Check the ball's velocity and slow it down if beyond a threshold - var properties = Entities.getEntityProperties(ball); + var properties = Entities.getEntityProperties(ball, ['velocity']); if (properties) { var velocity = Vec3.length(properties.velocity); if ((velocity > 0) && (velocity < MAX_BRAKING_SPEED)) {