Best way for a frame-based level editor in CTF 2.5+ ?

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.
  • Hi!

    I'm currently looking at either making my own level editor or perhaps build/use an already existing level editor. I would love to know if there's any good example/extension for this.

    Currently, I'm creating my levels in different frames which isn't optimal at all.
    However, from what I have read, it should be possible to build a level this way. A way to save every items position from that frame into an array or file which will be loaded at the "engine frame".

    This is perhaps the only good way to go forward and not have to copy everything from the "engine frame" into all the other level frames?
    I also read that perhaps a level editor isn't needed with 2.5+ as we can now store all the coding in global events and/or in the behavior of an active object?

    Is there anyone who has done this that can give me any directions where to start, which way forward is the way to go as for now?

    My project: Please login to see this link.
    - vSv

  • To make a save procedure, you can do it like this:

    Give all objects the same qualifier, for instance Group.Engine.
    Create a String Tokenizer object. Install it from the extension manager if you don't have it. It's extremely useful.

    In the event editor, have a button or key run a For Each loop on the qualifier. You may for instance name the loop "Save".

    Now make a new event and add an on For Each loop condition for the qualifier.
    In this event you will add all the needed information of each object to a string. You may use a global string for best performance. Let's call it LevelString.
    Split every data with a delimiter such as a comma or any other special character. Like this: OName$("Group.Engine") +","+ X("Group.Engine")+","+Y("Group.Engine"). Remember to include the name of the qualifier. It will pick the name of the actual object.
    Finally make an event to add another different delimiter to split each object in the string. Place it above the other event, and add a condition to check if the string is not empty, so it only gets inserted if there allready is at least one object present in the string.

    This should store the entire level. Now you can load the string into an edit object or something else and save it to file.

    To load the level, add your delimiters into String Tokenizer and 2D split the string. Then run a fastloop to run through all X items (the objects) and retrieve each Y item (the data / positions) where you need them. The first item is item 0, the one is 1 etc...
    Use the Create By Name action to create the object, and then set positions and other data to the qualifier.

    This method works whether you're making a fully custom level editor, or a semi-custom one like the one you're talking about.

    You can use an array instead of a string, but doing it this way makes it very easy for you to read through the levels in a file to see if everything's correct.

  • Here you go: Please login to see this link.

    This is pretty much the optimal way of doing it. Basically you create seperate levels and then save them to a different Z position in an array. Then you have a Game Frame which houses all of your events and then you load the correct Z position for whatever you need.

    With that said, 2.5+ improved its Global Events so it's realistically possible now to have individual frames as levels and the engine in Global Events.

    Please login to see this link.
    Please login to see this link.|Please login to see this link.|Please login to see this link.

  • [MENTION=5138]Popcorn[/MENTION] Thank you! I'm going to try to follow your guide tomorrow after I have completed the task of turning all my backdrops to active objects.

    My project: Please login to see this link.
    - vSv

  • For my game, I created a level editor for saving all my data informations in array files for each level.
    For background and tiles, i'm using Tiled Map Editor (Please login to see this link.) and I export my scene in PNG picture for each layer. It's possible to load the TMX files (wich is an XML) but there is not good XML extension with Clickteam saddly, both are buggy so it's kind of complicate.

    With Clickteam Fusion, I've one frame, wich load my level at the beggining with a loop. That's not really hard, but you have to be organized and know how is working array, Ini, XML, etc...

    Anyway, with 2.5+ DLC I guess you can use global event and have a frame for each level of your game.
    Someone to confirm?

    Developer of Inexistence available on Steam :
    Please login to see this link.

    Edited once, last by Jonathan (July 16, 2019 at 7:50 PM).

  • I hope so - that's what I'm doing. The downsides I can see so far are:

    - You need to make each object Global so that you can change it from anywhere. I don't think there is an option to automatically create all actives as "Global" which is a bit of a bummer. Feature request?

    - You need to add each active object to every frame or any code referencing that object won't work for that particular frame. In this respect, it's not truly "global."

    I personally think a level editor is the best way to go, but the prospect of spending time developing and debugging what is basically a whole new project is not very appealing to me - especially now that Global Events are viable, despite the points above.

  • Quote

    - You need to add each active object to every frame or any code referencing that object won't work for that particular frame. In this respect, it's not truly "global."

    What? If your object are global and are on a specific frame (for exemple a "template frame"), you still have to copy past each of them in all your layers? You can't just use theme from your template frame? Damn, such a shame.

    Developer of Inexistence available on Steam :
    Please login to see this link.

  • You don't have to copy/paste them manually from one frame to another. You can create objects at runtime from any frame you like, using the left column in the Create Object dialog. However, this only works with the Create object action, not the Create object by name action.

    Please login to see this picture.

    Please login to see this link.
    My Fusion Tools: Please login to see this link. | Please login to see this link. | Please login to see this link.

  • It seems I got stuck quite early.



    In this event you will add all the needed information of each object to a string. You may use a global string for best performance. Let's call it LevelString.

    Should I use the String Tokenizer object or just an ordinary String object here?



    Split every data with a delimiter such as a comma or any other special character. Like this: OName$("Group.Engine") +","+ X("Group.Engine")+","+Y("Group.Engine"). Remember to include the name of the qualifier. It will pick the name of the actual object.

    I have ensured that everything that should be saved has the Group.Engine qualifier.
    But when I try to use the OName$("Group.Engine") +","+ X("Group.Engine")+","+Y("Group.Engine") on the String Tokenizer or an ordinary String I get this error message "Mixed string and numbers.".

    My project: Please login to see this link.
    - vSv

  • You don't have to copy/paste them manually from one frame to another. You can create objects at runtime from any frame you like, using the left column in the Create Object dialog. However, this only works with the Create object action, not the Create object by name action.

    Thank you, I didn't know that :D
    Unfortunately it only works in Frame Events. It doesn't work in Global Events or in Behaviors.

    Back to topic, I use a global active called "gameEngine" and store as behavior all the events that should be in Frame Events. Also I copy from a template frame called "assets" all the global objects that are used in the level (in each frame). So a level frame contains the level layout, the "gameEngine", and I manually copy other needed objects like PMO etc.
    It would help a lot if I could create objects from other frames using behaviors.
    The downside is that I can't use qualifiers :( .

    The alternative would be to move the events from "gameEngine" back to the Frame Events, create the assets (PMO, camera etc) dynamically from events, the level layout remains the same, and use qualifiers.
    The downside would be that I have to copy/paste manually the events in each frame. So yeah, best code reuse/ sarcasm.

  • Ah, I'm sorry. You'll need to put str$() around the numbers. So for instance str$(X("Group.Engine")) should work fine :) Regarding the string, you can use a normal string or a global string as I suggested. The string tokenizer you will only use to load data from a string. If you want me to make an example, I can do that. I haven't look at the other examples that was posted though. They may work just fine for what you want :)

  • [MENTION=5138]Popcorn[/MENTION] Sure, that would be helpful! I can look at your example tomorrow and try to learn from it. Thank you!

    My project: Please login to see this link.
    - vSv

  • Okay, putting the "str$" before the qualifier worked. But now I'm stuck at the next step.

    Finally make an event to add another different delimiter to split each object in the string. Place it above the other event, and add a condition to check if the string is not empty, so it only gets inserted if there allready is at least one object present in the string.

    I'm sorry but I really don't follow you here on what the new event should look like.
    I'm attaching my .mfa so you can look.

  • I just had to bump this thread as I've run into a problem with my largest map. The game simply crashes when there are more than 4400 engine objects that need to save/load (and I have around 10700 engine objects in the map).

    Is it in any way possible to make a change in this awesome level loading system provided by [MENTION=5138]Popcorn[/MENTION] to load only certain sections of a map? and how would I go about doing that?
    For example, save 25% chunks of the map into different strings, and then only load those strings when the player character is near those parts of the map where that specific string is stored?
    Perhaps I also need a way to remove the parts of the map that are not near the player as well and reload them if the player gets near them again?

    Anyone done anything like this?

    My project: Please login to see this link.
    - vSv


  • Anyway, with 2.5+ DLC I guess you can use global event and have a frame for each level of your game.
    Someone to confirm?

    I'm agree, before +DLC it was difficult to write flexible code without custom editor but now, I write all global code in global events editor use qualifiers. The scene events it's for specific actions for this level (scenario)
    .

  • I just had to bump this thread as I've run into a problem with my largest map. The game simply crashes when there are more than 4400 engine objects that need to save/load (and I have around 10700 engine objects in the map).

    Is it in any way possible to make a change in this awesome level loading system provided by @Please login to see this link. to load only certain sections of a map? and how would I go about doing that?
    For example, save 25% chunks of the map into different strings, and then only load those strings when the player character is near those parts of the map where that specific string is stored?
    Perhaps I also need a way to remove the parts of the map that are not near the player as well and reload them if the player gets near them again?

    Anyone done anything like this?

    I think you kinda answered your own question. It's possible to divide it into sections, but every game is different, so I guess you need to come up with your own solution. For instance, if you have objects that can move between the different sections, you have to take that into account. There are different approaches. If you can pull off to always destroy everything that's for instance 400 pixels or more from the visible area, and load the object's that's between, then I think that's the best solution. However, you might need to change the way you store everything, so that it can be sorted by position. For example you can use an array and store a string for each 200 pixels. I have not done this so you will have to experiment :)

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!