as3 marquee select drag multiple child objects - actionscript-3

Can anyone tell me how to achieve marquee selection effect with AS3 to select multiple movieclips by drawing a dynamic rectangle around them and then drag and drop them anywhere?

Don't use startDrag() if you need multiple objects to be draggable, since it only allows one object to be dragged at a time. Instead, listen for mouse events and do the moving manually:
var oldX:int;
var oldY:int;
var dragging:Boolean = false;
function onMouseDown(evt:MouseEvent):void {
dragging = true;
oldX = evt.stageX;
oldY = evt.stageY;
}
function onMouseMove(evt:MouseEvent):void {
if (!dragging) return;
var dX:int = evt.stageX - oldX;
var dY:int = evt.stageY - oldY;
for (int i = 0; i < selectedClips.length; i++) {
var clip:DisplayObject = selectedClips[i];
clip.x += dX;
clip.y += dY;
}
oldX = evt.stageX;
oldY = evt.stageY;
}
function onMouseUp(evt:MouseEvent):void {
dragging = false;
}
This code assumes that:
Your array of selected objects is called selectedClips.
Your array of selected objects all inherit from DisplayObject.
You have added event listeners on all draggable objects for the MOUSE_DOWN, MOUSE_MOVE, and MOUSE_UP mouse events which call these functions.
If any of those three conditions are not met, update my code or your code to work properly. Also, if you need to do any additional handling when the objects are dropped, you can use the mouse up handler to add custom code.

Related

AS3 Error drag and drop multiple draggable object to multiple target

I want to make the game drag and drop to create multiple draggable objects and it can dragged to multiple targets. But I encountered an error when I drag to the first object that I choose to certain target object is not dragged to the target and then I drag it to another target then succeed. I wanted to fix it. And if you can fix it when the object is dragged to the target and then want to be replaced by another object then the dragged object will be replaced and returned to its original position.
This is a overview the program
And this is the source codes that I use
var xPos:int;
var yPos:int;
var poin:int = 0;
var namaobj1:String;
var namaobj2:String;
addListeners(membaca, menulis, berenang, sepakbola, melukis, memasak, menari, bercocoktanam, beladiri, bermainmusik);
proses.addEventListener(MouseEvent.CLICK,proses1);
function getPosition(target:Object):void
{
xPos = target.x;
yPos = target.y;
}
function dragObject(e:MouseEvent):void
{
getPosition(e.target);
e.target.startDrag(true);
}
function stopDragObject(e:MouseEvent):void
{
if (e.target.hitTestObject(getChildByName("target2")))
{
e.target.x = getChildByName("target2").x;
e.target.y = getChildByName("target2").y;
namaobj2 = e.target.name;
}
else if (e.target.hitTestObject(getChildByName("target1")))
{
e.target.x = getChildByName("target1").x;
e.target.y = getChildByName("target1").y;
namaobj1 = e.target.name;
}
else
{
e.target.x = xPos;
e.target.y = yPos;
}
pil1.text = namaobj1;
pil2.text = namaobj2;
e.target.stopDrag();
}
function addListeners(... objects):void
{
for (var i:int = 0; i < objects.length; i++)
{
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, dragObject);
objects[i].addEventListener(MouseEvent.MOUSE_UP, stopDragObject);
}
}
I'm using draggable objects by putting addListener function.
I also include his .fla can be downloaded here ( TEST.FLA ) rather you can more easily apply fixed codes
You can add Mouse_UP event in your targets instead of you dragged objects. Then when the MOUSE_UP event is trigged, you will know which objects is your target(e.target) without hitTestObject. The code is as follows:
You could have to set dragged object's mouseEnabled when mouse down, and true after dragged.

How to add a keyboard navigation to a Flash AS3 based app?

I would like to make my Flash AS3 based app more accessible with a keyboard navigation.
What's the best way to add to every MovieClip with a MouseEvent.CLICK the ability to get selected through the TAB and clicked/fired through ENTER?
Some basic example of my code:
nav.btna.addEventListener(MouseEvent.CLICK, openSection);
dialog.btnx.addEventListener(MouseEvent.CLICK, closeDialog);
function openSection(event:Event=null):void
{
trace("nav.btna")
}
function closeDialog(event:Event=null):void
{
trace("dialog.btnx")
}
I remember that there was a AS3 function that enabled that every MovieClip with a MouseEvent could be fire through ENTER if the MovieClip was selected with TAB. I can't remeber the function though.
I think the problem may be that you are attempting this with a MovieClip instead of a button (Button or SimpleButton).
I made a simple test by creating buttons instead of MovieClips in my library and this worked as expected:
// I have 4 buttons (button1, button2, etc) on the stage
for(var i:int = 1; i <= 4; i++)
{
var mc = getChildByName("button" + (i+1));
mc.tabIndex = i;
mc.addEventListener(MouseEvent.CLICK, onClicked);
}
function onClicked(e:MouseEvent):void
{
trace(e.currentTarget + " clicked");
}
stage.focus = stage;
I initially ran this test with MovieClip instances, and while they would show that the tab was working (a yellow border shows up), the MouseEvent.CLICK was never firing. Once I switched to actual buttons (SimpleButton in this case), it worked with both the Enter and Space keys.
EDIT:
To answer the question posed in the comments, this is a quick-and-dirty way to "convert" MovieClips to SimpleButtons at runtime:
// I have 4 MovieClips (button1, button2, etc) on the stage
for(var i:int = 1; i <= 4; i++)
{
var mc:MovieClip = getChildByName("button" + i) as MovieClip;
var button:SimpleButton = convertMovieClipToButton(mc);
button.tabIndex = i;
button.addEventListener(MouseEvent.CLICK, onClicked);
}
function convertMovieClipToButton(mc:MovieClip):SimpleButton
{
var className:Class = getDefinitionByName(getQualifiedClassName(mc)) as Class;
var button:SimpleButton = new SimpleButton(new className(), new className(), new className(), new className());
button.name = mc.name;
button.x = mc.x;
button.y = mc.y;
mc.parent.addChildAt(button, getChildIndex(mc));
mc.parent.removeChild(mc);
return button;
}

AS3 - Drag using If statement to Next Scene.

I am making an interactive game - and I have this code so far. Where drop1 is a coin and the user drops it into target1 (box) and once they have done they they are able to watch the video play in the next scene. AS you can see when drop1 (coin) is dropped onto the box the coin then disappears
//Array to hold the target instances, the drop instances,
//and the start positions of the drop instances.
var hitArray:Array = new Array(hitTarget1);
var dropArray:Array = new Array(drop1);
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);
}
//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;
drop1.visible = false;
}else{
target.x = positionsArray[dropIndex].xPos;
target.y = positionsArray[dropIndex].yPos;
}
}
NOW... I want the code to know when the user has dropped the coin in the box and IF the user has they can then watch the video but can only watch the video if they drop the coin in box. How can i code this?
please help.
thank you
If you're still struggling you can always try reading the MANUAL..? I suspect this is why you've had no answer so far. Travelling between frames/scenes requires either gotoAndPlay or gotoAndStop. Check: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/MovieClip.html#gotoAndPlay()
Look at example two for scene jumping code. Where it says "intro" (frame label) it's okay to just use a number but scenes must have names.. e.g:
mc1.gotoAndPlay("intro", "Scene 12");
or in your case something like below (assuming you have named it as scene_video)
if (target.hitTestObject(hitArray[dropIndex])) {
target.x = hitArray[dropIndex].x;
target.y = hitArray[dropIndex].y;
drop1.visible = false;
gotoAndStop(1, "scene_video"); }
Again I'm assuming your video player is on frame 1 of that scene so stopping there allows users a chance to watch the video player.

use 1 object multiple times in as3?

