how to move a movie clip from a ref movie clip - actionscript-3

I want to make a movieClip which has a reference of another movie clip move.
But when i do it it stays still.
Here is an example code i am trying to do
var movieClip1 = new movieClip();
var movieClip2 = new movieClip();
movieClip1.ref = movieClip2;
movieClip1.x = 0;
movieClip2.x = 0;
addChild(movieClip1);
addChild(movieClip2);
while(movieClip1.x !=300){
movieClip1.x +=1;
// i want to make the reference of the clip move as well
movieClip1.ref.x = movieClip1.x;
}

How are you wanting it to move? Progressively, 1 unit at a time? If so Don't use a while loop or it will simply jump straight to 300 (x position).
Instead use some sort of update loop like an enter frame listener:
addEventListener(Event.ENTER_FRAME, Update);
function Update(e:Event):void
{
mc1.x++;
mc1.ref.x = mc1.x;
}

Related

AS3 Drag and Drop

I want to make a pairing-ups by drag and drop. There are three items are supposed to move on corresponding other three items on the stage. However I can predict that adding children dynamically change the all indexes (z/depth/whatever). So when 'accidentally' someone hovers over a matched pair, mouse will be over item but dragged one stands behind. At that time 'dropping' will possibly ruin the programme.
Is there any way to avoid that situation? Any help will greatly appreciated.
You should set dragging object above all:
Sprite(draggingObject.parent).setChildIndex(draggingObject, Sprite(draggingObject.parent).numChildren - 1);
also you need to listen MOUSE_UP event at stage value.
Worked example:
import flash.display.Sprite;
import flash.events.MouseEvent;
var container:Sprite = new Sprite();
var dragged:Sprite;
addChild(container);
var card:Sprite;
for (var j:uint = 0; j < 10; j++) {
card = new Sprite();
container.addChild(card);
card.buttonMode = true;
card.graphics.beginFill(0x000000);
card.graphics.drawRect(0,0,30,30);
card.x = j*40;
card.addEventListener(MouseEvent.MOUSE_DOWN, stardDragListener);
}
stage.addEventListener(MouseEvent.MOUSE_UP, stopDragEvent);
function stardDragListener(e:MouseEvent):void {
dragged = Sprite(e.currentTarget);
Sprite(dragged.parent).setChildIndex(dragged, Sprite(dragged.parent).numChildren - 1)
dragged.startDrag();
}
function stopDragEvent(e:MouseEvent):void {
if (dragged) dragged.stopDrag();
}

Add a new instance of movie clip each time I click

I'm trying to create a movie clip every time I click the stage. I know that addChild does not add new instances, so every time I click, the previous cube disappears. I tried using an array to create multiple movie clips with no success. I'm pretty new to ActionScript, so I'm sorry for this naive question.
stage.addEventListener(MouseEvent.CLICK, spawnCube);
var i:int = 0;
var p1:cube = new cube();
function spawnCube(event:MouseEvent):void
{
p1.name = "p1";
p1.x = mouseX;
p1.y = mouseY;
arr.push(p1);
addChild(arr[i]);
i++;
}
Place new Cube() call into your click handler, this way it'll create a new cube properly.
function spawnCube(event:MouseEvent):void
{
var p1:Cube=new Cube(); // this
p1.x = mouseX;
p1.y = mouseY;
arr.push(p1);
addChild(p1); // also this, because now "p1" has a new cube each time
i++;
}
You have only one instance of Cube so every time you call addChild() you just place the same instance in other place. You have to create new cube var p1:cube = new cube(); every time you click.

AS3 / removeChild/addChild by clicking button

