Applying Drag, Snap Back Into Original Position To An Array - actionscript-3

I am attempting to drag a movie clip and then have it snap back into its original position after being released. I want to apply this functioniality to an array with actionscript3. Here is the code so far:
var dragArray:Array = new Array;
dragArray.push(blockSmalla);
dragArray.push(blockSmallb);
dragArray.push(blockSmallc);
dragArray.push(blockSmalld);
dragArray.push(blockSmalle);
var startPosition:Point;
function drag(e:Event):void {
dragArray[i].startDrag();
startPosition = new Point( dragArray[i].x, dragArray[i].y);
}
function dragStop(e:Event):void {
dragArray[i].stopDrag();
dragArray[i].x = startPosition.x;
dragArray[i].y = startPosition.y;
startPosition = null;
}
for (var i:uint = 0; i < dragArray.length; i++) {
dragArray[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
dragArray[i].stage.addEventListener(MouseEvent.MOUSE_UP, dragStop);
}
The function is not being applied to the array. Any suggestions?

I think what null was trying to tell you is that within each function scope you should remove dragArray[i] and use e.currentTarget instead.
Here's a simple fix:
var dragArray:Array = new Array;
dragArray.push(blockSmalla);
dragArray.push(blockSmallb);
dragArray.push(blockSmallc);
dragArray.push(blockSmalld);
dragArray.push(blockSmalle);
var startPosition:Point;
function drag(e:Event):void {
e.currentTarget.startDrag();
startPosition = new Point( e.currentTarget.x, e.currentTarget.y);
}
function dragStop(e:Event):void {
e.currentTarget.stopDrag();
e.currentTarget.x = startPosition.x;
e.currentTarget.y = startPosition.y;
startPosition = null;
}
for (var i:uint = 0; i < dragArray.length; i++) {
dragArray[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
dragArray[i].addEventListener(MouseEvent.MOUSE_UP, dragStop);
}
Also note I removed the stage reference on your MouseUp listener.

Related

Need to remove a child using hit test object function

i am trying to make a function where i drop some seeds into a bucket and the seeds are removed however the function will just be the seeds colliding with the bucket.
I have both of the objects as movieclips and have a basic hitTestObject conditional statement, i have no idea why the feed_mc wont be removed.
if(bucket_mc.hitTestObject(feed_mc))
{
if(stage.contains(feed_mc))
removeChild(feed_mc);
}
thank you in advance
Sorry should have edited here
my code
var Necessities:Array = new Array (Seed, shelter, water);
for(var i:int = 0; i< 10; i++)
{
var pickObjects = Necessities[int(Math.random()* Necessities.length)];
var Objects:MovieClip = new pickObjects();
addChild(Objects);
Objects.x = Math.random() + 600;
Objects.y = Math.random() * stage.stageHeight;
}
stage.addEventListener(Event.ENTER_FRAME, feedHen);
function feedHen(e:Event):void {
if(hen_mc.hitTestObject(Objects))
{
if (Objects.parent)
Objects.parent.removeChild(Objects);
}
}
Seems like
if(feed_mc.parent){
feed_mc.parent.removeChild(feed_mc);
}
should help - if you are not sure what DisplayObjectContainer is parent
edit
I think this should work
var Necessities:Array = new Array (Seed, shelter, water);
//store Objects here
var objectsVector:Vector.<MovieClip> = new Vector.<MovieClip>();
for(var i:int = 0; i< 10; i++){
var pickObjects = Necessities[int(Math.random()* Necessities.length)];
var Objects:MovieClip = new pickObjects();
addChild(Objects);
objectsVector.push(Objects);//add to Vector
Objects.x = Math.random() + 600;
Objects.y = Math.random() * stage.stageHeight;
}
stage.addEventListener(Event.ENTER_FRAME, feedHen);
function feedHen(e:Event):void {
for(var i: int = objectsVector.length - 1; i >= 0; i--){//loop through stored objects
if(hen_mc.hitTestObject(objectsVector[i])){
if (objectsVector[i].parent){
objectsVector[i].parent.removeChild(objectsVector[i]);
objectsVector.splice(i, 1);//remove from storage
}
}
}
}
However I'd suggest checking on some mouse events instead of ENTER_FRAME to reduce number of function calls

How can I put MovieClip into 3D array?

I want to create 3d array which holds movieclips and textfields. Here's my code:
public function init():void
{
//initalize the arrays
for (var _x:int = 0; _x <= MAX_X; _x++)
{
colArray = new Array();
for (var _y:int = 0; _y <= MAX_Y; _y++)
{
textArray = new Array();
for (var _z:int = 0; _z <= MAX_Z; _z++)
{
var txt:TextField = new TextField();
textArray.push(txt);
}
var mc:MovieClip = new MovieClip();
colArray.push(mc);
}
rowArray.push(colArray);
}
}
public function addBoxes(isUpdate:Boolean):void
{
for (var _y:int = 0; _y <= MAX_Y; _y++)
{
for (var _x:int = 0; _x <= MAX_X; _x++)
{
for (var _z:int = 0; _z <= MAX_Z; _z++)
{
// Create captions
var mcCaption:MovieClip = createMc("captionBox", false);
spSource.addChild(mcCaption);
mcCaption.addEventListener(MouseEvent.MOUSE_DOWN, mcCaptionHandler);
colArray[_x][_y][_z] = mcCaption;
mcCaption.x = nextXpos;
mcCaption.name = "beatCaption_" + _y;
// trace(colArray[_x][_y][_z]);
}
}
}
...
}
I want some text on my movieclips. How can I do that? My code is giving me error: TypeError: Error #1010: A term is undefined and has no properties.
Is this statement wrong?
colArray[_x][_y][_z] = mcCaption; // mcCaption is a movieclip
You don't have a 3D array, because textArray in the innermost cycle is not pushed into colArray but instead you stuff a MC in there. Also, you are asking a wrong array to retrieve a 3-depth object. In your code rowArray is 2D array (would be 3D if you'd stuff textArray in there), colArray is a 1D array of MCs, and then you are trying to refer colArray[_x][_y][_z] - this one resolves to:
colArray[_x] = empty Movieclip, created at init()
colArray[_x][_y] = undefined (the MC is empty, there's no property _y regardless of its value
colArray[_x][_y][_z] = runtime error, you're trying to query undefined's properties.
So, you have to check if your init() is correctly written, because if you need a 3D array, you are not making one right now. My guess is this:
public function init():void
{
//initalize the arrays
for (var _x:int = 0; _x <= MAX_X; _x++)
{
colArray = new Array();
for (var _y:int = 0; _y <= MAX_Y; _y++)
{
textArray = new Array();
for (var _z:int = 0; _z <= MAX_Z; _z++)
{
textArray.push(null); // placeholder
}
colArray.push(textArray);
}
rowArray.push(colArray);
}
}
The nulls pushed in the innermost loop will then be replaced if you use rowArray[_x][_y][_z] = mcCaption;

Mouse_leave cannot make movieclip snap back

I am trying to make a small drag and drop application in flash , i have been able to achieve the following -
1)Drag the movie clips
2)Make sure that two movieclips do not interchange positions when put over each other
3)Make sure the MC that is being dragged stays on top of other movieclips ..
4)Make the movieclip stay when its dropped at designated position
However there is one very important thing i am unable to achieve , when the cursor moves out of stage , the movie clips gets stuck to the cursor , i want that the moment the user goes out of stage the clip that is being dragged goes back to its original position ...
I have tried using the mouse_leave option for this but it does not work...
I am adding the code for drag and drop as below , please guide me here -
Drag Code -
Array to hold the target instances, the drop instances,
and the start positions of the drop instances.
var hitArray:Array = new Array(hitTarget1,hitTarget2,hitTarget3);
var dropArray:Array = new Array(drop1,drop2,drop3);
var positionsArray:Array = new Array();
This adds the mouse down and up listener to the drop instances
and add the starting x and y positions of the drop instances
into the array.
for (var i:int = 0; i < dropArray.length; i++) {
dropArray[i].buttonMode = true;
dropArray[i].addEventListener(MouseEvent.MOUSE_DOWN, mdown);
dropArray[i].addEventListener(MouseEvent.MOUSE_UP, mUp);
positionsArray.push({xPos:dropArray[i].x, yPos:dropArray[i].y});
}
This drags the object that has been selected and moves it
to the top of the display list. This means you can't drag
this object underneath anything.
function mdown(e:MouseEvent):void {
e.currentTarget.startDrag();
setChildIndex(MovieClip(e.currentTarget), numChildren - 1);
}
And here is the drop code
This stops the dragging of the selected object when the mouse is
released. If the object is dropped on the corresponding target
then it get set to the x and y position of the target. Otherwise
it returns to the original position.
function mUp(e:MouseEvent):void {
var dropIndex:int = dropArray.indexOf(e.currentTarget);
var target:MovieClip = e.currentTarget as MovieClip;
target.stopDrag();
if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
}else{
target.x = positionsArray[dropIndex].xPos;
target.y = positionsArray[dropIndex].yPos;
}
}
Please tell me how to use mouse_leave here and make the snap back,
used it in the both drag and drop section like this below
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
but always get some error like stage does not support property x etc. i add some code like equating the x and y but it does not work .. please guide
Jin
MOUSE_LEAVE shows if we are in or out of the stage, but doesn't detect the position of the mouse. You have to collect mouse's data on MOUSE_DOWN, to restrict the instance into the limits.
const LL:uint = 0;
const LT:uint = 0;
const LR:uint = stage.stageWidth;
const LB:uint = stage.stageHeight;
function EnterFrame(e:Event):void {
e.target.x = mouseX;
e.target.y = mouseY;
if (mouseX < LL) {e.target.x = LL;} else if (mouseX > LR) {e.target.x = LR;}
if (mouseY < LT) {e.target.y = LT;} else if (mouseY > LB) {e.target.y = LB;}
}
In your function 'mdown':
e.currentTarget.addEventListener(Event.ENTER_FRAME, EnterFrame);
In your function 'mUp':
target.removeEventListener(Event.ENTER_FRAME, EnterFrame);
General method
Here is the way this can be done. On MOUSE_UP outside the limits, the target is [object stage]. So you have to create a variable __last that will make you recognize the instance (p1 or another) clicked on MOUSE_DOWN. StartDrag() isn't needed:
const LL:uint = 0;
const LT:uint = 0;
const LR:uint = stage.stageWidth;
const LB:uint = stage.stageHeight;
function EnterFrame(e:Event):void {
e.target.x = mouseX;
e.target.y = mouseY;
if (mouseX < LL) {e.target.x = LL;} else if (mouseX > LR) {e.target.x = LR;}
if (mouseY < LT) {e.target.y = LT;} else if (mouseY > LB) {e.target.y = LB;}
}
var __last:*;
p1.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
function OnMouseDown(e:MouseEvent):void {
__last = MovieClip(e.target);
__last.addEventListener(Event.ENTER_FRAME, EnterFrame);
}
this.stage.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
function OnMouseUp(e:MouseEvent):void {
if(__last) __last.removeEventListener(Event.ENTER_FRAME, EnterFrame);
}
To snap it back to original position
const LL:uint = 0;
const LT:uint = 0;
const LR:uint = stage.stageWidth;
const LB:uint = stage.stageHeight;
var __last:*;
var dropIndex:int;
function EnterFrame(e:Event):void {
if (mouseX < LL || mouseX > LR || mouseY < LT || mouseY > LB) {
__last.x = positionsArray[dropIndex].xPos;
__last.y = positionsArray[dropIndex].yPos;
__last.stopDrag();
}
}
var hitArray:Array = new Array(hitTarget1, hitTarget2, hitTarget3);
var dropArray:Array = new Array(drop1, drop2, drop3);
var positionsArray:Array = [];
for (var i:int = 0; i < dropArray.length; i++) {
dropArray[i].buttonMode = true;
dropArray[i].addEventListener(MouseEvent.MOUSE_DOWN, mdown);
dropArray[i].addEventListener(MouseEvent.MOUSE_UP, mUp);
positionsArray.push({xPos:dropArray[i].x, yPos:dropArray[i].y});
}
function mdown(e:MouseEvent):void {
__last = e.currentTarget;
dropIndex = dropArray.indexOf(__last);
setChildIndex(MovieClip(__last), numChildren - 1);
__last.startDrag();
addEventListener(Event.ENTER_FRAME, EnterFrame);
}
function mUp(e:MouseEvent):void {
if (__last.hitTestObject(hitArray[dropIndex])) {
__last.x = hitArray[dropIndex].x;
__last.y = hitArray[dropIndex].y;
} else {
__last.x = positionsArray[dropIndex].xPos;
__last.y = positionsArray[dropIndex].yPos;
}
__last.stopDrag();
removeEventListener(Event.ENTER_FRAME, EnterFrame);
}