I'm trying to make something like bookmarks, I have 1 note on the stage and when the user clicks it, it starts to drag and the users drops it where they want. the problem is I want these notes to be dragged multiple times.. here is my code:
import flash.events.MouseEvent;
//notess is the instance name of the movie clip on the stage
notess.inputText.visible = false;
//delet is a delete button inside the movie clip,
notess.delet.visible = false;
//the class of the object i want to drag
var note:notes = new notes ;
notess.addEventListener(MouseEvent.CLICK , newNote);
function newNote(e:MouseEvent):void
{
for (var i:Number = 1; i<10; i++)
{
addChild(note);
//inpuText is a text field in notess movie clip
note.inputText.visible = false;
note.x = mouseX;
note.y = mouseY;
note.addEventListener( MouseEvent.MOUSE_DOWN , drag);
note.addEventListener( MouseEvent.MOUSE_UP , drop);
note.delet.addEventListener( MouseEvent.CLICK , delet);
}
}
function drag(e:MouseEvent):void
{
note.startDrag();
}
function drop(e:MouseEvent):void
{
e.currentTarget.stopDrag();
note.inputText.visible = true;
note.delet.visible = true;
}
function delet(e:MouseEvent):void
{
removeChild(note);
}
any help will be appreciated.
You need to create a new instance of your note class when you drop, copy the location and other variables from the note you were dragging, add your new note to the stage, and return the dragging note to its original position.
Something like:
function drop($e:MouseEvent):void
{
$e.currentTarget.stopDrag();
dropNote($e.currentTarget as Note);
}
var newNote:Note;
function dropNote($note:Note):void
{
newNote = new Note();
// Copy vars:
newNote.x = $note.x;
newNote.y = $note.y;
// etc.
// restore original note.
// You will need to store its original position before you begin dragging:
$note.x = $note.originalX;
$note.y = $note.orgiinalY;
// etc.
// Finally, add your new note to the stage:
addChild(newNote);
}
... this is pseudo-code really, since I don't know if you need to add the new note to a list, or link it to its original note. If you Google ActionScript Drag Drop Duplicate, you will find quite a few more examples.
I think you are not target the drag object in drag function and problem in object instantiation
for (var i:Number = 1; i<numberOfNodes; i++) {
note = new note();
addChild(note);
...
....
}
function drag(e:MouseEvent):void{
(e.target).startDrag();
}
If you are dragging around multiple types of objects (eg. Notes and Images), you could do something like this, rather than hard coding the type of object to be instantiated.
function drop(e:MouseEvent):void{
// Get a reference to the class of the dragged object
var className:String = flash.utils.getQualifiedClassName(e.currentTarget);
var TheClass:Class = flash.utils.getDefinitionByName(className) as Class;
var scope:DisplayObjectContainer = this; // The Drop Target
// Convert the position of the dragged clip to local coordinates
var position:Point = scope.globalToLocal( DisplayObject(e.currentTarget).localToGlobal() );
// Create a new instance of the dragged object
var instance:DisplayObject = new TheClass();
instance.x = position.x;
instance.y = position.y;
scope.addChild(instance);
}

Record Paper.js path object and redraw again later

I draw with a mouse Paper.js. I need to keep these strokes and replay them at the same rate as in the video replay. How can I accomplish this?
In paper.js, the onFrame() function is called up to 60 times per second, while the onMouseMove() function "is called when the mouse moves within the project view", and contains the position of the mouse. By using both functions you can store the mouse motions and replay them later with close to the same time between positions.
var mousePosition = null;
function onMouseMove(event) {
if (mousePosition != null) {
var path = new Path();
path.strokeColor = 'black';
path.moveTo(mousePosition);
path.lineTo(event.point);
}
mousePosition = event.point;
}
var recordedPositions = [];
var delayFrames = 60;
function onFrame(event) {
if (mousePosition != null) {
recordedPositions.push(mousePosition);
if (recordedPositions.length > delayFrames) {
var path = new Path();
path.strokeColor = 'red';
delayedPositionIndex = recordedPositions.length - delayFrames;
path.moveTo(recordedPositions[delayedPositionIndex - 1]);
path.lineTo(recordedPositions[delayedPositionIndex]);
}
}
}
I do not know the timing accuracy/resolution/dependability of onFrame(). Alternatively you could just use javascript timing events as in this answer: How can I use javascript timing to control on mouse stop and on mouse move events