hi i'm trying to use requestAnimationFrame for my game and I actually use this code below, but as you can see ".bind()" create every loop a new function that slow down my game... I'm looking for a "efficient" solution for the best perfomance, thank you in advance :D
function myClass() {
this.loop = function() {
window.requestAnimationFrame(this.loop.bind(this));
/* here myGameLoop */
}
this.loop();
}
above code works but is slow.. instead this "standard" code give me "Type error":
window.requestAnimationFrame(this);
I have also found e tried this Q&A: requestAnimationFrame attached to App object not Window works just ONE time then give the same "Type error" :(
try if you don't believe me: http://jsfiddle.net/ygree/1 :'(
Without knowing the whole story of your object (what else is in there); you could simplify life by just doing this:
function myClass() {
var iHavAccessToThis = 1;
function loop() {
iHavAccessToThis++;
/* here myGameLoop */
requestAnimationFrame(loop);
}
loop();
//if you need a method to start externally use this instead of the above line
this.start = function() { loop() }
//...
return this;
}
Now you don't need to bind anything and you access local scope which is fast.
And then call:
var class1 = new myClass();
class1.start();
Related
When developing Google Apps Scripts, I make use of libraries since there's lots of shared code. If I have a library A:
function foo() { ... }
Then if I use that library in another script, B, the foo function is exposed via a library resource and gets called like:
function bar() {
A.foo();
...
}
However, the Google AddOn documentation says to never use libraries. So I prep the AddOn by combining all the library files, which puts everything in the same context, and now the same call from bar should be foo() and not A.foo().
I've been trying to think of some trick or way of doing all this that will allow me to combine the files without going through and rewriting all the library function calls (e.g., find 'A.' replace '') or transferring all the functions to an object (e.g., A = { foo: function() {...} }). I'd like to be able to just copy and paste all the library bits, but I can't figure (or find) a way to do it.
Does this little example help? There might be a better/easier way to do it, but it works with minimal editing of the original library. The other common method of exposing a library's functions don't seem to work with apps script.
Option 1:
var a = new A();
function main() {
Logger.log(a.foo());
}
function A() {
var self = this;
self.foo = function() {
return "Hello, world!";
}
function bar() {
return "I'm private!";
}
}
Option 2:
A little more complicated using prototype...
function main() {
var a = new A();
Logger.log(a.foo());
}
var A = function() {
var self = this;
self.bar = function() {
return "World!";
}
}
A.prototype.foo = function() { //Prototype public stuff
return "Hello, " + this.bar();
}
Either way they will have to modified a bit. Does anybody else know a better way?
Let's say I have a series of animations that I want to execute in sequence. If I do it like this, am I creating a huge call stack that eats up more memory than necessary?
function ch1():void {
var someVar:uint;
function doThis();
...
...
ch2();
}
function ch2():void {
var someOtherVar:String;
function doThat();
...
...
ch3();
}
function ch3():void {
var evenMoreVar:Number;
function doMore();
...
...
ch4();
}
Would it be better to call the next function by doing something like this to avoid a huge call stack?
function ch1():void {
addEventListener("ch1_end",ch2);
var someVar:uint;
function doThis();
...
...
dispatchEvent(new Event("ch1_end"));
}
Using events is a better way to deal with sequences like yours, but in some simple cases you can just delay each call a little so you can be sure they will not run in the same time and cause freezing your swf , try to use something simple like setTimeout and see the results, if it is not good then you should try useing the events as you have described in your question .
var nextCallDelay:Number = 20; // in milliseconds, change it to fit your needs
function ch1():void {
var someVar:uint;
function doThis();
...
...
setTimeout(ch2, nextCallDelay);
}
function ch2():void {
var someOtherVar:String;
function doThat();
...
...
setTimeout(ch3, nextCallDelay);
}
function ch3():void {
var evenMoreVar:Number;
function doMore();
...
...
setTimeout(ch4, nextCallDelay);
}
How about you return something instead so you don't have that huge stack of interconnected functions ?
function ch1():void {
return true
}
function ch2():void {
return true
}
function myAnim(){
var ani1 = ch1();
var ani2 = ch2();
}
I'm no code genius, but a fan of action script.
Can you help me on this:
I have a function that depending on the object selected, will call event listeners to a set of 'sub-items' that are already on stage (I want to reuse this subitems with changed parameters upon click, instead of creating several instances and several code).
So for each selected 'case' I have to pass diferent variables to those 'sub-items', like this:
function fooMenu(event:MouseEvent):void {
switch (event.currentTarget.name)
{
case "btUa1" :
trace(event.currentTarget.name);
// a bunch of code goes here
//(just cleaned to easy the view)
/*
HELP HERE <--
here is a way to pass the variables to those subitems
*/
break;
}
}
function fooSub(event:MouseEvent):void
{
trace(event.target.data);
trace(event.currentTarget.name);
// HELP PLEASE <-> How can I access the variables that I need here ?
}
btUa1.addEventListener(MouseEvent.CLICK, fooMenu);
btUa2.addEventListener(MouseEvent.CLICK, fooMenu);
btTextos.addEventListener(MouseEvent.CLICK, fooSub);
btLegislacao.addEventListener(MouseEvent.CLICK, fooSub);
Anyone to help me please?
Thank very much in advance. :)
(I'm not sure I got your question right, and I haven't developed in AS3 for a while.)
If you want to simply create function with parameters which will be called upon a click (or other event) you can simply use this:
btUa1.addEventListener(MouseEvent.CLICK, function() {
fooMenu(parameters);
});
btUa2.addEventListener(MouseEvent.CLICK, function() {
fooMenu(other_parameters)
}):
public function fooMenu(...rest):void {
for(var i:uint = 0; i < rest.length; i++)
{
// creating elements
}
}
If you want to call event listeners assigned to something else you can use DispatchEvent
btnTextos.dispatchEvent(new MouseEvent(MouseEvent.CLICK))
Remember, you can't use btTextos.addEventListener(MouseEvent.CLICK, carregaConteudo("jocasta")); because the 2nd parameter you pass while adding Eventlistener will be considered as function itself - there are two proper ways to use addEventListener:
1:
function doSomething(event:MouseEvent):void
{
// function code
}
element.addEventListener(MouseEvent.CLICK, doSomething); //notice no brackets
2:
element.addEventListener(MouseEvent.CLICK, function() { // function code });
So:
function fooSub(event:MouseEvent, bla:String):void
{
trace(event.currentTarget.name+" - "+bla);
// bla would be a clip name.
}
codebtTextos.addEventListener(MouseEvent.CLICK, function(e:MouseEvent) { fooSub(e, "jocasta") } );
Or try something like this if you want content to be dynamically generated:
btUa1.addEventListener(MouseEvent.CLICK, function() {
createMenu(1);
});
btUa2.addEventListener(MouseEvent.CLICK, function() {
createMenu(2);
});
function createMenu(id):void
{
// Switching submenu elements
switch (id)
{
case 1:
createSubmenu([myFunc1, myFunc2, myFunc3]); // dynamically creating submenus in case you need more of them than u already have
break;
case 2:
createSubmenu([myFunc4, myFunc5, myFunc6, myFunc7]);
break;
default:
[ and so on ..]
}
}
function createSubmenu(...rest):void {
for (var i:uint = 0; i < rest.length; i++)
{
var mc:SubItem = new SubItem(); // Subitem should be an MovieClip in library exported for ActionScript
mc.addEventListener(MouseEvent.CLICK, rest[i] as function)
mc.x = i * 100;
mc.y = 0;
this.addChild(mc);
}
}
Your question is rather vague; what "variables" do you want to "pass"? And what do you mean by "passing the variable to a sub item"? Usually "passing" means invoking a function.
If you can be more specific on what exactly your trying to do that would be helpful. In the meantime, here are three things that may get at what you want:
You can get any member of any object using bracket notation.
var mc:MovieClip = someMovieClip;
var xVal:Number = mc.x; // The obvious way
xVal = mc["x"]; // This works too
var propName:String = "x";
xVal = mc[propName] ; // So does this.
You can refer to functions using variables
function echo(message:String):void {
trace(message);
}
echo("Hello"); // The normal way
var f:Function = echo;
f("Hello"); // This also works
You can call a function with all the arguments in an array using function.apply
// Extending the above example...
var fArgs:Array = ["Hello"];
f.apply(fArgs); // This does the same thing
Between these three things (and the rest parameter noted by another poster) you can write some very flexible code. Dynamic code comes at a performance cost for sure, but as long as the frequency of calls is a few hundred times per second or less you'll never notice the difference.
I'm having some problems with an event handler in the object below. I can't remember the error message but it basically said that it could not find the function. The code below is an example of what I'm trying to do.
var anObject = function () {
var n = 0;
var HandleClick(e) {
n ++;
};
return {
Init: function () {
var app = UiApp.getActiveApplication();
var handler = app.createServerHandler("HandleClick");
var com = UiApp.LoadComponent("MyGui", {prefix: "a"});
com.getElementById("button").addClickHandler(handler);
}
}
}
Would really appreciate a work-around if possible, if that is not possible then please tell me what you would suggest because I'm not sure how best to get around this.
Thanks guys.
All handler functions must be top level functions on your script. It's not possible to have it inside an object like this.
I'm writing a display class in Javascript (using jQuery) which may be instantiated before a web page has loaded. If the page isn't ready when the constructor is called, the instance is added to a static instances field for the class, which is iterated over when the page has loaded:
function MemDisplay(ready_callback) {
this.readyCallback = ready_callback;
if (MemDisplay.ready) {
this.linkToPage();
} else {
MemDislay.instances.push(this);
}
}
//this makes sure that the ready callback can be sent when the page has loaded
MemDisplay.ready = false;
MemDisplay.instances = [];
$(document).ready(function () {
var i;
MemDisplay.ready = true;
for (i = 0; i < MemDisplay.instances.length; i += 1) {
MemDisplay.instances[i].linkToPage();
} });
//example truncated for brevity
When I run this through JSLint, I get this error:
Problem at line 25 character 9:
'MemDislay' is not defined.
MemDislay.instances.push(this);
I need to reference MemDisplay.instances in the constructor, but the constructor is where MemDisplay is defined, so I'm puzzled about how to make this work while fitting within JSLint's guidelines. Is there a better way to do this? Should I just ignore JSLint in this instance?
JSLint here is actually highlighting a broader issue with the code without saying so.
You are referencing a class (MemDisplay) but never instantiating it as an object. I.e. you are treating the class like an already-instantiated object.
I've created a very simple equivalent to what you are trying to achieve (also at this JSFiddle)
function MyClass(p1, p2){
this.param1 = p1; //class member/property - use this to access internally.
if (this.param1 === 1){ //you might want to consider doing this as part of some setter method
alert("test");
}
this.MyMethod = function(){ //class method/function
alert("MyMethod Called");
};
}
var myObj = new MyClass(1,2); //instantiate
alert(myObj.param1); //get value of object member (you can set as well)
myObj.MyMethod(); //call a method
It'll take a bit of reorgansiation, but by declaring the values up front, you can get make JSLint happy.
My brain must have figured this out while I slept: the trick is to attach the field to the prototype, which seems pretty obvious now that I've thought of it, since that's what you have to do to define class methods.
The following checks out in JSLint, and demonstrates the sharing of a field between all instances of MyClass (or see this code on jsfiddle):
/*global alert */
function MyClass(name) {
this.name = name;
MyClass.prototype.field += 1;
}
MyClass.prototype.field = 0;
MyClass.prototype.myMethod = function () {
alert(this.name + "'s class's field is " + MyClass.prototype.field);
};
var myObj = new MyClass("first");
myObj.myMethod();
var myOtherObj = new MyClass("second");
myObj.myMethod();
myOtherObj.myMethod();
I'm not sure if there's a prettier way to do it, as having 'prototype' all over the place feels a bit excessive, on the other hand it could be a good thing because it makes it clear that prototype.field does not belong to the instance.