Nepeo's Forum Posts

  • One other thing that I remembered is some devices have their own restrictions. We had a bug... probably over a year ago that uppercase characters in package IDs prevented SOME devices from installing the APK. The editor now produces a warning if you try to use them. But it's possible that there are some other edge cases that we don't know of.

  • Installing APKs hasn't really changed, but the package installer app has always been a bit of a pain. It never gives you a reason why an APK cannot be installed, and there can be multiple reasons.

    Things to check:

    • Uninstall any applications with the same package ID
    • Try a fresh build and copy ( APK might have been corrupted in the copy )
    • Ensure your using a debug APK, as unsigned release APKs cannot be installed
    • Check your minimum version is lower than the target device
    • Ensure "Allow install from untrusted sources" is enabled in settings

    One other thing to look out for is Play Protect. This is Google's system for preventing malicious applications from being installed. They have 2 blacklists as far as I can tell, a global "don't install this app" list which every device has and a second list which the device maintains. If the app is on either it will silently fail to install. Sometimes when installing an APK it will ask if you trust it, not trusting it is the default action and will add it to the local blacklist. Preventing you from installing it in future ( it won't ask again, and you cannot change your mind ). I think building a new version of the APK works around this, that or it is removed from the list after awhile. But it can be frustrating when testing many APK files ( like I have to... ).

  • As dop2000 says changing the seed every tick won't make your dice rolls any more random.

    The operation to update the seed is relatively slow, as it does additional setup for the Perlin noise generation.

    I'm not sure what your intention for the dice is but the AdvancedNoise plugin also includes the ability to generate a list of non repeating numbers, like shuffling a deck of unique cards.

  • DoudouSupreme Sorry I have been away, still catching up on things.

    I believe the condition is triggered when the order explicitly fails, not when it is cancelled. I can't remember most of the purchase flow off the top of my head. I don't believe we have an event for the purchase being cancelled, but we could probably add one if it was wanted.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • Including the plugin into your game, and selecting the "replace system random" tickbox will change all random based system expressions to use the AdvancedRandom's Psuedo random number enerator (PRNG) instead of the browser's PRNG. The advantage to this being that the browser doesn't not offer a way to read/modify the seed of it's PRNG, but AdvancedRandom does. Knowing the seed allows use to produce a repeatable sequence of seemingly random values, useful if players want to share this seed with others to get the same results. Or if you want to cherry pick one or more sequences that suits your game ( a common way of improving the quality of procedural generation ).

    If the "seed" property of the plugin is left blank, which it is by default, then it will use the browser PRNG to create a 10 letter seed and initialise itself. You can modify the seed at runtime using the "Set seed" action which accepts a string of any length. The "Seed" expression will return the current seed and the "RandomSeed" expression will return a new 10 letter seed generated using the browser PRNG.

    If you want to you can call the "Set seed" action with the "CurrentSeed" expression to reset the random number sequence to it's beginning.

  • mekonbekon is right on both counts.

    When a table is created it's added to a dictionary, using the name as a key, and is set as the "active" table. Using "Set probability table" gets the one with the given name from the dictionary and sets it as the "active" table. The weighted expression always uses the "active" table.

    Entries in a probability table are not unique, you can have multiple ones with the same name and/or weight. The reasoning is that it allows you to merge multiple lists into a single table, without having to look for and merge duplicates. You can pass a weight of "0" in and it will remove the first entry with a matching name. It gives more flexibility, but I never decided if it was more complex than what people needed it for.

    In terms of other stuff you've chatted about, there is probably some room for polish. While it was something we considered useful we got fairly minimal feedback at the time it was released, so it hasn't been adjusted much.

    You can't change the weight of an entry after it's been created, but you can always remove it and add a new one with a higher value.

    Importing from JSON might be nice, but it's quite easy to do with a for loop already ( parse JSON, for each: add probability entry ).

    I did consider adding a variation of "Weighted" that also took a table name, but again it's quite easy to do without. It's easy to bloat plugins with too many features and ACEs, which then makes them hard to maintain. Unless something is impossible to do, or it's a really useful shortcut we avoid adding such features.

    One thing that does occur to me as useful would be the ability to read all the entries in the table, so that it can be serialized for later ( if for example certain drops were removed after being obtained and you wanted that to be preserved without having to keep another list somewhere ).

  • Shubi that's an interesting question.

    I'll answer your second question first. While the dimensions of the image does affect the size once encoded, I think it is being stored as a PNG file. PNG files deal well with repeated data, so large blocks of colour and small palettes can massively reduce the file size. This can mean an image with large dimensions can take up less space than a smaller one.

    Now for the original question it's important to consider that you can store things in 2 ways with the local storage plugin. A piece of binary data ( which is basically what an image is ) can be stored as an a array of bytes ( N ) or a Base64 String ( N * 1.33 * Bytes per character ). Note that the latter is multiplied by the bytes per character, so is dependent on what character encoding is being used underneath. I don't actually know what is used in this situation, and it might vary between browsers.

    The best solution is to probably just store the binary data for the image in local storage without converting it to anything, as you know exactly how many bytes will be stored.

    The convoluted option would be to do the text encoding yourself with the BinaryData plugin, like so: BinaryData.SetFromText(BinaryData.GetBase64()) and stash it. As BinaryData uses UTF-8 for text you know it would only use 1 byte per character.

  • WesleyDeveloper9 Use the "system: compare values" condition, allows you to evaluate 2 expressions and compare them with an equality operator ( <, >, ==, !=, >=, <= )

  • There's quite a lot of the plugins which don't expose anything to the scripting API. But this doesn't mean you cannot work with them from scripts. In most cases you can create a function on the event sheet that say, plays an audio file, then call the function from your script using runtime.callFunction. You can do the opposite by declaring a JS function in your script file, then inserting an inline script block on the event sheet that calls the function. I think a lot of people at the moment are focusing on using only scripting or event sheets in their project but in reality they both have advantages and weaknesses vs the other. It's easy to integrate one with the other, so it makes sense to use both where they are strongest.

    Here is an adjusted version of the audio scripting demo to show how to use this mixture of JS functions and Event sheet functions to interface between the 2 systems.

  • Base64 strings can use up substantial memory, particularly if you have a lot of them. It's worth considering this ahead of time in case it will cause issues.

    Base64 uses ~33% more memory than equivalent binary data. Additionally as it's been placed in a JS string it will use twice that again ( JS strings use a 16 bit character encoding, even though base64 values only use 7 bits ). So for instance if you have 30 bytes of binary data, it will take 40 bytes to store it as base64 and a JS string of that base64 data will use 80 bytes.

  • The CanvasSnapshot expression returns a Blob URL for the snapshot. Blob URLs only work as long the blob they are associated, when the preview is refreshed the Blob for the snapshot is deleted. So all you are actually storing is an ID number for a Blob that no longer exists.

    If you wish to store it I would recommend using the BinaryData plugin to convert that Blob URL into a Base64 string. Base64 is a text based encoding of the binary data itself, it is not as efficient as a Blob URL but can be serialized. I updated your example to do this:

    dropbox.com/s/g8p8xii1k4aavls/SaveImageTest.c3p

  • I think I would actually stick clear of the audio system for deciding if they can "hear" you. A really simple version would to spawn an invisible sprite over the character, scaled by the "volume" of the action. If the sprite overlaps an enemy then the enemy hears you. If you don't want to use a sprite then you can do a simple "volume" vs distance check against each enemy. volume / (distance * distance ) > threshold

    This doesn't give you fancy stuff like directional audio or object occlusion. You could use line of sight in combination with a range limit for that ( the range being volume / (distance * distance ) ). Sound behaves very similar to light, which is what LOS is simulating. It's also possible to simulate audio reflection with LOS, but requires more work and soaks up more CPU time.

    This doesn't mean you can't use audio positioning for your game, but I think it should be for audio output only.

  • The Audio Scripting example provides a thin layer on top of the browser Audio APIs in the form of the AudioManager.js script. The browser API has no concept of tags. Tags are an abstraction to make it easier to control multiple forms of audio in the event sheet, where audio objects cannot be placed in variables or collections.

    You need to store the references and called the required method with the reference to stop it. If you want to use tags then you can implement it yourself by adding the functionality to the AudioManager class. The AudioManager class in this example plays audio using 2 different methods: WebAudio and HTML Audio Elements. Both have different advantages, and different methods to manipulate them.

    WebAudio API

    HTML Audio element

  • It's unlikely to, but that of course depends on how much data each dictionary contained. 1000 items isn't very much though.

  • Yup this is totally possible. You can add multiple Dictionary, Array, Binary Data and JSON objects to a project. You can use these in any combination to compose complex types through serialization.