Nepeo's Forum Posts

    As Ashley says WebAssembly isn't all about performance. The first thing on the WASM website:

    WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

    So it's really about being able to use other programming languages on the web. Depending on the situation it can run faster than JavaScript (JS) but well written JS can often run at a comparable speed. It's a bit of a myth that JS is slow, there is some historical truth to it but browser developers have done some amazing work on making it run faster. Looking at the V8 blog can show you some of the very impressive work that the Chrome/V8 team are doing. Most of the performance issues you will find with web apps are caused by the developer either doing too much HTML manipulation or overworking the GPU, which would both still be an issue with a compiled language.

    There's an excellent article by the team who develop the source-map library who rewrote their JS library in Rust and then compiled it to WASM. They claimed it ran 5.89 times faster than the original version, which is a pretty nice performance improvement. But the story doesn't end there; an independent developer called Vyacheslav Egorov saw their article and was curious why the JS version was that much slower. In response he profiled the JS code and rewrote the slowest parts, until the JS version ran faster than the Rust version. The source-map team took some of his changes to improve the rust version further, but in the end the 2 versions were very similar in terms of performance.

    It wasn't all about "WASM is better than JS" or the other way around. Vyacheslav is quite clear in his article that he isn't trying to play the 2 languages off against each other. Rather that you should be aware of the advantages, disadvantages and pitfalls of the language you are working in. The best thing you can do to improve performance is to profile and optimise your hot paths.

    A key point he makes towards the end of his argument is that for such a small improvement it might not be worth the considerable effort required to rewrite a program in a different language which is harder to work with.

    [...] I am not gonna declare here that «we have successfully reached parity with the Rust+WASM version». However at this level of performance differences it might make sense to reevaluate if it is even worth the complexity to use Rust in source-map.

    The nicest thing about WASM is that you don't have to choose your hill, your program can be a mix of JS and WASM. We use WASM for the core the AdvancedRandom plugin, and it works really well. Pseudo random number generators (PRNG) often depend on large integer values and wide bitwise operations, which isn't something JS does. So being able to write in a language that CAN do that was really helpful. Similarly audio formats are very complicated, so instead of trying to port the opus codec to JS which would have been a HUGE undertaking we compiled it to WASM which was comparatively easy. As a bonus it's probably faster, but we don't have anything to compare it to.

  • I think this is related to whatever the bug is with browser saves at the moment. There's some issue where we are losing metadata related to projects stored in the browser save file system. The "key is not defined" is an error which should be fixed in the next release that is in the recovery system that prevents file objects with no meta from being lost. I guess this is happening "randomly" because the user has the back up location setting set to "Browser". As for the unhelpful error message from the save system; I had thought that those errors wouldn't be appearing anymore in r149+ but I guess I missed one of the places the error messages are being inspected.

  • AllanR we don't have an option to remove an entry at the moment, but it would be fairly simple to add.

    Another tool which AdvancedRandom adds which could be useful here is the permutation table. It creates a list of unique numbers in a random order. If you create a permutation table the size of your word array you can just increment through the permutation table and use the value to select a word that hasn't been used before ( effectively it's a round about way to "shuffle" your word array ).

  • If your following the beta channel you can use the AdvancedRandom.Weighted expression that was added in r149.

    It works by creating a table of values with different probabilities, which you can then randomly select from.

    For simple use you can do something like the following:

  • The easiest way would be for your flutter code to request the camera permission before loading the webview. For Android permissions you need to list the permission in the manifest as well as request it when required.

    Trying to communicate between flutter code and your webview will likely prove hard, and possibly insecure. The Cordova exports we use for Android and iOS have a "bridge" to allow passing data and instructions between Java and JS code. You would likely have to implement this yourself for flutter...

  • Added another item to my todo list to reply here when it's done! It will be at least a couple of weeks until I get a chance, but I will likely have a batch of high priority work to do around then as well... We'll see how things go.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Best of luck, feel free to ask me if you have any questions.

  • I believe we're using version 16 of admob at the moment, we used to use the latest but there was a breaking change introduced in 17. So it got "temporarily" set to 16. It's been pending on my TODO list to make the plugin work with 17, and go back to always using the latest version. But there wasn't an urgent reason ( other than it not working I can't remember any notable changes ).

    By the looks of it there isn't any steps other than use the latest SDK that we need to take. I'll update my TODO list and try to get around to it sooner rather than later.

    redfoc The multiplayer plugin uses WebRTC data channels to transmit data. These can be set to a UDP style mode which is low latency, but is "unreliable". It's also peer to peer so one player acts as the game server, if that user has a limited bandwidth then the other players will suffer.

    Websockets can only work via TCP which is "reliable" but with higher latency. As it's done via a dedicated server you have to manage server resources for your game, but data centers have good internet connections so bandwidth problems are going to be less of an issue. Only individual users who have poor connections suffer.

    As your dealing with trying to sync data over the internet some level of prediction and correction will be required to maintain smooth animation. This can be really gnarly to get right, and causes "snapping" or "rubber banding" in online games when user latency is high.

    Websockets can definitely be used for this style of game, after all this is what the original "io" games used. But you will have to deal with the latency and prediction issues somehow.

    Typically MMO style games use "sharding techniques" so that players are on different servers depending on where they are in the game. When you have large numbers of players in one area they tend to churn because of this. They will also design their gameplay so that split second timing is less important, and limit how much players can interact with each other.

  • Soul3 we haven't tried doing any integration with the flutter webview, and your solution sounds somewhat hybrid. The usermedia plugin has specific code in it to request the camera permission at runtime if it detects it was an Android(cordova) export using the cordova permissions plugin. If the plugin is absent, or if your using a different export type it will not request the permissions for you. It's important that the permissions are specified in the AndroidManifest.xml and requested as required at runtime, otherwise you won't be able to access camera input.

    If you are using the microphone with the camera you will also have to request additional permissions.

    Its an almost complete project, can i email it to you?...

    Sure, send it over to iainbom@scirra.com and I will take a look.

    Try out some of your ideas as to how you caused the corruption and let me know if any work.

    There is a (very) rare project corruption bug out in the wild which has been mentioned in support a couple of times, but nobody has reported a replication to us yet. If you can find a way of reproducing this project corruption it would be great if you could file an issue for us to look into.

    If you have no backup for that file then I can take a look and see if I can recover it for you. Depending on whats wrong it might be missing some assets.

  • Kraudi there's a technique called Signed Distance Fields ( SDF ) which you could use here to help you. The basic idea is that you have a function that returns the distance from any position to the closest point on the surface of an object. If the position is inside the object then the distance is negative ( hence "Signed" distance fields ). Circles are probably the easiest SDF, and by the looks of it you only need circles. So that's convenient! Here's the function for a circle written in JS, it's mostly simple maths so should be easy enough to read.

    function circleSDF (point_x, point_y, center_x, center_y, radius) {
    	let dx = point_x - center_x;
    	let dy = point_y - center_y;
    	return Math.sqrt(dx * dx + dy * dy) - radius;
    }
    
    function distance_to_closest_ball (cueball) {
    	let smallest_distance = Infinity;
    
    	for (const ball of balls) {
    		let distance = circleSDF(cueball.x, cueball.y, ball.x, ball.y, cueball.radius + ball.radius);
    
    		if (distance < smallest_distance) {
     			smallest_distance = distance;
     		}
     	}
    
     	return smallest_distance;
    }
    

    The trick here is that you can use your "move along the line" technique with that function. Before moving you can check what the shortest distance to any ball is. You now know that it's safe to move that distance along the line, as there are no objects within that radius of the cue ball. Repeat the check distance, and move along line until the check distance tells you the distance is effectively 0. You will now be at exactly the position the cue ball collides with another ball.

    There's a few minor gotchas. First is that you need to keep count of how far you have moved along the line, as if you don't hit anything the loop will continue forever. Second if you do get a collision the distance is likely to be a very small number ( like 0.0000000007 ) instead of zero because of floating point error, so you should check if the distance is under 0.0001 or something. Lastly the circleSDF function assumes the point is particle ( no size ) so it doesn't take into account the radius of the cue ball. The way I resolved this above is to pass the radius of the cueball and the other ball added together instead.

    There's a fair amount of information about SDF techniques online, but it's mostly about using them for 3D rendering... which is quite complicated. Just so your aware.

  • No worries LukeW :) The site sometimes has difficulty recognising user names for boring reason, you can use [ @Nepeo ] instead and it generally works.

  • DiegoM probably needs to have a look at this.