Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Rotating Sprite Center Axis

Contributor ,
Jan 28, 2013 Jan 28, 2013

Hi,

I found an interesting tutorial (link) and created a working model, adapting it as needed.

So far, when I center the container sprite and rotate it, it appears to first rotate from a 0,0 registration point, instead of from its center. I've tried to changet he sprite's registration point, but so far this hasn't worked/helped. Nothing else has worked to fix this rotation problem.

I must be doing something wrong.

Here's the AS3 (to view, add to first frame of new FLA, 1024X768 stage, color black). Rotation segments below are commented as       //ROTATION.:

import flash.display.Sprite;

    import flash.events.MouseEvent;

    import flash.events.Event;

    import flash.text.TextField;

    //import flash.geom.ColorTransform;

stop();

    //public class bejewelled extends Sprite {

        var gems_array:Array=new Array();

        var aGem:Sprite;

        var selectorBox:Sprite=new Sprite();

        var selectorRow:int=-10;

        var selectorColumn:int=-10;

        var red:uint = 0xFF0000;

        var green:uint = 0xFF00;

        var blue:uint = 0xFF;

        var yellow:uint = 0xFFFF00;

        var cyan:uint = 0xFFFF;

        var magenta:uint = 0xFF00FF;

        var white:uint = 0xFFFFFF;

        var colours_array:Array=new Array(red,green,blue,yellow,cyan,magenta,white);

        var clickPossible:Boolean=false;

        var score_txt:TextField=new TextField();

        var hint_txt:TextField=new TextField();

        var score:uint=0;

        var inaRow:uint=0;

        var match:Boolean = true;

        var gemSize:uint = 96;

        var format:TextFormat = new TextFormat();

        var rotate:Boolean=false;

        var container:Sprite = new Sprite(); // Create the container sprite

         //var newColorTransform:ColorTransform = exitBtn.transform.colorTransform;

        //newColorTransform.color = 0xff0000;

        //exitBtn.transform.colorTransform = newColorTransform;

        function bejewelled() {

            // Game initiation

            format.size = 40;

            format.font = 'Arial';

            // Create and style score text

            addChild(score_txt);

            score_txt.textColor=0xFFFFFF;

            score_txt.x=gemSize*9.6;

            score_txt.autoSize = TextFieldAutoSize.LEFT;

            score_txt.defaultTextFormat = format;           

            // Create and style hint text

            addChild(hint_txt);

            hint_txt.textColor=0xFFFFFF;

            hint_txt.x=gemSize*9.6;

            hint_txt.y=gemSize;

            hint_txt.autoSize = TextFieldAutoSize.LEFT;

            hint_txt.defaultTextFormat = format;

            // Create Gems in rows and columns

            addChild(container); // Add the container to the display list (stage)

            for (var i:uint=0; i<8; i++) {

                gems_array=new Array();

                for (var j:uint=0; j<8; j++) {

                    do {

                        gems_array=Math.floor(Math.random()*7);

                    }

                        while (rowLineLength(i,j)>2 || columnLineLength(i,j)>2);

                    aGem=new Sprite();

                    aGem.graphics.beginFill(colours_array[gems_array]);

                    aGem.graphics.drawCircle(gemSize/2,gemSize/2,gemSize/2.07);

                    aGem.graphics.endFill();

                    aGem.name=i+"_"+j;

                    aGem.x=j*gemSize;

                    aGem.y=i*gemSize;

                    container.addChild(aGem);

                }

            }

            //Center the container sprite

            container.width = container.width - 10;

            container.height =  container.height - 10;           

            container.x = (stage.stageWidth-container.width)/2;

            container.y = (stage.stageHeight-container.height)/2;

            // Create and style selector box

            container.addChild(selectorBox);

            selectorBox.graphics.lineStyle(2,red,1);

            selectorBox.graphics.drawRect(0,0,gemSize,gemSize);

            selectorBox.visible=false;

            // Listen for user input

            container.addEventListener(MouseEvent.CLICK,onClick);

            addEventListener(Event.ENTER_FRAME,everyFrame);

        }

        // Every frame...

        function everyFrame(e:Event):void {

            //Assume that gems are not falling

            var gemsAreFalling:Boolean=false;

            // Check each gem for space below it

            for (var i:int=6; i>=0; i--) {

                for (var j:uint=0; j<8; j++) {

                    // If a spot contains a gem, and has an empty space below...

                    if (gems_array != -1 && gems_array[i+1]==-1) {

                        // Set gems falling

                        gemsAreFalling=true;

                        gems_array[i+1]=gems_array;

                        gems_array=-1;

                        trace("#");

                        trace(i+"_"+j);

                        container.getChildByName(i+"_"+j).y+=gemSize;

                        container.getChildByName(i+"_"+j).name=(i+1)+"_"+j;

                        break;

                    }

                }

                // If a gem is falling

                if (gemsAreFalling) {

                    // don't allow any more to start falling

                    break;

                }

            }

            // If no gems are falling

            if (! gemsAreFalling) {

                // Assume no new gems are needed

                var needNewGem:Boolean=false;

                // but check all spaces...

                for (i=7; i>=0; i--) {

                    for (j=0; j<8; j++) {

                        // and if a spot is empty

                        if (gems_array==-1) {

                            // now we know we need a new gem

                            needNewGem=true;

                            // pick a random color for the gem

                            gems_array[0]=Math.floor(Math.random()*7);

                            // create the gem

                            aGem=new Sprite();

                            aGem.graphics.beginFill(colours_array[gems_array[0]]);

                            aGem.graphics.drawCircle(gemSize/2,gemSize/2,gemSize/2.07);

                            aGem.graphics.endFill();

                            // ID it

                            aGem.name="0_"+j;

                            // position it

                            aGem.x=j*gemSize;

                            aGem.y=0;

                            // show it

                            container.addChild(aGem);

                            // stop creating new gems

                            break;

                        }

                    }

                    // if a new gem was created, stop checking

                    if (needNewGem) {

                        break;

                    }

                }

                // If no new gems were needed...

                if (! needNewGem) {

                    // assume no more/new lines are on the board

                    var moreLinesAvailable:Boolean=false;

                    // check all gems

                    for (i=7; i>=0; i--) {

                        for (j=0; j<8; j++) {

                            // if a line is found

                            if (rowLineLength(i,j)>2 || columnLineLength(i,j)>2) {

                                // then we know more lines are available

                                moreLinesAvailable=true;

                                // creat a new array, set the gem type of the line, and where it is

                                var lineGems:Array=[i+"_"+j];

                                var gemType:uint=gems_array;

                                var linePosition:int;

                                // check t's a horizontal line...

                                if (rowLineLength(i,j)>2) {

                                    // if so, find our how long it is and put all the line's gems into the array

                                    linePosition=j;

                                    while (sameGemIsHere(gemType,i,linePosition-1)) {

                                        linePosition--;

                                        lineGems.push(i+"_"+linePosition);

                                    }

                                    linePosition=j;

                                    while (sameGemIsHere(gemType,i,linePosition+1)) {

                                        linePosition++;

                                        lineGems.push(i+"_"+linePosition);

                                    }

                                }

                                // check t's a vertical line...

                                if (columnLineLength(i,j)>2) {

                                    // if so, find our how long it is and put all the line's gems into the array

                                    linePosition=i;

                                    while (sameGemIsHere(gemType,linePosition-1,j)) {

                                        linePosition--;

                                        lineGems.push(linePosition+"_"+j);

                                    }

                                    linePosition=i;

                                    while (sameGemIsHere(gemType,linePosition+1,j)) {

                                        linePosition++;

                                        lineGems.push(linePosition+"_"+j);

                                    }

                                }

                                // for all gems in the line...

                                for (i=0; i<lineGems.length; i++) {

                                    // remove it from the program

                                    container.removeChild(container.getChildByName(lineGems));

                                    // find where it was in the array

                                    var cd:Array=lineGems.split("_");

                                    // set it to an empty gem space

                                    gems_array[cd[0]][cd[1]]=-1;

                                    // set the new score

                                    score+=inaRow;

                                    // set the score setter up

                                    inaRow++;

                                }

                                // if a row was made, stop the loop

                                break;

                            }

                        }

                        // if a line was made, stop making more lines

                        if (moreLinesAvailable) {

                            break;

                        }

                    }

                    // if no more lines were available...

                   //ROTATION

                    if (! moreLinesAvailable) {

                        if(rotate){

                            container.rotation+=5;                           

                            if(container.rotation%90==0){

                                rotate=false;

                                container.rotation=0;

                                rotateClockwise(gems_array);

                                while(container.numChildren>0){

                                    container.removeChildAt(0);

                                }

                                for (i=0; i<8; i++) {

                                    for (j=0; j<8; j++) {

                                        aGem=new Sprite();

                                        aGem.graphics.beginFill(colours_array[gems_array]);

                                        aGem.graphics.drawCircle(gemSize/2,gemSize/2,gemSize/2.07);

                                        aGem.graphics.endFill();

                                        aGem.name=i+"_"+j;

                                        aGem.x=j*gemSize;

                                        aGem.y=i*gemSize;

                                        container.addChild(aGem);                                       

                                        container.addChild(selectorBox);

                                        selectorBox.graphics.lineStyle(2,red,1);

                                        selectorBox.graphics.drawRect(0,0,gemSize,gemSize);

                                        selectorBox.visible=false;

                                    }

                                }

                            }

                        }

                        else{

                            // allow new moves to be made

                            clickPossible=true;

                            // remove score multiplier

                            inaRow=0;

                        }

                    }

                }

            }

            // display new score

            score_txt.text=score.toString();

        }

        // When the user clicks

        function onClick(e:MouseEvent):void {

            // If a click is allowed

            if (clickPossible) {

                // If the click is within the game area...

                if (mouseX<container.x+gemSize*8 && mouseX>0 && mouseY<container.y+gemSize*8 && mouseY>0) {

                    // Find which row and column were clicked

                    var clickedRow:uint=Math.floor((mouseY-container.y)/gemSize);

                    //var clickedRow:uint=Math.floor(e.target.y/gemSize);

                    var clickedColumn:uint=Math.floor((mouseX-container.x)/gemSize);

                    //var clickedColumn:uint=Math.floor(e.target.x/gemSize);

                    // Check if the clicked gem is adjacent to the selector

                    // If not...

                    if (!(((clickedRow==selectorRow+1 || clickedRow==selectorRow-1)&&clickedColumn==selectorColumn)||((clickedColumn==selectorColumn+1 || clickedColumn==selectorColumn-1) && clickedRow==selectorRow))) {

                        // Find row and colum the selector should move to

                        selectorRow=clickedRow;

                        selectorColumn=clickedColumn;

                        // Move it to the chosen position

                        selectorBox.x=gemSize*selectorColumn;

                        selectorBox.y=gemSize*selectorRow;

                        // If hidden, show it.

                        selectorBox.visible=true;

                    }

                    // If it is not next to it...

                    else {

                        // Swap the gems;

                        swapGems(selectorRow,selectorColumn,clickedRow,clickedColumn);

                        // If they make a line...

                        if (rowLineLength(selectorRow,selectorColumn)>2 || columnLineLength(selectorRow,selectorColumn)>2||rowLineLength(clickedRow,clickedColumn)>2 || columnLineLength(clickedRow,clickedColumn)>2) {

                            // remove the hint text

                            hint_txt.text="";

                            // dis-allow a new move until cascade has ended (removes glitches)

                            clickPossible=false;

                            // move and rename the gems

                            container.getChildByName(selectorRow+"_"+selectorColumn).x=e.target.x;//clickedColumn*gemSize;

                            container.getChildByName(selectorRow+"_"+selectorColumn).y=e.target.y;//clickedRow*gemSize;

                            container.getChildByName(selectorRow+"_"+selectorColumn).name="t";

                            container.getChildByName(clickedRow+"_"+clickedColumn).x=selectorColumn*gemSize;

                            container.getChildByName(clickedRow+"_"+clickedColumn).y=selectorRow*gemSize;

                            container.getChildByName(clickedRow+"_"+clickedColumn).name=selectorRow+"_"+selectorColumn;

                            container.getChildByName("t").name=clickedRow+"_"+clickedColumn;

                            match = true;

                            rotate = true;

                        }

                        // If not...

                        else {

                            // Switch them back

                            swapGems(selectorRow,selectorColumn,clickedRow,clickedColumn);

                            match = false;

                        }

                        if (match) {

                            // Move the selector position to default

                            selectorRow=-10;

                            selectorColumn=-10;

                            // and hide it

                            selectorBox.visible=false;

                        }

                        else {

                            // Set the selector position

                            selectorRow=clickedRow;

                            selectorColumn=clickedColumn;

                            // Move the box into position

                            selectorBox.x=gemSize*selectorColumn;

                            selectorBox.y=gemSize*selectorRow;

                            match = false;

                            // If hidden, show it.

                            selectorBox.visible=true;

                        }

                    }

                }

                // If the click is outside the game area

                else {

                    // For gems in all rows...

                    for (var i:uint=0; i<8; i++) {

                        // and columns...

                        for (var j:uint=0; j<8; j++) {

                            // if they're not too close to the side...

                            if (i<7) {

                                // swap them horizontally

                                swapGems(i,j,i+1,j);

                                // check if they form a line

                                if ((rowLineLength(i,j)>2||columnLineLength(i,j)>2||rowLineLength(i+1,j)>2||columnLineLength(i+1,j)>2)) {

                                    // if so, name the move made

                                    selectorBox.x = j*gemSize;

                                    selectorBox.y = i*gemSize;

                                    selectorBox.visible = true;

                                    hint_txt.text = (i+1).toString()+","+(j+1).toString()+"->"+(i+2).toString()+","+(j+1).toString();

                                }

                                // swap the gems back

                                swapGems(i,j,i+1,j);

                            }

                            // then if they're not to close to the bottom...

                            if (j<7) {

                                // swap it vertically

                                swapGems(i,j,i,j+1);

                                // check if it forms a line

                                if ((rowLineLength(i,j)>2||columnLineLength(i,j)>2||rowLineLength(i,j+1)>2||columnLineLength(i,j+1)>2) ) {

                                    // if so, name it

                                    selectorBox.x = j*gemSize;

                                    selectorBox.y = i*gemSize;

                                    selectorBox.visible = true;

                                    hint_txt.text = (i+1).toString()+","+(j+1).toString()+"->"+(i+1).toString()+","+(j+2).toString();

                                }

                                // swap the gems back

                                swapGems(i,j,i,j+1);

                            }

                        }

                    }

                }

            }

        }

        //Swap given gems

        function swapGems(fromRow:uint,fromColumn:uint,toRow:uint,toColumn:uint):void {

            //Save the original position

            var originalPosition:uint=gems_array[fromRow][fromColumn];

            //Move original gem to new position

            gems_array[fromRow][fromColumn]=gems_array[toRow][toColumn];

            //move second gem to saved, original gem's position

            gems_array[toRow][toColumn]=originalPosition;

        }

        //Find out if there us a horizontal line

        function rowLineLength(row:uint,column:uint):uint {

            var gemType:uint=gems_array[row][column];

            var lineLength:uint=1;

            var checkColumn:int=column;

            //check how far left it extends

            while (sameGemIsHere(gemType,row,checkColumn-1)) {

                checkColumn--;

                lineLength++;

            }

            checkColumn=column;

            //check how far right it extends

            while (sameGemIsHere(gemType,row,checkColumn+1)) {

                checkColumn++;

                lineLength++;

            }

            // return total line length

            return (lineLength);

        }

        //Find out if there us a vertical line

        function columnLineLength(row:uint,column:uint):uint {

            var gemType:uint=gems_array[row][column];

            var lineLength:uint=1;

            var checkRow:int=row;

            //check how low it extends

            while (sameGemIsHere(gemType,checkRow-1,column)) {

                checkRow--;

                lineLength++;

            }

            //check how high it extends

            checkRow=row;

            while (sameGemIsHere(gemType,checkRow+1,column)) {

                checkRow++;

                lineLength++;

            }

            // return total line length

            return (lineLength);

        }

        function sameGemIsHere(gemType:uint,row:int,column:int):Boolean {

            //Check there are gems in the chosen row

            if (gems_array[row]==null) {

                return false;

            }

            //If there are, check if there is a gem in the chosen slot

            if (gems_array[row][column]==null) {

                return false;

            }

            //If there is, check if it's the same as the chosen gem type

            return gemType==gems_array[row][column];

        }

           //ROTATION

           function rotateClockwise(a:Array):void {

            var n:int=a.length;

            for (var i:int=0; i<n/2; i++) {

                for (var j:int=i; j<n-i-1; j++) {

                    var tmp:String=a;

                    a=a[n-j-1];

                    a[n-j-1]=a[n-i-1][n-j-1];

                    a[n-i-1][n-j-1]=a[n-i-1];

                    a[n-i-1]=tmp;

                }

            }

        }

