Skip to main content
Known Participant
January 24, 2014
Answered

Tile Based Movement in AS3

  • January 24, 2014
  • 2 replies
  • 1671 views

Hello i am still trying to create tile based movement. What i mean by that is the character can move smoothly but will always end up in the middle of a tile (just like the pokemon games). I have managed to make it work if the player uses only one key, however in combination with other keys it does not work. I was hoping someone could give me advise how to fix the code or perhaps some better/easier way to do it.

Here is my code so far (this is only for left and right key) my character movieclip has the instance name char

import flash.ui.Keyboard;

import flash.events.KeyboardEvent;

import flash.events.Event;

import fl.transitions.easing.*;

import com.greensock.*;

var pixelsMoved:Number = 0;

var pixelsLeft:Number = 0;

var tweening:Boolean = false;

var rightKeyDown:Boolean = false;

var leftKeyDown:Boolean = false;

addEventListener(Event.ENTER_FRAME,Loop);

stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyPress);

stage.addEventListener(KeyboardEvent.KEY_UP,KeyRelease);

function Loop(event:Event):void

{

    if (tweening == false)

    {

        if (rightKeyDown == true)

        {

            char.x += 1;

            pixelsMoved += 1;

        }

       

        else if (leftKeyDown == true)

        {

            char.x -= 1;

            pixelsMoved += 1;

        }

       

        if (pixelsMoved >= 25)

        {

            pixelsMoved = 0;

            pixelsLeft = 25;

        }

    }

}

function KeyPress(event:KeyboardEvent):void

{

    if (event.keyCode == Keyboard.RIGHT)

    {

        rightKeyDown = true;

    }

   

    if (event.keyCode == Keyboard.LEFT)

    {

        leftKeyDown = true;

    }

}

function KeyRelease(event:KeyboardEvent):void

{

    pixelsLeft = 25 - pixelsMoved;

   

    if (event.keyCode == Keyboard.RIGHT)

    {

        if (tweening == false)

        {

            var moveRight:TweenLite = new TweenLite(char,pixelsLeft,{x:char.x + pixelsLeft,ease:None.easeNone,useFrames: true,onComplete: resetVars});

        }

        rightKeyDown = false;

        tweening = true;

    }

   

    if (event.keyCode == Keyboard.LEFT)

    {

        if (tweening == false)

        {

            var moveLeft:TweenLite = new TweenLite(char,pixelsLeft,{x:char.x - pixelsLeft,ease:None.easeNone,useFrames: true,onComplete: resetVars});

        }

        leftKeyDown = false;

        tweening = true;

    }

}

function resetVars():void

{

    tweening = false;

    pixelsLeft = 0;

    pixelsMoved = 0;

}

Any help is much apreciated!

This topic has been closed for replies.
Correct answer kglad

you can use else-if statements for right/left and for up/down but not right/left/up/down in your Loop function.

you also will find it easier to just use four booleans to determine what action to take in Loop.

2 replies

Inspiring
January 25, 2014

I am not sure I understand all the requirements. Also I guess you refer to pacman game - not pokemon.

In any case, here is something that works pretty smooth at 60fps. Note there are no ENTER_FRAME handlers - all animations are handled by TweenLite.

Just dump the code on a timeline in a new FLA - it is not meant to be injected into your existing code. So, this is just an independent fully functional concept. All objects are created dynamically by the script - you don't have to do anything to view/test this example.

Read comments.

import com.greensock.easing.Ease;

import com.greensock.easing.Linear;

import com.greensock.easing.Sine;

import com.greensock.TweenLite;

import flash.display.Graphics;

import flash.display.Shape;

import flash.display.Sprite;

import flash.events.KeyboardEvent;

import flash.geom.Point;

import flash.ui.Keyboard;

var board:Sprite;

var tileSide:Number = 40;

var numRows:int = 10;

var numCols:int = 14;

var char:Shape;

var _currentKey:uint = 0;

var tween:TweenLite;

init();

function init():void

{

          drawBoard();

          configStage();

}

function configStage():void

{

          stage.scaleMode = StageScaleMode.NO_SCALE;

          stage.align = StageAlign.TOP_LEFT;

          stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPress);

          stage.addEventListener(KeyboardEvent.KEY_UP, onKeyRelease);

}

function onKeyRelease(e:KeyboardEvent):void

{

          // if the latest processed key was not release - we block the latest pressed key

          if (e.keyCode == _currentKey)

                    _currentKey = 0;

}

function onKeyPress(e:KeyboardEvent):void

{

          currentKey = e.keyCode;

}

function get tile():Shape

