troublesum's Forum Posts

  • Others might have a better way but i created a plugin for me to do this as well. Its basically a 3 dimensional named array (hash table) with a ton of features. But it supports merging/loading JSON objects and retrieving data by key name. Your well come to give it to try

    Example for what you doing: (Note its a 3 dimensional array so since the JSON object is 2 dimensional the data was loaded to "default"

    [attachment=1:5ccyf6gw][/attachment:5ccyf6gw]

    Here is the plugin and the example capx

    [attachment=0:5ccyf6gw][/attachment:5ccyf6gw]

  • Ninetendoo - Thanks but i would consider it settled. I'm not going to release it per his wishes. But the capx (which doesn't use the plugin but is what the plugin is based off of) at least provides a foundation for anyone that wants learn about the method.

  • farflamex Glad it helped.. The reason for the nested for-each loops is because the c2 array object is 3 dimensional and your based on the string the data values were in the 3rd dimension of the array so you have to dig into each level to find it and separate it.

  • I got into an interesting discussion with Ashley about this over a plugin I created to overcome this very problem.

    You can read it here. He didn't like how I worked around this issue and ill be the first to admit i don't know half as much about this subject as he does but I learned (accidentally created) a different method of syncing objects that under low latency conditions works near flawless.

    https://www.scirra.com/forum/viewtopic.php?t=109031

    So I can say that based on my experience your not seeing network latency cause this problem, (I assume all your tests are local but your still seeing lag), what you are experiencing is JavaScript not being fast enough to perform interpolation under low latency conditions. The method i came up with is called extrapolation where objects position is predicted based on its last state. What I do is synchronize instructions instead of objects. IE if player 1 presses left he calls a function on all devices that moves the player left. No object synchronization, just instruction synchronization.

    It appears the upload attachment feature is down for the moment so if you click the link and go to the last page i uploaded a capx the demonstrates how this done. Its more complicated but it does prove the theory. After doing some reading online the conclusion for me is that extrapolation is great under low latency conditions but not so much under high latency. So while it may solve your problem you having now it could create a other problems depending how good your users connection is to the game. Its really a damned if you do damned if you don't sort of thing for now. But check it out. Maybe it will help.

  • Not sure what you have tried but assuming your returning the C2 array AsJSON to php then this should decode it and put it in to a usable array.

    Also I found a syntax error in your string you provided, you have an extra bracket after the 60 that is breaking the decoding. I fixed it in my example.

    $JsonC2ArrayString = '{"c2array":true,"size":[3,1,1],"data":[[[60]],[[1]],[[25]]]}';
    
    //Have to use the true condition to output as a array and not object
    $jsonArray = json_decode($JsonC2ArrayString, true);
    
    //The array data is located in the "data" object of the first level of the JSON string
    $c2ArrayData = $jsonArray['data'];  
    
    $output = array();
    
    //Generate out put of data. 
    foreach ($c2ArrayData as $z) {
          foreach ($z as $y) {
                foreach ($y as $x) {
    	          $output[count($output)] = $x;
    	    }
          }
    }
    
    //$output[0] = 60
    //$output[1] = 1
    //$output[2] = 25
    
    [/code:visqtsuu]
  • Ashley Fair enough.. I appreciate the response. Thank you

    Edit: Apparently what I'm doing is extrapolation?, not interpolation. I move objects based on its current state as opposed to the object movement being interpolated from one point to another. If latency is low extrapolation does provide better results (which is why i show no lag on local games) but if latency is high interpolation would be better.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • troublesum - what, so you don't even implement interpolation or input prediction? Have you actually tested that over a real-world connection?

    Ashley I wanted to address this:

    Interpolation is predicting the next logical location based on speed and direction in between recieving input commands. Since i only call functions that act on simulate behaviors that are subject to dt, isn't interpolation is already handled. Both players call move left for player 1 at the same time and the simulated action is adjusted for dt so they move across the screen in sync regardless of framerate as there locations are interpolated by dt being accounted for in the behavior movement.

    As for input prediction since i latch a function call in place until sending another that is in essence input prediction. Player 1 sends the move left command and each peer latches that command in place and continues (persists) to call it until receiving another action call from the same action group (IE Stop, move right etc..).

    So yes, I do implement interpolation (So long as i only use movement that has dt accounted for which all behaviors have including physics if set to frame rate independent) and I do input prediction by latching (persisting) function calls . I do feel this method provides the cleanest and simplest method of lag free control (When used by plugin to make it easier). Can you use for this erratic x,y positioning that is not subject to dt... probably not (it would be very complicated). But for movements generated by a behavior that are subject to dt. Yes you absolutely can.

    Please, test my capx, im confident in its ability to sway your opinion. [Just uses functions with out any 3rd party plugins] (just run/preview in a coupe of browsers, click connect on each, and then use arrow keys to move players)

    [attachment=0:3cfzgdyo][/attachment:3cfzgdyo]

    In any case i wont push this any further i just think it would be helpful for others if this was more easily made available. Thank you

  • rexrainbow - THANKYOU!! I I just took a look at your MPwrap and saw how you found the instances.

    This is what i needed. I was other wise lookup the instance based on the UID i passed. Since there is only one instance this will work perfectly.

    if (inst instanceof cr.plugins_.Multiplayer.prototype.Instance){
    }
    [/code:cro4p6fo]
    
    Can't believe i forgot i could check instanceof (facepalm). Yes I saw your plugin but ill admit i didn't use it because i wanted persisted function calling and different methods of directing the who receives the function call (Mine works the exact same was as the official Function plugin when calling except you specify who gets the call [Everyone, Everyone But Me, Host Only, PeerId etc]). Ashley seems to think I'm wrong about persisted function calling but if you would only try my capx provided in the above post (does not have my plugin but proves function calling the theory)  you would see it makes a world of difference and works better than any multiplayer demo currently available. In any case ill respect his wishes and not publish my plugin less some specifically asks but im still using it for my self. 
    
    Thank you again!
  • Not really.. I don't have much experience with plugin properties yet. But I don't think properties have read-only setting (could be wrong)... but it would kind of defeat the purpose i think of something the user is intended to be able to change that is set to read only.

  • Ashley Did you try the capx?

  • try this

    var pluginInstances = {}; //This will store your plugin instances.
    var pluginInstancesIndex = 0; // A Simple index counter
    
    function IDEInstance(instance, type)
    {
        assert2(this instanceof arguments.callee, "Constructor called as a function");
    
        this.instance = instance;
        this.type = type;
        this.properties = {};
    
        pluginInstances[pluginInstancesIndex++] = this.properties; // Add this to store the new properties instances to the colleciton
    
        for (var i = 0; i < property_list.length; i++) 
            this.properties[property_list[i].name] = property_list[i].initial_value;
    
    }
    
    IDEInstance.prototype.OnPropertyChanged = function(property_name)
    {
        //When the property changes get the val
        var val = this.properties[property_name]
        for(var i in pluginInstances){
                //Then loop through the instances and apply it to all
    	    pluginInstances[i][property_name] = val;
        }
    }
    
    [/code:36ng7frt]
  • Ashley - I think this more a suitable reason you might like than using functions for moving objects. Take a look at the screen shot. See how easy it is for the host to sync misc/dynamic data to all peers with a single function call. Very straight forward. No mess... just set the data and pass it in a function to all peers.

    [attachment=0:3vostxr9][/attachment:3vostxr9]

    Every peer has the "Update" function so when the host calls it they all receive the data he sent to it. Super easy.. any way sorry for ranting but I'm just tying to drive the point home that this is very powerful and adds a ton of flexibility with out any complicated algorithms. You don't have to use functions for moving objects if you dont wan't to but for syncing miscellaneous data its really helpful!

  • Ashley Were you able to test the capx? Yes i tested it.. not across the world but it works over my 4g wireless connection without any problems. Since each device does all its own work you simply send the instruction of what work should be performed. (IE Move Left, Move Right Jump, etc..) If its work that needs to be ticked you simply latch it (persist) the call based on the tag (action group). So move left is latched until another instruction from the same tag (action group) is received whether that be stop, move right, etc.. It literally takes 3 instructions to move a player all the way across the screen in sync as long as you using a dt behavior. If latency is under 200 ms (by all accounts anything larger would make multiplayer useless anyway) functions are called near real time on all devices at the same. Just to account possible spikes in latency I send an additional set position instruction every half second to adjust. Sure some functions are always only called by the host like when a hit is registered (IE Player 1 will send the function that he fired when he presses the fire button but it only counts as a hit if the host sees it hit another player). Basic multiplayer mechanics still apply. But for movement i believe this is as good as gets.

    I hope you see the value in this method of data transmission and maybe add the UID expressions for me (really for everyone else since i use this plugin anyway). Even if not for movement (which i think is what your against), the power of function synchronization adds tons of value to multiplayer plugin (which I still can't thank you enough for adding). Imagine how easy chat would be for someone if they have a text box with function that updates its text. The host/peer could update the text on every device with a single action by calling the very function that the text box is tied to. No funny code.. just call the function tht would normally just update it on your screen but instead, poof same text on all devices. Or if the host want to let every one know what the next level is they should load. Or updating dynamic data the host can update arrays/dictionaries on each device with a single function call.. and so on..

  • Ashley I think your missing what im trying to go for. I have created a multiplayerPlatform example that works off of nothing but functions. There are no synced objects. Just functions. You will see my capx has basically no lag (compared to sync objects mine has none). , movement is smooth and control is fluid. Others have found this be helpful but too complicated. So I took the logic and turned it into a plugin so it wouldn't be as confusing for others to replicate.

    Take a look at this example. It has no plugin. its just functions and a complicated algorithm. Open up 2,3,4 etc.. browser windows (supports more than 2 players) and click connect on each. Then move the players around with arrow keys. There is something to be said for using simulated actions that input prediction will never be as a good as. Please try it and tell me if you think all the code from this example isnt worth turning it into a plugin.

    [attachment=0:2wdl1c3h][/attachment:2wdl1c3h]

    All i need is reliable way to access the UID from Function/Multiplayer to eliminate half the code necessary that makes this capx work. There is a ton of benefit to syncing functions. Please, I'm genuinely asking you take a look at the capx, try it and let me know if you wont reconsider?

  • So I've created a really neat Multiplayer Function calling plugin that allows any player (host or peer) to call any function for every player at the same time with a single action call. It ties the officially supported plugins (Function/Multiplayer) together so you don't need to do anything other than add this plugin, create your functions as you normally do and then call them with this plugin instead of the Function plugin to enable calling it on multiple devices at the same time. This allows you to syncronize data with out having to associate objects or build your own method for encoding and decoding multiplayer messages. Just call a function and it happens on every device at the same time.

    Example: When Player 1 calls "MoveLeft" on a key press he has the option to send that function call to everyone at the same time so they all call it at the same time and each players screen sees player 1 move left. Or when Player 1 scores a point the host can call a function to update it on everyones device. Simple!

    Or in this example When a peer joins a room he calls a function spawn him self on everyones screen and then call a function on everyone elses devices for them to spawn them selves on his screen. 2 lines of code, 2 functions and all players are on the same screen.

    [attachment=2:2iwhlfg9][/attachment:2iwhlfg9]

    Supports calling a function for

    • Everyone
    • Everyone but him self
    • Host Only
    • Him self only (Like a normal function)
    • Direct To Peer

    It has advanced function calling methods as well that allows for triggering a function only once until reset or persisting the function call on the other end until reset. (IE MoveLeft could execute an action that simulates move left from a behavior and is sent only once by the player while hes holding the key down but is continuously called on the other end every tick until you tell it to stop by taking your finger off the key) Provides precision control and reduces bandwidth requirements for smooth movement. I'm sure some of you have seen my multiplayer example capx that uses this theory (not this plugin) that I have posted on other threads that proves this.

    Example:

    [attachment=1:2iwhlfg9][/attachment:2iwhlfg9]

    It works flawlessly and set up is easy. Simply add the function and on start initialize it with the function.uid and multiplayer.uid and then set a multiplayer trigger for it. Thats it!! you can start calling functions at will from this point on.

    [attachment=0:2iwhlfg9][/attachment:2iwhlfg9]

    HOWEVER Here is where I have a problem. Currently because both Function and Multiplayer are global objects their UID's dont show up as select-able expressions. I had to modify the existing plugins to add it (this is frowned upon and i cant release the plugin if it requires the user to do that). Before i can release this plugin i need a way getting the UID for global objects? I could have missed something but can't seem to find it anywhere and I have scoured the code and event action options with no luck in finding the Function/Multiplayer UID, but does any else know if this can achieved. If a method doesn't exists Ashley would you be willing to put the UID's as select-able expression for the Function and Multiplayer object so i can use them in the event sheet to init my plugin? I would really like to release to this plugin. Thank you