How to add Looped URLRequest image and add them to 1 viewport?

I am trying to loop (add images from Loader thru URLRequest), And the images are added to contentHolder, and then i place all these images which are inside contentHolder into a viewport. But at the moment I have to put the add images to viewport step inside the loop, so it creates a problem, which is each loop, a viewport is added. So 10 viewport overlaps each other. I tested it in debug mode and when the first image is loaded i can quickly slide it, because the viewport has a scrollpane, then second image is added, and i can slide that one, and third one is added on top etc.
But if i put the add Holder to viewport step outside the loop, it gives me the error Error #2007: Parameter child must be non-null, i dont know what to do. Please help, thanks for your time! I had been trying this for 6 hrs already!
And the error is on the line viewport.addChild(_contentHolder1); which is the last part of the code, if you scroll to the bottom.
for (var j:int = 5; j < somedata.length; j++)
{
if(somedata[j]){
var myLoader:Loader = new Loader();
var image:Bitmap;
var url:URLRequest = new URLRequest("http://www.rentaid.info/rent/"+somedata[j]);
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
myLoader.load(url);
function onImageLoaded(e:Event):void {
image = new Bitmap(e.target.content.bitmapData);
var currentY:int = 10;
var h = image.height;
var k=image.width/image.height;
_contentHolder = new Sprite();
_contentHolder.y = currentY;
currentY += _contentHolder.height + 10;
addChild(_contentHolder);
_contentHolder.addChild(image);
for (var j:int = 5; j <somedata.length; j++)
{
_contentHolder1 = new Sprite();
addChild(_contentHolder1);
_contentHolder1.addChild(_contentHolder);
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder1);
var scroller:TouchScroller = new TouchScroller();
scroller.width = 300;
scroller.height = 265;
scroller.x = 10;
scroller.y = 100;
scroller.viewport = viewport;
addChild(scroller);
}
}}
Edit:
var loadedArray:Array = new Array();
var counter:int=0;
function loadImage():void{
for (var j:int = 5; j < somedata.length; j++)
{
if(somedata[j]){
var loader:Loader = new Loader();
var image:Bitmap;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.load(new URLRequest("http://www.rentaid.info/rent/"+somedata[j][counter]));
}
}
}
function onImageLoaded(e:Event):void {
loadedArray.push(e.currentTarget.loader.content as Bitmap);
if(counter == somedata.length-1){
var _contentHolder: Sprite = new Sprite;
addChild(_contentHolder);
for(var i:uint = 5; i < loadedArray.length; i++){
_contentHolder.addChild(loadedArray[i]);
currentY += _contentHolder.height + 10;
}
}
else{
counter++;
loadImage();
}
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
var scroller:TouchScroller = new TouchScroller();
scroller.width = 300;
scroller.height = 265;
scroller.x = 10;
scroller.y = 100;
scroller.viewport = viewport;
addChild(scroller);
}
you can use Starling Framework and a loader loop such as:
private var count:uint = 0; //add this in your class
private var imagesVector:Vector.<Image> = new Vector.<Image>(); //add this in your class
private var imagesUrlVector:Vector.<String> = new <String>["url1","url2","url3","etc"]; //add this in your class
private function loadImages():void
{
//create the loader
var loader:Loader = new Loader();
//when texture is loaded
loader.contentLoaderInfo.addEventListener ( Event.COMPLETE, onComplete );
//load the texture
loader.load( new URLRequest (imagesUrlVector[count]));
}
private function onComplete ( e : Event ):void
{
// grab the loaded bitmap
var loadedBitmap:Bitmap = e.currentTarget.loader.content as Bitmap;
// create a texture from the loaded bitmap
var texture:Texture = Texture.fromBitmap ( loadedBitmap );
var card:CustomImage = new CustomImage(texture);
imagesVector.push(card);
trace("load image number" + count);
count++;
if (count < imagesUrlVector.length) {
loadImages();
} else displayImages();
}
private function displayImages():void {
var x:uint = 150;
var i:Number;
for (i = 0; i < cardVector.length; i++ )
{
x += 100;
imagesVector[i].x = x;
addChild(imagesVector[i]);
}
}

