Use single event on more than one actor in libgdx - libgdx

I have two objects of Actor both of them having their different input listener having almost same position on stage. My question is how to detect touch on both of them using single InputEvent.

Are their positions overlapping and you would actually touch both with your single input?
If you touch both, you can set the return value of the input listener of the upper (higher on the stage / touched first) Actor to false, so the input doesn't count as processed yet and gets passed through to the lower Actor.

Related

Can I use **hitTestObject** with only the inside part of an object?

I want to use hitTestObject with only the inside (visual) part of the object, not the outside part or the border.
How can I use that?
By default, hitTestObject checks only the bounding box of the specified object to check for collision, which is the "outside" part you're referring to. There's another function, hitTestPoint() which checks whether a given point collides with another object, and hitTestPoint allows you to check for rough collisions (only the bounding box) or for precise collisions (the "visual" part only); however, it only works for a given point.
So, if you have two objects and you want to check whether their visual parts overlap, and not their bounding boxes, then you have two options:
1) Check only one point, e.g. the x and y coordinate of one displayObject, with the entire shape of the other displayObject, or
2) Create an invisible "border" of separate displayObjects which reside in the first displayObject, and check whether any of their coordinates collide with the "visual" part of the second displayObject.
In either case, you will have to use hitTestPoint(); this takes Stage coordinates, so you'll have to use localToGlobal() to convert it.
//where shapeAa is a shape nested within a displayObject 'shapeA', and you want to check whether shapeA collides with shapeB
var globalPt:Point = shapeAa.localToGlobal(new Point());
shapeB.hitTestPoint(globalPt.x, globalPt.y, true);
//...repeat for other shapes nested within shapeA, along its border, i.e. shapeAa...shapeAz
There's various libraries that allow you to test precisely for collision (and if you're using BitmapData instead of Sprite/MovieClip/etc. then you can check whether the objects accurately collide without the need of such libraries).

Draw letters based on points on mouse click in action script 3

I asked to draw line between objects in stage (e.g points) on mouse click over 2 of these objects
example : if I want to write 'A' i need to set 5 point and connect them by clicking all these points like:
*
* *
* *
This question isn't very specific. Which part are you having problems with? The Graphics object provides methods for drawing lines. It's very easy to draw between points with drawTo(...)
For a quick intro see: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7dd9.html
First, you have to detect the user's mouse click and convert that into some sort of form of data that you can use to draw a line with.
Use the MouseEvent class and EventListeners to detect a user's mouse click. If you don't know how to use event listeners, refer to here.
The dispatched MouseEvent object has a stageX and stageY property which refers to the X and Y coordinates of where the mouse click occurred. These two pieces of data can be used to create a Point object. Instantiate and store this point object somewhere convenient - so that when you have more than 2 of them, you can then refer to AndySavage's answer on how to draw a line with those two Point objects.
Basically, you want to create a Point object every time a mouse click occurs, and then check internally the amount of Point objects you have. If you have one, don't do anything, because you need two points to draw a line. If you have more than one, then use the two latest Point objects you obtained to draw a line.
Tip:
If you store the points into a vector, then every time a mouse click occurs, you can push a Point object inside. Then, check the length of that vector, and if it is greater than 1, you can access the last two elements by using the it's length - 1 and length - 2 as indices.
You can read the documentation on the Vector and Point classes by searching on google. (Type something like "as3 api Vector") I'd add links but I can only add less than two per post right now.

Has anyone experienced side effects (including performance issue) of using getObjectsUnderPoint?

