Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AdvancedJump] Add wall jump, wall sliding, air jump and dash #325

Merged
merged 1 commit into from
Jul 24, 2022

Conversation

github-actions[bot]
Copy link
Contributor

@github-actions github-actions bot commented Dec 16, 2021

Changes

This update adds:

  • The air jump behavior that lets platformer characters jump in mid-air.
  • The wall jump behavior that lets platformer characters jump and slide against walls.
  • The horizontal dash behavior that makes platformer characters dash horizontally.
  • The dive dash behavior that makes platformer characters dash toward the floor.

These behaviors are ready to use and let extensions users define their own game rules.

AdvancedJumpEvents

The behaviors doesn't use any kind of collision condition nor move any object manually. It only rely on the platformer extension collision handling and movement. So, they are efficient and less prone to weird side effects.

"PlatformerConfigurationStack" is the only behavior that uses JavaScript.

Behavior interactions

AdvancedJumpDiagram

Handling "Allow to jump again" conflicts (CoyoteAndAirJumpIntegrater)

Both the air jump behavior is executed before the coyote time behavior use the actions to allow or forbid to jump in mid-air. This can result to miscalculations of the number of remaining air jumps. The "CoyoteAndAirJumpIntegrater" handles the following cases.

When the Air jump behavior is executed before the Coyote time behavior, these scenarios will happen:

Coyote jump time frame is missed

  • the character falls
  • Air jump: allow to jump again and decrement jump counter
  • Coyote time: allow to jump again
  • Coyote time: forbid to jump
  • It's now impossible to jump, Air jump needs to be reset

Coyote jump happens in the time frame

  • the character falls
  • Air jump: allow to jump again and decrement jump counter
  • Coyote time: allow to jump again
  • the character jump, this should be handled as a floor jump

When the Air jump behavior is executed after the Coyote time behavior, these scenarios will happen:

Coyote jump time frame is missed

  • the character falls
  • Coyote time: allow to jump again
  • Coyote time: forbid to jump
  • Air jump: allow to jump again and decrement jump counter
  • OK

Coyote jump happens in the time frame

  • the character falls
  • Coyote time: allow to jump again
  • the character jump, this should be handled as a floor jump

Handling character configuration changes conflicts (PlatformerConfigurationStack)

In previous versions, the wall jump behaviors were saving the configuration before changing it for doing wall sliding or wall leaps. This can't work if another behavior does the same because when the configuration changes cross with each other. For instance, one will save the configuration of the other custom movement and put it back instead of the actual character configuration.

BehaviorConfigConflict

The "Platformer character configuration stack" behavior allow to handle these conflicts. This behavior keeps track of the configuration changes like layers. The background is the character configuration setup by the user and each behavior add a layer that can change some properties. When an extension changes the configuration, it adds a layer on top and when the behavior decides to revert its change, it removes the layer. This way behaviors don't override each other changes.

ConfigurationLayers

Checklist

  • I've followed all of the best practices.
  • I confirm that this extension can be integrated to this GitHub repository, distributed and MIT licensed.

Demonstration

JavaScript part

Revert configuration changes

Revert configuration changes for one identifier and update the character configuration to use the most recent ones.

const behaviorName = eventsFunctionContext.getBehaviorName("Behavior");
const object = objects[0];
const behavior = object.getBehavior(behaviorName);
/** @type {gdjs.PlatformerObjectRuntimeBehavior} */
const character = object.getBehavior(behavior._getPlatformerCharacter());
/** @type {string} */
const id = eventsFunctionContext.getArgument("Identifier");

if (id === undefined) {
    return;
}

/** @type {{id:string, gravity: float, maxFallSpeed: float, jumpSpeed: float, jumpSustainTime: float, acceleration: float, deceleration: float, maxSpeed: float}[]} */
const configurationChanges = behavior.__configurationChanges || [];

