From 39a1b9e75d74de4c7df246b5ca0d775e8287b914 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 26 Apr 2016 11:21:56 -0700 Subject: [PATCH] update script/tutorials --- scripts/tutorials/createCow.js | 82 +-- scripts/tutorials/createDice.js | 20 +- scripts/tutorials/createPistol.js | 97 ++- scripts/tutorials/entity_scripts/cow.js | 60 +- scripts/tutorials/entity_scripts/pistol.js | 765 +++++++++------------ scripts/tutorials/makeAvatarClap.js | 163 +---- 6 files changed, 508 insertions(+), 679 deletions(-) diff --git a/scripts/tutorials/createCow.js b/scripts/tutorials/createCow.js index 7ff59b2e38..7446aa0fd0 100644 --- a/scripts/tutorials/createCow.js +++ b/scripts/tutorials/createCow.js @@ -1,6 +1,3 @@ - -// cowSpawner.js -// examples/cows // // Created by Eric Levin on 3/25/16 // Copyright 2016 High Fidelity, Inc. @@ -11,43 +8,48 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - var orientation = MyAvatar.orientation; - orientation = Quat.safeEulerAngles(orientation); - orientation.x = 0; - orientation = Quat.fromVec3Degrees(orientation); - var center = Vec3.sum(MyAvatar.getHeadPosition(), Vec3.multiply(2, Quat.getFront(orientation))); +// references to our assets. entity scripts need to be served from somewhere that is publically accessible -- so http(s) or atp +var SCRIPT_URL ="http://hifi-production.s3.amazonaws.com/tutorials/entity_scripts/cow.js"; +var MODEL_URL = "http://hifi-production.s3.amazonaws.com/tutorials/cow/cow.fbx"; +var ANIMATION_URL = 'http://hifi-production.s3.amazonaws.com/tutorials/cow/cow.fbx'; +// this part of the code describes how to center the entity in front of your avatar when it is created. +var orientation = MyAvatar.orientation; +orientation = Quat.safeEulerAngles(orientation); +orientation.x = 0; +orientation = Quat.fromVec3Degrees(orientation); +var center = Vec3.sum(MyAvatar.getHeadPosition(), Vec3.multiply(2, Quat.getFront(orientation))); - var SCRIPT_URL = Script.resolvePath("cowEntityScript.js?"); - var cow = Entities.addEntity({ - type: "Model", - modelURL: "http://hifi-content.s3.amazonaws.com/DomainContent/production/cow/newMooCow.fbx", - name: "playa_model_throwinCow", - position: center, - animation: { - currentFrame: 278, - running: true, - url: "http://hifi-content.s3.amazonaws.com/DomainContent/Junkyard/Playa/newMooCow.fbx" - }, - dimensions: { - x: 0.739, - y: 1.613, - z: 2.529 - }, - dynamic: true, - gravity: { - x: 0, - y: -5, - z: 0 - }, - shapeType: "box", - script: SCRIPT_URL, - userData: "{\"grabbableKey\":{\"grabbable\":true}}" - }); +// An entity is described and created by specifying a map of properties +var cow = Entities.addEntity({ + type: "Model", + modelURL: MODEL_URL, + name: "example_cow", + position: center, + animation: { + currentFrame: 278, + running: true, + url: ANIMATION_URL + }, + dimensions: { + x: 0.739, + y: 1.613, + z: 2.529 + }, + dynamic: true, + gravity: { + x: 0, + y: -5, + z: 0 + }, + lifetime: 3600, + shapeType: "box", + script: SCRIPT_URL, + userData: JSON.stringify({ + grabbableKey: { + grabbable: true + } + }) +}); - - function cleanup() { - Entities.deleteEntity(cow); - } - - Script.scriptEnding.connect(cleanup); +Script.stop(); \ No newline at end of file diff --git a/scripts/tutorials/createDice.js b/scripts/tutorials/createDice.js index f687a3823b..3d45d00bc8 100644 --- a/scripts/tutorials/createDice.js +++ b/scripts/tutorials/createDice.js @@ -21,9 +21,7 @@ var DIE_SIZE = 0.20; var madeSound = true; // Set false at start of throw to look for collision -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -SoundCache.getSound("http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav"); - +SoundCache.getSound("http://hifi-production.s3.amazonaws.com/tutorials/dice/diceCollide.wav"); var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to create new objects." @@ -32,17 +30,19 @@ var screenSize = Controller.getViewportDimensions(); var BUTTON_SIZE = 32; var PADDING = 3; -Script.include(["libraries/toolBars.js"]); +//a helper library for creating toolbars +Script.include(["../default/libraries/toolBars.js"]); var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL, "highfidelity.dice.toolbar", function(screenSize) { return { x: (screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING), y: (screenSize.y - (BUTTON_SIZE + PADDING)) }; }); + var offButton = toolBar.addOverlay("image", { width: BUTTON_SIZE, height: BUTTON_SIZE, - imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", + imageURL: "http://hifi-production.s3.amazonaws.com/tutorials/dice/close.png", color: { red: 255, green: 255, @@ -56,7 +56,7 @@ var deleteButton = toolBar.addOverlay("image", { y: screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, height: BUTTON_SIZE, - imageURL: HIFI_PUBLIC_BUCKET + "images/delete.png", + imageURL: "http://hifi-production.s3.amazonaws.com/tutorials/dice/delete.png", color: { red: 255, green: 255, @@ -65,7 +65,7 @@ var deleteButton = toolBar.addOverlay("image", { alpha: 1 }); -var diceIconURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/images/dice.png" +var diceIconURL = "http://hifi-production.s3.amazonaws.com/tutorials/dice/dice.png" var diceButton = toolBar.addOverlay("image", { x: screenSize.x / 2 + PADDING, y: screenSize.y - (BUTTON_SIZE + PADDING), @@ -94,7 +94,7 @@ function shootDice(position, velocity) { for (var i = 0; i < NUMBER_OF_DICE; i++) { dice.push(Entities.addEntity({ type: "Model", - modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx", + modelURL: "http://hifi-production.s3.amazonaws.com/tutorials/dice/goldDie.fbx", position: position, velocity: velocity, rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), @@ -111,7 +111,7 @@ function shootDice(position, velocity) { lifetime: LIFETIME, shapeType: "box", dynamic: true, - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav" + collisionSoundURL: "http://hifi-production.s3.amazonaws.com/tutorials/dice/diceCollide.wav" })); position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); } @@ -151,4 +151,4 @@ function scriptEnding() { } Controller.mousePressEvent.connect(mousePressEvent); -Script.scriptEnding.connect(scriptEnding); +Script.scriptEnding.connect(scriptEnding); \ No newline at end of file diff --git a/scripts/tutorials/createPistol.js b/scripts/tutorials/createPistol.js index 2a5a72096f..ae2f398840 100644 --- a/scripts/tutorials/createPistol.js +++ b/scripts/tutorials/createPistol.js @@ -1,37 +1,74 @@ // -// Rat.js -// examples/toybox/entityScripts +// Copyright 2016 High Fidelity, Inc. // -// Created by Eric Levin on11/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 -/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ +// + +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1.5, Quat.getFront(Camera.getOrientation()))); +var SCRIPT_URL = "http://hifi-production.s3.amazonaws.com/tutorials/entity_scripts/pistol.js"; +var MODEL_URL = "http://hifi-production.s3.amazonaws.com/tutorials/pistol/gun.fbx"; +var COLLISION_SOUND_URL = 'http://hifi-production.s3.amazonaws.com/tutorials/pistol/drop.wav' + +var pistolProperties = { + type: 'Model', + modelURL: MODEL_URL, + position: center, + dimensions: { + x: 0.05, + y: 0.23, + z: 0.36 + }, + script: SCRIPT_URL, + color: { + red: 200, + green: 0, + blue: 20 + }, + shapeType: 'box', + dynamic: true, + gravity: { + x: 0, + y: -5.0, + z: 0 + }, + lifetime: 3600, + restitution: 0, + damping: 0.5, + collisionSoundURL: COLLISION_SOUND_URL, + userData: JSON.stringify({ + grabbableKey: { + invertSolidWhileHeld: true + }, + wearable: { + joints: { + RightHand: [{ + x: 0.07079616189002991, + y: 0.20177987217903137, + z: 0.06374628841876984 + }, { + x: -0.5863648653030396, + y: -0.46007341146469116, + z: 0.46949487924575806, + w: -0.4733745753765106 + }], + LeftHand: [{ + x: 0.1802254319190979, + y: 0.13442856073379517, + z: 0.08504903316497803 + }, { + x: 0.2198076844215393, + y: -0.7377811074256897, + z: 0.2780133783817291, + w: 0.574519157409668 + }] + } + } + }) +}; + +var pistol = Entities.addEntity(pistolProperties); -(function() { - var scriptURL = Script.resolvePath('pistol.js'); - var _this; - PistolScriptSpawner = function() { - _this = this; - this.forceMultiplier = 1; - }; - - PistolScriptSpawner.prototype = { - - enterEntity: function() { - - Script.load(scriptURL); - }, - - preload: function(entityID) { - this.entityID = entityID; - }, - - }; - - // entity scripts always need to return a newly constructed object of our type - return new PistolScriptSpawner(); -}); \ No newline at end of file +Script.stop(); \ No newline at end of file diff --git a/scripts/tutorials/entity_scripts/cow.js b/scripts/tutorials/entity_scripts/cow.js index 1150be6b36..117864beb6 100644 --- a/scripts/tutorials/entity_scripts/cow.js +++ b/scripts/tutorials/entity_scripts/cow.js @@ -1,6 +1,3 @@ - -// cowEntityScript.js -// examples/cows // // Created by Eric Levin on 3/25/16 // Copyright 2016 High Fidelity, Inc. @@ -12,57 +9,76 @@ // - (function() { - Script.include("../libraries/utils.js"); var _this = this; _this.COLLISION_COOLDOWN_TIME = 5000; + _this.preload = function(entityID) { - this.preload = function(entityID) { - print("EBL Preload!!"); + //set our id so other methods can get it. _this.entityID = entityID; - _this.mooSound = SoundCache.getSound("https://s3-us-west-1.amazonaws.com/hifi-content/eric/Sounds/moo.wav") - _this.mooSoundOptions = {volume: 0.7, loop: false}; + //load the mooing sound + _this.mooSound = SoundCache.getSound("http://hifi-production.s3.amazonaws.com/tutorials/cow/moo.wav") + _this.mooSoundOptions = { + volume: 0.7, + loop: false + }; + + //variables we will use to keep track of when to reset the cow _this.timeSinceLastCollision = 0; _this.shouldUntipCow = true; } - this.collisionWithEntity = function(myID, otherID, collisionInfo) { - if(_this.shouldUntipCow) { - Script.setTimeout(function() { - _this.untipCow(); - _this.shouldUntipCow = true; - }, _this.COLLISION_COOLDOWN_TIME); - } + _this.collisionWithEntity = function(myID, otherID, collisionInfo) { + //we dont actually use any of the parameters above, since we don't really care what we collided with, or the details of the collision. + + //5 seconds after a collision, upright the cow. protect from multiple collisions in a short timespan with the 'shouldUntipCow' variable + if (_this.shouldUntipCow) { + //in Hifi, preface setTimeout with Script.setTimeout + Script.setTimeout(function() { + _this.untipCow(); + _this.shouldUntipCow = true; + }, _this.COLLISION_COOLDOWN_TIME); + } _this.shouldUntipCow = false; - + } - this.untipCow = function() { + _this.untipCow = function() { // keep yaw but reset pitch and roll var cowProps = Entities.getEntityProperties(_this.entityID, ["rotation", "position"]); var eulerRotation = Quat.safeEulerAngles(cowProps.rotation); eulerRotation.x = 0; eulerRotation.z = 0; var newRotation = Quat.fromVec3Degrees(eulerRotation); + + //we zero out the velocity and angular velocity so the cow doesn't change position or spin Entities.editEntity(_this.entityID, { rotation: newRotation, - velocity: {x: 0, y: 0, z: 0}, - angularVelocity: {x: 0, y: 0, z:0} + velocity: { + x: 0, + y: 0, + z: 0 + }, + angularVelocity: { + x: 0, + y: 0, + z: 0 + } }); - + //play the mooing sound when we untip! if it isn't already playing. _this.mooSoundOptions.position = cowProps.position; if (!_this.soundInjector) { _this.soundInjector = Audio.playSound(_this.mooSound, _this.mooSoundOptions); } else { + //if its already playing, just restart _this.soundInjector.setOptions(_this.mooSoundOptions); _this.soundInjector.restart(); } } -}); +}); \ No newline at end of file diff --git a/scripts/tutorials/entity_scripts/pistol.js b/scripts/tutorials/entity_scripts/pistol.js index 2cccf95986..8062de4e8e 100644 --- a/scripts/tutorials/entity_scripts/pistol.js +++ b/scripts/tutorials/entity_scripts/pistol.js @@ -1,477 +1,360 @@ -// +// // pistol.js -// examples // -// Created by Eric Levin on 11/12/2015 -// Copyright 2013 High Fidelity, Inc. +// Created by Eric Levin on11/11/15. +// Copyright 2015 High Fidelity, Inc. // -// This is an example script that turns the hydra controllers and mouse into a entity gun. -// It reads the controller, watches for trigger pulls, and adds a force to any entity it hits // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -Script.include("../../../libraries/utils.js"); -Script.include("../../../libraries/constants.js"); +(function() { -var GUN_FORCE =20; - -Messages.sendMessage('Hifi-Hand-Disabler', "both"); - -var gameName = "Kill All The Rats!" -// var HOST = "localhost:5000" -var HOST = "desolate-bastion-1742.herokuapp.com"; -var socketClient = new WebSocket("ws://" + HOST); -var username = GlobalServices.username; -var currentScore = 0; - -function score() { - currentScore++; - socketClient.send(JSON.stringify({ - username: username, - score: currentScore, - gameName: gameName - })) -} - - -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -var fireSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Guns/GUN-SHOT2.raw"); -var LASER_LENGTH = 100; -var LASER_WIDTH = 2; -var POSE_CONTROLS = [Controller.Standard.LeftHand, Controller.Standard.RightHand]; -var TRIGGER_CONTROLS = [Controller.Standard.LT, Controller.Standard.RT]; -var MIN_THROWER_DELAY = 1000; -var MAX_THROWER_DELAY = 1000; -var RELOAD_INTERVAL = 5; -var GUN_MODEL = HIFI_PUBLIC_BUCKET + "cozza13/gun/m1911-handgun+1.fbx?v=4"; -var BULLET_VELOCITY = 10.0; -var GUN_OFFSETS = [{ - x: 0.04, - y: 0.26, - z: 0.04 -}, { - x: 0.04, - y: 0.26, - z: 0.04 -}]; - -var GUN_ORIENTATIONS = [Quat.fromPitchYawRollDegrees(0, 90, 90), Quat.fromPitchYawRollDegrees(0, -90, 270)]; - -//x -> y -//y -> z -// z -> x -var BARREL_OFFSETS = [ { - x: -0.12, - y: 0.12, - z: 0.04 -}, { - x: 0.12, - y: 0.12, - z: 0.04 -} ]; - - - -var pointers = []; - -pointers.push(Overlays.addOverlay("line3d", { - start: ZERO_VECTOR, - end: ZERO_VECTOR, - color: COLORS.RED, - alpha: 1, - visible: true, - lineWidth: LASER_WIDTH -})); - -pointers.push(Overlays.addOverlay("line3d", { - start: ZERO_VECTOR, - end: ZERO_VECTOR, - color: COLORS.RED, - alpha: 1, - visible: true, - lineWidth: LASER_WIDTH -})); - -var mapping = Controller.newMapping(); -var validPoses = [false, false]; -var barrelVectors = [0, 0]; -var barrelTips = [0, 0]; - - -// If enabled, anything can be shot, otherwise, an entity needs to have "isShootable" set in its userData -var shootAnything = true; - - -function update(deltaTime) { - // FIXME we should also expose MyAvatar.handPoses[2], MyAvatar.tipPoses[2] - var tipPoses = [MyAvatar.leftHandTipPose, MyAvatar.rightHandTipPose]; - - for (var side = 0; side < 2; side++) { - // First check if the controller is valid - var controllerPose = Controller.getPoseValue(POSE_CONTROLS[side]); - validPoses[side] = controllerPose.valid; - // Need to adjust the laser - var tipPose = tipPoses[side]; - var handRotation = tipPoses[side].rotation; - var barrelOffset = Vec3.multiplyQbyV(handRotation, BARREL_OFFSETS[side]); - barrelTips[side] = Vec3.sum(tipPose.translation, barrelOffset); - barrelVectors[side] = Vec3.multiplyQbyV(handRotation, { + var ZERO_VECTOR = { x: 0, - y: 1, + y: 0, z: 0 - }); + }; + var _this; + var DISABLE_LASER_THRESHOLD = 0.2; + var TRIGGER_CONTROLS = [ + Controller.Standard.LT, + Controller.Standard.RT, + ]; + var RELOAD_THRESHOLD = 0.95; - var laserTip = Vec3.sum(Vec3.multiply(LASER_LENGTH, barrelVectors[side]), barrelTips[side]); - // Update Lasers - Overlays.editOverlay(pointers[side], { - start: barrelTips[side], - end: laserTip, - alpha: 1, - }); + Pistol = function() { + _this = this; + this.equipped = false; + this.forceMultiplier = 1; + this.laserLength = 100; - } -} + this.fireSound = SoundCache.getSound("http://hifi-production.s3.amazonaws.com/tutorials/pistol/GUN-SHOT2.raw"); + this.ricochetSound = SoundCache.getSound("http://hifi-production.s3.amazonaws.com/tutorials/pistol/Ricochet.L.wav"); + this.playRichochetSoundChance = 0.1; + this.fireVolume = 0.2; + this.bulletForce = 10; + this.showLaser = false; + this.laserOffsets = { + y: 0.095 + }; + this.firingOffsets = { + z: 0.16 + } - -function displayPointer(side) { - Overlays.editOverlay(pointers[side], { - visible: true - }); -} - -function hidePointer(side) { - Overlays.editOverlay(pointers[side], { - visible: false - }); -} - -function fire(side, value) { - if (value == 0) { - return; - } - Audio.playSound(fireSound, { - position: barrelTips[side], - volume: 0.5 - }); - - var shotDirection = Vec3.normalize(barrelVectors[side]); - var pickRay = { - origin: barrelTips[side], - direction: shotDirection }; - createMuzzleFlash(barrelTips[side]); - var intersection = Entities.findRayIntersectionBlocking(pickRay, true); - if (intersection.intersects) { - Script.setTimeout(function() { - createEntityHitEffect(intersection.intersection); - if (shootAnything && intersection.properties.dynamic === 1) { - // Any dynamic entity can be shot - Entities.editEntity(intersection.entityID, { - velocity: Vec3.multiply(shotDirection, GUN_FORCE) + Pistol.prototype = { + canShoot: false, + + startEquip: function(id, params) { + this.equipped = true; + this.hand = params[0] == "left" ? 0 : 1; + }, + + continueEquip: function(id, params) { + if (!this.equipped) { + return; + } + this.updateProps(); + if (this.showLaser) { + this.updateLaser(); + } + this.toggleWithTriggerPressure(); + }, + + updateProps: function() { + var gunProps = Entities.getEntityProperties(this.entityID, ['position', 'rotation']); + this.position = gunProps.position; + this.rotation = gunProps.rotation; + this.firingDirection = Quat.getFront(this.rotation); + var upVec = Quat.getUp(this.rotation); + this.barrelPoint = Vec3.sum(this.position, Vec3.multiply(upVec, this.laserOffsets.y)); + this.laserTip = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.laserLength)); + this.barrelPoint = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.firingOffsets.z)) + var pickRay = { + origin: this.barrelPoint, + direction: this.firingDirection + }; + }, + toggleWithTriggerPressure: function() { + this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]); + + if (this.triggerValue < RELOAD_THRESHOLD) { + this.canShoot = true; + } + if (this.canShoot === true && this.triggerValue === 1) { + this.fire(); + this.canShoot = false; + } + + if (this.triggerValue < DISABLE_LASER_THRESHOLD && this.showLaser === true) { + this.showLaser = false; + Overlays.editOverlay(this.laser, { + visible: false + }); + } else if (this.triggerValue >= DISABLE_LASER_THRESHOLD && this.showLaser === false) { + this.showLaser = true + Overlays.editOverlay(this.laser, { + visible: true }); } - if (intersection.properties.name === "rat") { - score(); - createBloodSplatter(intersection.intersection); - Entities.deleteEntity(intersection.entityID); - } - //Attempt to call entity method's shot method - var forceDirection = JSON.stringify({ - forceDirection: shotDirection + }, + updateLaser: function() { + + Overlays.editOverlay(this.laser, { + start: this.barrelPoint, + end: this.laserTip, + alpha: 1 }); - Entities.callEntityMethod(intersection.entityID, 'onShot', [forceDirection]); - - }, 0); - - } -} - - -function scriptEnding() { - Messages.sendMessage('Hifi-Hand-Disabler', 'none'); - mapping.disable(); - for (var i = 0; i < pointers.length; ++i) { - Overlays.deleteOverlay(pointers[i]); - } - MyAvatar.detachOne(GUN_MODEL); - MyAvatar.detachOne(GUN_MODEL); - clearPose(); -} - -MyAvatar.attach(GUN_MODEL, "LeftHand", GUN_OFFSETS[0], GUN_ORIENTATIONS[0], 0.40); -MyAvatar.attach(GUN_MODEL, "RightHand", GUN_OFFSETS[1], GUN_ORIENTATIONS[1], 0.40); - -function showPointer(side) { - Overlays.editOverlay(pointers[side], { - visible: true - }); -} - - - -mapping.from(Controller.Standard.LT).hysteresis(0.0, 0.5).to(function(value) { - fire(0, value); -}); - - -mapping.from(Controller.Standard.RT).hysteresis(0.0, 0.5).to(function(value) { - fire(1, value); -}); -mapping.enable(); - -Script.scriptEnding.connect(scriptEnding); -Script.update.connect(update); - - -function createEntityHitEffect(position) { - var flash = Entities.addEntity({ - type: "ParticleEffect", - position: position, - lifetime: 4, - "name": "Flash Emitter", - "color": { - red: 228, - green: 128, - blue: 12 }, - "maxParticles": 1000, - "lifespan": 0.15, - "emitRate": 1000, - "emitSpeed": 1, - "speedSpread": 0, - "emitOrientation": { - "x": -0.4, - "y": 1, - "z": -0.2, - "w": 0.7071068286895752 - }, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -3.1415927410125732, - "azimuthFinish": 2, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": 0, - "y": 0, - "z": 0 - }, - "particleRadius": 0.03, - "radiusSpread": 0.02, - "radiusStart": 0.02, - "radiusFinish": 0.03, - "colorSpread": { - red: 100, - green: 100, - blue: 20 - }, - "alpha": 1, - "alphaSpread": 0, - "alphaStart": 0, - "alphaFinish": 0, - "additiveBlending": true, - "textures": "http://ericrius1.github.io/PartiArt/assets/star.png" - }); - Script.setTimeout(function() { - Entities.editEntity(flash, { - isEmitting: false - }); - }, 100); + releaseEquip: function(id, params) { + this.hand = null; + this.equipped = false; + Overlays.editOverlay(this.laser, { + visible: false + }); + }, -} + triggerPress: function(hand, value) { + if (this.hand === hand && value === 1) { + //We are pulling trigger on the hand we have the gun in, so fire + this.fire(); + } + }, + fire: function() { -function createBloodSplatter(position) { - var splatter = Entities.addEntity({ - type: "ParticleEffect", - position: position, - lifetime: 4, - "name": "Blood Splatter", - "color": { - red: 230, - green: 2, - blue: 30 - }, - "maxParticles": 1000, - "lifespan": 0.3, - "emitRate": 1000, - "emitSpeed": 0.5, - "speedSpread": 0, - "emitOrientation": { - "x": -0.4, - "y": 1, - "z": -0.2, - "w": 0.7071068286895752 - }, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -3.1415927410125732, - "azimuthFinish": 2, - "emitAcceleration": { - "x": 0, - "y": -5, - "z": 0 - }, - "accelerationSpread": { - "x": 0, - "y": 0, - "z": 0 - }, - "particleRadius": 0.05, - "radiusSpread": 0.03, - "radiusStart": 0.05, - "radiusFinish": 0.05, - "colorSpread": { - red: 40, - green: 0, - blue: 30 - }, - "alpha": 1, - "alphaSpread": 0, - "alphaStart": 0, - "alphaFinish": 0, - "textures": "http://ericrius1.github.io/PartiArt/assets/star.png" - }); + Audio.playSound(this.fireSound, { + position: this.barrelPoint, + volume: this.fireVolume + }); - Script.setTimeout(function() { - Entities.editEntity(splatter, { - isEmitting: false - }); - }, 100) + var pickRay = { + origin: this.barrelPoint, + direction: this.firingDirection + }; + this.createGunFireEffect(this.barrelPoint) + var intersection = Entities.findRayIntersectionBlocking(pickRay, true); + if (intersection.intersects) { + this.createEntityHitEffect(intersection.intersection); + if (Math.random() < this.playRichochetSoundChance) { + Script.setTimeout(function() { + Audio.playSound(_this.ricochetSound, { + position: intersection.intersection, + volume: _this.fireVolume + }); + }, randFloat(10, 200)); + } + if (intersection.properties.dynamic === 1) { + // Any dynaic entity can be shot + Entities.editEntity(intersection.entityID, { + velocity: Vec3.multiply(this.firingDirection, this.bulletForce) + }); + } + } + }, -} + unload: function() { + Overlays.deleteOverlay(this.laser); + }, + createEntityHitEffect: function(position) { + var sparks = Entities.addEntity({ + type: "ParticleEffect", + position: position, + lifetime: 4, + "name": "Sparks Emitter", + "color": { + red: 228, + green: 128, + blue: 12 + }, + "maxParticles": 1000, + "lifespan": 0.15, + "emitRate": 1000, + "emitSpeed": 1, + "speedSpread": 0, + "emitOrientation": { + "x": -0.4, + "y": 1, + "z": -0.2, + "w": 0.7071068286895752 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": Math.PI, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 2, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.03, + "radiusSpread": 0.02, + "radiusStart": 0.02, + "radiusFinish": 0.03, + "colorSpread": { + red: 100, + green: 100, + blue: 20 + }, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 0, + "alphaFinish": 0, + "additiveBlending": true, + "textures": "http://hifi-production.s3.amazonaws.com/tutorials/pistol/star.png" + }); -function createMuzzleFlash(position) { - var smoke = Entities.addEntity({ - type: "ParticleEffect", - position: position, - lifetime: 1, - "name": "Smoke Hit Emitter", - "maxParticles": 1000, - "lifespan": 4, - "emitRate": 20, - emitSpeed: 0, - "speedSpread": 0, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": 0, - "azimuthStart": -3.1415927410125732, - "azimuthFinish": 3.14, - "emitAcceleration": { - "x": 0, - "y": 0.5, - "z": 0 - }, - "accelerationSpread": { - "x": .2, - "y": 0, - "z": .2 - }, - "radiusSpread": .04, - "particleRadius": 0.07, - "radiusStart": 0.07, - "radiusFinish": 0.07, - "alpha": 0.7, - "alphaSpread": 0, - "alphaStart": 0, - "alphaFinish": 0, - "additiveBlending": 0, - "textures": "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png" - }); - Script.setTimeout(function() { - Entities.editEntity(smoke, { - isEmitting: false - }); - }, 100); + Script.setTimeout(function() { + Entities.editEntity(sparks, { + isEmitting: false + }); + }, 100); - var flash = Entities.addEntity({ - type: "ParticleEffect", - position: position, - lifetime: 4, - "name": "Muzzle Flash", - "color": { - red: 228, - green: 128, - blue: 12 }, - "maxParticles": 1000, - "lifespan": 0.1, - "emitRate": 1000, - "emitSpeed": 0.5, - "speedSpread": 0, - "emitOrientation": { - "x": -0.4, - "y": 1, - "z": -0.2, - "w": 0.7071068286895752 - }, - "emitDimensions": { - "x": 0, - "y": 0, - "z": 0 - }, - "polarStart": 0, - "polarFinish": Math.PI, - "azimuthStart": -3.1415927410125732, - "azimuthFinish": 2, - "emitAcceleration": { - "x": 0, - "y": 0, - "z": 0 - }, - "accelerationSpread": { - "x": 0, - "y": 0, - "z": 0 - }, - "particleRadius": 0.05, - "radiusSpread": 0.01, - "radiusStart": 0.05, - "radiusFinish": 0.05, - "colorSpread": { - red: 100, - green: 100, - blue: 20 - }, - "alpha": 1, - "alphaSpread": 0, - "alphaStart": 0, - "alphaFinish": 0, - "additiveBlending": true, - "textures": "http://ericrius1.github.io/PartiArt/assets/star.png" - }); - Script.setTimeout(function() { - Entities.editEntity(flash, { - isEmitting: false - }); - }, 100) + createGunFireEffect: function(position) { + var smoke = Entities.addEntity({ + type: "ParticleEffect", + position: position, + lifetime: 1, + "name": "Smoke Hit Emitter", + "maxParticles": 1000, + "lifespan": 4, + "emitRate": 20, + emitSpeed: 0, + "speedSpread": 0, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": 0, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 3.14, + "emitAcceleration": { + "x": 0, + "y": 0.5, + "z": 0 + }, + "accelerationSpread": { + "x": 0.2, + "y": 0, + "z": 0.2 + }, + "radiusSpread": 0.04, + "particleRadius": 0.07, + "radiusStart": 0.07, + "radiusFinish": 0.07, + "alpha": 0.7, + "alphaSpread": 0, + "alphaStart": 0, + "alphaFinish": 0, + "additiveBlending": 0, + "textures": "http://hifi-production.s3.amazonaws.com/tutorials/pistol/smoke.png" + }); + Script.setTimeout(function() { + Entities.editEntity(smoke, { + isEmitting: false + }); + }, 100); + var flash = Entities.addEntity({ + type: "ParticleEffect", + position: this.barrelPoint, + "name": "Muzzle Flash", + lifetime: 4, + parentID: this.entityID, + "color": { + red: 228, + green: 128, + blue: 12 + }, + "maxParticles": 1000, + "lifespan": 0.1, + "emitRate": 1000, + "emitSpeed": 0.5, + "speedSpread": 0, + "emitOrientation": { + "x": -0.4, + "y": 1, + "z": -0.2, + "w": 0.7071068286895752 + }, + "emitDimensions": { + "x": 0, + "y": 0, + "z": 0 + }, + "polarStart": 0, + "polarFinish": Math.PI, + "azimuthStart": -3.1415927410125732, + "azimuthFinish": 2, + "emitAcceleration": { + "x": 0, + "y": 0, + "z": 0 + }, + "accelerationSpread": { + "x": 0, + "y": 0, + "z": 0 + }, + "particleRadius": 0.05, + "radiusSpread": 0.01, + "radiusStart": 0.05, + "radiusFinish": 0.05, + "colorSpread": { + red: 100, + green: 100, + blue: 20 + }, + "alpha": 1, + "alphaSpread": 0, + "alphaStart": 0, + "alphaFinish": 0, + "additiveBlending": true, + "textures": "http://hifi-production.s3.amazonaws.com/tutorials/pistol/star.png" + }); + Script.setTimeout(function() { + Entities.editEntity(flash, { + isEmitting: false + }); + }, 100) -} + }, + + preload: function(entityID) { + this.entityID = entityID; + this.laser = Overlays.addOverlay("line3d", { + start: ZERO_VECTOR, + end: ZERO_VECTOR, + color: COLORS.RED, + alpha: 1, + visible: true, + lineWidth: 2 + }); + }, + }; + + // entity scripts always need to return a newly constructed object of our type + return new Pistol(); +}); \ No newline at end of file diff --git a/scripts/tutorials/makeAvatarClap.js b/scripts/tutorials/makeAvatarClap.js index 9b21075ae7..c51e7a8d3a 100644 --- a/scripts/tutorials/makeAvatarClap.js +++ b/scripts/tutorials/makeAvatarClap.js @@ -1,148 +1,39 @@ // -// clap.js -// examples +// Created by James B. Pollack @imgntn on April 18, 2016. +// Copyright 2016 High Fidelity, Inc. // -// Copyright 2014 High Fidelity, Inc. -// -// This sample script watches your hydra hands and makes clapping sound when they come close together fast, -// and also watches for the 'shift' key and claps when that key is pressed. Clapping multiple times by pressing -// the shift key again makes the animation and sound match your pace of clapping. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +// An animation of the avatar clapping its hands while standing +var ANIM_URL = "http://hifi-production.s3.amazonaws.com/tutorials/avatarAnimation/clap.fbx"; -var clapAnimation = HIFI_PUBLIC_BUCKET + "animations/ClapAnimations/ClapHands_Standing.fbx"; -var ANIMATION_FRAMES_PER_CLAP = 10.0; -var startEndFrames = []; -startEndFrames.push({ start: 0, end: 10}); -startEndFrames.push({ start: 10, end: 20}); -startEndFrames.push({ start: 20, end: 30}); -startEndFrames.push({ start: 30, end: 40}); -startEndFrames.push({ start: 41, end: 51}); -startEndFrames.push({ start: 53, end: 0}); +// overrideRoleAnimation only replaces a single animation at a time. the rest of the motion is driven normally +// @animationRole - name of animation +// @animationURL - url +// @playbackRate - frames per second +// @loopFlag - should loop +// @startFrame +// @endFrame +MyAvatar.overrideRoleAnimation("idleStand", ANIM_URL, 30, true, 0, 53); -var lastClapFrame = 0; -var lastAnimFrame = 0; +//stop a a minute because your hands got tired. +Script.setTimeout(function(){ +MyAvatar.restoreRoleAnimation("idleStand"); +Script.stop(); +},60000) -var claps = []; -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap1Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap2Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap3Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap4Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap5Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap6Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap7Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap8Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap9Rvb.wav")); -claps.push(SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/claps/BClap10Rvb.wav")); -var numberOfSounds = claps.length; - -var clappingNow = false; -var collectedClicks = 0; - -var clickStartTime, clickEndTime; -var clickClappingNow = false; -var CLAP_START_RATE = 15.0; -var clapRate = CLAP_START_RATE; -var startedTimer = false; - -function maybePlaySound(deltaTime) { - // Set the location and other info for the sound to play - - var animationDetails = MyAvatar.getAnimationDetails(clapAnimation); - - var frame = Math.floor(animationDetails.frameIndex); - - if (frame != lastAnimFrame) { - lastAnimFrame = frame; - } - - for (var i = 0; i < startEndFrames.length; i++) { - if (frame == startEndFrames[i].start && (frame != lastClapFrame)) { - playClap(1.0, Camera.getPosition()); - lastClapFrame = frame; - } - } - - var palm1Position = MyAvatar.getLeftPalmPosition(); - var palm2Position = MyAvatar.getRightPalmPosition(); - var distanceBetween = Vec3.length(Vec3.subtract(palm1Position, palm2Position)); - - var palm1Velocity = Controller.getPoseValue(Controller.Standard.LeftHand).velocity; - var palm2Velocity = Controller.getPoseValue(Controller.Standard.RightHand).velocity; - var closingVelocity = Vec3.length(Vec3.subtract(palm1Velocity, palm2Velocity)); - - const CLAP_SPEED = 0.7; - const CLAP_DISTANCE = 0.15; - - if ((closingVelocity > CLAP_SPEED) && (distanceBetween < CLAP_DISTANCE) && !clappingNow) { - var volume = closingVelocity / 2.0; - if (volume > 1.0) volume = 1.0; - playClap(volume, palm1Position); - clappingNow = true; - } else if (clappingNow && (distanceBetween > CLAP_DISTANCE * 1.2)) { - clappingNow = false; - } -} - -function playClap(volume, position) { - var clip = Math.floor(Math.random() * numberOfSounds); - Audio.playSound(claps[clip], { - position: position, - volume: volume - }); -} - -var FASTEST_CLAP_INTERVAL = 150.0; -var SLOWEST_CLAP_INTERVAL = 750.0; - -Controller.keyPressEvent.connect(function(event) { - if(event.text == "SHIFT") { - if (!clickClappingNow) { - clickClappingNow = true; - clickStartTime = new Date(); - lastClapFrame = 0; - } else { - // start or adjust clapping speed based on the duration between clicks - clickEndTime = new Date(); - var milliseconds = Math.max(clickEndTime - clickStartTime, FASTEST_CLAP_INTERVAL); - clickStartTime = new Date(); - if (milliseconds < SLOWEST_CLAP_INTERVAL) { - clapRate = ANIMATION_FRAMES_PER_CLAP * (1000.0 / milliseconds); - playClap(1.0, Camera.getPosition()); - MyAvatar.stopAnimation(clapAnimation); - MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false); - } - collectedClicks = collectedClicks + 1; - } - } +//or stop when the script is manually stopped +Script.scriptEnding.connect(function () { +MyAvatar.restoreRoleAnimation("idleStand"); }); -var CLAP_END_WAIT_MSECS = 300; -Controller.keyReleaseEvent.connect(function(event) { - if (event.text == "SHIFT") { - collectedClicks = 0; - if (!startedTimer) { - collectedClicks = 0; - Script.setTimeout(stopClapping, CLAP_END_WAIT_MSECS); - startedTimer = true; - } - } -}); - -function stopClapping() { - if (collectedClicks == 0) { - startedTimer = false; - MyAvatar.stopAnimation(clapAnimation); - clapRate = CLAP_START_RATE; - clickClappingNow = false; - } else { - startedTimer = false; - } -} - -// Connect a call back that happens every frame -Script.update.connect(maybePlaySound); \ No newline at end of file +//overRideAnimation replaces all animations, so you dont have to provide a role name +// @animationURL - url +// @playbackRate - frames per second +// @loopFlag - should loop +// @startFrame +// @endFrame +//MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53);