From 35c05fdebb3757a251391ead3377cd81157db57c Mon Sep 17 00:00:00 2001 From: Gary Weiss Date: Fri, 28 Oct 2016 22:47:28 +0300 Subject: [PATCH] fix sprite calculation errors --- README.md | 83 ++++++++++++++++++++++++++----- examples/animated-crosshairs.html | 6 ++- src/crosshairs.js | 33 ++++++------ 3 files changed, 94 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index fe5c4ac..a29532f 100644 --- a/README.md +++ b/README.md @@ -146,33 +146,92 @@ veri.setup({ direction: Veri.vec3(0, 0, -1) // the lookAt vector3 }, - // crosshairs: + // Animated Crosshairs + // // provide a list of targets that the crosshairs can activate - // each target must have a name and direction + // each target must have a name and direction. The direction is + // specified using Veri.rot3 (syntactic sugar for THREE.Euler), + // reduced to theta (vertical angle) and phi (horizontal angle) + // // hitRadius - radians offset which is considered // part of the target + // // hitTime - time in milliseconds until the target is considered "clicked" - // sprite - optional sprite for animation. Include src, - // columns, rows, and count. - // If not specified + // + // sprite - optional sprite for animation. Must be a "power-of-two" image, + // meaning the width and height must be powers of two, though not necessarily + // identical to each other. Includes attributes: + // src - url + // columns, rows - columns and rows in the sprite + // count - number of actual images in the sprite. + // objWidth, objHeight - size of invisible rectangle used to project the sprite. + // width, height - if the images are not exact fractions of the sprite + // width and height, specify them here. + // + // If sprite is not specified // then a small ring is used to indicate selection progress // // Note: use the event emitter to determine crosshairs state. crosshairs: { + type: "animated-crosshairs", + debug: false, targets: [ { name: "play", - direction: Veri.vec3(-1, 0, -1) + direction: Veri.rot3(0, -100) }, { name: "stop", - direction: Veri.vec3(-1, 0, -1) + direction: Veri.rot3(0, -80) }], - hitRadius: 0.1, + hitRadius: 10, hitTime: 6000, sprite: { - src: "../resources/sprite/all2048.png", - columns: 16, - rows: 13, - count: 208 + src: "../resources/sprite/circle.png", + distance: 300, + columns: 8, + rows: 8, + count: 60, + objWidth: 60, + objHeight: 60, + width: 60, + height: 60 + } + }, + + // Animated buttons + // + // Rather than having an animated crosshairs, in this case the + // buttons themselves start animating when a static crosshairs enters + // the button area. + // + // Provide a list of animated targets that the crosshairs can activate. + // Each target must have a name and direction, a hitRadius, a hitTime, + // and the corresponding sprite descriptor. The sprite has its own + // direction but it typically matches the target. + // + // sprite - describe the actual crosshairs image. Not really a sprite + // + // Note: use the event emitter to determine crosshairs state. + crosshairs: { + type: "animated-buttons", + debug: false, + targets: [{ + name: "start", + direction: Veri.rot3(0, -100), + hitRadius: 16, + hitTime: 6000, + sprite: { + // same as above, but also include a direction + direction: Veri.rot3(0, -100) + } + }], + sprite: { + src: "resources/img/crosshairs.png", + distance: 380, + objWidth: 50, + objHeight: 50, + columns: 1, + rows: 1, + count: 1 } }, diff --git a/examples/animated-crosshairs.html b/examples/animated-crosshairs.html index 0811224..08e45ee 100644 --- a/examples/animated-crosshairs.html +++ b/examples/animated-crosshairs.html @@ -55,12 +55,14 @@ hitTime: 6000, sprite: { src: "../resources/sprite/circle.png", - distance: 200, + distance: 300, columns: 8, rows: 8, count: 60, objWidth: 60, - objHeight: 60 + objHeight: 60, + width: 60, + height: 60 } }, }); diff --git a/src/crosshairs.js b/src/crosshairs.js index f62fd86..79c4b56 100644 --- a/src/crosshairs.js +++ b/src/crosshairs.js @@ -18,7 +18,6 @@ class Crosshairs { this.lastTarget = null; this.hitStart = null; this.hitPercent = 0; - this.lastPercent = -1; } showVec(v) { @@ -54,9 +53,16 @@ class Crosshairs { sprite.texture = spriteTexture; sprite.texture.wrapS = sprite.texture.wrapT = THREE.RepeatWrapping; - var repeatX = 1 / sprite.columns; - var repeatY = 1 / sprite.rows; - sprite.texture.repeat.set(repeatX, repeatY); + // repeat is the number of times the texture should repeat on each + // axis. when it's less than one, we indicate that it should be a + // fraction of the image + sprite.repeatX = 1 / sprite.columns; + sprite.repeatY = 1 / sprite.rows; + if (sprite.width && sprite.height) { + sprite.repeatX = sprite.width / sprite.texture.image.width; + sprite.repeatY = sprite.height / sprite.texture.image.height; + } + sprite.texture.repeat.set(sprite.repeatX, sprite.repeatY); var geometry = new THREE.PlaneGeometry(sprite.objWidth, sprite.objHeight, 1, 1); var spriteMaterial = new THREE.MeshBasicMaterial({ transparent: true, @@ -90,10 +96,12 @@ class Crosshairs { } // update the sprite + // calculate row, column and corresponding offsets var imageIndex = Math.floor(sprite.count * percent); - - sprite.texture.offset.x = (imageIndex % sprite.columns) / sprite.columns; - sprite.texture.offset.y = 1 - (Math.floor(imageIndex / sprite.columns) + 1) / sprite.rows; + var col = (imageIndex % sprite.columns); + var row = Math.floor(imageIndex / sprite.columns) + 1; + sprite.texture.offset.x = col * sprite.repeatX; + sprite.texture.offset.y = 1 - row * sprite.repeatY; if (sprite.texture.offset.y !== window.oldY || sprite.texture.offset.x !== window.oldX) { @@ -209,13 +217,10 @@ class Crosshairs { // update the crosshairs this.updateSprite(0, cameraDirection, this.params.sprite); } else if (this.params.type === 'animated-crosshairs') { - if (this.lastPercent !== this.hitPercent) { - this.lastPercent = this.hitPercent; - if (this.params.sprite) { - this.updateSprite(this.hitPercent, cameraDirection, this.params.sprite); - } else { - this.updateCrosshairs(this.hitPercent, cameraDirection); - } + if (this.params.sprite) { + this.updateSprite(this.hitPercent, cameraDirection, this.params.sprite); + } else { + this.updateCrosshairs(this.hitPercent, cameraDirection); } } }