how to pass this (MovieClip) as a parameter? - actionscript-3

How can I pass the keyword this OR an instance name as a parameter inside a function?
function (reference:InstanceName):void // kind of what I want
{
reference.gotoAndPlay("frameLabel");
}

To clarify jozzeh's correct answer: your problem is variable scope. The "this" keyword's scope is contained to the owning object - you would need to establish the proper scope of the parent timeline in your function call:
function goTo( reference:MovieClip ):void
{
reference.gotoAndPlay("Start");
}
goTo(this.root); // variable scope of "this" is now at the class level
Obviously, we sometimes need parameter initializers, but in this case - a reference to 'this' is going to throw an error. If this is a function that has a changing value, sometimes the focus of which is of its own root, you'd need to handle the initializing logic outside of the method sig.
good luck!

I have never seen this being referenced like that...
The 'this' within a function is a reference to the object that initialized the function.
example:
var test:String = "testing the test."
test.myfunction();
function myfunction():void{
//this = the variable "test"
this.indexOf('test');
}
Also if you want to pass a variabel to a function it should be like this:
var test:String = "testing the test."
myfunction(test);
function myfunction(mystring:String):void{
var indexer:Number = mystring.indexOf('test');
}

Related

nested function cant find itself in Typescript

I have the following code:
//Main Entry Point.
start() {
this.init();
this.gameLoop();
}
//Init, runs only once.
init() {
let initalEntity1: Entity = new Entity(10, 10, Gender.female);
let initalEntity2: Entity = new Entity(60, 60, Gender.male);
console.log("There are " + this.Entities.length + " Items in the entities Array")
this.Entities.push(initalEntity1, initalEntity2);
console.log("There are " + this.Entities.length + " Items in the entities Array")
}
gameLoop() {
console.log("Performing a Game Loop");
requestAnimationFrame(this.gameLoop);
//MAIN LOOP THROUGH ENTITIES
for (let i in this.Entities) {
this.Render.drawEntitysToScreen(this.Entities[i].EntityPosition, this.Entities[i].gender);
}
}
It enters into start() fine, and also performs all of the init() functionality. it them proceeds onto gameloop() which it will run once, however the line requestAnimationFrame(this.gameLoop); which is ment to retrigger the function to be called as a Canvas frame is causing the following error:
TypeError: this is undefined
trying to requestAnimationFrame(gameLoop); but it causes the typescript compiler to get upset...
This is due to how this binding works in javascript. The way by which you are passing this.gameLoop to requestAnimationFrame is essentially passing an unbound gameLoop function, and so when it is called, it has lost reference to its this.
There are a number of possible solutions to this problem:
You can bind this.gameLoop to this inside of the class constructor, like so:
constructor() {
this.gameLoop = this.gameLoop.bind(this);
}
You can bind this.gameLoop to this as part of the gameLoop method definition. Rather than defining gameLoop like
gameLoop() {
If you instead use
gameLoop = () => {
it will be automatically bound to this. This is a property of using the fat arrow for function declarations: it automatically performs binding to the this that exists at the function declaration.
You can change how you pass gameLoop to requestAnimationFrame:
requestAnimationFrame(() => this.gameLoop());
This again takes advantage of the automatic this binding performed by the arrow function, but instead of doing it as part of the class method declaration you can simply do it lazily at the time you need it to be bound.
Note, however, that doing it this way does mean that a new function will be created each time gameLoop is called.
When you call this.gameLoop() within start, the value for this inside gameLoop's body will be the class gameLoop belongs to, because you call gameLoop as a property of this (the class).
When you pass a function reference its value for this might be anything when the function is called from somewhere else.
Solution 1 | Using Function.prototype.bind
bind the value for this as you give the function to requestAnimationFrame. By doing this you explicitly say:
Let the argument to bind be this inside any call to gameLoop, regardless of how it is called, or where it is called from.
requestAnimationFrame(this.gameLoop.bind(this));
Note that bind returns you a new function, so the original gameLoop function that is still a property of your class remains unchanged.
Solution 2 | Using an arrow function
Define an arrow function to eventually execute the call to gameLoop instead of requestAnimationFrame. The this value within arrow functions is static, and is inherited from the execution context enclosing the function declaration.
requestAnimationFrame(() => this.gameLoop());

AS3: Returning value from another function after event happened

Basically I want to check if a user exists in a database using AMF (and that works great!). But then I want to return the boolean value to another function (in another class) that originally called the "checkUserExistance" function. But, since the database connection isn't immidiate, this function will always return a false value (even if "result" is true). So I would like to have the return-line inside the "onUserChecked"-function but that of course gives me an error. I thought I could create an eventListener, but then, the "return userExists"-line would also have to be inside another function, which doesnät work(?)... What can I do?
public function checkUserExistance(username:String) {
var responderBOOLEAN:Responder = new Responder(onUserChecked, onFault)
var userExists:Boolean = false;
connection.connect(gateway);
connection.call("User.checkUser", responderBOOLEAN, username);
connection.close();
function onUserChecked(result:Boolean):void {
userExists = result;
}
return userExists;
}
I'm sorry but you are trying to force an Asynchronous call to a Synchronous one and this is WRONG.
See here
You should learn how to handle events in the correct way.
What can i suggest you that helped me a lot is this
The only true answer here is to save userExists as a member variable, and dispatch event when the server returns you a response. The client side of the things should be similar to:
// add listener, ServerEvent is a custom event (see below)
server.addEventListener(ServerEvent.CHECK_RESPONSE, onCheckResponse);
server.checkUserExistance('username'); // start the query
function onCheckResponse(e:ServerEvent):void {
if (e.userExists) {
}
}
// inside server class
function onUserChecked(result:Boolean):void {
userExists = true;
dispatchEvent(new ServerEvent(ServerEvent.CHECK_RESPONSE, userExists));
}
/* ServerEvent is a custom class that extens Event
Such classes are used so you can pass special properties in them
via constructor (pass data, store it into member variable)
and through getter for that variable.
If you don't like it, simply add/dispatch Event.COMPLETE
and use public property to get userExists from server
*/

ActionScript 3: Assigning a named function to a variable of type Function

I'm working with a game loop and am attempting to handle user input by assigning various methods to a variable of type Function depending on the games state.
I'm assigning a defined function called InputState1 to my Function variable inputFunction:
var inputFunction:Function = InputState1;
where InputState1 is:
public function InputState1():void
{
// input logic
}
and call inputFunction in the game loop's update method:
override protected function update(timeDelta:Number):void
{
trace(inputFunction);
inputFunction();
}
When I trace the inputFunction, it returns an empty function.
Is it possible to assign a named function to a function variable and if so, how would I go about doing this properly?
Solution: I was invoking my function variables call method instead of just calling the function. It works now.
What I have understood from your argument is that you want a game state to be identified and act according to it, well you always can define a String holding the game state value which updates as game state changes, and make a function returning that string,(or directly comapre that string wth defined states)
var gameState:String="initial";
override protected function update(timeDelta:Number,gameState:String):void
{
gameState="newstate"; //depending upon your condition requirement
}
if(gameState="requredState"){
//do required stuff
}
The issue was that I was invoking my function variable's call method instead of just calling the function. It works now and I've edited the code in my question to the correct version.

weird behavior of variables in anonymous functions?

Could anyone explain why the trace result of the code below are "5,5,5,5,5" rather than "1,2,3,4,5" and how do you make the anonymous function refer the collect element in the array?( in this example, "var item" should be referring list[0],[1],[2],[3],[4]).
var list:Array=[1,2,3,4,5];
var funcs:Array=[];
for each(var item:int in list){
funcs.push( function(){
trace(item);
});
}
for each(var func:Function in funcs){
func();
}
trace result: 5,5,5,5,5
The problem with your code is that you create a closure which you access later.
For what you want to do you need to create multiple closures that can be later accessed.
var list:Array=[1,2,3,4,5];
var funcs:Array=[];
var closure_factory = function(index) {
return function() { trace(index); };
};
for each(var item:int in list){
funcs.push(closure_factory(item));
}
for each(var func:Function in funcs){
func();
}
This is the result of two things:
Function-level scope in AS3: the variable declaration inside for each(var item:int in list) is equivalent to declaring a var item:int at the beginning of your function (in your example, at the start of your code).
Anonymous functions are closures, which contain not only the code that you specify trace(item), but also the environment for that code to run in. Specifically, each of the anonymous functions created by your code knows that it should use the item variable (declared at function scope) for printing (via trace()).
So, what happens is that item gets assigned all the elements of list, and then retains the last value (which is 5). It exists (does not go out of scope), and when those anonymous functions fire, each of them looks at the same item and prints the same value.

How to pass parameters to external function through map.event.addListener

I want to add listeners to google map events, but not using anonymous functions but named, external functions as this happens inside a loop, I do not want to define an anonymous function right there, but instead use a named, external function:
Not:
for (...) {
googleMap.event.addListener(instance, eventName, function() {...});
}
But rather sth. like:
doSomething = function(parameter1, parameter2...) {
...
}
for (...) {
googleMap.event.addListener(instance, eventName, params, doSomething);
}
When "instance" is a google map marker, I can add the parameter(s) to the marker using marker.set(paramName, paramValue) and then access the parameters inside the event handler function via this.paramName, but is there any other way to pass values to the event handler function when I don't want to use an anonymous one?
Any advice welcome, Roman.
I had the same problem. Here is a solution. It genuinely avoids the create function in a loop problem, by using the pattern described here
In JavaScript, what are specific reasons why creating functions within a loop can be computationally wasteful?
Which I call the "function factory" pattern.
The other ingredients are that inside the function "this" refers to the object which raised the function (the thing on the map which was clicked, or whatever), and because JavaScript is completely dynamic, you can attach additional properties at will to the thing which was clicked, and query them by calling this.blah inside the function
function doSomethingHandlerFactory(){
var f = function(event){
//do something, for example call a method on a property we attached to the object which raised the event
this.blah.clicked(event);
};
return f;
}
//add a property to the google overlay object (for example a polyline which we've already set up)
thePolyline.blah = ...;
//get a handle for a function, attach the event (in this case to a polyline), and keep
//a reference to the event (in case we want to call removeListener later). The latter
//is optional.
var f = doSomethingHandlerFactory();
var ev = google.maps.event.addListener(thePolyline, 'click', f);
I hope this helps someone out.
How about wrapping your named function in an anonymous function:
google.maps.event.addListener(instance, eventName, function() { doSomething(parameter1, parameter2,...) });