Nepeo's Forum Posts

  • I have taken a quick look at your project and as far as I can tell your events look okay. The only thing I would consider changing is that you attempt to create a new advert each time you "play", but you don't always show it. Given that you randomly choose in the same block if you will show an advert to the user it may make sense to only create an advert if you have decided to show one that time. Similarly looking at the event that displays the advert you don't check if one has actually loaded. It's worth noting that Admob doesn't always send you an advert when you ask for one. Usefully the plugin will actually not create a new advert if one is already loaded. As such I would suggest this slight adjustment:

    on start of layout {
    	choose(0, 1) = 1 {
    		create interstitial advert id: AD_ID show: FALSE
    	}
    }
    
    is PLAYER_DEAD
    is interstitial loaded {
    	show interstitial
    }
    

    Now as for the reason why it's not working for you, it's not particularly clear yet. I will do a quick build with my advert credentials to verify your project. As your credentials have been cleared I cannot verify that you had set them up correctly. When sending projects that involve admob I suggest replacing the numerical parts in the ID's with "X" so that we can see roughly what your settings are without you sending us your ID's. Like so: ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX

  • Yeah I guess it is, although I have no idea what would cause it. Something for Ashley to look at I think.

    I added a simple speedometer using the sum sqrt((player.Y - previousX) ^ 2 + (player.Y - previousY) ^ 2) / dt and the player speed appears to double when passing through the moveto instances.

  • The project you have shared is private, I cannot view it.

  • Interesting question. The premise reminds me of a game, but I can't quite remember the name of it. I think the premise is you find a phone and have to find out about the owner by sending messages to their contacts, looking at their photos, etc.

    Some of the requirements have parallels to a dialog system, which Laura has been writing a tutorial series about.

    I would probably create a JSON file with the data for your emails in, something like this:

    {
    	"first_email": {
    		"subject": "Welcome",
    		"from": "auto@ai.io"
    		"body": "Hello",
    		"responses": [
    			{
    				"body": "Hello to you too!,
    				"trigger": "second_email"
    			}
    		]
    	},
    	"second_email": { ... }
    }
    

    Each email is keyed with a textual ID, so you can easily look it up. Then the email object itself contains the various bits of text you would want to display on the screen but it also contains an array of response objects. The responses basically being a body of text and an ID of another email which the AI sends back to you. Allowing for a branching dialogue tree.

    In terms of saving what emails are visible you just need an array of the email IDs which are visible. To "delete" an email remove it from the array. When an email is "received" add it to the list. You should be able to quite easily save that array to localstorage to persist the game state between sessions.

  • For your slope had you rotated a rectangle or just changed the collision poly to be a slope? It sounds like that solution is based on the assumption that the slope is just a rotated version of your flat terrain.

    A similar but slightly different solution is to store a "slopeAngle" variable on the instance, then use that to rotate the characters. I believe that is how the old sonic games worked. But it obviously requires you to go over each slope, figure out the angle and then store it in the instance.

  • Glad I could help, if either of you have any questions feel free to ask me. These sorts of transforms are very useful to know, and can be applied to all sort of stuff. They can be a little difficult to visualise at first because you have to think about a range of values not a single absolute value. Also the complete solution can be very confusing to look at. Think about each step you need to do, then work them together to get the result.

    I briefly touched on some similar maths in my tutorial for the Advanced Random plugin for tweaking noise functions. Noise functions basically take an input value and transform it into a new value. I actually used sine for some examples in the tutorial because it behaves exactly like a noise function.

    I've come across a few websites over the years that allow you to look at graphs of a function like that. I normally just search around for them. Saying that I'm fairly sure I've used Desmos in the past, and it's one of the best ones I've used! is right that if you want it to start at 0 you will have offset it on the x direction by a quarter of it's period. Usefully cosine is identical to sine but offset by a quarter of it's period. So you can use (1 + cos((x * Pi) / 10)) * 5 (or for Desmos \left(1\ +\ \cos\left(\frac{x\ \cdot\ \pi}{10}\ \right)\right)\ \cdot\ 5 ) to get the same curve but starting at 0.

  • As says the sine function returns a value between -1 and 1. The input to the function repeats every 2 Pi because of it's relation to Pi and a circle. However, if you tweak the input and output a little you can change them to the ranges you want

    Firstly the input; if you wanted it to repeat every 20 seconds instead of every 6.28 ( 2 * Pi ) seconds what you need to do it "normalise" your input by dividing it by the desired period time / 20 this will give you a value between 0 and 1. Now you can multiply by the required period. (time / 20) * (2 * Pi) or simplified (time / 10) * Pi.

    Secondly the output range. You only want a positive value, but there's actually 2 ways of doing this, depending on how you want it to behave. An easy option is to use absolute to convert it to a positive value like so abs(sin(time)). But remember that sine is a curve, what you've effectually done is place a mirror along the x-axis, hence it will be rounded at the top and spiky at the bottom. In animation this gives you a bouncing ball effect. Accelerating as it falls, and decelerating as it climbs. The other option is to offset the curve so that it is always positive 1 + sin(time) but this will change the range to between 0 and 2. We wanted an output of 0 to 500 anyway so we need half the output then scale it by 500 ((1+sin(time)) / 2) * 500 or if we simplify it (1+sin(time)) * 250.

    Let's combine those 2 parts together:

    250 * (1 + sin((time / 10) * Pi))

    When testing things like this it's useful to actually visualise the results on a graph. I recommend trying it out on a graphing tool like Desmos.

    Here's some of the formulas for the expressions I mentioned, you should just be able to paste them into Desmos.

    • \sin x
    • \sin\left(\frac{x\ \cdot\ \pi}{10}\ \right)
    • \left|\sin\left(x\right)\right|
    • 1-\left|\sin\left(x\right)\right|
    • \frac{\left(1\ +\ \sin\left(\frac{x\ \cdot\ \pi}{10}\ \right)\right)}{2}\
    • \left(1\ +\ \sin\left(\frac{x\ \cdot\ \pi}{10}\ \right)\right)\ \cdot\ 5
  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • We'd seen quite a few users placing titles and comments in arrays to make it easier for them to work with the files. But this of course adds areas of non-data to your data file, making it larger and more complicated to read. So the change was just to improve the editor workflow for those people.

    If you want to refer to a column by name you could add some constant variables to your event sheet, then use those variables to lookup the data from the array.

    LEVEL_DATA_TIME = 0
    LEVEL_DATA_RED = 1
    LEVEL_DATA_BLUE = 2
    LEVEL_DATA_YELLOW = 3
    LEVEL_DATA_GREEN = 4
    
    Array.At(index, LEVEL_DATA_TIME)
    

    However, if you prefer to actually index by a string then you might want to look into the JSON plugin. As it gives you a lot more flexibility to your data structure.

  • I've always considered the name "native ads" to be rather misleading, all the advert types are "native". The description given for them is "[...]ad assets that are presented to users via UI components that are native to the platform." which is fine, except banner adverts also fall under that description. I would explain them as more of a "build your own advert".

    The major reasoning for using a "Native ad" is that you can style it so that it integrates better with your application. However, a major restriction I can see it that it can only be used within the Android UI framework, which Construct doesn't use. Also the content seems to lend itself to a sort of "install this app now" tile. I'm not really sure how you would integrate this sort of content into gameplay.

    I think in general it would be complicated to use, and not actually integrate very well. However, if someone could come up with a clear explanation on how it would work with construct and show there is sufficient interest in it then we will reconsider it.

    Feature request should be put on our feature request platform construct3.ideas.aha.io/ideas

  • boulerzzz I've merged the changes over and published a new revision. Initial tests seem okay, but I hadn't replicated this specific bug myself. Let me know how you get on.

  • I tried the automatic function conversion and had no issues, are you changing it by hand?

  • It's because the element you have registered the handlers to has a height of 0, so it's impossible to drag n drop onto. Is there a reason for using "fb-root"? I'm not even sure whats it's supposed to be for. If you just want the entire page then document.body is ideal.

    There's an easier way to bind events to elements than what you've used BTW. HTMLElements have the method addEventListener which allows you to attach a function to an event. It's simple and clean. Typically adding an attribute with a snippet of script like you do there is only used in HTML files to make it clearer that an event is bound to that particular element, but as your manipulating the element in JS it makes sense to use addEventListener instead. Here's an example of using it to listen to "click" events from an element.

    function onclick (e) {
    	console.log("something clicked!");
    }
    
    const element = document.getElementById("myelement");
    
    element.addEventListener("click", onclick);
    

    Note that you pass in a reference to the onclick function, not a string, and that the name of the event isn't prefixed with "on".

    Here's a lightly modified version of your script which should work.

    function ondrop(ev) {
    	//prevents file from being opened
    	ev.preventDefault();
    	console.log('drop', ev);
    }
    
    function ondragover(ev) {
    	 ev.preventDefault();
    // 	 ev.dataTransfer.dropEffect = "move";
    	 console.log('drag', ev);
    }
    
    runOnStartup(async runtime =>
    {
    	const element= document.body;
    	element.addEventListener("drop", ondrop);
    	element.addEventListener("dragover", ondragover);
    });
    
    
  • LaurenceBedford we have 1st party support for app rating now within the share plugin.

    I don't remember seeing this thread in the past, for obvious reasons we can't read everything on the forums. Creating a new issue on the github public bug tracker, basically saying "can you add version x.x.x of the plugin "my-cordova-plugin" to the build service whitelist, is the best way to ask.

    Doing security reviews on plugins can be kind of time consuming ( depending on how the plugin is configured ) so unless someone still wants this plugin added to the list I won't review it yet.

  • boulerzzz I was looking at it before xmas, but we were basically on code freeze for the last week so as not to cause any drama while people were away. I'll take a look today and update this thread when it's sorted.

  • As you've seen we don't have a "indexOf" expression in the JSON plugin yet. But I believe it's not actually that useful, as it would basically only allow you to check the index of a string or a number in an array. The structure you have is an array of objects, and you want to check a specific key within each of those objects instead, which is a more complicated search.

    Typically I would suggest using a different structure instead, or if that isn't feasible then use a loop with a conditional inside ( if we implemented an expression for this is how it would work ).

    Looking at your JSON I would instead suggest

    {
    	/* ... */
    	"buildings": {
    		"weaponsmith": { /* ... */ },
    		"weaponTraining": { /* ... */ },
    		"elementTraining": { /* ... */ }
    	}
    }
    

    This only has 1 real limitations in comparison to your structure; you cannot have more than 1 "building" with the same "objectName". On the plus side you can now refer to that object using "objects.buildings.weaponsmith" without having to search for the key you need. So it's dependent on what you need out of your data.