const index = configurationChanges.findIndex(value => value.id === id);
if (index >= 0) {
    configurationChanges.splice(index, 1);

    // Update the configuration with the most recent changes.
    /** @type {string[]} */
    const settingNames = behavior.__settingNames;
    for (const settingName of settingNames) {
        const configuration = configurationChanges.find(value => value[settingName] !== undefined);
        const settingValue = configuration[settingName];
        // Methods can't be stored because the character instance could change.
        switch (settingName) {
            case "gravity":
                character.setGravity(settingValue);
                break;
            case "maxFallSpeed":
                character.setMaxFallingSpeed(settingValue);
                break;
            case "jumpSpeed":
                character.setJumpSpeed(settingValue);
                break;
            case "jumpSustainTime":
                character.setJumpSustainTime(settingValue);
                break;
            case "acceleration":
                character.setAcceleration(settingValue);
                break;
            case "deceleration":
                character.setDeceleration(settingValue);
                break;
            case "maxSpeed":
                character.setMaxSpeed(settingValue);
                break;
        }
    }
}

Configure a character property

Configure a character property for a given configuration layer and move this layer on top.

const behaviorName = eventsFunctionContext.getBehaviorName("Behavior");
const object = objects[0];
const behavior = object.getBehavior(behaviorName);
/** @type {gdjs.PlatformerObjectRuntimeBehavior} */
const character = object.getBehavior(behavior._getPlatformerCharacter());
/** @type {string} */
const settingName = eventsFunctionContext.getArgument("SettingName");
/** @type {float} */
const settingValue = eventsFunctionContext.getArgument("SettingValue");
/** @type {string} */
const id = eventsFunctionContext.getArgument("Identifier");

/** @type {{id:string, gravity: float, maxFallSpeed: float, jumpSpeed: float, jumpSustainTime: float, acceleration: float, deceleration: float, maxSpeed: float}[]} */
const configurationChanges = behavior.__configurationChanges || [];

const index = configurationChanges.findIndex(value => value.id === id);
let configurationChange;
if (index < 0) {
    configurationChange = {id:id, gravity: undefined, maxFallSpeed: undefined, jumpSpeed: undefined, jumpSustainTime: undefined, acceleration: undefined, deceleration: undefined, maxSpeed: undefined}
    configurationChanges.splice(0, 0, configurationChange);
}
else {
    configurationChange = configurationChanges[index];
    // Move the configuration change on top
    if (index > 0) {
        configurationChanges.splice(index, 1);
        configurationChanges.splice(0, 0, configurationChange);
    }
}
configurationChange[settingName] = settingValue;

@github-actions github-actions bot added the ✨ New extension A new extension label Dec 16, 2021
@github-actions github-actions bot added this to Needs review in Extensions review Dec 16, 2021
@github-actions github-actions bot mentioned this pull request Dec 16, 2021
2 tasks
@shadow00dev
Copy link

WallJumpingAndAirJumpingExample.zip
WallJumpingAndAirJumping.zip

these are the new files for this btw(I've changed the desc of the extension since I forgot to add one)

@shadow00dev
Copy link

how would I update the files in this?, cuz I don't think it updates to my latest one

@D8H
Copy link
Contributor

D8H commented Dec 17, 2021

This submission is related to this one:

Behaviors about jumping should be integrated with the "Advanced Jump" extension.

@shadow00dev
Copy link

This submission is related to this one:

ooh didnt see that when i did PR(maybe my tiredness got to me)

Behaviors about jumping should be integrated with the "Advanced Jump" extension.

both(airjump and walljump)?

@D8H
Copy link
Contributor

D8H commented Dec 18, 2021

Behaviors about jumping should be integrated with the "Advanced Jump" extension.

both(airjump and walljump)?

Everything that uses the action to jump again. This is to make sure there is no conflict when using the features together.

@shadow00dev
Copy link

shadow00dev commented Dec 18, 2021

okay

@shadow00dev
Copy link

okay so asked me to make the extension part of the advanced jump right?, which means I would need to give an export for that one right?

@shadow00dev
Copy link

Extension:
the one I added into the "Advanced jump" extension
Advanced jump.zip

the one I made earlier(i made some changes to it)
WallJump and AirJump.zip

Example

this has both in it
WallJumpingAndAirJumpingExtensionExample.zip

@shadow00dev
Copy link

Extension and example.zip

I assume you meant merge it to advanced jump so I decided not to make the changes to the one I made(well I made the air and wall jump in the advanced jump thing to but you get what I mean hopefully), anyway changes are I added a condition for checking if the object is next to the wall and changed "block" object to wall object(cuz for wall jump it makes more sense)

@D8H
Copy link
Contributor

D8H commented Dec 25, 2021

There should not be any action that the extension user needs to execute every frame. The lifecycles are used for this.

  • To let the user chooses between the 2 modes Falling/KeyReleased, a property can be used.
  • Same for the key parameter, make it a property.
    I will add conditions in the PlatformerCharacter to check if a Jump, Left, Right... key is pressed or released (with physical keys or simulate actions) to avoid to pass a key name that would work with a gamepad (but we can keep key name properties for now).

Relying on other objects every frame should be avoid at all cost.
Can you try to implement the wall jump without the raycast?
I was thinking of this condition instead:

  • Left or Right is pressed
  • and X position stays the same as previous frame
  • Jump was pressed less than 0,xxx seconds ago
    It will confict with the air jump so if a wall jump could happen but the air jump already did in the time frame , we must make sure that the air jump wasn't counted.

The air jump counter could probably be reset when a wall jump happens. As it's not possible to have an optional required behavior, we will probably end-up with most of the behavior requiring on each other. At the end, the 3 behaviors will probably be merged, but let's keep 3 behaviors for now.

I'm not sure the "falling" mode is useful. Do you know any games that works like this?

@D8H D8H added the 🏗 Need a change in GDevelop This extension needs a change in GDevelop to work label Dec 26, 2021
@shadow00dev
Copy link

i dont know how to do it without raycast(cuz um any another way like collision would be buggy unless I have points) and I need to check if the object is collision with wall for the conflitch thing okay i could do that, for falling then i would say well i personally know of no games but i think its a good idea(that's just my opinion doe) and may i keep the 2 added behaviors as that would be easier in most ways for me at least but if you want i can try to merge them in the main one

@shadow00dev
Copy link

for the object thing i could make an object group called walls maybe and put it in desc for it?

@shadow00dev
Copy link

I was thinking of this condition instead:

  • Left or Right is pressed
  • and X position stays the same as previous frame
  • Jump was pressed less than 0,xxx seconds ago
    It will confict with the air jump so if a wall jump could happen but the air jump already did in the time frame , we must make sure that the air jump wasn't counted.

oooh you said this, ill try it

@D8H
Copy link
Contributor

D8H commented Dec 26, 2021

i dont know how to do it without raycast(cuz um any another way like collision would be buggy unless I have points) and I need to check if the object is collision with wall

What about the solution I suggested? (Edit, ok)

may i keep the 2 added behaviors as that would be easier in most ways for me at least

Of course, this is what I suggested, it will be easier to write them in their own behavior first.

@shadow00dev
Copy link

i dont know how to do it without raycast(cuz um any another way like collision would be buggy unless I have points) and I need to check if the object is collision with wall

What about the solution I suggested? (Edit, ok)

may i keep the 2 added behaviors as that would be easier in most ways for me at least

Of course, this is what I suggested, it will be easier to write them in their own behavior first.

ooh kay btw I didn't understand the solution you gave and my idea of using a object group didn't work

@shadow00dev
Copy link

and i don't wanna do left or right pressed and I'm unsure what to do for it and I used a action(for walljump at least) cuz of I needed it to say the object, unless I check if there is a wall next to player then idk another way to do it

@shadow00dev
Copy link

ooh i remembered some mobiles game with double jump having a falling system for instead of released though I cant name them :(

@D8H
Copy link
Contributor

D8H commented Dec 26, 2021

and i don't wanna do left or right pressed and I'm unsure what to do for it and I used a action(for walljump at least) cuz of I needed it to say the object, unless I check if there is a wall next to player then idk another way to do it

That's ok, I can help for this. I'll give it a try after your next version.

@shadow00dev
Copy link

and i don't wanna do left or right pressed and I'm unsure what to do for it and I used a action(for walljump at least) cuz of I needed it to say the object, unless I check if there is a wall next to player then idk another way to do it

That's ok, I can help for this. I'll give it a try after your next version.

okay all I can really do is change air jump cuz idk what to do for wall jump and my walls group idea failed

@shadow00dev
Copy link

can we talk on discord cuz i found a issue and well its cuz of the lifecycle function?

@shadow00dev
Copy link

Example and Extension

changes:

air jump is now fully the behavior

wall jump only has 1 action(this is cuz I need to know what object is on the wall, but I believe D8H said he would try to do a wall-jumping system for it, so in theory this is temporary(hopefully))

@shadow00dev
Copy link

Example and Extension

I've merged air jump and wall jump together and made wall jump work without action now(but there is still two new behaviors one for key released and one for falling types)

@D8H
Copy link
Contributor

D8H commented Dec 28, 2021

My version with working air and wall jumps still in their own behaviors.

I'll take a look at yours.

@D8H
Copy link
Contributor

D8H commented Dec 28, 2021

I can't test your version because I don't have a QWERTY, but the code seem more complicated than mine and the speed should not be used to check if an object doesn't move as the platformer behavior could have an option to keep its speed when colliding obstacles one day and it would break it.

Take a look at my version and if you are ok with it, we can add actions and conditions to allow to change the configuration and the state.
A wall sliding could be interesting to do too.

@shadow00dev
Copy link

A wall sliding could be interesting to do too.

i didn't do that cuz my way of doing it isn't good I think(but I might be able to make a better system of mine for it)

@github-actions
Copy link
Contributor Author

github-actions bot commented Feb 2, 2022

Errors were detected in this submission:

❌ 9 Errors found in extension 'WallAndAirJump':

  ⟶ ❌ (🔧) [Dots in sentences]: Field 'shortDescription' of the extension description misses a dot at the end of the sentence!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the extension description is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'fullName' of the function 'WalllJump' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'WalllJump' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'WalllJump parameter 'BehaviorForMainObject' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'fullName' of the function 'AirJump' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'AirJump' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'AirJump parameter 'BehaviorForMainObject' is not filled out!
  ⟶ ❌ [Extension name consistency]: Extension filename should be exactly the name of the extension (with .json extension). Please rename 'WallJumpingAndAirJumping.json' to 'WallAndAirJump.json'.


❌ 9 Errors found in extensions - please fix them before generating the registry.

@github-actions
Copy link
Contributor Author

github-actions bot commented Feb 2, 2022

Errors were detected in this submission:

❌ 7 Errors found in extension 'AdvancedJump':

  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'RevertConfiguration' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureGravity' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureDeceleration' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureMaxSpeed' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureAcceleration' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureMaxFallSpeed' is not filled out!
  ⟶ ❌ [JavaScript disallowed properties]: Found disallowed properties in extension 'AdvancedJump':
{
  allowedProperties: [
    'makeUuid',
    'rgbToHex',
    'evtTools',
    'Variable',
    'RuntimeObject',
    'Logger'
  ],
  disallowedProperty: 'PlatformerObjectRuntimeBehavior',
  objectName: 'gdjs'
}


❌ 7 Errors found in extensions - please fix them before generating the registry.

@github-actions
Copy link
Contributor Author

github-actions bot commented Feb 2, 2022

Errors were detected in this submission:

❌ 6 Errors found in extension 'AdvancedJump':

  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'RevertConfiguration' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureGravity' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureDeceleration' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureMaxSpeed' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureAcceleration' is not filled out!
  ⟶ ❌ [Filled out names and descriptions]: Required field 'description' of the function 'ConfigureMaxFallSpeed' is not filled out!


❌ 6 Errors found in extensions - please fix them before generating the registry.

@D8H D8H changed the title [Auto PR] [AdvancedJump] Wall jump and air jump [AdvancedJump] Add wall jump, wall sliding, air jump and dash Feb 2, 2022
@D8H D8H requested a review from a team February 2, 2022 18:46
@shadow00dev
Copy link

why have add dash this is advanced jump, not advanced movement?

@D8H
Copy link
Contributor

D8H commented Feb 2, 2022

why have add dash this is advanced jump, not advanced movement?

The dash can't be in its own extension because we couldn't make it work with the wall jump.
Are you suggesting to rename the extension "Advanced platformer movements" ?

@shadow00dev
Copy link

shadow00dev commented Feb 2, 2022

Are you suggesting to rename the extension "Advanced platformer movements" ?

yep, I understand why dash is added but it is called Advanced jump so it wouldn't make sense, so something like Advanced platformer movements or something like that would be better in my opinion, well if there's a dash or another movement types like dash then it would be better(in my opinion)

@VegeTato
Copy link
Contributor

VegeTato commented Feb 2, 2022

-In the example the texts should say "Left shift" and "Left ctrl" not right (since left is the key)
-Why dashing is not working in the example project "Project" and working in the online example "Build"
-Log messages action should be deleted since its disabled
-"WallJump" > "AbsorbFallingSpeed" Unknown actions
-"WallJump" > "PreEvents" Unknown actions and spelling issue
1
22
-"WallJump" "WallSlidingGravity" > spelling issue
33
-"WallJump" "SetWallSlidingGravity" > spelling issue (same as previous ss)
-"DiveDash" > "SimulateDiveKey" Unknown actions
-"HorizontalDash" > "SimulateDashKey" Unknown actions
-"HorizontalDash" > "AbortDash> Unknown actions

this is a very cool update for the extension, and very useful, it looks very good in the example, but when i download the project dashing its not working, no idea why

@D8H
Copy link
Contributor

D8H commented Feb 2, 2022

-In the example the texts should say "Left shit" and "Left ctrl" not right (since left is the key)
-"WallJump" > "PreEvents" spelling issue

Thanks, I updated the project.

-Why dashing is not working in the example project "Project" and working in the online example "Build"

Have you updated to GDevelop 5.0.127? (I'm adding it next to the link)

-Log messages action should be deleted since its disabled -"WallJump"

They will be very useful for the next person that changes the behaviors.

-"WallJump" "WallSlidingGravity" > spelling issue

A gravity is an acceleration. Its a distance * time^-2.

@VegeTato
Copy link
Contributor

VegeTato commented Feb 2, 2022

oh didnt know it requires the latest version of gdevelop, i will update it 👍

@D8H D8H removed the ✨ New extension A new extension label Feb 2, 2022
@D8H D8H moved this from Needs changes to Needs review in Extensions review Feb 3, 2022
Extensions review automation moved this from Needs review to Approved - awaiting merge Feb 9, 2022
@D8H D8H requested a review from a team March 13, 2022 13:47
@D8H
Copy link
Contributor

D8H commented Mar 13, 2022

I'm too much involved in this extension to merge it.
Can someone make a review?

@4ian
Copy link
Collaborator

4ian commented Mar 23, 2022

@Bouh can you make a quick check before we merge this? :)

@Bouh
Copy link
Contributor

Bouh commented Mar 24, 2022

  • Missing behaviors descriptions in the extension description

    • The Advanced Jump behavior ...?
    • The Air Jump behavior lets platformer characters jump in mid-air.
    • The Wall Jump behavior lets platformer characters jump and slide against walls.
    • The Dive Dash behavior makes platformer characters dash toward the floor.
    • The Horizontal Dash behavior makes platformer characters dash horizontally.
    • The Platformer Configuration Stack behavior ...?
    • The Coyote And Air Jump Integrater behavior ...?
  • Behaviors cannot be used without Platformer Configuration Stack and Coyote And Air Jump Integrater

There are a lot of behaviors and two technical behaviors required, if they are not present the other behaviors don't work.
If these technical behaviors can be merged with the other it could reduce the barrier to using this extension.
Keep in mind the concept of GDevelop, we hide the technical part, asking for adding two behaviors that fix calculations that are not interesting for users, users don't want to deal with it.

OR

One big behavior rather than adding technical behaviors to resolve conflicts between platformer character and fix miscalculations with Coyote And Air Jump Integrater inside this extension update.
And we could even add a debug check box to enable the logger!

@D8H
Copy link
Contributor

D8H commented Mar 28, 2022

  • Missing behaviors descriptions in the extension description

    * [ ]   The _Advanced Jump_ behavior ...?
    * [x]   The _Air Jump_ behavior lets platformer characters jump in mid-air.
    * [x]   The _Wall Jump_ behavior lets platformer characters jump and slide against walls.
    * [x]   The _Dive Dash_ behavior makes platformer characters dash toward the floor.
    * [x]   The _Horizontal Dash_ behavior makes platformer characters dash horizontally.
    * [ ]   The _Platformer Configuration Stack_ behavior ...?
    * [ ]   The _Coyote And Air Jump Integrater_ behavior ...?
    
    • Behaviors cannot be used without Platformer Configuration Stack and Coyote And Air Jump Integrater

There is no Advanced Jump behavior, it's called Coyote time from a user point of view. I asked for this name at the time because I though it wouldn't be possible to do separated behaviors.

The last 2 behaviors doesn't really provide direct game features. I think there is no need to get into details in the extension description.

There are a lot of behaviors and two technical behaviors required, if they are not present the other behaviors don't work. If these technical behaviors can be merged with the other it could reduce the barrier to using this extension. Keep in mind the concept of GDevelop, we hide the technical part, asking for adding two behaviors that fix calculations that are not interesting for users, users don't want to deal with it.

The Platformer Configuration Stack behavior can actually be useful for extension users that need to change Platformer Character configuration.

One big behavior rather than adding technical behaviors to resolve conflicts between platformer character and fix miscalculations with Coyote And Air Jump Integrater inside this extension update.

Ok, these 2 behaviors are small enough to be merged without making them hard to maintain.

And we could even add a debug check box to enable the logger!

The debug is only useful for extension mainteners. I think it should not be exposed to extension users.

@D8H
Copy link
Contributor

D8H commented Mar 28, 2022

A build with the last change to check everything is ok:
https://liluo.io/instant-builds/6b71ad38-fd20-42b9-a20b-d8999036f109

The air jump behavior lets platformer characters jump in mid-air.
The wall jump behavior lets platformer characters jump and slide against walls.
The horizontal dash behavior makes platformer characters dash horizontally.
The dive dash behavior makes platformer characters dash toward the floor.
@D8H D8H force-pushed the extension/shadow00dev/324 branch from 48677ae to 3e720b4 Compare July 3, 2022 19:26
@github-actions github-actions bot requested a review from a team as a code owner July 3, 2022 19:26
@D8H
Copy link
Contributor

D8H commented Jul 3, 2022

I couldn't rebase the commit history because of the case change of the "extensions" folder, but the commit are still accessible on my fork: https://github.com/D8H/GDevelop-extensions/commits/AirJump

@D8H D8H mentioned this pull request Jul 6, 2022
2 tasks
@D8H D8H merged commit efc4c50 into main Jul 24, 2022
Extensions review automation moved this from Approved - awaiting merge to Added to GDevelop Jul 24, 2022
@D8H D8H deleted the extension/shadow00dev/324 branch July 24, 2022 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔄 Extension update An update for an existing extension
Projects
Extensions review
  
Added to GDevelop
Development

Successfully merging this pull request may close these issues.

None yet

6 participants