I have several movie clips into a frame the size of the stage and I have to switch through a button between those pages.
So if I press button, should all the other frames removeChild and the one where he is called to go addChild.
Edit: I have the actionscript placed in the timeline of the movieClip so the button is not on the stage but I put in the movie clip using action script.
So what DodgerThud showed here is not possible because the button has changed since that is in the movieClip('s).
I think I need to place the same code in every movieClip.
Put all of your MovieClips into a Vector or Array.
When you click the button, you should cycle through the Vector/Array and check if the MovieClip is currently on stage with contains(DisplayObject). If the Movieclip IS currently on the stage, remove it and add another one to the stage, for example, the next one in the Vector/Array.
var vec:Vector.<MovieClip> = new Vector.<MovieClip>
vec[0] = new MovieClip();
vec[1] = new MovieClip(); //example with MovieClips
vec[2] = new MovieClip();
addChild(vec[0]); //add one of the MovieClips to stage
button.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
for(var i:int = 0; i < vec.length; i++) //go through the Vector one by one
{
if(contains(vec[i]) //if the Object at position i in the Vector is on stage
{
removeChild(vec[i]); //remove the Object
var next:int = i; //create a temporary holder
if(next == vec.length) //check if the displayed Object was the last in the list
{
next = 0; //if so, set to 0
}else{
next++; //otherwise, only add 1
}
addChild(vec[next]); //add the next Object to the stage. If the removed Object was the last in the Vector, it'll add the first Object in the Vector to the list
break; //escape the for loop, otherwise it'll always only show the last Object
}
}
}
Something like ...
function tueHandler(e:MouseEvent):void
{
while(numChildren > 0)
removeChildAt(0);
addChild(whatever);
}

Enemy move randomly

To make things quick, I have an arrangement of tiles that a player and an enemy are on.
public static var floor1:Array = new Array(7);
floor1[0] = [0,1,1,1,1,1,0];
floor1[1] = [1,1,1,1,1,1,1];
floor1[2] = [1,1,1,0,1,1,1];
floor1[3] = [1,1,0,0,0,1,1];
floor1[4] = [1,1,1,0,1,1,1];
floor1[5] = [1,1,1,1,1,1,1];
floor1[6] = [0,1,1,1,1,1,0];
public function Main()
{
var tilew:int = 60;
var tileh:int = 60;
for (var i:int=0; i<floor1.length; i++)
{
for (var u:int=0; u<floor1[i].length; u++)
{
var cell:MovieClip = new Tile();
cell.gotoAndStop(floor1[i][u]);
cell.x = ((u-i)*tileh);
cell.y = ((u+i)*tilew/2);
addChild(cell);
cell.addEventListener(MouseEvent.ROLL_OVER, mouseover);
cell.addEventListener(MouseEvent.ROLL_OUT, mouseout);
cell.addEventListener(MouseEvent.CLICK, mouseclick);
cell.addEventListener(Event.ENTER_FRAME, beginfloor1);
}
}
var player:Player = new Player();
addChild(player);
player.mouseEnabled = false;
player.x = 5 * (tileh);
player.y = 5 * (tilew/2);
var enemy:Enemy = new Enemy();
addChild(enemy);
enemy.mouseEnabled = false;
enemy.x = 9 * (tileh);
enemy.y = 9 * (tileh/2);
My goal is to have the enemy move randomly on tiles in his range. What I did was create a square graphic called enemyVisionArea that checks which tile is hitting the enemy, which is basically surrounding tiles.
I have a timer function that tells the enemy to move every 5 seconds if the player isn't near him and if he's next to an available tile.
function timerenemy (event:TimerEvent){
if (enemy.enemyVisionArea.hitTestObject(enemyMover) && !player.visionPoint.hitTestObject(enemyMover.tileMiddle))
{
enemy.x = (enemyMover.x)+55;
enemy.y = (enemyMover.y)+20;
trace("moved");
}
}
enemyMover is a variable that I made equal to the tile objects.
function beginfloor1(event:Event)
{
enemyMover = event.currentTarget as Tile;
}
It just stays where it is. I'm just want to have the enemy move on its own on any tile that its enemyVisionArea is hitTesting a nearby tile. The beginfloor1 function doesn't seem to be working. Is there any way I can declare enemyMover = event.currentTarget as Tile and have the enemy move on a random tile that its enemyVisionArea is hitTesting?
If this is confusing, I can post the full code.
You are assigning 49 enterframe listeners which are called in sequence, and they ALL change one single variable to the cell they are attached to. Of course, the last tile is what's always assigned.
I expect that you want an enemy to check if there's a tile available for it to move to. You are essentially checking for one tile which is enemyMover - how do you determine what's that tile? You have to check all available tiles that are around the enemy, make a list of them and select one out of that list that's not the current tile, then move the enemy there.
So, first you need a complete tileset to be addressable from somewhere. The best way will be to declare a class-wide var tileset:Array and fill it where you make new tiles. Drop the Event.ENTER_FRAME listener from the code there, as it's useless. Then, in your timerevent that's for the enemy you do check all of the tileset if they are within your enemy's vision area (you use hitTestObject, I'd use clear distance grid-wise or coordinate-wise - it's a whole lot faster), if so, you add them to the TEMPORARY array you create within that function. Of course, if your enemy is at the currently processed cell, you ignore it - you have to move your enemy, not make him stand in place. Then, select (somehow, it's up to you) what cell your enemy should move to, and execute a move. Yes, if you want your enemy to move randomly, select a cell at random by its index via Math.floor(Math.random()*selectedcells.length).

HitTest for objects not yet on Stage

I need to add a MovieClip to stage, the limitation being that it should only be added to an empty area on the stage. The stage itself either contains complex shapes or is manipulable by the user i.e. he can drag/move objects to change the empty area. The hitTest and hitTestObject methods need DisplayObject already available on the stage. What is the right way to go - the only solution I can imagine is having added my object on the stage and then repeatedly doing hit tests?
[Imagine it to something like adding sprites in a video game - they must spawn in empty regions; if they pop out from inside of each other, then it'll look really odd.]
Well, when you create a new class, just turn it off with a variable and set the visibility to false, then loop until there is no hitTest.
A silly example:
public class someClass extends Sprite
{
private var objectsOnStage:Array;
public function someClass(objectsArray:Array) {
objectsOnStage = objectsArray;
visible = false;
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event){
removeEventListener(Event.ADDED_TO_STAGE, init);
addEventListener(Event.ENTER_FRAME, SEARCH);
}
private function SEARCH(e:Event) {
var doesHit:Boolean = false;
x = Math.round(Math.random() * (550 - 0)) + 0;
y = Math.round(Math.random() * (400 - 0)) + 0;
for (var i:int = 0; i < objectsOnStage; i++) {
if (doesHit) break;
if (this.hitTestObject(objectsOnStage[i])) {
doesHit = true;
}
}
if (doesHit) return;
placedInit();
}
private function placedInit() {
visible = true;
removeEventListener(Event.ENTER_FRAME, SEARCH);
//now init the stuff you want.
}
}
You just check if bounding boxes of both clips overlaps. Like this:
import flash.geom.Rectangle;
import flash.display.MovieClip;
// create simple movie clips that has a rectangle shape inside
var sym1 : MovieClip = new Sym1();
var sym2 : MovieClip = new Sym2();
// get a rectanle of both clipt
var boundingBox1 : Rectangle = sym1.getBounds(this);
var boundingBox2 : Rectangle = sym2.getBounds(this);
// check if bounding boxes of both movie clips overlaps
// so it works like hitTestObject() method
trace( boundingBox1.intersects( boundingBox2) )
I know this post is super old, but in case it helps anybody --
If you need to do a hit test on a movieclip that isn't on the stage. A workaround is to rasterize it to a bitmap first.
var bitmapData:BitmapData = new BitmapData(mc.width, mc.height, true, 0x0000000);
bitmapData.draw(mc);
if (bitmapData.getPixel32(x, y) > 0) {
// Hit true.
}