bejewelled();  

Any help appreciated.

TOPICS
ActionScript
1.5K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 28, 2013 Jan 28, 2013

You can't programmatically move a registration point but what you usually do is move the contents of the clip into negative space.

e.g. a 100px X 100px box, move the position to -50x by -50x. Then the registration is in the center.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Jan 28, 2013 Jan 28, 2013

Actually you sort of can change the reg point. Using a similar example as I posted above:

var a:MovieClip = new car(); //library clip

addChild(a);

a.x = 50; a.y = 50;

changeRegPt(a, a.width/2, a.height/2);

function changeRegPt(dobj:DisplayObjectContainer,x:Number,y:Number){

    var r:Rectangle = dobj.getBounds(dobj);

    for(var i:uint=0;i<dobj.numChildren;i++){

        dobj.getChildAt(i).x -= r.x+x;

        dobj.getChildAt(i).y -= r.y+y;

    }

    dobj.x += r.x+x;

    dobj.y += r.y+y;

}

addEventListener(Event.ENTER_FRAME, up);

function up(e:Event):void

{

          a.rotation += 1;

}

So, instead of sticking the car in a container, you just call changeRegPoint first and then rotate as normal... If you wanted it to rotate about the front center of the hood you'd just do:

changeRegPt(a, a.width, a.height/2);

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 28, 2013 Jan 28, 2013

