简体   繁体   中英

Tweened Kinetic.js shape doesn't fire most of clicks

Purpose

I'm making a simple "shoot the word" game, where user needs to click on some moving rectangles with words to "shoot" them.

Problem

So i create some objects and move them using simple kinetic.js tweening.

Word creation

function createWord(value){

 //here comes some word object construction var wordGroup = new Kinetic.Group({ x: 0, y: 0 }); var padding = 10; wordGroup.label = new Kinetic.Text({ x: padding, y: padding, text: value, fontFamily: 'Times New Roman', fontSize: 30, fill: 'white' }); wordGroup.tag = new Kinetic.Rect({ x: 0, y: 0, width: wordGroup.label.width() + (padding << 1), height: wordGroup.label.height() + (padding << 1), fill: 'black', shadowColor: 'black', shadowBlur: 10, shadowOffset: {x:10,y:20}, shadowOpacity: 0.5, cornerRadius: 10 }); wordGroup.add(wordGroup.tag); wordGroup.add(wordGroup.label); wordGroup.shoot = function(){ //shooting mechanism (simple stop from moving and remove from scene) wordGroup.tween.pause(); wordGroup.clean(); dropNextWord(); //drops fresh blood! (new word instead of shooted) } wordGroup.clean = function(){ //remove from scene and set it free to drop again wordGroup.remove(); wordGroup.isActive = false; } wordGroup.move = function(callback){ //animates word wordLayer.add(wordGroup); moveToSide(wordGroup, callback); //calls moving function } wordGroup.on('click', function(e){ wordGroup.shoot(); }); return wordGroup; } 

Tweening part

//move word to opposite side
function moveToSide(word, callback){
    var side = Math.random();

    var d = 100;

    spawnFromSide(word, side); //set random side word position

    tweenPosition = {
        x: word.x(),
        y: word.y()
    }

    if(side < 0.25){ //left
        tweenPosition.x = - d;
    } else if(side > 0.25 && side < 0.5){ //right
        tweenPosition.x = defaultStageWidth + d;
    } else if(side > 0.5 && side < 0.75){ //up
        tweenPosition.y = - d;
    } else { //down
        tweenPosition.y = defaultStageHeight + d;
    }

    word.tween = new Kinetic.Tween({
        node: word,
        duration: 4,
        easing: Kinetic.Easings.Linear,
        x: tweenPosition.x,
        y: tweenPosition.y,
        onFinish: function(){
            word.clean();
            callback();
        }
    });

    word.tween.play();
}

But the problem is that click event doesn't fire on large amount of user clicks. As i think, this caused by delayed drawHit() calls inside tweening mechanism, that draws new object position before updating the hit area, so when we shoot object thinking that we hit its current position we miss because its hit area still have the same old position.

示意图延迟图

Live example

http://jsfiddle.net/hd6z21de/7/

Take a minute on shooting to see this effect in action

Solved this weird behavior by listening canvas touches and check if pointer collide some target word-rect by myself instead of using their own onclick events.

//i listen to canvas because of my app specific, you could simple listen your own layer or even document

$("canvas").bind('click', function(event){

  var x = (event.pageX) / stage.scaleX(); //you don't need to divide by scale if your stage isn't scaled as mine does var y = (event.pageY) / stage.scaleY(); var wordArray = wordGroup.getChildren(); for(var i = 0; i < wordArray.length; i++){ //go through all words and check if we shoot someone (is mouse position included in some word rect) if(x > wordArray[i].x() && y > wordArray[i].y() && x < (wordArray[i].x() + wordArray[i].width()) && y < (wordArray[i].y() + wordArray[i].height())){ wordArray[i].shoot(); //shoot that word break; } } } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM