8000 Release Beta 4.9.0 · jakubg1/OpenSMCE · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Beta 4.9.0

Compare
Choose a tag to compare
@jakubg1 jakubg1 released this 12 Mar 20:24
· 93 commits to master since this release

Happy Birthday, OpenSMCE! You've just turned 5 this year!

Although the initial commit has been made a few months into the project, the first ever demo has been created and shown on March 12, 2020! Here's how it looked:
obraz

It's crazy how big this engine has grown up since! Thank you all so much for your support!

You might have noticed that the releases are happening less and less often. However, they are also getting bigger and bigger! So big, that it actually makes the changelog so big that it's getting quite unmanageable.
Also, the converter is only ever updated just before a release, which makes you essentially stuck on the previous version of the engine if you want to play Luxor or Luxor Amun Rising.

Because of that, expect a new release in May 7! That's right! From now on, the new versions will be released on a bi-monthly basis, most likely on the first Wednesday of each month.

Let's now dive into this one of the longest changelogs ever made for this project.

Happy matching!

Changelog

Game Development

Changes in config.json:

  • Added a few optional fields:
    • canvasRenderingMode - Can be one of two values:
      • "filtered" - The canvas will be stretched smoothly.
      • "pixel" - The canvas will preserve all pixels as they are. Useful for pixel art games.
    • tickRate - The number of ticks to be performed per second, 120 by default.
  • The useUI2 field has been removed.

Changes in gameplay.json:

  • In the ui section:
    • A new optional field has been added, buttonReleaseSound.
      • The default Sound Event that will be played whenever any UI button is released.
    • The buttonClickSound and butonHoverSound fields are now optional.
      • If they are not specified and a button has no own sound specified, no sound will be played.
    • The levelAdvanceSound field has been removed.
  • In the sphereBehavior section:
    • Added three new optional fields:
      • invincibleScarabFrontMatters - When the invincibleScarabs flag is set, the frontmost sphere train will matter the most when calculating the speed.
      • noScarabAttraction - If set, the scarab will not attract the spheres in front of it to itself.
      • instantMatches - If true, the spheres will match instantly when they can match. If the match effect has a delay, the sphere will be attached to the nearest sphere and will match after the specified period of time. This behavior is still experimental as there are some edge cases which do not work well at this moment.
    • The invincibleScarabs and noScarabs fields are now optional.
  • In the lightningStorm section:
    • A new optional boolean field has been added: cancelWhenNoSpheresToDestroy - If true (default), the entire lightning storm batch will be cancelled if there are no spheres to strike. If false, only this particular strike will not happen and the storm will carry on.
  • Added a new optional section: levelVariables.
    • Level Variables are numbers stored by the Level. Any number (including none) of them can be defined.
    • The variables are reset every time the level is restarted or finished.
    • They can be accessed using Expression Variables in the level namespace. For example to get the value of a test level variable, write [level.test].
    • Contains any number of Level Variables, keyed by name.
    • The only supported values are numbers.
  • The levelSequence section has been removed.
    • Its contents should be moved to a level sequence file.

