Script.include("line.js"); var AUDIO = { crowdBoos: [ SoundCache.getSound("atp:c632c92b166ade60aa16b23ff1dfdf712856caeb83bd9311980b2d5edac821af.wav", false) ], crowdCheers: [ SoundCache.getSound("atp:0821bf2ac60dd2f356dfdd948e8bb89c23984dc3584612f6c815765154f02cae.wav", false), SoundCache.getSound("atp:b8044401a846ed29f881a0b9b80cf1ba41f26327180c28fc9c70d144f9b70045.wav", false), ], batHit: [ SoundCache.getSound("atp:6f0b691a0c9c9ece6557d97fe242b1faec4020fe26efc9c17327993b513c5fe5.wav", false), SoundCache.getSound("atp:5be5806205158ebdc5c3623ceb7ae73315028b51ffeae24292aff7042e3fa6a9.wav", false), SoundCache.getSound("atp:e68661374e2145c480809c26134782aad11e0de456c7802170c7abccc4028873.wav", false), SoundCache.getSound("atp:787e3c9af17dd3929527787176ede83d6806260e63ddd5a4cef48cd22e32c6f7.wav", false), SoundCache.getSound("atp:fc65383431a6238c7a4749f0f6f061f75a604ed5e17d775ab1b2955609e67ebb.wav", false), ] } var PITCH_THUNK_SOUND_URL = "http://hifi-public.s3.amazonaws.com/sounds/ping_pong_gun/pong_sound.wav"; var pitchSound = SoundCache.getSound(PITCH_THUNK_SOUND_URL, false); var PITCHING_MACHINE_URL = "atp:87d4879530b698741ecc45f6f31789aac11f7865a2c3bec5fe9b061a182c80d4.fbx"; var PITCHING_MACHINE_OUTPUT_OFFSET_PCT = { x: 0.0, y: 0.25, z: -1.05, }; var PITCHING_MACHINE_PROPERTIES = { name: "Pitching Machine", type: "Model", position: { x: 0, y: 0.8, z: -18.3, }, velocity: { x: 0, y: -0.01, z: 0 }, gravity: { x: 0.0, y: -9.8, z: 0.0 }, registrationPoint: { x: 0.5, y: 0.5, z: 0.5, }, rotation: Quat.fromPitchYawRollDegrees(0, 180, 0), modelURL: PITCHING_MACHINE_URL, dimensions: { x: 0.4, y: 0.61, z: 0.39 }, collisionsWillMove: false, shapeType: "Box", }; PITCHING_MACHINE_PROPERTIES.dimensions = Vec3.multiply(2.5, PITCHING_MACHINE_PROPERTIES.dimensions); var DISTANCE_FROM_PLATE = PITCHING_MACHINE_PROPERTIES.position.z; var PITCH_RATE = 5000; var BASEBALL_MODEL_URL = "atp:7185099f1f650600ca187222573a88200aeb835454bd2f578f12c7fb4fd190fa.fbx"; var BASEBALL_MIN_SPEED = 2.7; var BASEBALL_MAX_SPEED = 5.7; var BASEBALL_RADIUS = 0.07468; var BASEBALL_PROPERTIES = { name: "Baseball", type: "Model", modelURL: BASEBALL_MODEL_URL, shapeType: "Sphere", position: { x: 0, y: 0, z: 0 }, dimensions: { x: BASEBALL_RADIUS, y: BASEBALL_RADIUS, z: BASEBALL_RADIUS }, collisionsWillMove: true, angularVelocity: { x: 17.0, y: 0, z: -8.0, x: 0.0, y: 0, z: 0.0, }, angularDamping: 0.0, damping: 0.0, restitution: 0.5, friction: 0.0, lifetime: 20, //collisionSoundURL: PITCH_THUNK_SOUND_URL, gravity: { x: 0, y: 0,//-9.8, z: 0 } }; var pitchingMachineID = Entities.addEntity(PITCHING_MACHINE_PROPERTIES); var pitchFromPosition = { x: 0, y: 1.0, z: 0 }; var pitchDirection = { x: 0, y: 0, z: 1 }; function shallowCopy(obj) { var copy = {} for (var key in obj) { copy[key] = obj[key]; } return copy; } function randomInt(low, high) { return Math.floor(randomFloat(low, high)); } function randomFloat(low, high) { if (high === undefined) { high = low; low = 0; } return low + Math.random() * (high - low); } var ACCELERATION_SPREAD = 10.15; function Baseball(position, velocity, ballScale) { var self = this; // Setup entity properties var properties = shallowCopy(BASEBALL_PROPERTIES); properties.position = position; properties.velocity = velocity; /* properties.gravity = { x: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD), y: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD), z: 0.0, }; */ properties.dimensions = Vec3.multiply(ballScale, properties.dimensions); // Create entity this.entityID = Entities.addEntity(properties); this.trail = null; this.onHit = function() { return true; }; this.hasBeenHit = false; this.boundCollisionCallback = function(a, b, c) { self.collisionCallback.call(self, a, b, c); }; Script.addEventHandler(this.entityID, "collisionWithEntity", this.boundCollisionCallback); /* if (false && Math.random() < 0.5) { for (var i = 0; i < 50; i++) { Script.setTimeout(function() { Entities.editEntity(entityID, { gravity: { x: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD), y: randomInt(-ACCELERATION_SPREAD, ACCELERATION_SPREAD), z: 0.0, } }) }, i * 100); } } */ } Baseball.prototype = { collisionCallback: function(entityA, entityB, collision) { var self = this; this.hasBeenHit = true; var properties = Entities.getEntityProperties(this.entityID, ['position', 'velocity']); this.trail = new InfiniteLine(properties.position, { red: 255, green: 128, blue: 89 }); var lastPosition = properties.position; //Vec3.print("Velocity", properties.velocity); //Vec3.print("VelocityChange", collision.velocityChange); var speed = Vec3.length(properties.velocity); playRandomSound(AUDIO.batHit, { position: properties.position, volume: 2.0 }); var sounds = null; if (speed < 5.0) { sounds = AUDIO.crowdBoos; } else { sounds = AUDIO.crowdCheers; } var self = this; this.trailInterval = Script.setInterval(function() { var properties = Entities.getEntityProperties(self.entityID, ['position']); if (Vec3.distance(properties.position, lastPosition)) { self.trail.enqueuePoint(properties.position); lastPosition = properties.position; } }, 50); Entities.editEntity(self.entityID, { velocity: Vec3.multiply(2, properties.velocity), gravity: { x: 0, y: -9.8, z: 0 } }); var removeHandler = this.onHit(entityB, collision); if (removeHandler) { Script.removeEventHandler(self.entityID, "collisionWithEntity", self.boundCollisionCallback); } }, cleanupTrail: function() { if (this.trail) { Script.clearInterval(this.trailInterval); this.trailInterval = null; this.trail.destroy(); this.trail = null; } } } function playRandomSound(sounds, options) { if (options === undefined) { options = { volume: 1.0, position: MyAvatar.position, } } Audio.playSound(sounds[randomInt(sounds.length)], options); } var lastTrail = null; function vec3Mult(a, b) { return { x: a.x * b.x, y: a.y * b.y, z: a.z * b.z, }; } var lastBall = null; var injector = null; function pitchBall() { if (lastBall) { lastBall.cleanupTrail(); } var machineProperties = Entities.getEntityProperties(pitchingMachineID, ["dimensions", "position", "rotation"]); var pitchFromPositionBase = machineProperties.position; var pitchFromOffset = vec3Mult(machineProperties.dimensions, PITCHING_MACHINE_OUTPUT_OFFSET_PCT); pitchFromOffset = Vec3.multiplyQbyV(machineProperties.rotation, pitchFromOffset); var pitchFromPosition = Vec3.sum(pitchFromPositionBase, pitchFromOffset); var pitchDirection = Quat.getFront(machineProperties.rotation); var ballScale = machineProperties.dimensions.x / PITCHING_MACHINE_PROPERTIES.dimensions.x; print("Creating baseball"); var speed = randomFloat(BASEBALL_MIN_SPEED, BASEBALL_MAX_SPEED) var timeToPassPlate = (DISTANCE_FROM_PLATE + 1.0) / speed; var baseball = new Baseball(pitchFromPosition, Vec3.multiply(speed, pitchDirection), ballScale); lastBall = baseball; baseball.onHit = function(entityB, collision) { var properties = Entities.getEntityProperties(entityB, ["name"]); var name = properties.name; print("Hit: " + name); if (name == "backstop") { print("STRIKE"); } else if (name == "bat") { print("HIT"); Script.setTimeout(function() { playRandomSound(sounds, { position: { x: 0 ,y: 0, z: 0 }, volume: 1.0, }); }, 500); } //Script.clearTimeout(strikeTimeout); return true; } if (!injector) { injector = Audio.playSound(pitchSound, { position: pitchFromPosition, volume: 1.0 }); } else { injector.restart(); } } Script.scriptEnding.connect(function() { Entities.deleteEntity(pitchingMachineID); }) Script.setInterval(pitchBall, PITCH_RATE);