Handling Multiple TimerEvent

Below is simplified version of a game I am creating. Basically, the game have some circles. Each circle shoot bullets that is dispatched with timerEvent. When the circle is clicked it is removed from the stage. However, the bullet still keeps on dispatching. I couldn't figure out how to stop timerEvent of each individual circle when it is clicked.
var _timer:Timer = new Timer(1000);
var speed:int = 20;
for(var i:int=0; i<= 3; i++)
{
var _shape:MovieClip = new MovieClip();
_shape.graphics.beginFill(0x999999);
_shape.graphics.lineStyle(1, 0x000000);
_shape.graphics.drawCircle(0, 0, 20);
_shape.graphics.endFill();
addChild(_shape);
_shape.x = (stage.stageWidth)/5;
_shape.y = (stage.stageHeight)/3 + _shape.height*i*1.5;
_shape.name = "_shape"+i;
_shape.buttonMode = true;
_shape.addEventListener(MouseEvent.CLICK, removeMovieClip);
bullets(_shape);
}
function bullets(_shape:MovieClip):void
{
_timer = new Timer(Math.random()*100);
_timer.addEventListener(TimerEvent.TIMER, startFiring);
_timer.start();
function startFiring(e:TimerEvent):void
{
speed ++;
var _bullet:MovieClip = new MovieClip();
_bullet.graphics.beginFill(0x999999);
_bullet.graphics.lineStyle(1, 0x000000);
_bullet.graphics.drawRect(0, 0, 5,2);
_bullet.graphics.endFill();
addChild(_bullet);
_bullet.x = _shape.x + speed ;
_bullet.y = _shape.y;
}
}
function removeMovieClip(e:MouseEvent):void
{
removeChild(getChildByName(e.currentTarget.name));
// how to stop the timerEvent of clicked circle?
}
//var _timer:Timer = new Timer(1000); //I don't think this is necessary
var speed:int = 20;
for(var i:int=0; i<= 3; i++)
{
var _shape:MovieClip = new MovieClip();
_shape.graphics.beginFill(0x999999);
_shape.graphics.lineStyle(1, 0x000000);
_shape.graphics.drawCircle(0, 0, 20);
_shape.graphics.endFill();
addChild(_shape);
_shape.x = (stage.stageWidth)/5;
_shape.y = (stage.stageHeight)/3 + _shape.height*i*1.5;
_shape.name = "_shape"+i;
_shape.buttonMode = true;
bullets(_shape);
}
function bullets(_shape:MovieClip):void
{
_shape.timer = new Timer(Math.random()*100);
_shape.timer.addEventListener(TimerEvent.TIMER, startFiring);
_shape.timer.start();
_shape.addEventListener(MouseEvent.CLICK, removeMovieClip);
function startFiring(e:TimerEvent):void
{
speed ++;
var _bullet:MovieClip = new MovieClip();
_bullet.graphics.beginFill(0x999999);
_bullet.graphics.lineStyle(1, 0x000000);
_bullet.graphics.drawRect(0, 0, 5,2);
_bullet.graphics.endFill();
addChild(_bullet);
_bullet.x = _shape.x + speed ;
_bullet.y = _shape.y;
}
function removeMovieClip(e:MouseEvent):void
{
//stop the time and remove its listeners
e.target.timer.stop(); // you might need to cast this into Timer object
e.target.timer.removeEventListener(TimerEvent.TIMER, startFiring);
removeChild((MovieClip)e.target);
// how to stop the timerEvent of clicked circle?
}
}