将可拖动对象与AS3中的目标对象配对

时间:2015-06-10 18:59:19

标签: actionscript-3 flash

我目前坚持使用下面的方法。我不完全确定使用“hitTestObject”方法是否适合将各个部分配对到各自的位置。我至少能够将棋子与他们各自的位置相匹配(这是我能做的最好的,而且我觉得我做错了)但我现在已经不知道有多少棋子确实在他们正确的位置。例如当我将棋子移动到另一个棋子时,它仍会算作一个,我也想避免重复计数,例如,如果pawn已经在正确的位置,它将只计为1,如果它被移动,那么该计数将被删除。只计算正确磁贴中的碎片。

我的目标是能够使所有的棋子都可以拖动,并确定它们是否在各自的位置。如果所有棋子都在他们的位置,它将跟踪或调用一个功能。

谢谢!

import flash.events.Event;
import flash.display.MovieClip;
import flash.events.MouseEvent;

/* Declaring an X and Y variable to be used as a reset container */ 
var xPos: int, yPos: int;

/* Attaching event listeners for each chess piece */
addListeners(
    king, queen, bishop_1, bishop_2, knight_1, knight_2, rook_1, rook_2,
    pawn_1, pawn_2, pawn_3, pawn_4, pawn_5, pawn_6, pawn_7, pawn_8);


/* Getting the original x and y postion to be used as a reset */
function getPosition(currentTarget: Object): void {
    xPos = currentTarget.x;
    yPos = currentTarget.y;
}

/* Function to get the suffix value of an object. example, I need to get the value 4 from "pawn_4" */
function getLastCharInString($s: String, $pos: Number): String {
    return $s.substr($s.length - $pos, $s.length);
}

/* A simple function that rotates the chess piece */
function lift(object: Object, rot: Number) {
    object.rotation = rot;
}

function dragObject(e: MouseEvent): void {
    getPosition(e.currentTarget);
    lift(e.currentTarget, -10);

    getChildByName(e.currentTarget.name + "_hs").alpha = 1;


    e.currentTarget.startDrag();
}

/* This variable is supposed to hold the value of each piece that is correctly placed in each tile. 
The total score should be 16 as there are 16 pieces. Only correcly placed piece should be added in the total score. */
var counter:int;

function stopDragObject(e: MouseEvent): void {


    var curretTarget = e.currentTarget.name;

    lift(e.currentTarget, 0);

         /* Hide active hotspots  */
    getChildByName(e.currentTarget.name + "_hs").alpha = 0;

    var multiplePieceSufix = Number(getLastCharInString(curretTarget, 1));

    if (multiplePieceSufix >= 1) {


        /* Boolean variables that checks whether the current piece is active*/
        var isPawn: Boolean = false,
            isBishop: Boolean = false,
            isKnight: Boolean = false,
            isRook: Boolean = false,
            currentTargeName;

        var widthDiff = getChildByName(e.currentTarget.name + "_hs").width - getChildByName(e.currentTarget.name).width / 2;
        var heightDiff = getChildByName(e.currentTarget.name + "_hs").height - getChildByName(e.currentTarget.name).height / 2;

        if (curretTarget.substr(0, 4) == "pawn") {
            isPawn = true;
        } else if (curretTarget.substr(0, 6) == "bishop") {
            isBishop = true;
        } else if (curretTarget.substr(0, 6) == "knight") {
            isKnight = true;
        } else if (curretTarget.substr(0, 4) == "rook") {
            isRook = true;
        }


        if (isPawn == true) {

            /* there are total of 8 pieces of pawn */
            for (var w = 1; w < 9; w++) {

                currentTargeName = this["pawn_" + w + "_hs"];

                if (e.target.hitTestObject(currentTargeName)) {

                    /* For some reason the chess pieces are not aligning with their "_hs" version, I already checked their registry point and it seem to be normal.
                     so to fix, I had to manually add some hard coded values to adjust their location. */
                    e.currentTarget.x = currentTargeName.x - 8;
                    e.currentTarget.y = currentTargeName.y + currentTargeName.height;

                }
            }

        } else if (isBishop == true) {

            for (var x = 1; x < 3; x++) {

                currentTargeName = this["bishop_" + x + "_hs"];

                if (e.target.hitTestObject(currentTargeName)) {

                    e.currentTarget.x = currentTargeName.x - 9;
                    e.currentTarget.y = currentTargeName.y + currentTargeName.height - 18;

                }
            }

        } else if (isKnight == true) {

            for (var y = 1; y < 3; y++) {

                currentTargeName = this["knight_" + y + "_hs"];

                if (e.target.hitTestObject(currentTargeName)) {

                    e.currentTarget.x = currentTargeName.x - 8;
                    e.currentTarget.y = currentTargeName.y + currentTargeName.height;

                }
            }

        } else if (isRook == true) {

            for (var z = 1; z < 3; z++) {

                currentTargeName = this["rook_" + z + "_hs"];

                if (e.target.hitTestObject(currentTargeName)) {

                    e.currentTarget.x = currentTargeName.x - 8;
                    e.currentTarget.y = currentTargeName.y + 62;

                }
            }

        }


    } else {


        if (e.target.hitTestObject(getChildByName(e.currentTarget.name + "_hs"))) {

            /* Again, I'm not sure why the pieces are not aligning as intended.
            modX and modY is a holder for the adjustment value. I'm not comfortable
            seeing this approach myself, but I also run out of ideas how to fix it. */ 

            var modX: Number, modY: Number;

            if (e.currentTarget.name == "king") {
                modX = 11;
                modY = 53;
            } else {
                modX = 11;
                modY = 29;
            }

            e.currentTarget.x = getChildByName(e.currentTarget.name + "_hs").x - modX;
            e.currentTarget.y = getChildByName(e.currentTarget.name + "_hs").y + getChildByName(e.currentTarget.name + "_hs").height - modY;

        }

    }

    /* This is supposed to add to the total score or count of how many pieces are placed correctly.
    Thie problem with thi scounter, as it also counts any piece that is places to any "_hs" */
    counter++;

    trace(counter);

    e.currentTarget.stopDrag();
}


function addListeners(...objects): void {
    for (var i: int = 0; i < objects.length; i++) {
        objects[i].addEventListener(MouseEvent.MOUSE_DOWN, dragObject);
        objects[i].addEventListener(MouseEvent.MOUSE_UP, stopDragObject);

        // hide hotspots
        getChildByName( objects[i].name + "_hs" ).alpha = 0;

    }
}

来源:Download the FLA here

-

更新

我在代码中添加了注释,以阐明我想要完成的任务。

我打算在flash中进行棋盘游戏,其功能和行为与此类似。用户可以将对象拖动到指定的图块并检查该对象是否属于那里。

1 个答案:

答案 0 :(得分:1)

在审核您的代码后,您的问题非常广泛。我要把它配对到你主要担心的事情 - 得分/计数正确移动的部分。

现在,每次拖动对象时都会执行以下操作:

counter++;

这意味着无论您在何处拖动对象,计数器都会递增,无论您拖动对象的次数如何。 (所以即使这件作品已经在正确的位置,如果再次拖动它仍然会增加你的计数器)。

您需要做的是将标志与每个对象相关联以指示它是否位于正确的位置,并在每次拖动对象时将该标志设置为适当的值。

这样的事情:

 //don't use target, use currentTarget
 if (e.currentTarget.hitTestObject(currentTargeName)) {
      e.currentTarget.correct = true; //since MovieClips are dynamic, you can just make up a property on them and assign a value to it.

      //to fix your alignment:
      e.currentTarget.x = currentTargeName.x + ((currentTargetName.width - e.currentTarget.width) * 0.5);
      e.currentTarget.y = currentTargeName.y + currentTargeName.height;
 }else{
      //if the hit test is false, mark it as NOT correct
      e.currentTarget.correct = false;
 }

然后,稍后知道当前计数,迭代所有部分并检查其correct值。如果你的所有作品都在阵列中,这将会容易得多。

var allPieces:Array = [king, queen, bishop_1, bishop_2, knight_1, knight_2, rook_1, rook_2,
pawn_1, pawn_2, pawn_3, pawn_4, pawn_5, pawn_6, pawn_7, pawn_8];

function countCorrect():Boolean {
    var ctr:int = 0;
    for(var i:int=0;i<allPieces.length;i++){
        if(allPieces[i].correct) ctr++;
    }
    return ctr;
}

trace(countCorrect() + " of " allPieces.length " are correct");

顺便说一下,这样做的最佳方法是使用一些自定义类文件。但是,这需要对代码进行完整的重构。

此外,你可能不想使用hitTestObject,因为即使一个片段主要是在一个邻居上,只要它的1个像素的一个像素接触到该片的1个像素,它仍然是真的。最好是在瓷砖上做hitTestPoint,然后传入工件的中心点(工件的中间部分必须接触瓷砖才能计算)。

//a point that is the center of the events current target (the piece)
var point:Point = new Point();
point.x = e.currentTarget.x + (e.currentTarget.width * 0.5);
point.y = e.currentTarget.y - (e.currentTarget.height * 0.5);

if (currentTargetName.hitTestPoint(point)) {