Bounds are determined at the current frame. If the user has a clip that animates, causing it to expand or collapse, your changeRegPt() method won't work. At the point an ENTER_FRAME would need to continuously re-echeck the bounds and that's extremely expensive. Also, custom objects don't always have an x/y property or aren't on the display list, like StageWebView. More logic is needed, there is no magic bullet here.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jan 28, 2013 Jan 28, 2013

Hi Sinious and dmeN,

Thank you for these suggestions and better understanding. I think one challenge is that the export will run full screen on different devices. So, I am not sure that a fix that changes X and Y by a fixed amount, like -100, can work.

Interestingly, in the original script in the tutorial (see link) the sprite rotates OK in a 640X480 stage, but looks like it is set at 0,0 (top left), not centered.

I am guessing from your replies that there is no easy way to simply center that spite? (I've tried the registration point change-found it in this forum, posted by kglad- but in this situation, as you have noted, it will not produce a center rotation.)

So, it appears that without a complete re-write (unfortunately, beyond my ability), no easy way to accomplish a center rotation?

saratogacoach

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jan 28, 2013 Jan 28, 2013

You can't shift a registration point. Boy, it'd be a great feature, but you can't. Your job is to move "everything that clip controls" into the center of that point. Components, AIR native bindings (StageWebView), GPU elements (StageVideo), you name it. You must, as always, measure twice, cut once. If you didn't pre-plan all your work for immutable center point registration, you need to do the work of moving those elements (whatever they are, in their respective manner) to your central registration point yourself.

Next project you'll do I bet you won't forget it .

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jan 28, 2013 Jan 28, 2013
LATEST

Hi sinious,

Yes, true. A good learning experience.

The link in the  postings above is not connecting. Here it is: http://www.emanueleferonato.com/2012/11/09/bejeweled-as3-engine-with-array-rotation/

Best Wishes,

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Jan 28, 2013 Jan 28, 2013

OK, way too much code. By default, everything will rotate from top left. If you want to change that you need to change the positions of the content within the container, not the container itself.

For example if you do something like this:

var a:Sprite = new Sprite(); //container

addChild(a);

a.x = 100; a.y = 100;

var b:MovieClip = new car(); //clip from library

a.addChild(b);

addEventListener(Event.ENTER_FRAME, up);

function up(e:Event):void

{

          a.rotation += 1;

}

The car added to the container will rotate about it's top left point... because that's where the container rotates about. To fix, move the car so the containers top/left is at the car's center like so:

var a:Sprite = new Sprite();

addChild(a);

a.x = 100; a.y = 100;

var b:MovieClip = new car();

a.addChild(b);

b.x -= b.width / 2;

b.y -= b.height / 2;

addEventListener(Event.ENTER_FRAME, up);

function up(e:Event):void

{

          a.rotation += 1;

}

You'll notice all that changed is moving the car 1/2 it's width and height.

HTH

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines