Flash Escape Game Item - actionscript-3

I'm making a flash game that requires picking up items. The item disappears when you click on it, but it reappears when you leave the room and come back. I tried setting a variable in the function and then using an if statement in the main code but that didn't work because the variable is local. And if I declare the variable outside the function, it reinitializes when you enter the frame(return to the room). A global variable should solve this problem. I know everyone says they're bad to use but I'm just looking for a solution.
//Pick up key
key_btn.addEventListener(MouseEvent.MOUSE_UP, getKey);
function getKey(Event: MouseEvent):void{
var gotKey:Boolean = true;
}
if(gotKey == true){
key_btn.visible = false;
}

First of all: I suggest you to keep all codes in one frame and use movieclips to represent different rooms.
You can add a layer for the global vars and expand it, such as this:

Related

CreateJS way of switching ticker on & off

I'm developing a canvas game that happens to have several scenes. Each scene might end up being a static final frame after having finished. The circumstances are that the ticker and the listener for the "tick" event are still running and keep on rendering full speed - which is asking for cpu usage.
I have tried to remove the listeners at the end of scene and add them back wenn the user interacts and starts the next scene.
I wonder what would be the "createJS" way of doing this.
I see some other options but am a bit lost how to proceed:
Caching the "whole" last frame. Will it make the ticker do "absolutely nothing" performance-wise?
Pause the ticker and check for the paused attribute in the handleTick method: Seems to not take the CPU usage completely down.
Can somebody recommend a way?
On a side note: I need my real "this" object inside the tick function that is bound to the ticker. How can I achieve this? Right now I use this code:
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event) {
// Actions carried out each tick (aka frame)
if (!event.paused) {
// Actions carried out when the Ticker is not paused.
}
}
Inside handleTick "this" is not my object that added the listener.
A simple createjs.Ticker.removeEventListener("tick", handleTick); should do just fine as long as handleTick exists in your current scope. See this example.
There are a couple ways to access the scope of the object that assigned the tick listener. For example, you could simply assign this to a local variable like so:
var _this = this;
function handleTick(){
//"_this" now refers to the scope that defined handleTick.
}
Or you can use a delegate. In this example I'm using jQuery's proxy function to scope handleTick to this.
var handleTick = $.proxy(function(){
//"this" refers to the scope that defined handleTick.
}, this);
createjs.Ticker.addEventListener("tick", tickHandler);

AS3 Global Variables

Ok so I have managed to do this once before but I simply cannot remember how or find the source I found back then. I am making a simple flash game. There are several characters moving. To make each level more difficult than the other I have decided to alter the movement speed of each character from level to level. If I declare and assign values to these variables on my main timeline in frame 1 it doesn't work the way I want it. When you go to level 2, which is in another frame, the speed goes up like it should. But when you go to the next level, which is level 1 with higher movement speed, the value assignment is processed again, which means the movement speed goes back to scratch.
//frame 1
var speed:int = 5;
//level accomplished, speed++, goto frame 2
//frame 2
//level accomplished, speed++, goto frame 1
And then all the code on frame 1 runs again, setting the value of "speed" back to 5.
I have tried putting the variable in a class, but the problem is still the same, everytime it goes back to frame 1 the code "var speed:Speed = new Speed();" runs again and the value of the variable goes back to whatever I assigned in the speed.as file.
I have tried so many different combinations to just make the global variables inside a package but outside any class so that it is always globally accessible without creating a new object.
Here is my current code:
//speed.as
package
{
public var speed:int = 5;
}
//game.fla
import speed;
trace(speed);
This throws the error "Access of possibly undefined property speed..."
As I said, I have tried many different combinations and got a lot of different errors, been googling and digging for 8-9 hours and it's driving me crazy. You guys are now my last hope, I would be very grateful for an answer easily telling me how to use my global variables (I know global variables are bad, seen a lot of people writing it even though I don't really know why), if there is another easy and better solution please do tell, but I don't want to rewrite the entire code or anything to make it compatible with some other solution. I know that global variables will solve this problem for me, I just don't know how to use them.
I will need instructions on what to do in both the .as file and the .fla file. Thanks in advance!
Does it cycle between frame 1 and 2? If it does, use functions to do it instead. You don't need the .fla.
//Declare variables
var speed:int = 5;
//In this case I use a button to transit into the frame. Edit the code as you wish.
btnLevel1.addEventListener(MouseEvent.CLICK, level1);
private function level1(e:MouseEvent):void
{
MovieClip(root).gotoAndStop(2);
speed++;
//Your other code for the level goes here
btnLevel2.addEventListener(MouseEvent.CLICK, level2);
}
private function level2(e:MouseEvent):void
{
MovieClip(root).gotoandStop(3);
speed++;
//Again, your other code goes here
btnLevel1.addEventListener(MouseEvent.CLICK, level1);
}
Should work, I think.
I think you should try changing it to
package{
public class Speed{
public static var SPEED:int = 5;
}
}
and then access it via
trace(Speed.SPEED)
But: this is very dirty :)
Ok so I found a little workaround, not global variables in a separate package, but variables that can be accessed by my entire timeline.
I simply made an extra frame with just code. In this frame I put my variables + a frameCounter variable. On my first frame I put this code:
if (frameCount == 0)
{
gotoAndStop(7);
}
So the code declaring the variables only runs once. Probably not the best solution but atleast it works as intended =)

