Posts by MuddyMole

Welcome to our brand new Clickteam Community Hub! We hope you will enjoy using the new features, which we will be further expanding in the coming months.

A few features including Passport are unavailable initially whilst we monitor stability of the new platform, we hope to bring these online very soon. Small issues will crop up following the import from our old system, including some message formatting, translation accuracy and other things.

Thank you for your patience whilst we've worked on this and we look forward to more exciting community developments soon!

Clickteam.

    Here's another simple and purely math-based solution:

    Cx = ((Ax + Bx) * 0.5) + ((By - Ay) * 0.866025404)
    Cy = ((Ay + By) * 0.5) - ((Bx - Ax) * 0.866025404)

    The first part just gives the position of a point half way between A and B.
    An easy way to rotate a vector (in this case, the vector from A to B) by 90 degrees is to invert one of the two components and then swap them, which is what the second part does.
    And finally, the ratio of the length of one of the sides of an equilateral triangle to its height is 0.866025404, so the last part just multiplies by that amount. We can derive that value either by using trigonometry, as Sin(60°), or by using Pythagoras' theorum, as √(1² - 0.5²).

    Theoretically, this method probably ought to be marginally faster, as it doesn't use any trigonometric functions.
    Note also, that there are two valid solutions to the problem, as point C could be to either the left or the right of the line from A to B. The version above is for the first of those, but switching which of the two vector components you invert would give the other:

    Cx = ((Ax + Bx) * 0.5) - ((By - Ay) * 0.866025404)
    Cy = ((Ay + By) * 0.5) + ((Bx - Ax) * 0.866025404)

    You just have to run a fastloop to search for all the other copies of the same value, and delete those as well.

    Usin the List's "find" expression: Please login to see this attachment.

    Or using a slightly different method, that ought to be a bit more performant for very large lists: Please login to see this attachment.

    Having been with CT from early CnP TGF days and seeing how the software has evolved.
    I love to use it on occasion but now I'm a little more travelled as far as software building goes there are many solutions out there.

    I hope that's still true, but I sometimes wonder. You and I both came in at the beginning, when Clickteam software was far less capable, but also far simpler, and we've been able to learn all the new features gradually, as and when they were introduced. I can't help thinking that for someone just getting started now, it must be pretty overwhelming.
    It's the same with everything though. Every now and then I think "maybe I'll just give that other game engine another try", but then I do, and I'm greeted with something like this:

    Please login to see this picture.

    ...and I just think "Nope!", and immediately uninstall it again. I bet if I'd started using it 15 years ago though, I'd have been fine.

    Surely you've experienced the frustration of clunky, dumbed-down websites with enormous buttons and barebones features that were clearly designed for a touchscreen phone, but require annoyingly massive mouse gestures to navigate on PC (or conversely, tried to navigate a desktop-centric website on a phone).

    Not in the last decade or so, I haven't. In fact, this only helps to demonstrate my point.
    In the early days, all websites were optimized for desktop browsers, and if you tried viewing them on a mobile device, you were going to have a terrible time (and before that even, there was WAP, which everyone here has probably already forgotten, because it was so bad).

    Then eventually, websites started to detect the visitor's browser, and would redirect visitors on mobile devices to an entirely different version of the website, which had been made specifically for them (at additional cost, of course). That was when web designers were still using tables for layout, and specifying the size of elements in pixels or other non-density-independent units. This is pretty much the stage we're at now with most other software - different versions having to be made for different devices.

    Nowadays though, we have this thing called "responsive web design", where websites are dynamic, and a single design can automatically adjust itself to look good and function smoothly whatever device and browser the visitor is using, and whatever additional accessibility requirements they might have. It's very rare that you see a website that isn't made this way now - not least because it's a key factor that Google uses when ranking search results. This could be the future of other types of software too, if Web Apps take off.

    I don't really understand your point about input peripherals on consoles vs PC vs mobile. Console hardware supports the use of a mouse and keyboard, and smartphones and browsers support the use of a gamepad - it's up to the consumer which peripherals they purchase, and up to the developer which they want to support. Even if a developer decides that a console gamer probably won't have a mouse, and they need to implement an additional control system, that's still far less work than porting the entire game to a completely different system.

    Incidentally, I'm not saying Web Apps are going to be suitable for everything - big AAA games are one of the very few cases where ultimate performance really does matter a lot, so that's where "proper" programming still has its place.

    Do you need to run HTML5 games using a browser?

    That's actually a complicated question to answer, as they can work in different ways (hybrid apps, PWAs, electron, neutralino/tauri, etc) but essentially, yes, behind the scenes, they are running in a browser - although they have access to lower level functionality that normal websites don't, which means a well made example won't have the issues you experienced. And obviously, as they become more widely adopted, they're only going to become more powerful. While Apple may be actively trying to kill PWAs now, it was they who first came up with the idea to begin with - originally, the plan was for all iPhone apps to be web apps, so even they can see the potential (that's what scares them, in fact).

    When Java (not Javascript) was first created, it was marketed as offering the ability to "write once, run anywhere", but it never actually delivered on that promise. This is exactly what Web Apps could offer though - applications that can be written once, and will then simply work on anything, whether it's a smartphone, tablet, PC, smartwatch, etc and regardless of operating system. Developers don't need to learn a million different languages. Businesses don't need to pay people to remake the same project 5 times. In the case of CF2.5, it means no separate exporters that take Clickteam years to develop, cost users extra to buy, and then quickly become obsolete (XNA? OUYA?). No need to port extensions to every different runtime either (which usually doesn't happen, because the original developer doesn't know the required programming language).

    This is what has allowed C3 to progress so rapidly, while CF3 has languished in development hell, year after year.

    For me personally, the tight integration of Javascript in C3 is huge. CF2.5 events are very user friendly, which is great for beginners, but it's an incredibly slow and clunky way of generating code - particularly for anything moderately complex, like pathfinding or AI. It's much, much quicker and easier to write actual code to do that. The only way to do that in CF2.5 is by creating an extension, and like I already said, CF2.5 extensions are a total mess. Related to that, you might have noticed a number of threads recently, asking about the best way to save a game in CF2.5, and the honest answer is that there is no good way. It's always "You could use INI file, BUT..." or "You could use an array, BUT..." . In C3, every object has an expression "asJSON" which converts its entire state into a single JSON string - or even simpler, there's a function to automatically save the entire gamestate as a JSON string.

    Will F3 be subscribtion based, does anyone knows this for sure? I hope not!! I would rather pay $300 for it. If it will be subscribtion then I will am out.

    No announcement has been made or hints given, and I doubt any decision has been made either (since there's nothing to suggest F3 will be coming any time soon, it would seem a bit premature). I think people just started to speculate based on the subscription model becoming increasingly widespread in recent years.

    And of course, $300 is only equivalent to 3 years subscription to C3, which is far less than the product's lifespan, so if it is sold as a one-off purchase, then it's entirely possible that it might cost considerably more than that - but of course, that's also purely speculation.

    Well, I said "might not be" because that's a whole other discussion, and I don't have all the facts.

    I totally agree about web technologies being the way forward though - if you ever read one of those "MMF3 wishlist" threads from 15 years ago, you'll see C3 ended up being pretty much exactly what I was wishing for even back then (I've been using Clickteam products since Klik n Play).
    I have absolutely no doubt that sooner or later, most software will be built using them (cutting edge 3D games being one of the few exceptions). The web has better GPU hardware acceleration than CF2.5 (WebGPU being based on DX12/Vulkan rather than DX11). Ignoring WebAssembly etc for now, Javascript is undeniably slower than a compiled language like C++, but only about 8 times slower, and modern hardware is so fast that it really doesn't matter (my 2020 smartphone is 4-5 times more powerful than the 2015 laptop) - even if it's not the fastest, it's fast enough. Being able to leverage the Javascript knowledge that I already possess would be huge - whereas extensions in CF2.5 are a mess, and have to be rewritten for every runtime.

    Many popular productivity apps like the Google Office suite and Canva are already built as web apps. I think the reason that games of the kind made with CF2.5 (casual, 2D) haven't followed suit is that they are only really played on mobile devices these days, not PCs - and Apple have done absolutely everything they could (including breaking any and all regulations) to kill web apps. In fact, Apple are back in the news again this week, for this very reason - Please login to see this link.

    I understand the reason for making C3 subscription based, but it doesn't mean I have to like it! There was a similar backlash against Adobe's Creative Cloud. In fairness, a £105 per year subscription, while expensive compared to CF2.5, is still pretty cheap as hobbies go - I spend more than that in a month, playing badminton.

    So the process you describe doesn't sound particularly impressive to me: some guy copies Clickteam's ideas and builds a rudimentary imitation. It's not good enough, so he builds it again, but it's still tin-pot. Eventually someone else copies him, and tries to make a product that's satisfactory. Many years later, and with the cumulative benefit of multiple developers building off the back of each others' ideas, we maybe have a program, in Gdevelop1 v5, that could be taken seriously by serious game developers. All this does is demonstrate that it takes a bloody long time to develop a good piece of software.

    I don't think that's being entirely fair either. It's mainly a question of pricing.

    C3 as a tool, is superior to CF2.5, and the fact that its built on web technologies is a huge plus for me. If it were available as a reasonably priced one-time purchase, it would be a no-brainer, but the subscription-only business model is a dealbreaker. It might not be the best choice for a fast-paced 2D platformer for PC like yours, but you must realize that's an incredibly niche genre.

    GD5 is at the opposite end of the spectrum. It's nowhere near as good as CF2.5, but it's free, and you can't argue with free. I think there is probably even an expectation among many new game developers that they shouldn't have to spend money on a game engine, since The Big Three professional-grade game engines are all free.

    And then there's CF2.5 - reasonably priced, and reasonably capable. It's an awkward spot to be in, as anyone making a commercial game will likely choose C3 (or learn programming and use U/UE/G), while a hobbyist who just wants to make games for fun will likely choose GD5. I'm not really sure who its target audience is...

    I made this little example: Please login to see this link.

    Haven't tested it thoroughly, so can't guarantee it doesn't have bugs - you can let me know if you find any...
    It works very much along the lines of what Stiggits suggested, but with a slightly different string structure:
    [5:sword][50:potion][100:herb][75:empty][1:magic sword]

    So basically, it's like you have a big bag containing 5 swords, 50 potions, 100 herbs, etc, and you reach in and pick one item totally at random. There are 20 times as many herbs in the bag as there are swords, so you're 20 times as likely to pick one.
    When you pick an item, you can make it so that it has no effect on the probability of that item being picked again (the item goes back in the bag), the probability is reduced (the item does NOT go back in the bag), or that item can't be picked again (all items of that type are removed from the bag).

    It's all done as a self-contained widget, just using 1 active object, so it'll work in any runtime.

    Excel is a pain.
    The older XLS format is an extremely complicated binary format, so you can basically forget about it.

    The newer XLSX format is really just a zip file, containing a whole bunch of XML files, including the Worksheet XML files which hold the actual data you want.

    Note that Excel can directly export just these Worksheet XML files, so if that's an option for you, it's obviously easier to do that instead of working with the XLSX file. I made an array/Excel converter years ago, which used Excel XML files. I don't remember which is the most recent, but there are a few different versions in my onedrive - Please login to see this link. (note that using the easyxml extension means they need some .dll file to work, which will be mentioned in the help files)

    If you only need to work with single worksheets, rather than multi-sheet workbooks (or can export each separately), then it's going to be much easier to export the data as a CSV file, which is vastly simpler to parse. If it's at all possible, I'd go this route.

    Another option is to load the file into Google Sheets, and then using a script (which can be found online), export the data as JSON, which again can be parsed relatively easily (there's a JSON extension for Fusion).

    Similarly, if you have the Google Sheets spreadsheet stored in the cloud, it may be possible to access the data from it using the API, but likely not easy. I made a web-based tool (ie. written in javascript, not using Fusion) to convert between Fusion arrays and Google Sheets documents, which worked fine, except that Google has incredibly strict requirements for accessing data, so to publish it for other people to use would require jumping through a huge amount of hoops (stuff like recording a youtube video of me describing exactly what data I need to access, and the reason why, etc).

    Using an ActiveX control might be an option too, although ActiveX is considered obsolete these days, and in my experience just crashes Fusion.

    That's right, but instead of using the object's X position, you may want to test the edges of the object - ie. "X coordinate of left edge", "Y coordinate of top edge" etc.
    That way, it'll work if any part of the object's bounding box is on screen, rather than just the hotspot (it's a small detail that may or may not be significant, but with larger objects especially, it makes sense).

    There's no condition to compare those directly though, so you'll need to use the object's "Compare expression to a value" condition (do NOT use "Compare two general values" if there are going to be multiple instances of the object).

    Also, note that if you just say "add 1 to a counter", it will add 1 if ANY instance is within view, but will never add more than 1, even if many instances are within view.
    Instead, set the counter to "Number of selected objects".

    eg.
    * Enemy: X Right( "Enemy" ) >= X Left Frame
    + Enemy: X Left( "Enemy" ) <= X Right Frame
    + Enemy: Y Bottom( "Enemy" ) >= Y Top Frame
    + Enemy: Y Top( "Enemy" ) <= Y Bottom Frame
    Counter : Set Counter to NSelectedObjects( "Enemy" )

    I've never even tried publishing an Android app, but I've still encountered this kind of thing from Google.
    A while back, I spent a fair bit of time creating a very simple little online tool that used the Google Sheets API to convert between CF2.5 array files and Google Sheets files stored in the cloud.
    It all worked fine, until I tried to publish it so that someone other than me could use it, and then they wanted all of this:

    Please login to see this picture.

    Needless to say, that was the end of that...

    I have a small request - a "stop fastloop immediately" action.

    For example:

    + Start of frame
    -> Run fastloop "test", 1 time

    + On loop "test"
    -> Add 1 to counter
    -> Stop fastloop "test"

    + On loop "test"
    -> Add 1 to counter

    The counter will end up reading "2", because the "stop loop" action only prevents the next loop from beginning - it doesn't actually stop the current loop. In particular, if you're creating a the Fusion equivalent of a function, that you call by running a fastloop 1 time, it would be convenient (and more efficient) to have an action to make it stop.

    It's a pain to always have to say something like this:

    + Start of frame
    -> Set thisLoopIsDone to 0
    -> Run fastloop "test", 10 times

    + On loop "test"
    + thisLoopIsDone = 0
    + Some condition...
    -> Add 1 to counter
    -> Set thisLoopIsDone to 1
    -> Stop fastloop "test"

    + On loop "test"
    + thisLoopIsDone = 0
    + Some other condition...
    -> Add 1 to counter

    It seems like it would be relatively quick and easy to implement?

    Yep. I hate to be negative, but there are at least two very good reasons not to:
    1) It's very complicated and requires a huge amount of work, so it will very likely never happen (I'm not aware of even a single finished multiplayer online game made in CF2.5 / MMF2). It's not fun work either - designing the game and creating the artwork may be work, but they're also fun, so even if the project never amounts to anything, you'll still have enjoyed the process. The same cannot be said of multiplayer stuff, which is ultra-tedious.

    2) The chicken and egg problem - noone will play your game, because noone else is playing your game. Unless you're a major studio with an established following, you'd have to put a huge amount more work into marketing and making the game look good.

    I'd say make a single-player game, and if you see it through to completion, and it's good, and you get really lucky, then you'll attract some players and can start thinking about adding multiplayer.

    Who wants a little maths lesson?

    The shader for the tile-based voxel environment is pretty much finished now, so it's time to move on to the next part of the engine - other objects that can be placed within the environment.

    Please login to see this picture.

    Let's start with 2D "billboard" sprites - and just while we figure out the maths, we'll work in two-dimensions only.

    So, first of all we need a vector pointing in the direction the camera is facing:
    camDirX = cos(cameraAngle)
    camDirY = 0 - sin(cameraAngle)
    (right now, that's a "unit vector", with a length of 1)

    Please login to see this picture.

    Next we need a vector (purple) perpendicular to that, some distance in front of the camera, and with a length equal to the width of the viewing window. If if we were to draw lines from each end of this vector to the camera, the area inside would be our field of vision.
    The distance of this vector from the camera (ie. the length of the orange vector) defines how wide the field of vision is - the shorter the distance, the wider the field of vision (we just pick a value that looks "right").

    Next, let's calculate the vector perpendicular to the camera direction vector. To do this, we simply swap the X and Y components, inverting one of them. Note that there are two possibilities - either 90 degrees to the left or 90 degrees to the right - so we'll pick the vector to the right.
    perpCamDirX = -1 * camDirY
    perpCamDirY = camDirX

    Please login to see this picture.

    Now, we need the vector from the camera to the sprite (white).
    camToSprX = spritePosX - cameraPosX
    camToSprY = spritePosY - cameraPosY

    Next comes the clever part. Instead of using the sprite's position relative to the X and Y axis, we can find its position relative to the camera direction (orange) and the vector perpendicular to that (blue). We can find the length of the light purple vector by calculating the "dot product" of the sprite's position vector and the camera direction vector:
    camToSprA = (camToSprX * camDirX ) + (camToSprY * camDirY)

    Note that if this value is negative, it means the sprite is behind the camera, and will therefore not be visible.

    And we can find the length of the light green vector by calculating the dot product of the sprite's position vector and the vector perpendicular to the camera direction:
    camToSprB = (camToSprX * perpCamDirX ) + (camToSprY * perpCamDirY)

    To get the gradient of the line from the camera to the sprite (white), we can divide the second of those values (green) by the first (purple).
    gradSpr = camToSprB / camToSprA

    Next, we need to find the gradient of a line from the camera to the right edge of the field of vision (red). We could do the same as before, but there's an easier way. We know that the length of the orange vector is simply our cameraDistance variable. We also know that the total length of the purple vector is equal to the width of the viewing window, so if we halve that we get the length of vector to the right of the camera direction. Divide one by the other, and we have the gradient of the red line:
    gradView = (viewWidth / 2) / cameraDistance

    Please login to see this picture.

    If we divide gradSpr by gradView, we get the position of the horizontal position of the sprite relative to the centre of the viewing window. A value of 0 means the sprite is in the centre of the view. A value of +1 means the sprite is at the right edge of the view. A value of -1 means the sprite is at the left edge of the view. A value outside the range -1 to +1 means the sprite is outside the field of view.

    If we add 1 and then divide the result by 2, we convert that to a value in the range 0 to 1, and if we multiply this value by the width of the viewing window, we get the horizontal position of the sprite on screen, in pixels (light mauve).

    It's basically the same for the vertical position, although things do start to get complicated if we add another degree of freedom for the camera (roll)... And then there's the small matter of scaling the sprite with distance...

    It would probably depend on the hardware you use. I have a USB version of the ELM327 (or at least a cheap Chinese clone of it), which communicates through a virtual COM port, so I'd imagine you would be able to use the Serial object extension with it (same as communicating with an Arduino or Pololu etc). If you have a bluetooth version, I'd guess you're probably out of luck.

    You'd be a much, much braver man than me to mess with this stuff though, as there's the very real potential to cause serious and expensive damage to your car, if you don't know exactly what you're doing (given that I managed to burn out a few servos before I was able to get a Pololu working with the serial object, there's no way I'd try it on my car).