AS3 洗牌影片剪辑
AS3 shuffling movieclips
我已经添加了基本目标并为我的拼图块应用了拖放,现在我在洗牌方面遇到了麻烦。例如,在玩家完成或打开 fla 后,每次都会在舞台的随机位置开始拼图。我了解使用数组以某种方式进行洗牌,但我不确定如何实现这一点。我已经将 19 个拼图的实例存储在数组中,但现在我不知道如何处理这个数组。其他教程超出了我的范围,让我摸不着头脑。
刚开始为 Flash Professional 编写代码,所以是的,如果您能帮助我整理电影剪辑,即拼图,我们将不胜感激。
这是我的代码,我不会把所有的东西都贴出来,因为从 P1 到 P19 基本上是复制粘贴:
import flash.events.Event;
stage.addEventListener(Event.ENTER_FRAME, EntFrame)
function EntFrame(e: Event) : void
{
P1.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
function fl_ClickToDrag(event:MouseEvent):void
{
P1.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
function fl_ReleaseToDrop(event:MouseEvent):void
{
P1.stopDrag();
}
if (T1.hitTestObject(P1.Tar1))
{
P1.x = 313.15;
P1.y = 242.75;
}
P19.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag_19);
function fl_ClickToDrag_19(event:MouseEvent):void
{
P19.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop_19);
function fl_ReleaseToDrop_19(event:MouseEvent):void
{
P19.stopDrag();
}
if (T19.hitTestObject(P19.Tar19))
{
P19.x = 624.35;
P19.y = 455.60;
}
}
嗯,一般情况下你可以用下面的代码洗牌:
var shuffledVector:Vector.<someClass> = new Vector.<someClass>;
while (originalVector.length > 0) {
shuffledVector.push(originalVector.splice(Math.random() * originalVector.length, 1)[0]);
}
更长的解释版本:
var shuffledVector:Vector.<someClass> = new Vector.<someClass>; //We will store our shuffled vector in here
var randomIndex:int; //Random index from the originalVector
var resultVector:Vector.<someClass>; //result from the originalVector.splice(...) function
var randomElement:someClass; //Random element from the originalVector
while (originalVector.length > 0) { //We will reduce the size of the originalVector until the originalVector is empty.
randomIndex = Math.random() * originalVector.length; //Calculate a random index within the range of the originalVector from 0 to originalVector.lenght-1 (note that the range decreases by one on every loop)
randomVector = originalVector.splice(randomIndex, 1); //Use splice to remove one element at the randomly choosen index, we will receive a vector with the removed element...
randomElement = randomVector[0]; //...so we need to access the element
shuffledVector.push(randomElement); //Add the randomly choosen element to our shuffled vector
}
我已经按照我建议使用向量而不是数组的方式编写了向量代码,但它背后的原理与数组相同。
在你的例子中,originalVector 是一个用你的 P1-P19 Movieclips 填充的向量,someClass 将是 MovieClip。 originalVector 最后是空的,可以用打乱后的那个替换,当然如果你把代码放在一个单独的函数中,这样会更有意义:
function Shuffle(originalVector:Vector.<someClass>) : void {
var shuffledVector:Vector.<someClass> = new Vector.<someClass>;
while (originalVector.length > 0) {
shuffledVector.push(originalVector.splice(Math.random() * originalVector.length, 1)[0]);
}
originalVector = shuffledVector;
}
题外话,但对进一步编码很重要: 其他人已经提到,在每一帧都添加 EventListeners 是不好的,因为这是绝对没有必要的。您只需要添加一次监听器。您的代码非常重复,您应该使用接受 MovieClip、x 和 y 的函数,然后调用该函数 19 次。
例如:
function setUpMovieClip(MC:MovieClip, x:int, y:int) : {
MC.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
//more code...
}
在 clickToDrag 函数中,您可以访问通过 event.target 属性:
单击的 MovieClip
function clickToDrag(e:MouseEvent) : {
e.target.startDrag();
//more code...
}
希望你明白了。
我希望这是更全面的答案。
首先,放弃那些内联函数。现在您创建了一个 ENTER_FRAME 侦听器,并且在该函数中定义了内联函数。这意味着每个帧滴答声(与您的帧速率相关,而不是主时间轴),这些函数将再次创建,并且由于您将它们添加为侦听器的处理程序,它们将永远保留在内存中。
这是一种编码方式,展示了减少冗余和消除内存泄漏的方法。这假设如下:
你在名为 T1
- T19
的舞台上有 19 个物体,它们代表棋子可能到达的位置。
舞台上有 19 个棋子 P1
- P19
,根据正确的位置,数字对应 T
个位置作品.
//let's create a function to randomize the piece location
function seedPieces() {
//create an array consisting of the integers 1 - 19
var unusedSpaces:Vector.<int> = new Vector.<int>;
var i:int;
for (i = 1; i <= 19; i++) {
//populate that array
unusedSpaces.push(i);
}
var curLocation:DisplayObject; //helper var for the loop below
var curPiece:Sprite; //helper var for the loop below
//loop 19 times (from 1 - 19) - one iteration for each piece
for (i = 1; i <= 19; i++) {
curPiece = this["P" + i] as Sprite; //you can get the piece this way, or use an array if you've made one, like `pieces[i];`
trace(curPiece.name);
//splice removes and returns the item at the specified index (in this case a random number between 0 and arrays length less 1) - the second parameter is amount of items to remove (just 1 for this case)
curLocation = this["T" + unusedSpaces.splice(int(Math.random() * unusedSpaces.length), 1)] as DisplayObject;
trace(" ",curLocation.name);
//move the piece to the random location:
curPiece.x = curLocation.x;
curPiece.y = curLocation.y;
}
}
//NOW, as an aside, you should use a loop to add all your listeners for the sake of sanity - if you have them in an array, loop through that, or use the sloppy way like this:
for (var i:int = 1; i <= 19; i++) {
Sprite(this["P" + i]).addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
}
//create a var to hold any piece that is currently being dragged, so you know which piece to stop drag on later
var currentDraggingItem:Sprite;
seedPieces();
function fl_ClickToDrag(event:MouseEvent):void
{
//assign this clicked item to the currentDraggingItem var
currentDraggingItem = event.currentTarget as Sprite;
//bring this one to the front
currentDraggingItem.parent.addChild(currentDraggingItem);
//you can use this one click handler for all pieces
//the piece that was actually clicked, is referenced by event.currentTarget
currentDraggingItem.startDrag();
//add the mouse up listener now that the mouse is currently DOWN
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
//listen every frame while dragging
stage.addEventListener(Event.ENTER_FRAME, EntFrame);
}
function fl_ReleaseToDrop(event:MouseEvent):void
{
//if currentDraggingItem has a value, stop drag it
if (currentDraggingItem) {
currentDraggingItem.stopDrag();
//send to the back
currentDraggingItem.parent.addChildAt(currentDraggingItem,0);
}
//remove the mouse up and enter frame listener now that the mouse is UP
stage.removeEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
stage.removeEventListener(Event.ENTER_FRAME, EntFrame);
if(checkComplete()){
//game over, do something
}
}
function EntFrame(e: Event) : void
{
//this will snap the peice to the correct spot when the mouse is touching the correct spot
if(currentDraggingItem){
if (this[currentDraggingItem.name.replace("P","T")].hitTestPoint(mouseX,mouseY))
{
currentDraggingItem.x = this[currentDraggingItem.name.replace("P","T")].x;
currentDraggingItem.y = this[currentDraggingItem.name.replace("P","T")].y;
}
}
}
function checkComplete():Boolean {
//use a loop to go through all your pieces and check if they are in the right spot. Again, you could have them in an array, or do it the lazy way
for (var i:int = 1; i <= 19; i++) {
if (!this["T"+i].hitTestObject(this["P"+i]))
{
return false;
}
}
return true;
}
我已经添加了基本目标并为我的拼图块应用了拖放,现在我在洗牌方面遇到了麻烦。例如,在玩家完成或打开 fla 后,每次都会在舞台的随机位置开始拼图。我了解使用数组以某种方式进行洗牌,但我不确定如何实现这一点。我已经将 19 个拼图的实例存储在数组中,但现在我不知道如何处理这个数组。其他教程超出了我的范围,让我摸不着头脑。
刚开始为 Flash Professional 编写代码,所以是的,如果您能帮助我整理电影剪辑,即拼图,我们将不胜感激。
这是我的代码,我不会把所有的东西都贴出来,因为从 P1 到 P19 基本上是复制粘贴:
import flash.events.Event;
stage.addEventListener(Event.ENTER_FRAME, EntFrame)
function EntFrame(e: Event) : void
{
P1.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
function fl_ClickToDrag(event:MouseEvent):void
{
P1.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
function fl_ReleaseToDrop(event:MouseEvent):void
{
P1.stopDrag();
}
if (T1.hitTestObject(P1.Tar1))
{
P1.x = 313.15;
P1.y = 242.75;
}
P19.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag_19);
function fl_ClickToDrag_19(event:MouseEvent):void
{
P19.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop_19);
function fl_ReleaseToDrop_19(event:MouseEvent):void
{
P19.stopDrag();
}
if (T19.hitTestObject(P19.Tar19))
{
P19.x = 624.35;
P19.y = 455.60;
}
}
嗯,一般情况下你可以用下面的代码洗牌:
var shuffledVector:Vector.<someClass> = new Vector.<someClass>;
while (originalVector.length > 0) {
shuffledVector.push(originalVector.splice(Math.random() * originalVector.length, 1)[0]);
}
更长的解释版本:
var shuffledVector:Vector.<someClass> = new Vector.<someClass>; //We will store our shuffled vector in here
var randomIndex:int; //Random index from the originalVector
var resultVector:Vector.<someClass>; //result from the originalVector.splice(...) function
var randomElement:someClass; //Random element from the originalVector
while (originalVector.length > 0) { //We will reduce the size of the originalVector until the originalVector is empty.
randomIndex = Math.random() * originalVector.length; //Calculate a random index within the range of the originalVector from 0 to originalVector.lenght-1 (note that the range decreases by one on every loop)
randomVector = originalVector.splice(randomIndex, 1); //Use splice to remove one element at the randomly choosen index, we will receive a vector with the removed element...
randomElement = randomVector[0]; //...so we need to access the element
shuffledVector.push(randomElement); //Add the randomly choosen element to our shuffled vector
}
我已经按照我建议使用向量而不是数组的方式编写了向量代码,但它背后的原理与数组相同。
在你的例子中,originalVector 是一个用你的 P1-P19 Movieclips 填充的向量,someClass 将是 MovieClip。 originalVector 最后是空的,可以用打乱后的那个替换,当然如果你把代码放在一个单独的函数中,这样会更有意义:
function Shuffle(originalVector:Vector.<someClass>) : void {
var shuffledVector:Vector.<someClass> = new Vector.<someClass>;
while (originalVector.length > 0) {
shuffledVector.push(originalVector.splice(Math.random() * originalVector.length, 1)[0]);
}
originalVector = shuffledVector;
}
题外话,但对进一步编码很重要: 其他人已经提到,在每一帧都添加 EventListeners 是不好的,因为这是绝对没有必要的。您只需要添加一次监听器。您的代码非常重复,您应该使用接受 MovieClip、x 和 y 的函数,然后调用该函数 19 次。 例如:
function setUpMovieClip(MC:MovieClip, x:int, y:int) : {
MC.addEventListener(MouseEvent.MOUSE_DOWN, clickToDrag);
//more code...
}
在 clickToDrag 函数中,您可以访问通过 event.target 属性:
单击的 MovieClipfunction clickToDrag(e:MouseEvent) : {
e.target.startDrag();
//more code...
}
希望你明白了。
我希望这是更全面的答案。
首先,放弃那些内联函数。现在您创建了一个 ENTER_FRAME 侦听器,并且在该函数中定义了内联函数。这意味着每个帧滴答声(与您的帧速率相关,而不是主时间轴),这些函数将再次创建,并且由于您将它们添加为侦听器的处理程序,它们将永远保留在内存中。
这是一种编码方式,展示了减少冗余和消除内存泄漏的方法。这假设如下:
你在名为
T1
-T19
的舞台上有 19 个物体,它们代表棋子可能到达的位置。舞台上有 19 个棋子
P1
-P19
,根据正确的位置,数字对应T
个位置作品.//let's create a function to randomize the piece location function seedPieces() { //create an array consisting of the integers 1 - 19 var unusedSpaces:Vector.<int> = new Vector.<int>; var i:int; for (i = 1; i <= 19; i++) { //populate that array unusedSpaces.push(i); } var curLocation:DisplayObject; //helper var for the loop below var curPiece:Sprite; //helper var for the loop below //loop 19 times (from 1 - 19) - one iteration for each piece for (i = 1; i <= 19; i++) { curPiece = this["P" + i] as Sprite; //you can get the piece this way, or use an array if you've made one, like `pieces[i];` trace(curPiece.name); //splice removes and returns the item at the specified index (in this case a random number between 0 and arrays length less 1) - the second parameter is amount of items to remove (just 1 for this case) curLocation = this["T" + unusedSpaces.splice(int(Math.random() * unusedSpaces.length), 1)] as DisplayObject; trace(" ",curLocation.name); //move the piece to the random location: curPiece.x = curLocation.x; curPiece.y = curLocation.y; } } //NOW, as an aside, you should use a loop to add all your listeners for the sake of sanity - if you have them in an array, loop through that, or use the sloppy way like this: for (var i:int = 1; i <= 19; i++) { Sprite(this["P" + i]).addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag); } //create a var to hold any piece that is currently being dragged, so you know which piece to stop drag on later var currentDraggingItem:Sprite; seedPieces(); function fl_ClickToDrag(event:MouseEvent):void { //assign this clicked item to the currentDraggingItem var currentDraggingItem = event.currentTarget as Sprite; //bring this one to the front currentDraggingItem.parent.addChild(currentDraggingItem); //you can use this one click handler for all pieces //the piece that was actually clicked, is referenced by event.currentTarget currentDraggingItem.startDrag(); //add the mouse up listener now that the mouse is currently DOWN stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop); //listen every frame while dragging stage.addEventListener(Event.ENTER_FRAME, EntFrame); } function fl_ReleaseToDrop(event:MouseEvent):void { //if currentDraggingItem has a value, stop drag it if (currentDraggingItem) { currentDraggingItem.stopDrag(); //send to the back currentDraggingItem.parent.addChildAt(currentDraggingItem,0); } //remove the mouse up and enter frame listener now that the mouse is UP stage.removeEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop); stage.removeEventListener(Event.ENTER_FRAME, EntFrame); if(checkComplete()){ //game over, do something } } function EntFrame(e: Event) : void { //this will snap the peice to the correct spot when the mouse is touching the correct spot if(currentDraggingItem){ if (this[currentDraggingItem.name.replace("P","T")].hitTestPoint(mouseX,mouseY)) { currentDraggingItem.x = this[currentDraggingItem.name.replace("P","T")].x; currentDraggingItem.y = this[currentDraggingItem.name.replace("P","T")].y; } } } function checkComplete():Boolean { //use a loop to go through all your pieces and check if they are in the right spot. Again, you could have them in an array, or do it the lazy way for (var i:int = 1; i <= 19; i++) { if (!this["T"+i].hitTestObject(this["P"+i])) { return false; } } return true; }