Flash CC error 1136 - actionscript-3

I'm trying to stop this slideshow by pressing spacebar and I keep encountering error 1136 with no hope.
stop();
gotoAndPlay(15);
stage.addEventListener(KeyboardEvent.KEY_DOWN, pressedKey);
function stopSlideshow (e:KeyboardEvent):void {
gotoAndStop("Home");
}
function pressedKey (event:KeyboardEvent):void {
if (event.keyCode == Keyboard.SPACE)
stopSlideshow();
}

The error 1136 is fired because you have defined the stopSlideshow() function with one parameter (an KeyboardEvent object) but when you've called it you forgot to pass it an KeyboardEvent object as its only argument.
So to avoid that, you can define the KeyboardEvent parameter as optional :
function stopSlideshow (e:KeyboardEvent = null):void
{
gotoAndStop("Home");
}
Also you can use the KeyboardEvent object used by your pressedKey() function as an argument :
function pressedKey(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.SPACE){
stopSlideshow(event);
}
}
Or you can define a new KeyboardEvent object, for example, like this :
var keyboard_event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN);
stopSlideshow(keyboard_event);
This will avoid the error but I don't know why you need the stopSlideshow()'s KeyboardEvent parameter because according to your posted code you can use that function without any parameter ...
Hope that can help.

Related

as3 How to dispatch a specific keyboard event

I was looking for this answer and had no luck. One place I looked actually had a very discouraging answer: "You cannot force mouse or keyboard events - they HAVE TO come from mouse or keyboard."
Huh?
I tried 'brute force' and came up with this solution. Maybe I'm going about it wrongly or stupidly; is there a better way?
I had a keyboard event that launched a class and wanted to put a sprite on the stage that would initiate this same action -- clicking on the sprite would launch the keyboard event (Escape key).
In the eventListener function, I traced the event e itself:
private function keys(e:KeyboardEvent):void {
trace("EscapeKey: ",e);
if (e.keyCode == 27) {
...
}
}
The output was
EscapeKey: [KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=27 keyCode=27 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]
I then had the mouseClick listener create and dispatch a new keyboardEvent using the values I got from the above trace:
private function pauseClick(e:MouseEvent):void {
var a:KeyboardEvent = new KeyboardEvent("keyDown", true, false, 27, 27, 0, false, false, false);
stage.dispatchEvent(a);
}
Presto!
Hopefully, this post will come in handy to others looking for these types of mouse/keyboard event redundancies.
EDIT --- A complete class example requested in comments:
package{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
public class KeyboardMouse extends Sprite {
private var pauseInfo:PauseInfo;
private var escapeKey:EscapeKey;
public function KeyboardMouse() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keys);
escapeKey = new EscapeKey();
stage.addChild(escapeKey);
pauseInfo = new PauseInfo();
pauseInfo.x = stage.stageWidth;
pauseInfo.y = stage.stageHeight;
pauseInfo.addEventListener(MouseEvent.CLICK,pauseClick);
addChild(pauseInfo);
}
private function keys(e:KeyboardEvent):void {
trace("KeyboardEvent ",e);
if (e.keyCode == 27) { // esc key
if (stage.contains(escapeKey)){
trace("remove escape");
escapeKey.visible = false;
}
else {
trace("show escape");
escapeKey.visible = true;
}
}
}
private function pauseClick(e:MouseEvent):void {
// The trace in 'keys' gives this:
//[KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=27 keyCode=27 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]
var a:KeyboardEvent = new KeyboardEvent("keyDown", true, false, 27, 27, 0, false, false, false);
stage.dispatchEvent(a);
}
}
}
Alright, now I get this. I just don’t get it’s purpose. Also there is, I think, an annoying error in the code.
First: you’ve shown that you can essentially ‘cast’ one type of event (e.g. MouseEvent) as another (KeyboardEvent). But you still have a listener function registered for each Event type (which, at some point, you’ll have to remove for memory management purposes) and a newly dispatched Event, so you’re not exactly minimizing code. What, exactly, is the value of this trick? Why not just register a single listener function with multiple event types? Within that function you can discriminate between the Event types and do stuff accordingly, for instance with a line like this:
if(e.type == 'keyDown' || e.type == 'click')
Second: you say: if (stage.contains(escapeKey)) and then you try to make the ‘visible’ property of escapeKey dependent on that. But by making the escapeKey.visible = false you’re not changing the fact that the stage still contains escapeKey. So the escapeKey will never become visible again because the 'else' condition doesn't exist. I believe that you want to say “removeChild(escapeKey)” and then “addChild(escapeKey)” instead of setting “escapeKey.visible = false” and then “escapeKey.visible = true”. Then you’re little program does what I think you want it to.
+1 and big props to #Neal Davis for his comments!
As he suggests, having one listener for both events with an argument of (e:Event) is a cleaner, less convoluted way of achieving the same result:
pauseInfo.addEventListener(MouseEvent.CLICK,keys);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keys);
private function keys(e:Event):void {
trace("EscapeKey: ",e);
if (e.keyCode == 27) {
...
}
}
Both listeners must still be removed at some point, though, even though only one Listener Function is handling both, of course!

AS3 - How do you call previous currentTarget from within a different event?

I have a dropdown menu that lets you select an item to be placed on the stage. The item is drag and droppable so I use event.currentTarget.startDrag(); to start the drag. Ok, everything works fine so far.
However, I also need to be able to rotate the item while it is being dragged (using the spacebar).
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void{
if (e.keyCode == Keyboard.SPACE){
rotate++;
if (rotate == 5){
rotate = 1;
}
WHATGOESHERE?.gotoAndStop(rotate);
}
If I hardcode in an instance name of an object everything works fine - so the rotate function is working properly. The problem is, how can I reference event.currentTarget from the startDrag function while inside of the keyDown event?
My first thought was to set event.currentTarget to a variable and then calling the variable from within the keyDown event. However, targetHold = event.currentTarget; does not seem to record the instance name of the object being clicked...
public var targetHold:Object = new Object;
function ClickToDrag(event:MouseEvent):void {
event.currentTarget.startDrag();
targetHold = event.currentTarget;
trace ("targetHold " + targetHold);
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void{
if (e.keyCode == Keyboard.SPACE){
rotate++;
if (rotate == 5){
rotate = 1;
}
targetHold.gotoAndStop(rotate); //does not work
}
}
function ReleaseToDrop(event:MouseEvent):void {
event.currentTarget.stopDrag();
}
As you click the object, it should have focus. If you register the listener for the KeyboardEvent on the object and not on the stage, it will be .currentTarget.
Here's an example of what I have in mind. Right after starting the drag, add the listener to the same object instead of the stage.
event.currentTarget.startDrag();
event.currentTarget.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
The proper way of doing this would be to define all the functionality in a class. Within a self contained class, you would not need any .currentTarget.
Here is how I would do this: (well, actually I'd follow #null's advice and encapsulate it in a sub class that all your dragable objects would extend, but that is a little broad so this will do)
public var targetHold:MovieClip; //don't make a new object, just create the empty var
public function YourConstructor(){
//your other constructor code
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown); //don't add the listener in the click function
}
private function clickToDrag(event:MouseEvent):void {
if(targetHold) ReleaseToDrop(null); //safeguard in case flash lost the focus during the mouse up
targetHold = event.currentTarget as MovieClip; //assign the current target. Might as well cast it as MovieClip and get code completion benefits
targetHold.startDrag();
trace ("targetHold " + targetHold);
}
private function myKeyDown(e:KeyboardEvent):void{
//check if target hold exists
if (targetHold != null && e.keyCode == Keyboard.SPACE){
rotate++;
if (rotate == 5){
rotate = 1;
}
targetHold.gotoAndStop(rotate);
}
}
private function ReleaseToDrop(event:MouseEvent):void {
if(targetHold) targetHold.stopDrag();
targetHold = null;
}

Why am I getting error 1118 here?

In the code below I have several MovieClips that are all TheBeetle(). They are in another MovieClip called gamelevel and also pushed in an array called bArray. previously I have indexed them in the gamelevel but after the event listener is called I cannot index them anymore and receive the error "1118: Implicit coercion of a value with static type Object to a possibly unrelated type flash.display:DisplayObject.". As the user clicks them, they die (and change the frame) and the dead body goes under other alive bodies, thats the reason I need to index them to 1 as they die. I understand what the error says but how can i do what i need to do?
The code works just fine but it wouldn't in the two lines i've mentioned in it, so take a look please:
public function clicked (event:MouseEvent)
{
if (event.target is TheBeetle && event.target.currentFrame <= 2)
{
var mc:Object = event.target
// TheBeetle is actually a MovieClip but i cannot write: var mc:MovieClip = event.target, if i do i receive 1118
if (mc.currentFrame == 1)
{
mc.gotoAndStop (Math.floor(Math.random() * 3 + 4));
}
else
{
mc.gotoAndStop (3);
}
mc.filters = null;
// Here i need to index the TheBeetle as i did before like gamelevel.setChildIndex(mc,1) but i'd receive 1118!
bArray.splice (bArray.indexOf(mc),1);
if (bArray.length == 0)
{
removeEventListener (Event.ENTER_FRAME,frameHandler);
waveTimer.removeEventListener (TimerEvent.TIMER_COMPLETE, changeLocation);
}
}
}
You need to explicitly cast target to the MovieClip Class:
var mc:MovieClip = MovieClip(event.target);
You may need to do this BEFORE the line that checks target's currentFrame, as 'Object' doesn't have a currentFrame method.
I would recommend to use soft casting when you work with events and targets. By soft casting, if you have catched wrong target, you will not have problems - cast process simply returns null.
public function clicked (e:MouseEvent){
var beetle: TheBeetle = e.target as TheBeetle;
if(beetle != null && beetle.currentFrame <= 2){
//Work with beetle as you want
}
}

Can't change Movieclip's current frame while setting depths of Movieclip's children

I'm trying to set the depth of every MovieClip contained in one big MovieClip called 'map'.
To do this, I made a function that runs on event ENTER_FRAME, i.e :
public function set_depth(map:MovieClip) {
var arr:Array = [];
for(var i=1;i<=map.numChildren;i++) {
arr.push({ "name" : map.getChildAt(i-1).name, "y" : map.getChildAt(i-1).y});
}
arr.sortOn("y", Array.NUMERIC);
for(var h=0;h<arr.length;h++) {
map.setChildIndex(map.getChildByName(arr[h].name), h);
}
}
What the function basically does is to sort MovieClip based on its y property and set the MovieClip index
based on the ordererd list of the MovieClips (the y property would eventually change on its own so the
index order will change too). The problem is, I can't seem to change the 'map' MovieClip frame
while the 'set_depth' function continously runs, for example I wanted to change the map current frame everytime
I pressed the Shift key which looked like this :
public function whenKeyUp(e:KeyboardEvent) {
if(e.keyCode == 16) {
trace('Shift pressed');
map.gotoAndStop(2);
}
}
Nothing's happened everytime I pressed Shift, eventhough the trace function gets called. However, if the
'set_depth' function gets commented/deleted, the map MovieClip changed its frame to 2 without any problem.
So, is there anyhting wrong with the code? Can I somehow fix it so that the map MovieClip can change
its frame while the set_depth function runs? Or is there any other solutions? Thanks in advance. Pardon my English
Assuming setDepth(map) is called from function yourEnterFrame(e: Event)..
Change this to
public function whenKeyUp(e:KeyboardEvent) {
if(e.keyCode == 16) {
map.removeEventListener(Event.ENTER_FRAME, yourEnterFrame);
map.addEventListener(Event.ENTER_FRAME, frameHunt);
trace('Shift pressed');
map.gotoAndStop(2);
}
}
And please add this
public function frameHunt(e: Event){
var map:MovieClip = MovieClip(e.target);
if( map.currentFrame != 2) return;
map.removeEventListener(Event.ENTER_FRAME, frameHunt);
map.addEventListener(Event.ENTER_FRAME, yourEnterFrame);
}

"if (MouseEvent.CLICK = true) " error in Actionscript 3?

These are the two errors;
1067: Implicit coercion of a value of type Boolean to an unrelated
type String.
1049: Illegal assignment to a variable specified as
constant.
I want to basically set it so, if mouse is click
the -y speed of symbol helicopter = variable 'speed'
Any help? Thanks
This test doesn't mean anything: MouseEvent.CLICK is a constant and its value is always "click". So (MouseEvent.CLICK) will always be true (testing a string returns true if this string is not null).
To check if the mouse is down, you should write something like that:
var mouseDown:Boolean;
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onMouseDown(event:MouseEvent):void
{
mouseDown = true;
}
function onMouseUp(event:MouseEvent):void
{
mouseDown = false;
}
function onEnterFrame(event:Event):void
{
if (mouseDown)
{
helicopter.y += speed;
}
else
{
//maybe fall?
}
}