Visit frame once?

I was wondering if there is a code that can make flash recognize if a certain frame has already been visited. Is there a way to go about doing this? I was thinking about making a function that traces a frame when the player is already one it. I want the function to deny entrance to that frame after it was viewed once.
Actionscript 3 doesn't care about frames. It's only flash that does.
So I would suggest keeping a global array of visited frames & populating it with frame numbers.
In frame code (I assumes you're coding in frames):
var visited:Boolean;
if (visited) return;
visited = true;
//... do frame actions
How about disabling or removing the option to go to back to a completed frame? i.e if there is a back/forward button. Just go to the next page and disable or remove the back button. It's hard to give good advice without knowing what you are trying to accomplish.
Try something like this. Setup an array of the same length as your movieclip in frames, all initialized to false.
var framesVisited:Array = [];
// since we're talking about frame numbers here, start at 1 instead of 0 like
// you normally might.
for(var i:int = 1, ilen:int = this.totalFrames ; i <= ilen ; i++){
framesVisited[i] = false;
}
Now, each time you visit a frame, make sure its corresponding array location is set to true.
framesVisited[this.currentFrame] = true;
Now in your function to check whether a frame has been visited, just return the value of the array.
public function hasFrameBeenVisited(frameNumber:int):Boolean{
return Boolean(framesVisited[frameNumber]);
}

Setting cursor priority with AIR native cursors

Is there a way to set the priority (CursorManagerPriority.HIGH) of a mouse cursor set via Mouse.cursor = '...';?
Long story short, I've had to resort to using the CursorManager to apply cursors, because setting the priority is crucial for my application due to the HTML control overriding all cursor changes without a high priority. Setting cursors with the cursor manager totally works, but the cursors aren't as fast/response as those rendered at the OS level (as described here).
If there isn't a way, my next question is: is there any way to suppress the cursor changes made by the HTML control? Setting mouseEnabled = false does it... but disables all mouse events on the HTML page, so that doesn't work.
Example:
This doesn't work:
setInterval(function():void { Mouse.cursor = 'ibeam'; }, 100);
Setting a cursor with a high priority works, however:
// ibeamCursor is an embedded PNG
CursorManager.setCursor(ibeamCursor, CursorManagerPriority.HIGH, -2, -4);
(this code is used at mx:Application scope)
I'm going to assume that you have access to the code for the HTML control...otherwise, I'm not sure you can do this at all.
I don't think you can set priority on cursors set by Mouse.cursor = "..."; (tho I could be wrong...if anyone has info to the contrary, feel free to correct me.)
However, I think you can very easily suppress cursor changes simply by using a boolean variable and an if-statement.
var customCursors:Boolean;
Then, on each place where the cursor changes occur...
if(customCursors == true)
{
Mouse.cursor = "mycursor";
}
This will allow or suppress changes to the cursors, simply by changing the customCursors variable.
However, there may be something more useful if you're dealing with two conflicting cursors, and you want one to only take place during certain instances. For that, you could try a different if statement.
In my own code, I want one cursor to show up only while dragging an object, but not just while the mouse is over it. One is inside the move event, and the other inside the over event. There was a third that would show up only when the object was dragged over a certain point, and when it was not, it needed to be the regular dragging cursor.
This created a rather annoying conflict...
To fix that, I actually checked the Mouse.cursor property in my if statement! The placement of various Mouse.cursor statements in my events created a sort of priority for the cursors. It works perfectly.
In my mouse over statement:
Mouse.cursor = "hand";
In my mouse down statement (where I start dragging):
Mouse.cursor = "dragging";
In my move statement:
if(Mouse.cursor == "draggingover")
{
Mouse.cursor = "dragging";
}
In my mouse up statement (where I stop dragging):
Mouse.cursor = "hand";
In my mouse out statement:
Mouse.cursor = "pointer";
I hope this helps! If it does, don't worry about overlooking this seemingly obvious solution...I think we're all prone to do so when we're looking for built-in functions.
If this isn't helpful, sorry. Again, I don't think there is another way, but if anyone knows of one, please weigh in.
I believe HTML control inherits from ScrollControlBase. Try fixing your Mouse issues on that parent control, rather than on the HTML control.
Also, you can try overriding the HTML control, adding code to remove default cursor look and feel. See this blog post, and just do the opposite.

hitTestObject, stopDrag stops drag on two movieclips even though function states one movieclip to stop drag

I have a function that states when movieclip1 is dragged and hits a line then it stops the drag, however it seems to stop the entire drag function in the swf on the other movieclips even though they arent called in the function. Can somebody please help me with this.
Regards
T
Here is the code:
function hitTest(event:Event):void
{
if (movieclip1.hitTestObject(line))
{
movieclip1.stopDrag();
}
else
{
}
}
Are you absolutely positive you only have one instance of movieclip1 on your stage? Definitely double check. Are you creating them dynamically, or are they preloaded when your SWF loads?
If they're preloaded:
Perhaps during testing you made some quick copies of it, and now those copies have the same name and they're all responding the same. That's my first guess.
If they're loaded dynamically:
Check the function where they're being created. If you're naming them in a loop (with a number on the end like the above), be sure that you're properly increasing the numeric value used on the end.