Changes in Level Sequence data: level_sequences/*.json

  • These are the same level sequences that have been sitting in gameplay.json until now.
  • Their home folder is level_sequences/ but as usual you can store them anywhere you want, since it's the $schema field in the file itself which determines the actual file type.
  • Added a new entry type:
    • "uiCallback" - Executes a UI callback. Has two required fields:
      • callback - The UI callback which should be executed.
      • waitUntilFinished - If true, the sequence will wait until the levelContinue function is executed on the UI script side. Otherwise, the sequence will immediately move on to the next step.
      • retriggerWhenLoaded - Defaults to true. If set, the callback will be retriggered when loading the level stopped on this step. This prevents softlocks.
  • For any type, a new optional field has been added:
    • muteMusic - If set, while the level is at this level sequence step, the background (both level and danger) music will be muted.
    • Note that in order to preserve current behavior, you will need to set this field in all entries of "end" and "fail" types.

NEW! Game Event data: game_events/*.json

  • Game Events are game-wide events which can be executed to achieve certain logic.
  • Currently, they can be executed by Collectible Effects and Sphere Effects.
  • Currently, they can modify level variables and player's current coin count, execute Collectible Effects and play Sound Events.
  • Their home folder is game_events, and as usual you can put them whenever you want, as it's the $schema field which tells of which type any particular file is.
  • The following Game Event types are available:
    • "sequence" - Executes a list of Game Events in specified order. Contains one field:
      • events - A list of Game Events to be executed.
    • "random" - Executes one randomly picked Game Event from the list.
      • events - A list of Game Events. One of them will be randomly picked from the list and executed.
    • "setCoins" - Sets the amount of coins for the current player.
      • value - The amount of coins this player will now have. This can be an Expression.
    • "setLevelVariable" - Sets the value of a level variable.
      • variable - The name of the Level Variable to be set.
      • value - A number, or a number expression. The new value for this Level Variable.
    • "collectibleEffect" - Executes a Collectible Effect on the current level.
      • collectibleEffect - A Collectible Effect to be executed.
    • "playSound" - Plays a Sound Event.
      • soundEvent - The Sound Event to be played.
    • All Game Event types support the following optional field:
      • conditions - A list of conditions (expressions evaluating to booleans). If any of these evaluate to false, the event will not be executed.

Changes in Level data: config/levels/level_X.json

  • Added a new required field:
    • sequence - The path to a Level Sequence which should be followed by this Level.
  • The matchEffect field must now reference the Sphere Effect by its full path, starting from the root game directory.
  • In the pathsBehavior entry, a new field has been added: trainRules.
    • This field unifies the colors, colorStreak, forceDifferentColor and spawnRules fields into one.
      • These have been of course removed.
    • It has a type field, which can be either "random", "pattern" or "waves".
    • For the "random" type:
      • The colors, colorStreak and forceDifferentColor fields have been moved inside this field, and the meaning of them remains unchanged.
      • A new optional field has been added: length.
        • It specifies the train length. If omitted, the spheres will spawn continuously, like with the spawnRules type set to "continuous".
      • Example:
        • Before:
          "colors": [1, 2, 3, 4],
          "colorStreak": 0.4,
          "forceDifferentColor": true
          "spawnRules": {
              "type": "waves",
              "amount": 30
          }
        • After:
          "trainRules": {
              "type": "random",
              "colors": [1, 2, 3, 4],
              "colorStreak": 0.4,
              "forceDifferentColor": true,
              "length": 30
          }
    • The "pattern" type has the following fields:
      • pattern - A list of colors to be generated in order. Wraps around.
      • length - If set, the train length. If omitted, the spheres will spawn continuously.
      • Example:
        "trainRules": {
            "type": "pattern",
            "pattern": [1, 2, 3, 4, 4, 3, 2, 1],
            "length": 30
        }
        • This example will spawn trains with 30 spheres, and they will always spawn like this: 123443211234432112344321123443.
    • The "waves" type:
      • In this type, the trains are predefined, and can be of varying length.
      • Contains the following sections:
        • key - A list of key definitons to be used as building blocks for train presets. Each entry can have the following fields:
          • key or keys - Respectively, a character or a list of characters. These are the keys defined by this entry.
          • colors - A list of colors which this key will be able to pick from. Each key will be assigned one random color from this list.
          • homogenous - Optional. If set, the color for this key will be picked once per train. Otherwise, once per key occurence in the train preset.
          • noColorRepeats - Optional. If multiple keys are specified for this entry, no color will be assigned to more than one key.
          • colorStreak - Optional. If not homogenous, this specifies the likelihood of the next key occurrence to pick the same color as the last one in the same train.
          • forceDifferentColor - Optional. If set, the newly picked color for this key will be different than the last one.
        • waves - A list of strings (train presets). Each string is composed of the keys defined in the key section and can have any number of characters, excluding zero.
        • behavior - One of the following:
          • "random" - The presets will be picked at random for each train.
          • "panic" - The presets will be drawn in the order specified in the list, and after it is exhausted, it will pick them randomly from the list.
          • "repeatLast" - The presets will be drawn in the order, and will be stuck at the last preset if the list is exhausted.
          • "repeat" - The presets will be drawn in the order, and the list will wrap around if it is exhausted.
      • Example:
        "trainRules": {
            "type": "waves",
            "key": [
                {
                    "keys": ["X", "Y", "Z"],
                    "colors": [1, 2, 3, 4, 5, 6],
                    "noColorRepeats": true,
                    "homogenous": true
                },
                {
                    "key": "A",
                    "colors": [1, 2, 3, 4, 5, 6],
                    "colorStreak": 0.4
                },
                {
                    "key": "O",
                    "colors": [7]
                }
            ],
            "waves": [
                "AAAAA",
                "XOXOX",
                "XYXYXZZ"
            ],
            "behavior": "panic"
        }
        • This example will:
          • first, spawn a train with 5 spheres of an assortment 6 colors with a color streak of 0.4,
          • then a train with 5 spheres, which consists of 2 black spheres (id=7) and 3 spheres of another color, all of which are the same color,
          • and then a train with 7 spheres having 3 different colors assorted in the XYXYXZZ pattern. The colors will always be unique for each train.
          • The subsequent trains will be randomly picked from the aforementioned presets.

Changes in Difficulty data: difficulties/*.json

  • Added a new required field, lifeConfig.
    • Contents depend on the type field, which can have the following values:
      • "score" - Lives will be earned every set amount of points. The following fields will be available:
        • startingLives - How many lives the player will start the game with.
        • scorePerLife - Every how many points an extra life should be granted.
        • countUnmultipliedScore - Optional. Whether the score counted for the next life will be unaffected by the difficulty multiplier. Defaults to false.
      • "coins" - Lives will be earned when a set amount of coins has been collected.
        • startingLives - How many lives the player will start the game with.
        • coinsPerLife - After how many collected coins an extra life should be granted. The coin counter will decrement by this value.
      • "none" - No life system. The player will be able to replay any level indefinitely.
        • No extra fields for this type.
    • Additionally, for all types (including "none"), two additional optional fields are available:
      • rollbackScoreAfterFailure - Whether the score will be reverted to the previous value when the level is lost. Defaults to false.
      • rollbackCoinsAfterFailure - Whether the coin count will be reverted to the previous value when the level is lost. Defaults to false.

This configuration matches the current behavior:

"lifeConfig": {
    "type": "coins",
    "startingLives": 2,
    "coinsPerLife": 30
}

Changes in Collectible data: config/collectibles/*.json -> collectibles/*.json

  • The speed and acceleration fields no longer use outdated Vector2 expression format, i.e. now they start with ${ instead of $expr{.
  • The folder with Collectibles now lives outside of the config/ folder. (config/collectibles/ -> collectibles/)
    • Note that Collectibles are still referred to with names. The names match the file collectibles/<name>.json.
      • This will be changed at some point.
  • Added a few new collectible effect types:
    • "setScoreMultiplier" - Multiplies all earned score by a given multiplier.
      • Contains the following fields:
        • multiplier - The score multiplier to be applied.
        • time - The duration of the effect, in seconds.
      • The score multipliers do not stack, and one overwrites another no matter whether it's higher or lower than the previous one.
    • "homingBugs" - Makes all shot spheres gravitate towards the largest sphere group of matching color.
      • Contains one field:
        • time - The duration of the effect, in seconds.
    • "executeGameEvent" - Executes a Game Event.
      • Contains one field:
        • gameEvent - The Game Event to be executed.
  • For the "changeGameSpeed" collectible effect type, the duration field has been renamed to time for consistency with other collectible effect types.
  • The count field in "multiSphere" and "lightningStorm" collectible effect types can be now an Expression.

Changes in Collectible Generator data: config/collectible_generators/*.json -> collectible_generators/*.json

  • The collectible generators are no longer stored in the config/collectible_generators folder, but rather directly in the collectible_generators directory instead.
  • The conditions field no longer accepts objects as list indices.
    • Instead, it accepts a list of Expressions, which must evaluate to booleans.
    • Each Expression in this list has a generator context, which contains the following field:
      • latestCheckpoint - The ID of the latest checkpoint achieved by the player. In vanilla Luxor games, this is equivalent to the current stage number.
  • In the collectibleGenerator type, the field name has been renamed to generator and now accepts a full Collectible Generator reference path instead.

Changes in Sphere Effect data: config/sphere_effects/*.json -> sphere_effects/*.json

  • The Sphere Effects are no longer stored in the config/sphere_effects folder, but rather directly in the sphere_effects directory instead.
    • All references to Sphere Eff 8FE0 ects in Level and Sphere data must be now full paths, starting from the root game directory.
  • Added two new optional fields: eventsBefore and eventsAfter.
    • Both of them are lists of Game Events which will be executed respectively before and after the Sound Events, Score Events and Collectible Generators assigned to that Sphere Effect are evaluated.
  • The destroyCollectible field now requires a full Collectible Generator path, instead of the file name.
  • The destroySound and destroyScoreEvent fields are now optional.

Changes in Level Set data: config/level_set.json

  • The fields checkpoints and startCheckpoints have been removed.
  • Instead, a new optional checkpoint field can be put into any time of a Level Entry, with the following fields:
    • id - The ID of the checkpoint that should be placed at that level entry.
    • unlockedOnStart - Optional. If set, this checkpoint will be automatically unlocked when a new profile is created.
  • Added a new entry type: "uiScript".
    • Calls a UI Script callback.
    • Has the following fields:
      • callback - The name of the UI Script callback to be executed without any parameters.
      • name - The entry name.

Changes in Sphere data: config/spheres/sphere_X.json

  • Changes in the sphere shoot behaviors:
    • For the "normal" shoot behavior type, two new optional fields have been added:
      • amount - The amount of spheres that will be launched from this sphere in the shooter.
      • spreadAngle - The total frustum angle of spheres, in radians.
  • Changes in the sphere hit behaviors:
    • Added two new hit behavior types:
      • "splitAndPushBack" - Divides the sphere group in front of the hit sphere and applies negative speed to the back part of it.
        • Contains a single parameter:
          • speed - The knockback speed, in pixels per second.
          • pierce - Optional. If set, the sphere will carry on and will not be destroyed.
      • "applyEffect" - Applies a Sphere Effect on the selected spheres and destroys the shot sphere.
        • Has the following fields:
          • selector - The Sphere Selector which will select the Spheres to apply the effect to.
          • effect - The Sphere Effect to be applied to all selected Spheres.
          • pierce - Optional. If set, the sphere will carry on and will not be destroyed.
    • For all sphere hit behavior types, besides "normal", a new optional field has been added:
      • pierce - If set, the shot sphere will not be destroyed and will carry on until it flies off the board.
    • For the "recolorSpheres" hit behavior type, the color field can be now an Expression.
  • The destroyCollectible field now requires a full Collectible Generator path, instead of the file name.
  • All references to Sphere Effects must be now full paths, starting from the root game directory.
  • The hitSoundBad field has been removed.
    • Instead, the hitSound sound event is now always used whenever the Sphere is attached to the spheres already in play.
    • To preserve the behavior, the sound event referred to in the hitSound field must have two entries, using a new Expression Context Variable shot.bad as its condition.
    • Example:
      {
          "$schema": "../../../schemas/sound_event.json",
          "sounds": [
              {
                  "sound": "sounds/collide_spheres_shot.ogg",
                  "conditions": [
                      "${![shot.bad]}"
                  ]
              },
              {
                  "sound": "sounds/collide_spheres_shot_bad.ogg",
                  "conditions": [
                      "${[shot.bad]}"
                  ]
              }
          ]
      }

Changes in Shooter data: config/shooters/*.json

  • A new field has been added: spheres.
    • It is a list of primary spheres that should be present in the shooter.
    • Each entry has the following fields:
      • pos - The position of the primary sphere.
      • shotPos - Optional. If defined, this is the position to which the sphere will be warped to when it's shot.
  • The ballPos field has been removed.
  • Added a new optional section: knockback.
    • It contains four fields:
      • duration - The duration of the knockback animation.
      • strength - How many pixels will the shooter traverse in the peak of the animation.
      • speedShotDuration - Optional. If set, this will be the animation duration while the Speed Shot powerup is active.
      • speedShotStrength - Optional. If set, this will be the animation strength while the Speed Shot powerup is active.

Example configuration for a Double Shooter:

"spheres": [
    {
        "pos": {
            "x": -20,
            "y": 5
        },
        "shotPos": {
            "x": 0,
            "y": 10
        }
    },
    {
        "pos": {
            "x": 20,
            "y": 5
        },
        "shotPos": {
            "x": 0,
            "y": -10
        }
    }
]

For a single shooter:

"spheres": [
    {
        "pos": {
            "x": 0,
            "y": 5
        }
    }
]

Changes in Color Generator data: config/color_generators/*.json

  • A new type of a color generator has been added: "giveUp".
    • This generator type will lock the shooter making it unable to discard any spheres and will draw a random color.
      • Apart from required colors and fallback fields, contains an optional boolean field:
        • spawnableColorsOnly - If set, only the colors which can appear on any of the paths specified in the current level will be able to be generated.
  • The colorsRemoveIfNonexistent field has been renamed to discardableColors.

Changes in Path Entity data: path_entities/*.json

  • The collectibleGenerator field now requires a full Collectible Generator path, instead of the file name.

Changes in Sprite data: sprites/*.json

  • The path field has been renamed to image for consistency with other resources.

Changes in Font data: fonts/*.json

  • Added a new optional field for the "image" type:
    • newlineAdjustment - Defaults to 0. Adjusts the spacing between lines in a multiline text.

Changes in Expressions: (anywhere where supported)

  • Added the following contexts:
    • color
      • Exists when a level is being played.
      • It has numeric fields: for example [color.1], [color.2], [color.-1] and so on for every registered sphere type.
        • They contain the amount of spheres of respective color on the board.
      • It has also a special field: [color.mostFrequent].
        • Each game tick, it is set to the sphere color which currently is the most abundant on the board.
        • Scarabs are excluded.
        • In case of a tie, the color will be randomly selected between the tied colors every game tick.
    • redirectedHitSphere
      • Will appear in Sphere Selectors referenced in the hitBehavior field of Spheres.
      • Is the same as hitSphere unless hitSphere is a scarab. In that case, redirectedHitSphere will contain the first sphere in front of the scarab.
  • Expressions are now more strictly checked for ${<expression>} syntax, which means that $expr{<expression>} and {<expression>} syntaxes are now removed.
  • All sphere contexts now have the following fields:
    • sphere.object - The object, used for comparisons.
    • sphere.color - The color ID of this sphere.
    • sphere.isOffscreen - Whether the sphere is offscreen.
  • For the Sphere Selectors, the following fields have been introduced to the Score Event referenced in the scoreEventPerSphere field:
    • sphere.distance - The distance between the selector's position and the sphere's position.
    • sphere.distanceX - Same as above, but only the X axis counts.
  • The Collectible Generator for a single sphere retains this field:
    • sphere.crushed - Whether the broken sphere has been a scarab that's been destroyed in a chain merger.
  • The Level Variables are available whenever a Level is currently being played:
    • level.<variable> - Returns the current value of the specified Level Variable.

Changes in UI Script and UI Data: ui/script.lua, ui/*.json

  • The UI2 system has been removed.
    • It was not being updated or used, and also SkilletUI is in the works. Check the commit e9c76b9 for more information.
  • The _NumStr and _BzLerp functions have been moved:
    • _NumStr -> _Utils.formatNumber
    • _BzLerp -> _Utils.bzLerp
    • You need to update these references in your UI script.
  • Changes in UI Script API:
    • The musicVolume function now takes an additional argument: duration.
      • In order to preserve the previous behavior, it must be set to 1 in the script.
      • Examples:
        • f.musicVolume("path/to/music_track.json", 1) -> f.musicVolume("path/to/music_track.json", 1, 1)
        • f.musicVolume("path/to/music_track.json", 0) -> f.musicVolume("path/to/music_track.json", 0, 1)
    • New functions have been added:
      • musicStop(music_track) - Stops the given music track. Use this instead of musicVolume(<music>, -1).
        • It has a single argument: duration - The fade time in seconds.
      • playSound(sound) - Plays a specified sound event.
      • levelRestartMusic() - Restarts the level music from the beginning.
      • levelContinue() - Triggers the next level sequence step, but only when the level is currently waiting for that to happen.
    • The levelBegin() and levelBeginLoad() functions have been removed.
      • In order to preserve the current behavior, you need to add the following entry to the level sequence, as the first entry (and move pointers to other entries appropriately):
      {
          "type": "uiCallback",
          "callback": "levelStart",
          "waitUntilFinished": true,
          "muteMusic": true
      }
      and in the UI script change:
      • f.levelBegin() to f.levelRestartMusic(); f.levelContinue(),
      • f.levelBeginLoad() to f.levelRestartMusic().
  • A new UI callback has been added: scoreAdded.
    • This callback is executed every time some score is added.
    • It has one parameter: [1] - the score that has been added.
  • Added a new UI Node function: resetHideDelay().
    • Used to reset the hide delay of the Node.
  • Two new identifiers have been added for scheduled UI actions:
    • "hideStart" - Executed when a scheduled (and only scheduled!) UI node starts to fade out.
    • "showStart" - Executed when a scheduled (and only scheduled!) UI node starts to fade in.
  • The spriteButton, spriteButtonCheckbox and spriteButtonSlider have three new optional fields:
    • clickSound - A Sound Event which will be played instead of the default click sound specified in gameplay.json if specified.
    • releaseSound - Ditto, but for button release.
    • hoverSound - Ditto, but for hover.

Gameplay

  • The game frames are now rendered on a canvas. When scaled to the window size, that canvas is then resized instead of game elements (sprites, fonts, etc.) themselves. This makes the display much more crisp and eliminates all bleeding coming from fractional scaling.
  • The particle effects now look much more closer to the original game!
  • Slightly changed the sphere physics when the reverse powerup is active, but it is not completely in parity with the original game yet.
  • Now you can hear the Speed Shot effect when releasing the sound effect slider in the options menu, just like in the original game.
  • The game now runs in 120 ticks per second instead of 60 in order to reduce jittering when dipping just below 60 frames per second.
  • All games will now start with their windows maximized. This is because their native resolution could exceed the screen size, which resulted in an overgrown window showing up. You can disable this behavior in the Boot Screen Settings.

Boot Screen, Debug and Console

  • Hiding incompatible games now works properly.
  • Fixed the page count and buttons still displaying when there is only one page of the game list.
  • Added an Edit Game button!
    • Right now, it doesn't do much. The only thing you can do there is previewing the sprites of the game.
    • When you select a sprite, it will show up, and a list of states and frames of that sprite will appear at the bottom.
    • The sprite can be zoomed in with a scroll wheel, but it cannot be panned yet.
    • At some point, this feature will be expanded!
  • Changes in the Console:
    • Tab auto-completion, albeit half-baked, is now technically there! It will currently only suggest the commands, and not the parameters, except for the new collectible command.
    • Added a new collectible command.
      • It's meant to spawn a Collectible on the screen, but this currently doesn't work.
      • The command completion works, though!
    • Commands which didn't work have been removed.
    • The up and down arrows now repeat if held. Useful for scrolling through the console history!
    • Empty input is no longer acceptable.
    • The command history will no longer have duplicate entries when executing the same command a few times.
  • Changes in the Crash Screen:
    • The error information no longer goes past the right side of the screen and wraps around properly.
    • The version number is now shown.
    • Changed the list of crash messages when using the crash command.
  • In the F4 debug menu, a new counter called Vec2PerFrame has been added.
    • This counter counts the total amount of Vector2 objects created every single frame.
    • As Vector2's are tables, creating many tables in such a short timespan can cause big performance drops. That's why the amount of them being created should be lowered as much as possible.

Bugfixes

  • [#131] Fixed a rare crash when merging spheres past the exit point.
  • Fixed crashes when opening various debug menus in certain situations.
  • Fixed a crash when loading a sphere with a sphere effect that doesn't have any particle effect assigned to it.
  • Fixed a softlock when exiting the game right before the level complete dialog.
  • Fixed the progress bar (and all objectives) resetting after starting the level's sequence, and not immediately after taking a life.
  • Long matches were partially broken.
  • WAV and MP3 files are now properly detected as sound files.
  • Fixed the particles lingering when the level with spheres using them is loaded.
  • If the level was failed while the warmup loop was still playing, the warmup sound will no longer keep playing forever.
  • Errors in Expression compilation no longer produce incorrect error information.
  • Fixed Path Entities not instantly following the volume changes. (50f4226)
  • Spheres no longer abruptly change their rolling animation frame after unpausing when the level is loaded.
  • Fixed Rich Presence saying Lives: nil when playing a game with a life config type set to "none".

And finally, a lot of strictly technical changes such as Documentation Generator or documentation fixes and changes which do not affect the game by themselves.

0