Skip to main content

News

Topic: analogue.js (Read 16126 times) previous topic - next topic

0 Members and 1 Guest are viewing this topic.
  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #15
With the latest version of analogue, I get an "invalid 'in' operand event" exception when loading a map with no accompanying JS file (for example, the test map I use for prototyping).  Previous versions handled this just fine (and so did persist, I think), so I'm guessing this is a regression?
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: analogue.js
Reply #16
Revision 9

Minor update.

Bug Fixes
- Fixes empty script evaluation regression.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #17
Damn, I forgot about this little wrinkle with persist/analogue, it's been so long since I wrote an actual persist script...

You can't change maps in the enter function, otherwise you get an exception: "ChangeMap() failed: Default enter map script already running!"  This breaks my opening cutscene, which is initiated from a blank starting map (so that the opening narration is on a black background), then switches to another map for a flashback, and finally switches to the starting town before giving the player control.  Know of any way around this, Radnen?
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: analogue.js
Reply #18
Oh, well, that's impossible. If you change map when you enter a map you'll be doing it forever. That's what the default map script does. When you save it with the file it does a run-once on the enter, after it does the default.

1. All default map scripts are ran.
2. All local map scripts are ran.

Since persist changes the default map script, you can't do some things since, well, it tries to stop you from an endless cycle. Using ChangeMap() in a default map script means another map is loaded, which means another entry, which means another ChangeMap() call (and repeat). Of course, persist and analogue work by changing the map script out each time a new map is loaded and so you wouldn't have that problem. However, the engine writers never foresaw that.

The workaround: SetDelayScript(1, "ChangeMap('map.rmp');");

Interestingly, if you set the delay to 0 you'll hang the engine! XD But at 1 it might blink the map for a frame...
  • Last Edit: June 30, 2013, 01:24:28 am by Radnen
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #19
Thanks.  I had to use a slightly different method, though.  I can't call ChangeMap() directly (I'm using Scenario so that would break the scene coordination), instead I have a teleport scenelet defined for Scenario that does the ChangeMap internally.  So what I had to do instead was, I still used SetDelayScript, but instead of just queuing the ChangeMap call, I created a function to run the whole cutscene, and set a delay script to call that function.  Works like a charm!
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: analogue.js
Reply #20
Revision 10

Stability update.

Bug Fixes
- Properly fixes long paths for Linux machines running Sphere.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #21
Are you sure using 'this' works properly? I haven't tested it yet, but I just skimmed through the code and discovered that you're calling event functions like this:

Code: (javascript) [Select]
map[event](map, world)


...which passes the global object as 'this'.  You should be using the .call method...
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: analogue.js
Reply #22
No, that works perfectly fine. Calling a function first uses the prototype it's bound to before anything else: it's calling a method of the map object. In many languages, if you call an object's method 'this' is implicitly set to the owner of the method, therefore you (usually) don't have to do something like this: myObject.call(myObject, params) each time you call a method.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #23
No, I knew that, I just wasn't sure if obj["func"] had the same semantics as obj.func.  E.g. If you do:
Code: [Select]
var f = obj.func;
f();


Then 'this' isn't set correctly (it's the global object).  I figured the array syntax would have the same problem.
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: analogue.js
Reply #24
Oh yeah obj["func"] is the same thing as obj.func, in fact I can just call map.enter() directly, but I'd have to do a separate call per method whereas the [] accessor can just loop through the calls. JS can be really neat sometimes!
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: analogue.js
Reply #25

Are you sure using 'this' works properly? I haven't tested it yet, but I just skimmed through the code and discovered that you're calling event functions like this:

Code: (javascript) [Select]
map[event](map, world)


...which passes the global object as 'this'.  You should be using the .call method...

That will actually pass map as this. Basically, here's how this works in JavaScript:







Invocation type                         Syntaxthis value
functionfn(arg);global object1
methodobj.fn(arg);
obj["fn"](arg);
obj
applyfn.call(self, arg);
fn.apply(self, argArray);
obj.fn.call(self, arg);
self
bind2var f = fn.bind(thing); f(arg);
var f = obj.fn.bind(thing); f(arg);
thing


It does not matter what happened prior to the invocation; e.g.
Code: (javascript) [Select]

var fn = obj.fn;
fn(1, 2, 3);

will behave as the first invocation pattern. Another example:
Code: (javascript) [Select]

fn(1, 2, 3);  // `this` is the global object (see footnote 1)
obj.fn = fn;
obj.fn(1, 2, 3);  // `this` is obj


obj.fn is exactly equivalent to and is merely syntactic sugar for obj["fn"].


  • Behavior changed in ECMAScript 5 strict mode. this value will be undefined if "use strict" is active. c.f. ES5 Appendix C

  • Requires ECMAScript 5 or an equivalent polyfill.


  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #26
Good to know, thanks alpha.  For some reason I always assumed that the interpreter converted this:
Code: (javascript) [Select]
obj["func"]();

...to this:
Code: (javascript) [Select]
var tmp = obj["func"];
tmp();


That is, that the indexing operation was evaluated before the function call, rather than the whole thing being atomic.  Must be my C/C++ instincts kicking in again...

So yeah, thanks for clearing that up! :)
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub

Re: analogue.js
Reply #27
You're not entirely wrong, although that varies from JS engine to JS engine.

Basically the runtime does
Code: (javascript) [Select]
var tmp = obj["func"];
tmp.call(obj);


No problem. this is one of those weird hairy corners of JS that I didn't fully understand for a while.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • Sphere Developer
Re: analogue.js
Reply #28
I found a bug:

Code: (javascript) [Select]
({
enter: function(map, world) { world.cows_eat_kitties = "Meoowww--MOOOOoooooo! ...*munch*"; },
kitty: {
    talk: function(self, world) {
        Abort(world.cows_eat_kitties);  // undefined?! wtf
    }
})


If I change all references to the world argument to analogue.world it works fine, but apparently analogue is passing different world objects to each handler...?

Edit: Come to think of it, didn't persist.js have this same issue?  This exact bug is why you wrote analogue.js in the first place... kind of ironic. ;)
  • Last Edit: April 14, 2015, 01:36:30 am by Lord English
neoSphere 5.9.2 - neoSphere engine - Cell compiler - SSj debugger
forum thread | on GitHub