{

          var shape:Shape = new Shape();

          shape.cacheAsBitmap = true;

          var color:uint = 0x808080;

          var g:Graphics = shape.graphics;

          g.lineStyle(1, color);

          g.beginFill(0xEBEBEB);

          g.drawRect(-tileSide / 2, -tileSide / 2, tileSide, tileSide);

          return shape;

}

function moveChar(targetX:int = 0, targetY:int = 0):void

{

          tween = TweenLite.to(char, 0.45, {x: targetX, y: targetY, ease: Linear.easeNone, onComplete: onTweenComplete});

}

function onTweenComplete():void

{

          /**

           * need to do that

           * a. if key is kept pressed

           * c. to override situations when another key is pressed simulataneously

           */

          currentKey = _currentKey;

}

function set currentKey(value:uint):void

{

          var targetPosition:Number = 0;

          /**

           * key value is proccessed if

           * a. key is allowed - via switch

           * b. there is no key pressed before or ptreviously pressed key _currentKey is the same as new value

           * c. tween in not active

           */

          if ((!_currentKey || _currentKey == value) && !tween._active)

          {

                    switch (value)

                    {

                              case Keyboard.RIGHT:

                                        targetPosition = char.x + tileSide;

                                        if (targetPosition < tileSide * numCols)

                                        {

                                                  moveChar(targetPosition, char.y);

                                                  charRotation = 0;

                                        }

                                        _currentKey = value;

                                        break;

                              case Keyboard.LEFT:

                                        targetPosition = char.x - tileSide;

                                        if (targetPosition >= 0)

                                        {

                                                  moveChar(targetPosition, char.y);

                                                  charRotation = 180;

                                        }

                                        _currentKey = value;

                                        break;

                              case Keyboard.UP:

                                        targetPosition = char.y - tileSide;

                                        if (targetPosition >= 0)

                                        {

                                                  moveChar(char.x, targetPosition);

                                                  charRotation = -90;

                                        }

                                        _currentKey = value;

                                        break;

                              case Keyboard.DOWN:

                                        targetPosition = char.y + tileSide;

                                        if (targetPosition < tileSide * numRows)

                                        {

                                                  moveChar(char.x, targetPosition);

                                                  charRotation = 90;

                                        }

                                        _currentKey = value;

                                        break;

                    }

          }

}

function set charRotation(value:Number):void

{

          if (char.rotation == -180)

                    char.rotation = 180;

          if (char.rotation == 180 && value == -90)

                    char.rotation = -180;

          else if (char.rotation == -90 && value == 180)

                    value = -180;

          TweenLite.to(char, 0.2 * (Math.abs((char.rotation - value) / 90) || 1), {rotation: value});

}

function drawBoard():void

{

          board = new Sprite();

          var numTiles:int = numRows * numCols;

          for (var i:int = 0; i < numTiles; i++)

          {

                    var t:Shape = tile;

                    t.x = tileSide * (i % numCols);

                    t.y = tileSide * int(i / numCols);

                    board.addChild(t);

          }

          board.addChild(addChar);

          addChild(board);

          board.x = board.y = 20 + tileSide / 2;

}

function get addChar():Shape

{

          var radius:Number = tileSide / 2 - 4;

          char = new Shape();

          var g:Graphics = char.graphics;

          g.lineStyle(1);

          g.beginFill(0xff0000);

          g.drawCircle(0, 0, radius);

          g.endFill();

          g.lineStyle(2);

          g.moveTo(0, 0);

          g.lineTo(radius, 0);

          g.beginFill(0x000000);

          g.moveTo(radius, 0);

          g.lineTo(radius - 10, 4);

          g.lineTo(radius - 10, -4);

          g.endFill();

          tween = new TweenLite(char, 1, null);

          char.cacheAsBitmap = true;

          return char;

}

Known Participant
January 27, 2014

Hey thank you for all your troubles! That is some very good code however it does take a small amount of time for flash to load the next tween which makes the character stop for a moment everytime it lands on a new tile. I have already found this tutorial which i am probably going to use. http://tbg.tonypa.pri.ee/tut05.html

Thanks for the help though

kglad
Community Expert
kgladCommunity ExpertCorrect answer
Community Expert
January 24, 2014

you can use else-if statements for right/left and for up/down but not right/left/up/down in your Loop function.

you also will find it easier to just use four booleans to determine what action to take in Loop.

Known Participant
January 24, 2014

Thanks but it still does not work, when both right and left key is pressed it doesn't work. Can i upload a swf file here? If you want to see what's wrong

kglad
Community Expert
Community Expert
January 24, 2014

if you want both right and left keys to be active, don't use if-else for them either and remove your tweening boolean.