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

Pairing a draggable object to a target object in AS3

我目前坚持使用下面的方法。我不完全确定使用“hitTestObject”方法是否适合将片段配对到各自的位置。我至少能够将棋子与它们各自的位置相匹配(这是我能做的最好的,我觉得我做错了)但我现在一直在计算实际上有多少棋子在它们正确的位置。例如当我将棋子移动到不同的图块时,它仍然会算作一个,我也想避免重复计数,例如,如果棋子已经在正确的位置,它只会算作 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 中制作棋盘游戏,它具有与此类似的功能和行为。用户可以将对象拖动到指定的图块并检查该对象是否属于那里。

查看您的代码后,您的问题很宽泛。我将把它与你最关心的问题配对——分数/正确移动的棋子计数。

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

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");

顺便说一句,最好的方法是使用一些自定义 class 文件。但是,这需要对您的代码进行完全重构。

此外,您可能不想使用 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)) {