Before I go making major change in my ongoing game project, I just want to hear from others if anyone has found any issues with getObjectsUnderPoint() function of the DisplayObject?
Update:
Not just the performance issue but any other limitations of using it (like it doesn't detect certain type of UIelements (just as example))
I will have three layers in my application (which an Isometric game)
Background -- This is just a background which stays in the bottom, has nothing to do with game
Middle Layer -- This is the playable area, Here all my game elements will be placed on this layer
Top Layer -- This is one dummy transparent layer covers entire playable area which interrupts all the mouse events. This is where I want to use the getObjectsUnderPoint()
So, player wants to click on the element, the top layer will interrupt the mouseevent and then check if there is something placed or just a plain background and take appropriate action like, notify the underneath object.
This really doesn't require to be done this way because I could simply add moues events for all those items placed on the map directly but because I would be using getObjectsUnderPoint() anyway to check if there is anything beneath the item.
If anyone can explain how this function works then it would be little easy for me to make a decision.
There was one annoying problem though. I don't know if they fixed it or not. At least it was there in 10.1 times.
If you have a container and you scaled it container.getObjectsUnderPoint will return wrong result. All the time. So everywhere where I needed getObjectsUnderPoint I had to call it from stage to get proper result.
It's an incomplete function. It returns graphical objects under the mouse, NOT all potential mouse targets for event or interaction purposes. It actually requires complex logic to examine the array returned by getObjectsUnderPoint to determine the mouse target, because the appropriate target (the one Flash would choose if you actually clicked that point) may not be in the list.
First you'd have to examine the object array in reverse, since the items are ordered back to front. You'd have to examine each object's entire parent chain, looking for a parent with mouseChildren = false that would cause it to intercept the event and become the target. Whether or not such an object is found, this final object you arrive at must have its mouseEnabled property set to true, otherwise you must skip it and move on to the next object in the array, which would be, for example, the next sprite or shape behind the one you initially checked. While going through the list, you must notice when the parent changes, at which point you need to assume that all children of that common parent had their mouseEnabled property set to false, in which case the parent would become the next candidate. This is actually extremely complicated, because you're working backwards in a bottom-up approach with an incomplete set of objects that was generated from the top-down.
To get actual potential mouse event targets, consistent with the default dispatching logic... it is actually easier to start from the stage in a top-down manner and walk backwards through the display hierarchy in a depth-first search, checking mouseChildren to determine whether you need to step into children, and checking mouseEnabled if it's to be a target, otherwise stepping into the container's children and repeating the process from back to front again. This is much more accurate, complete, and staightforward. The only problem is you have to code it yourself.

AS3 - Hit Test Object between two Movieclips in the same class file

I'm wondering if there is a method to do a hit test object between two movieclips from the same class. The movieclips are being spawned into the stage using a for loop.
Is it possible to if(item(event.currentTarget).hitTestObeject(item(thats not being selected at the moment?))) I'm doing a drag and drop game and am trying to not let the items stack above each other when dragged to the snapping slots on the stage. If not is there other methods avaliable? Thanks in advance (:
first of all, detecting, whether two display objects (sprites, movieclips, etc.) hit each other, is independent of the fact, that the objects are instances of the same class. The important thing is, you have two instances and they are display objects, so you're good to go.
If you want to do hit tests, then i would do the following:
Create a helper class, that holds an Array of all the items, which have already been created.
That helper class needs to add itself as a listener to all the items for the event, that you start drag an item.
Once an item is dragged, the helper class adds itself as a listener to the mouse move event of that item
in the mouse move event handler, the helper class does a hit test from the currently dragged item to each item in its list of items (simple for loop)
if a hit test results with true, you save item you have currently tested against, as this is the one, that you dragged item is overlapping with.
Now you can do measurements (comparing positions, bounding boxes of the two items, etc) to figure out, where to position your dragged item, so that it does not overlap anymore.
Don't forget to remove the mouse move event listener in the event of the user ending to drag.
A few weeks ago I was working on a project wich had very specific dragging, so we've decided not to use the Flex DragManager. Our, so called, DragManager is not doing anything special. The thing that I think is related with your work is the presence of snap blocks. In our case the snap blocks were simple groups. Every snap block has a reference to the object wich was dropped into it(let's say it is droppedItem). When trying to drop an item, or even before triggering the snapping mechanism, there is a simple check in the snap block
if (droppedItem == null)
And this was the solution in our case.
I'm not sure what are your snapping slots, but I hope that our approach will help you.
Best regards, Ivan

Getting started with a simple Flash game

I'd like to make a simple game where "discs" fall from the top of the screen and the user must catch them. I have a MovieClip which I want to resize to one of three randomly chosen sizes.
As I see it, there are four things that must be done.
Create and size the MovieClip
Position the MovieClip
Make the MovieClip fall
Determine when it is finished "falling" and see if the user has "caught" it.
My question is: How do I create, size and position the MovieClip? I've given it an identifier of "disc". Now what? Do I make an ENTER_FRAME event and do my creation there? How do I move the disc downwards? Do I use tweens, something else?
I'm primarily asking this as a sanity check.
I would use some kind of factory class that would be responsible for dropping random discs from the top of the stage.
Beside what you correctly mentioned, you will also need to:
define if the speed for falling is constant or not, you may need some acceleration tween. To move the objects downwards, you could use a native tween method, you will need to apply it to every disk that gets dropped.
define where the disk will start falling, it can be random or always from the same place.
you can find out if two objects are colliding using the AS3 hitTestObject method which belongs to the DisplayObject class.
you factory class could have a start() and stop() method. Once start() is fired, an infinite or ENTER_FRAME loop is started and disks start falling. If you want to create disks at a specific rate you could combine your loop with a timer to run code on a defined interval. For instance, every 3 seconds create 10 disks (using main loop) and drop them onto the stage.
Assuming that you have MovieClips named 'disc' & 'userHand' exported into actionscript, I'll summarize it in the foll way:
Generate the no of discs & Randomize their location. Start with something like:
var n:int = 30; //Total no of Discs
for(i:int=0;i<n;i++)
{
var mc:disc = new disc();
mc.x=Math.random()*stage.width(); //to scatter the discs across the stage
mc.y=-mc.height; //initially hide out a disc
addchild(mc);
}
Also add the Movie clip 'userhand' to stage.
Add enterframe handler function.
Fill in the enterframe handler to update (keep increasing) the y position of each disc.
Use hitTestObject() in the enterframe handler to determine hit among each 'disc' & 'userHand'.
Reset position of all the 'disc' clips which fall off the screen to random positions as initially.
You might want to look at programming particles.
http://r3dux.org/2010/01/actionscript-3-0-particle-systems-3-rain-effect/
At a very high level what you would do is.
You need to create a disc class.
You could give this class some variable properties like width, height,x etc.
In an enter frame in your main class you would add an enterframe function that creates new instances of disc passing it random values for each property.
Each instance of disc could also have its own entframe which increases its y position until it reaches the bottom of the screen. The disc would then remove its self from the stage. You could use an easing function passing it a random number to determine the rate at which its falls.
Say if its y position is greater than the stage height, remove the disc. If the user catches it (using a hit test maybe) also remove it.
It really recommend having a look at that link I posted.