Yann's Recent Forum Activity

  • vtrix

    Ok very interesting. At first I thought it was just a simple misuse, but it turned out there were a very peculiar issue.

    So first for the misuse, which is more of a design flaw for now, is that the foreach loop is actually modifying the current path to point to the property being foreached ( which doesn't work properly if you loop using an root based path (the loop will ignore the path <_<)). So, if you modify the current path inside the foreach loop, everything can get fucked up (:

    Here is one example case:

    considering this object:

    { "Wizard": {
          "stats":{
             "hp":100,
             "mp":80,
             "int":120,
             "dex":20,
             "str": 10
          },
          "buffs": {
             "hp":10,
             "mp":15,
             "int":10,
             "dex":3,
             "str": 2
          }
       }
    }[/code:2xof0hjw]
    
    Let say we want to loop through all the property and display their stats + buffs. It could be done like that:
    [code:2xof0hjw]
    -> System: set Current Path to root["Wizard","stats"]
    + JSON: foreach current[]  // using foreach root["Wizard","stats"] is broken
      Local text property = ""
      Local number value = 0
      -> System: set property to JSON.CurrentKey
      -> System: set value to JSON.Value(1,CurrentKey)
      -> System: set Current Path to root["Wizard","buffs"] // here you are modifying the looping path
      -> Text: Set text to property & ":" & value& " + " & JSON.Value(1) & " = " & value+ JSON.Value(1)[/code:2xof0hjw]
    
    Here is what will be output in the text object:
    [code:2xof0hjw]hp:100 + 10 = 110
    mp:15 + 15 = 30
    int:10 + 10 = 20
    dex:3 + 3 = 6
    str:2 + 2 = 4[/code:2xof0hjw]
    As you can see, after the first iteration, the loop is in fact looking into the buffs path
    and if you doesn't have the same properties in the two path you'll get some NaN or undefined values.
    
    I see two possible solutions to this problem:
     1. have a separated Current Path and Loop Path. As much as it makes sense now, I think it's a very confusing solution. What would be the current[]  in this situation? or maybe I should have root/current/loop... And what happens with nested loops? should I name those path like it's done with for loops and loopindex?... So yeah I'm not too sure about this idea
     2. have the loop reset the Current Path to the original path after each iterations. Good thing is, it's simple and straightforward to implement and use. Bad thing is, any change to the current path you do inside a loop will be lost at the end of the iteration (cannot be saved for later). But I think it's a very specific case and I can easily find a work around using an array in C2 and making a "savePath" and "buildPath" function.[code:2xof0hjw]// Function.Call("loadPath")
    + Function: On "loadPath"
       -> JSON: Set Current Path to root[]
       + Array: For each X element
          -> JSON: Set Current Path to current[Array.CurValue][/code:2xof0hjw][code:2xof0hjw]// Function.Call("savePath","path","you","want","to","save",...)
    + Function: On "savePath"
       -> Array: Set size to (0,1,1)
       + System: Repeat Function.ParamCount times
          -> Array: Push back Function.Param(loopindex) on X axis[/code:2xof0hjw]
    Though one weakness is that you can't dynamically save the path because you have no way, during a foreach loop, to know the entire path, you just know the CurrentKey. If you are recursively inspecting an entire unknown JSON it's harder to save a spacific path (probably doable if you save the path constantly during the recursion...)
    Maybe I could add a "foreach Node in the path"condition you could call in savePath instead of passing parameters.
    
    Anyway, now, for the real interesting stuff I discovered thanks to your capx:
    1. The list of parameters you pass in set Current Path to root["template","folder"], which is internally an array, is in fact built just once, and the same array object is passed over and over each time C2 reaches this action (at least during a given tick).
    And the plugin was using this very same array as a current path, and this array was modified when going through your two first foreach.
    That's why when you execute the run function a second time, you are already at root["template","folder","object1","path"] instead of root["template","folder"]. The array of argument was modified during the previous run.
    Hopefully this is easily solvable by using a copy of this array.
    2. A the end you logged properties (0, 1, 2, 3, 4 ,5 ,6)  that didn't really make sense since there were no array in your JSON. And the reason for that is that, in the second run, your first foreach was looping through the value at ["template","folder","object1","path"] which was actually the string "folder2". Javascript often consider strings as arrays of character, so you where looping through the 7 letters and was logging their indices. (which is more an unexpected feature than a bug )
  • vtrix

    it will obviously (:

  • vtrix

    Not sure I understand all that you are saying, an example capx to illustrate your case would be better.

    Anyway, a simple capx showing how to simply go from array to the JSON plugin:

    arrayToJSONplugin.capx

  • vtrix

    You guessed right, when I do

    JSON.ToJson(0,"Star1")[/code:2v4ltxd4]in javascript I in fact do[code:2v4ltxd4]JSON.stringify(this.root["Star1"]);[/code:2v4ltxd4](well not exactly since I loop through the arguments provided to go through the path, but in a nutshell that's what I do)
    
    So yeah, if you already have the JSON string as a template, instead of copying one object into another with that[code:2v4ltxd4]-> JSON: Load JSON at root["Star2"] to JSON.ToJson(0,"Star1")[/code:2v4ltxd4]Doing that:[code:2v4ltxd4]-> JSON: Load JSON at root["Star2"] to myTemplate[/code:2v4ltxd4] (with myTemplate containing the JSON string for your... template) 
    would be slightly more efficient but you still will do a javascript JSON.parse(myTemplate) which can potentially be a bit slow as well (meaning slower than just passing references in javascript)
    
    If I rename the Length property I would probably not use ObjectSize but just Size, so you could use it for arrays or objects. (Note that your projects using Length will break when I'll make this change... or I can just set it to deprecated for a while to give you the opportunity to change it)
    
    Not sure I get your thing about ID. If you want to reference a JSON object using some kind of numbering, an array seems ok, you just need that numbering to be consecutive. (well in theory, javascript allows non consecutive indexing but when generating a JSON from that, in chrome at least, you get an array with the holes filled with null)
    For example you could do:[code:2v4ltxd4]-> JSON: Create new array at root[]
    -> JSON: Create new object at root[2]
    -> JSON: Create new object at root[4][/code:2v4ltxd4]but then if you want to get back the JSON you'll get something like[code:2v4ltxd4][null,null,{},null,{}][/code:2v4ltxd4]The other possibility would be to reference them in an object using the ID as a key.
  • shinkan

    You can't do that kind of thing in any language I know of.

    JSON objects (a.k.a. dictionnary or hashtables) are values indexed using a key.

    The only way to change the key, for a given value, is, as you did, copying to another key and deleting the previous one.

    In javascript it wouldn't be a big deal because you would probably just swap objects references (the new key will point to the same object, hence no copy). But since, in construct2, you don't have access to any value type other than strings and number, it's not possible.

    To be clear, you would have that in javascript:

    // this creates an empty object
    // and put its reference in the variable root
    var root = {};
    
    // this creates an object with "name" and "size"
    // and  put its reference in the "Star1" property of root
    root["Star1"] = {"name":"somename","size":"somesize"};
    
    // "Star1" and "Star2" properties point to the same exact object
    root["Star2"] = root["Star1"];
    
    // for example:
    root["Star1"]["name"] = "plop";
    root["Star2"]["name"] == "plop"; // this will return true ("==" means "is equal?")
    
    // then to finish things up, in javascript you would do:
    delete root["Star1"];[/code:3clgjt1x]
    
    Now, the closest thing you can do with the current JSON plugin is:[code:3clgjt1x]-> JSON: Set Value at root["Star1"] to "{""name"":""somename"",""size"":""somesize""}"
    -> JSON: Load JSON JSON.ToJson(0,"Star1") at root["Star2"] // the copy
    -> JSON: delete root["Star1"][/code:3clgjt1x]
    as you notice it's almost the same
    The only difference is that after the copy (and before the delete) if you modify the object in "Star1", the one in "Star2" will be left untouched because it's not a reference but a copy.
    
    Modifying the key this way is totally fine, but you have to be carefull because copy is slower than just passing references. And going from an object to a JSON string to a new object is even slower than if you just copied each properties one by one. But it's a lot simpler (:
  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • vtrix

    Thing is, even in javascript you have no property/function to get the number of properties in an object. An object has no length per se.

    The way you can answer this question is to usually count them manually

    var count = 0;
    for (var p in myObject) {
        if(myObject.hasOwnProperty(p) {
             count++;
        }
    }[/code:1eqcbou2]
    I could implement that, but I'm not sure if it's a good idea to blend the boundaries between array and object. If the user can get the property count (which shouldn't really be called length) they might be tempted to believe they could loop through properties using indices... well still thinking about it.
    
    Hmm, yeah I might add that as well as "isEmpty" and "Clear" function for array and object. We'll see. Maybe renaming "Length" to "ElementCount" or something more general to cover array and objects with the same function... 
    Hmm according to json.org, objects contain "members" whereas arrays contain "elements"... not sure how far I should stick to the vocabulary.
    Hmm... "Size" might be better then.
  • zenox98

    What's uploaded to the arcade is just the event sheet structure. The arcade concatenates this with the whole runtime.

    If there's a bug, I would guess it's in the common javascript used in the arcade that's causing it. Somehow it probably became out of date with how firefox 28 works... not sure.

    I could maybe solve the problem by doing a new export, but I'm not even sure where is the last capx or if it would still work (nope I'm not lazy... not at all!)

    So... meh... maybe on one rainny day.

    Looking at it closely, the problem comes from the fact that firefox changed they renamed "noteOn" and "noteOff" function of the AudioContext's BufferSource object for "start" and "stop".

    So I guess I'm probably not the only one who should reexport their game. Or maybe better, scirra arcade should update its code to correct all the bugs in one place =) (dunno how hard it would be)

  • In my case events looked a lot like:

    Three: Create scene "myScene"
    Three: Create camera "myCamera" (fov:30, aspect:windowWidth/windowHeight)
    Three: Create CubGeometry "myCube" (10,10,10,1,1,1)
    Three: Create BasicMaterial "myMat" diffuse: "0xff0000"
    Three: Create Mesh "myMesh" with geometry "myCube" and material "myMat"
    Three: Create PointLight "myLight" intensity: "1.0"
    Three: Position object "myMesh" at (1,0,2)
    Three: Position object "myLight" at (2,5,2)
    Three: Position object "myCamera" at (2,5,-2)
    Three: Camera "myCamera" lookAt (1,0,2)
    Three: add object "myCamera" to scene "myScene"
    Three: add object "myMesh" to scene "myScene"
    Three: add object "myLight" to scene "myScene"
    Three: Render scene with camera "myCamera" and scene "myScene"[/code:1vgphv7x]
    At some point I think it's easier to do in javascript directly.... You lose almost all of c2's advantages.
  • TikTik

    I'm not sure I understand what you are saying

    But your browser blocking pop-ups is a security measure to avoid... well... pop-ups. So I'd say it's not possible to go around that.

  • I tried writing a set of plugins for three.js a year ago, but it became rapidely cumbersome.

    I tried two designs:

    1. everything in one plugin. But you have to handle references to every objects by tagging them... it was a pain. Also the ACE started to get very long

    2. one plugin per three.js type of object. So I had a renderer plugin, a camera plugin, geometry plugin, material plugin, light plugin, etc etc etc..

    In both case I wasn't really satisfied. But it worked:

    https://dl.dropboxusercontent.com/u/23551572/C2-Games/3DMaze/index.html made with the first design

    https://dl.dropboxusercontent.com/u/23551572/C2-Games/3DTest/index.html made with the second.

  • braingame

    recursive backtracker (though you should probably let old bug reports sleep (: )

Yann's avatar

Yann

Member since 31 Dec, 2010

Twitter
Yann has 5 followers

Connect with Yann