Releases: jakubg1/OpenSMCE
Beta 4.8.0
Hello! We're back with another update. This is a big one, as it brings official Luxor: Amun Rising support to the engine! Keep in mind however, that mods for this game aren't supported - only the original game. Don't worry, support for mods will come at some point!
You might have noticed that the releases are getting rarer and rarer. This is unfortunately true, but each release comes packed with more and more features! And this release is no exception - it is the biggest release yet when it comes to added features!
As always, the full list of changes can be found here.
Thank you @bchantech for a few contributions!
Happy matching!
Changelog
Game Support
- The Luxor: Amun Rising support is here!
- The game converter will detect Luxor Amun Rising automatically and will convert the game properly.
Game Development
The Resource Manager has been overhauled, and as such the way resources are loaded has changed. Instead of having to be in a specific folder, the resources now need to have an appropriate extension or, if it's a JSON file, a JSON schema assigned to it.
The resources contained in the root game folder, as well as in config
and maps
subfolders, are not loaded.
This also means that all resources must be now referred to with a full path, starting from the game's root directory. However, assets can be now placed inside maps, which use the special syntax:
map:asset/to/load.json
If you're editing a configuration file inside of a map and want to access a resource in that same map, you can omit the map name:
:asset/to/load.json
You can find out more information about the new syntax here.
- Changes in game data:
- The files
config/loadlist.json
andconfig/music.json
have been removed. - The
modules
folder has been removed. - Added Color Palettes!
- They were in the game already, but did not have any configuration files assigned to it and needed to be explicitly mentioned in the
config/loadlist.json
file. - They are located in
color_palettes/*.json
by default (notconfig/color_palettes/*.json
!). - Color Palettes, to be registered by the game, need their
$schema
field to end withschemas/color_palette.json
. - The data contains only one field:
image
- The image to be used as a color palette.
- All references to Color Palettes as images must now reference color palettes' configuration files instead. This includes particles and spheres.
- They were in the game already, but did not have any configuration files assigned to it and needed to be explicitly mentioned in the
- Added Music Tracks!
- Similarly to Color Palettes, they were in the game already, but they were all specified in a single file -
config/music.json
. - They are located in
music_tracks/*.json
by default (notconfig/music_tracks/*.json
!). - Music Tracks, to be registered by the game, need their
$schema
field to end withschemas/music_track.json
. - The data is an object with just one field:
audio
- The audio file to be used for this music track.
- You are now supposed to put full paths to the music tracks in order to access them.
- Example:
f.musicVolume("menu", 1)
->f.musicVolume("music_tracks/menu.json", 1)
- Example:
- Similarly to Color Palettes, they were in the game already, but they were all specified in a single file -
- Added Score Events!
- Score Events are objects which contain data about how many points should be given and how this information should be displayed for the user.
- Score Events are stored by default in
score_events/*.json
, notconfig/score_events/*.json
! - Score Events, to be registered by the game, need their
$schema
field to end withschemas/score_event.json
. - They have five fields:
score
- The amount of points to be given with this Score Event. Can be an Expression.ignoreDifficultyMultiplier
(optional) - If set, the score calculated by this Event will not be mutliplied by the current difficulty's score multiplier.text
(optional) - The text which should be displayed instead of the raw score value. Can be an Expression.font
(optional) - The font to be used for the FloatingText. If not specified, no FloatingText will appear.fonts
(optional) - A form used when the Score Event can produce texts with multiple different fonts.- It contains three required fields:
options
- A list of Fonts to choose from.default
- The fallback font if the choice does not pick any of the options.choice
- An integer expression which evaluates to a number. That number is the item index from theoptions
list, starting from 1. If an invalid index is returned, the font specified in thedefault
field is used.
- It contains three required fields:
- Added Path Entities!
- Path Entities are used as a universal superclass for data-driven entities like Bonus Scarabs, Scorpions, Path Introductions, Pyramid Blockers, Black Holes and more.
- They are located in
path_entities/*.json
by default (notconfig/path_entities/*.json
!). - They have A LOT of fields:
sprite
(Sprite) - The sprite to be used by the path entity.shadowSprite
(Sprite) - The shadow sprite to be used by the path entity.spawnPlacement
(string) - Where the path entity will be spawned at, or in relation to that place."start"
- The path entity will be spawned at the beginning of the path, and will move forwards along the path."end"
- The path entity will be spawned at the end of the path, and will move backwards along the path."furthestSpheres"
- The path entity will be spawned at the furthermost sphere on the path. The entity will move forwards along the path.
spawnOffset
(number) - If set, the initial location of the path entity will be moved by this amount in pixels, in the movement direction dictated by thespawnPlacement
field.speed
(number) [>=0] - The starting speed of this path entity, in pixels per second.acceleration
(number) [>=0] - The acceleration of this path entity, in pixels per second squared.maxSpeed
(number) [>=0] - The maximum speed of this path entity, in pixels per second.maxOffset
(number) [>=0] - The maximum distance from the initial location of the path entity, in pixels.destroyOffset
(number) - The offset from either of the path ends this path entity is going towards, when this entity will be destroyed. Defaults to0
.destroyTime
(number) [>0] - If set, this path entity will be destroyed after this many seconds of existence.destroyWhenPathEmpty
(boolean) - If set, this path entity will be destroyed if there are no spheres on that path.destroyAtClearOffset
(boolean) - If set, this path entity will be destroyed once it reaches the path's clear offset (i.e. Bonus Scarabs).particle
(Particle) - The one-time particle that this path entity will be spawning every set amount of pixels.particleSeparation
(number) [>0] - The distance between each particle, in pixels.renderParticlesInTunnels
(boolean) - If set, the trail produced by the entity will be seen over the tunnels.loopSound
(SoundEvent) - A looping sound event which will be played during the path entity's existence. (path_entity)collectibleGenerator
(CollectibleGenerator) - A collectible generator which will periodically generate collectibles from this path entity. (path_entity)collectibleGeneratorSeparation
(number) [>0] - The distance between each collectible generator activation, in pixels.destroyParticle
(Particle) - The one-time particle that this path entity will spawn upon destruction/despawning.destroySound
(SoundEvent) - A sound event which will be played when this path entity is destroyed. (path_entity)destroyScoreEvent
(ScoreEvent) - The score event which will be executed when this path entity is destroyed. (path_entity)destroyCollectibleGenerator
(CollectibleGenerator) - The collectible generator which will generate collectibles when this path entity is destroyed. (path_entity)canDestroySpheres
(boolean) - If set, this path entity will destroy all spheres which are further than this path entity's position.sphereDestroySound
(SoundEvent) - A sound event which will be played when this path entity destroys a sphere. (path_entity, sphere)sphereDestroyScoreEvent
(ScoreEvent) - A score event which will be executed when this path entity destroys a sphere. (path_entity, sphere)maxSpheresDestroyed
(integer) [>0] - If set, this path entity will be destroyed after destroying this amount of spheres.maxSphereChainsDestroyed
(integer) [>0] - If set, this path entity will be destroyed after destroying this amount of sphere chains (scarabs).- All besides
spawnPlacement
andspeed
are optional.
- Added Sphere Selectors!
- They're used to... select spheres. They can be destroyed or their color can be changed.
- They are located in
sphere_selectors/*.json
by default (notconfig/sphere_selectors/*.json
!). - They have one field:
operations
- A list of operations performed in sequence in order to form a list of spheres. Each item is an array, which contains the following fields:type
- A type of an operation. The only currently supported type is"add"
.condition
- A boolean expression evaluated for each sphere on the board. If the expression evaluates totrue
, the sphere is added to the list.- The expression has the
sphere
context, which is a different context than in Path Entities... It contains the following variables:distance
- Only Sphere Selectors which are not referenced from Collectible Effects have this variable. The distance from the se...
- The expression has the
- The files
Beta 4.7.2
Hello! After six months, it's time for another update! This time around, we've focused on even more parity changes with Luxor 1. This includes tweaks to sphere and powerup physics, sphere reload animation, sphere rolling sound, and a few other minor improvements!
We didn't forget about other features, such as path introduction, custom sphere sizes, smooth color change for reticals or experimental Z-axis support for paths!
As always, the full list of changes can be found here.
Thank you @bchantech for two contributions!
Changelog
Game development
-
Changes in
gameplay.json
:- Three new fields have been added to the
sphereBehavior
section:attractionForwardDecceleration
- Used when the sphere group is magnetizing, but moving forward at the same time.attractionForwardDeccelerationScarab
- As above, but only when magnetizing to a scarab.backwardsDecceleration
- How fast the spheres slow down while moving backwards.
- In the
scorpion
section, two new optional fields have been added:offset
- The starting offset of the Scorpion, counting from the end of the path, in pixels.acceleration
- How fast does the Scorpion accelerate per second.
- A new optional section has been added:
pathIntroduction
.- Inside, four required fields are located:
particle
- A one-time particle packet which spawns throughout the path.speed
- How fast does the trail go, in pixels per second.separation
- The distance between each particle, in pixels.separatePaths
- If set, each path will be introduced immediately after the previous one finishes. Otherwise, all paths will be introduced simultaneously.
- Inside, four required fields are located:
- The
collectibleBehavior
section has been removed.- The data inside has been moved to the collectible configs themselves.
- Three new fields have been added to the
-
Changes in sphere data:
- A few new fields have been added:
size
- The sphere diameter in pixels. Defaults to32
.- The sprite will be resized accordingly based on the size.
shadowOffset
- The shadow sprite offset, in pixels. Defaults to(4, 4)
, like it was before.
- A few new fields have been added:
-
Changes in map data:
- Added a new optional field to path node:
scale
.- The sphere size on that node will be multiplied by this value.
- This feature is not fully supported yet, and is filled with bugs - use at your own risk!
- Added a new optional field to path node:
-
Changes in level data:
- Added two optional fields:
warmupLoopSound
- A looping sound effect which is playing at the beginning of the level, while the spheres are rolling.failLoopSound
- A looping sound event which is playing while the spheres are rolling into the exit node.
- Added two optional fields:
-
Changes in collectible data:
- Added two new required fields:
speed
- The starting speed of this Collectible. It's a Vec2 expression, like beforehand.acceleration
- The acceleration of this Collectible. It's a Vec2 expression, like beforehand.
- Added two new required fields:
-
Changes in shooter data:
- A few new fields have been added, all optional:
hitboxOffset
- Defaults to(0, 0)
. It changes the relative position of the shooter's hitbox.shotCooldownFade
- The duration of the fade in animation. During this time, you still can't shoot the sphere.destroySphereOnFail
- If set, the sphere held by the shooter will show its destroy particles if the level is lost.
- In the
reticle
section, two new optional fields have been added:colorFadeTime
- The time which the reticle should take to fade into the new color, in seconds.nextColorFadeTime
- The time which the reticle's next color indicator should take to fade into the new color, in seconds.
- A few new fields have been added, all optional:
-
Changes in color generator data:
- The
near_end
type has been renamed tonearEnd
. - The following fields have been renamed:
has_to_exist
->hasToExist
select_chance
->selectChance
paths_in_danger_only
->pathsInDangerOnly
colors_remove_if_nonexistent
->colorsRemoveIfNonexistent
- The
colorsRemoveIfNonexistent
field is now optional.
- The
-
Changes in Expressions:
- A few new functions have been added:
sin(theta)
- Returns the sine of the given angle, in radians.cos(theta)
- Returns the cosine of the given angle, in radians.tan(theta)
- Returns the tangent of the given angle, in radians.max(a, b)
- Returns the bigger value ofa
andb
.min(a, b)
- Returns the lower value ofa
andb
.clamp(a, b, c)
- Returnsa
clamped to the minimum ofb
and the maximum ofc
.
- A few new functions have been added:
General
- The game will now load resources in 1/20-second intervals, loading as much resources as it can in every such interval. This further improves game loading times.
- Discord Rich Presence will now detect whether the user's username has been migrated and will not show a
#0
discriminator in that case. - The Luxor Game Converter script is now available for Linux users - thank you @lottieratworld for converting the script!
Gameplay
- The default sphere rolling speed is now
2/pi
, as it should have been the whole time. - The sphere appending animation has been once again tweaked, and it's now even smoother than before.
- The sphere's shadow now rotates alongside the sphere itself.
- The aiming reticle no longer disappears when the shooter is reloading.
- The F7 debug menu has got a few additions:
- A few helper lines are drawn when a sphere is being appended to a sphere group.
- The shooter's hitbox will be shown.
- Sphere Group origins will be marked as white dots.
- Vanilla Luxor gameplay:
- A few parity changes have been implemented, such as adjusted sphere speeds, powerup speeds and accelerations, new sphere reloading animation, sphere breaking animation when the level is lost, and sphere rolling sounds. The fireball has been nerfed.
Boot Screen
- A new text appears when there are no games installed:
Luxor_appendix
no longer appears as a pre-installed game - it's not a full game!
Game Documentation
Important changes have happened since last release, which are intended to make the config structure updates easier:
- The game documentation has got a new set of colors which includes a dark background, so it's kind of a dark mode.
- The source of all game documentation will be a set of DocLang (
*.docl
) files, located in the/doc/game/data
folder.- Right now, only JSON schemas are built from these files. This will extend to HTML documentation and config classes, hopefully in the next update.
- The HTML documentation files have been moved to
/doc/game/out
. They are also outdated, as there's currently no way to generate them.
Bugfixes
- [#113] Fixed a bug where clicking a button and moving the cursor away would still perform the click actions.
- Performing a version check could result in a crash due to the POST request function sometimes returning extra garbage before and after the desired contents. This doesn't matter at all since this feature is still disabled.
- The game would crash when starting a new level while the F7 debug menu was turned on.
- Turning Ultimately Satisfying Mode on or off via profile change would need a game restart in order to apply these changes.
A new sphere train could spawn when all objectives were reached right after clearing the board.(This bug is actually NOT fixed!)
Beta 4.7.1
Time for Beta 4.7.1. Not so much added considering how much time has passed.
This will be the last version for a long while: I've made the decision to feature freeze this project until all of the following are fully done:
- Code documentation
- Game documentation (including schemas for ALL files)
- Config classes (for ALL .json files)
- Incorporation of expressions everywhere when possible (particles, powerup generators, etc.)
After the above things are done, betas will resume starting from 4.8.0 and will focus on adding new features which are required to bump to Beta 5.0.0.
As always, the full list of changes can be found here. Thank you @ShamblesSM for a few contributions!
Happy matching!
Changelog
Game development
UI2
- An unfinished UI2 is available in this version.
- No documentation yet, but schemas are available.
- You can switch between UI1 (the current UI system) and UI2 with a new parameter in the main game config file, as shown right below.
Changes in game config:
- A new field,
useUI2
has been added.- If set to
true
, the game will use UI2 instead of legacy UI. - UI2 files are located in
ui2
folder, the legacy UI files can still be loaded fromui
.
- If set to
- In the
richPresence
section, a new field has been added:applicationID
.- This field is optional. If specified, this will be the application ID shown when the player is playing that game, instead of a default OpenSMCE application.
Changes in shooter data:
- A new field has been added,
ballPos
.- The primary ball position. Use
{x = 0, y = 5}
to retain the current behavior.
- The primary ball position. Use
Changes in expression format:
- Added support for multi-parameter functions.
- Expression evaluation now uses an indexed table, instead of a string of
if
statements. This makes it go faster. - Added new functions:
vec2(a, b)
returns aVec2
object. You can perform arithmetics on them as on numbers, except modulo and power.randomf(a, b)
returns a random floating point value from range[a, b)
.
Changes in gameplay.json
:
-
The field
collectibleBehaviour
has been renamed tocollectibleBehavior
. -
Inside this section, the
speed
andaccelerations
fields are now of an experimental Expression type.- This Expression must evaluate into a particular type, in this case
Vec2
. - Because there is a fixed number of types in JSON, Expressions are strings with a special formatting:
"$expr{expression}"
. - Example:
$expr{vec2(randomf(-100, 100), randomf(-250, -150))}
.
- This Expression must evaluate into a particular type, in this case
-
Added a new section, called
net
.- It's required only when you have Nets in your game.
- The section contains two fields:
"particle"
- A persistent particle packet which will be spawned and destroyed when the net appears and disappears, accordingly."posY"
- The Y position of the Net, in pixels.- Both fields must exist.
-
You can no longer create malicious UI scripts which could do potentially harmful actions, like deleting files from any place on your computer.
General
- The log file will now be saved when the engine crashes. This means it will include the crash message, too.
- It is now possible to bypass the Boot Screen and launch straight into a game of your choice.
- To accomplish this, create an
autoload.txt
file with the name of the game. That game will be automatically loaded on engine startup.
- To accomplish this, create an
- The
settings.json
file has been moved out of theengine
folder and is now located in the root directory.- The
engine
folder has been removed.
- The
- When loading the game, the game will no longer crash when it tries to load level files with wrongly formatted names.
- The Unifont font has been moved to the
assets
folder. - A new font has been added: DejaVu Sans.
- This font is now used in the Boot Screen instead.
- This is because the upcoming 12.0 version of LOVE2D changes its default font, which breaks the Boot Screen.
Gameplay
- The spheres will now be shot when no UI button is pressed, instead of the mouse cursor being at y<560.
- Changes to F4 debug screen:
- Colors which are not present on a board will now be hidden in the Color Manager section.
- The level section will now properly show objectives, instead of a broken progress display.
Boot Screen
- The build number is no longer shown in Boot Screen or in Discord Rich Presence.
- Instead, a version status message will pop up. (inactive in this version)
- Overhauled the settings screen:
- Now it's more consistent with the main boot screen.
- The checkboxes have been simplified to colored rectangles and are now arranged similarly to games in the game list.
- Added tooltips which describe the option which the mouse is currently hovering.
Bugfixes
- The native resolution now works properly during gameplay, when resizing the window, going back to Boot Screen and is no longer hardcoded.
- Spheres broken by Scorpions no longer count twice in the progress bar.
- Fixed Nets not saving when saving a level.
- The danger color counter could glitch out after using a Color Cloud or a Color Replacer.
- Fixed a bug which caused to improperly load assets when at least one of the resource types in the Load List was empty.
- Fixed Expressions failing to tokenize when they contain a
false
keyword.
Beta 4.7.0
New year, new update! And this time it's a big, biiig, BIIIIIG update! Beta 4.7.0 adds a ton of new features!
Shoutout to @Makowo for his first contribution!
As always, the full list of changes can be found here.
Happy matching!
Changelog
Game development
Changes in shooter data:
- Zuma Shooter: A new mandatory field has been added:
movement
.- There are two types of shooter movement, in the
type
field inside:"linear"
is the Luxor-styled shooter movement. The shooter will move on a line along X axis. Additional fields include:xMin
- The minimum X position of the shooter.xMax
- The maximum X position of the shooter.y
- The constant Y position of the shooter.angle
The constant rotation angle of the shooter, in degrees.0
means up.- All fields are mandatory numbers.
"circular"
is Zuma-styled shooter movement behavior. The shooter is locked in one place, but is able to rotate in any direction. Additional fields include:x
- The X position of the shooter.y
- The Y position of the shooter.- Again, both should be numbers.
- There are two types of shooter movement, in the
- Better Shooter appearance customization: New fields were added, so the appearance of the shooter is much less hardocded.
spriteOffset
({"x":0,"y":0}
) - The offset of the main shooter sprite.spriteAnchor
({"x":0.5,"y":0}
) - The anchor point of the main shooter sprite.shadowSpriteOffset
({"x":8,"y":8}
) - The offset of the shooter shadow sprite.shadowSpriteAnchor
({"x":0.5,"y":0}
) - The anchor point of the shooter shadow sprite.nextBallOffset
({"x":0,"y":21}
) - The offset of the next ball indicator sprite.nextBallAnchor
({"x":0.5,"y":0}
) - The anchor point of the next ball indicator sprite.sounds
- A table with two fields:sphereSwap
("sound_events/shooter_swap.json"
) - The sound event played when two spheres are swapped with each other.sphereFill
("sound_events/shooter_fill.json"
) - The sound event played when the shooter gets new spheres.
- All of these fields are required; in order to retain the current behavior, use values in brackets.
- Two new fields have been added:
shotCooldown
- The cooldown between shots.multishot
- If set, there can be more than one Shot Sphere on the board.nextBallSprites
- Contains next ball sprites for all possible sphere colors, keyed by their ID.- Each such object has the following fields:
sprite
- The path to the next color sprite for that shooter when that's the current next color.spriteAnimationSpeed
- The speed of the next sprite animation, in frames per second. Optional; by default it will not be animated.
- Each such object has the following fields:
Changes in level data:
- Different shooter positions per level: A new optional field has been added,
shooter
.- It contains two fields:
name
- The name of the shooter, defined inconfig/shooters/*.json
. Defaults to"default"
.movement
- Shooter movement data. The structure is exactly the same as in the shooter data (look above).- If not specified, defaults to the movement specified in the shooter data itself.
- It contains two fields:
- Different/multiple objectives per level: Added a new field,
objectives
.- It's a list of objectives which can be defined for each level.
- Each objective has two fields:
type
- Can have the following values:"destroyedSpheres"
- if the target describes how many spheres have to be removed from the board,"timeElapsed"
- if the target describes how many seconds the level has to be survived for,"score"
- if the target describes how much score in that level needs to be gained.
target
- The amount of spheres/seconds/points needed at minimum to consider the target reached.
- The field
target
has been removed.
Changes to sphere data:
- A new field has been added:
destroySound
.- It is a sound which only works when a sphere of that type is crushed (i.e. a scarab).
- This is a temporary solution; once more robust sound events are introduced, the crush check will be done in the sound event file instead.
- A new optional field has been added:
spriteRollingSpeed
.- When defined, the sphere sprite will roll with that speed in frames per pixel. Defaults to 1.
- The fields
nextSprite
andnextSpriteAnimationSpeed
have been removed.- Define next color sprites in the shooter instead. See above for description.
Changes in sphere effect data:
- Added a new field,
ghostTime
.- If set, the spheres will turn into ghosts for a set amount of time when destroyed using this effect.
- More about ghost spheres in this commit's description.
- If set, the spheres will turn into ghosts for a set amount of time when destroyed using this effect.
- A number of fields have been renamed, as follows:
infection_size
->infectionSize
infection_time
->infectionTime
apply_sound
->applySound
destroy_sound
->destroySound
destroy_font
->destroyFont
destroy_particle
->destroyParticle
destroy_collectible
->destroyCollectible
level_loss_protection
->levelLossProtection
can_boost_combo
->canBoostCombo
can_boost_chain
->canBoostChain
apply_chain_multiplier
->applyChainMultiplier
can_keep_combo
->canKeepCombo
cause_check
->causeCheck
Changes to gameplay.json
:
- In the
sphereBehaviour
section, six new fields have been added:joinSound
- A sound event to be played when two groups of spheres hit each other.newGroupSound
- A sound event to be played when a new sphere chain appears on the board.noScarabs
- If set totrue
, there will be no scarabs at the end of the sphere chains.knockbackTime
- Optional. If set, this will be the time during which the spheres' knockback speed will be "locked" and will not decrease over time.knockbackStopAfterTime
- Optional. If set totrue
, after theknockbackTime
elapses, the spheres will stop abruptly rather than slowly deccelerating.permitLongMatches
- Iftrue
, the spheres will try to make the biggest clump possible before matching together.
- The
invincible_scarabs
field has been renamed toinvincibleScarabs
.
Changes in expression format:
- The parser has been completely rewritten, however all existing expressions should work as before.
- String support has been added!
- New operators have been added:
a^b
raisesa
to the power ofb
.a..b
concatenates any two values together. If they are not strings, they are converted to them.
Changes in UI script:
- Added four new functions:
levelGetObjectives()
- Returns a list of objectives the current level has. Each objective has four fields:type
(string) - the same as in the level data itself.target
(number) - The target value of the objective, specified in the level data.progress
(number) - The current value of the objective.reached
(boolean) - Whether this objective has been reached (progress >= target
).
levelGetNewRecord()
- Returnstrue
if the currently played level for the current profile has yielded the most score in this level's history.levelGetCombo()
- Returns the current level combo.loadingGetProgress()
- Returns a percentage of loaded assets during the game loading.
- Two new callback functions have been added:
init
- Is executed at the very initialization of the splash.- Example contents (which makes it work like before):
function c.init(f) f.getWidgetN("splash"):show() f.getWidgetN("splash"):setActive() f.musicVolume("menu", 1) end
click
- Fired when the player clicks anywhere on the screen.- Has no parameters, so it's only usable in "click anywhere to continue" prompts.
- The
levelComplete
callback no longer conveys a boolean parameter which said whether the player has earned the new high score for this level.- Use the newly introduced
levelGetNewRecord
function instead.
- Use the newly introduced
- Added an optional integer parameter to the
levelGetProgress
function.- If supplied, the game will return the progress of
n
-th target defined in the level. - By default, the function will return the progress of the first target.
- If supplied, the game will return the progress of
- Removed the hardcoded progress bar update and the button appearing.
- Add the following code instead, to the
tick
callback:
-- update splash screen local splash = f.getWidgetN("splash") if splash then local progress = f.loadingGetProgress() f.getWidgetN("splash/Frame/Progress").widget.valueData = progress if progress == 1 then f.getWidgetN("splash/Frame/Button_Play"):show() end end
- Add the following code instead, to the
Changes in config.json
:
- Some fields have been renamed, as follows:
window_title
->windowTitle
engine_version
->engineVersion
native_resolution
->nativeResolution
rich_presence
->richPresence
Changes in config/highscores.json
:
- The
default_scores
field has been renamed todefaultScores
.
Changes in collectible generator data:
- A few types have been renamed.
collectible_generator
->collectibleGenerator
random_pick
->randomPick
color_present
->colorPresent
cmp_latest_checkpoint
->cmpLatestCheckpoint
Changes in level_set.json
:
- The
level_order
field has been renamed tolevelOrder
. - The level entry type
no_repeat
has been renamed tonoRepeat
. - The level entry field
unlock_checkpoints_on_beat
has been renamed tounlockCheckpointsOnBeat
Gameplay
- 3D sound is now working much better: the balance is no longe...
Beta 4.6.1
Hello there, it's time for Beta 4.6.1! This is the last version of this engine this year. I hope the next year will bring even more exciting features! To wrap up this one though, we are introducing a bunch of changes largely regarding the shooter, and an important bugfix.
Before we start out, shoutout to @Shambles_SM for a meaningful contribution to this release (reticle sprites)!
As always, the full list of changes can be found here.
Happy matching!
Changelog
Game development
In the config
directory of a game, a new folder called shooters
has been created.
For now, the only shooter possible is hardcoded to default
, hence the shooter's settings are now stored in shooters/default.json
.
The up-to-date schema is available. Note that the documentation is NOT updated.
Changes in shooter data:
- Added new fields:
sprite
(string) andshadowSprite
(string) allow for change of the appearance of the shooter.speedShotBeam.sprite
(string) - A sprite file to be used to draw the speed shot beam.hitboxSize
(Vector2) - The size of the Shooter's hitbox in pixels.
- The
shotSpeed
field has been renamed toshootSpeed
. - Speed shot data has been serialized to separate objects.
- The renames are as follows:
speedShotBeamRenderingType
->speedShotBeam.renderingType
speedShotBeamFadeTime
->speedShotBeam.fadeTime
speedShotBeamColored
->speedShotBeam.colored
- Note that the
speedShotParticle
is not migrated and remains a separate field in the main object.
- A new section,
reticle
, has been added. It contains the following fields (all of them are optional):sprite
(string) - The reticle sprite. If not defined, the old line-based reticle will be displayed instead.offset
(Vector2) - The offset of the reticle sprite.nextBallSprite
(string) - The sprite of a reticle's next sphere indicator. If omitted, it will not be displayed.nextBallOffset
(Vector2) - You probably get it by analogy.radiusSprite
(string) - The sprite of a circle indicator used when aiming with a range sphere, such as a fireball or a color cloud.
- The renames are as follows:
Changes in config/gameplay.json
:
- In the
sphereBehavior
section, a new field, calledluxorized
has been added.- If set to
true
, the engine will enable a few changes to the sphere physics. - For now, these are only related to knockback.
- The chain combo is preserved as long as any sphere is rolling back, not only when the spheres are magnetizing.
- Chaining spheres now cancel momentum for the frontmost part.
- If set to
- In the
bonusScarab
section, three new fields have been added.shadowSprite
is a sprite which should be used to draw the Bonus Scarab's shadow.loopSound
is a path to a sound event which should be played in a loop.destroySound
is a sound event which will be played when the Bonus Scarab is destroyed.
- In the
scorpion
section, five new fields have been added.shadowSprite
,loopSound
anddestroySound
- as above.sphereDestroySound
is a sound which should be played when the Scorpion destroys a sphere.destroyGenerator
is now properly documented. It did exist before.- Additionally, a hardcoded check which dictated whether the collectibles would spawn has been removed.
- The
shooter
section has been migrated to shooter data and is removed from here.
Changes in sphere data:
- The field
destroy_collectible
has been renamed todestroyCollectible
.
Changes in collectible effect data:
-
A new effect type,
activateNet
has been added.- It contains one parameter,
time
, which is the duration of the net. - Currently, the net has no graphical representation. This will be added at some point.
- The net Y position is hardcoded to 550.
- It contains one parameter,
-
Changes in level data:
- An optional field,
ambientMusicName
has been added.- Defines the name of music which is played all the time during this level.
- This does not interfere with normal level music.
- An optional field,
-
Changes to expression format:
- A negation operator has been added.
- The syntax is as follows:
!<thing to negate>
- For example,
!true
will returnfalse
.
- Note this is a binary operator; use with numbers may produce undefined results or crash the game.
- The syntax is as follows:
- Added conditional variables.
- Format:
[varname|expr]
- Loads a variable named
varname
, but when it doesn't exist,expr
is substituted instead.expr
can be any Expression, but it may not contain[]|
characters.
- Format:
- A negation operator has been added.
-
Now during a sphere destruction, a
crushed
variable will be set to a boolean value indicating whether this was a scarab which has been crushed. -
The
exprt
command in debug console now prints its debug value in Reverse Polish Notation (the way they are stored).
Gameplay
- A bunch of changes regarding sphere physics has been made, to bring it even closer to the original Luxor feeling.
- You can turn them off by setting
"luxorized": true
to"luxorized": false
ingames/Luxor/config/gameplay.json
. - Let me know if you like the changes!
- You can turn them off by setting
- Luxor 2-like collectible changes have been reverted.
Boot Screen
- There's now a build number in the corner, used for debugging purposes.
Code
- Quite a big portion of code documentation has been added. If you've checked out directly from GitHub, you may notice it's already been there for a long time. But oh well, this is the first release since that change, so I'm including this in the changelog as well!
- Additionally, a Visual Studio Code snippet has been created to ease class creation.
- The keyword is
!class
.
- The keyword is
- The converter is nearly ready to be included into a separate repository. Stay tuned!
Bugfixes
- [#79] TTF fonts did not work in fused/compiled mode. That is, when not running the code itself. If you don't understand, they just did not work at all for you.
- Fixed
level nil
in Rich Presence and the game crashing when trying to store you on a leaderboard. - Ultimately Satisfying Mode now works again. Yay....
- Fixed scarabs dropping gems even when crushed :D
Beta 4.6.0
Today we are releasing Beta 4.6.0. This version adds JSON schemas, stone spheres and a few lesser changes of mostly technical nature.
As always, the full list of changes can be found here.
Changelog
Game development
-
JSON schemas have been introduced.
- They are helper files for Visual Studio users in order to standardize JSON files made by potential modders.
- Currently only a few files are supported, let's hope it won't take forever to introduce this to other files.
- You can try them out, the appropriate schemas (if they exist) are linked in i.e.
config/gameplay.json
.
-
Expressions have been added!
- They can be created from a string which is just... well, an expression.
- For example:
2+2
evaluates to4
and-(8/0.5)+3
evaluates to-13
.
- For example:
- Expressions support numbers and booleans only (for now, that is). The operations that can be performed on them are as follows:
- Arithmetic:
a+b
,a-b
,a*b
,a/b
,a%b
- Comparison:
a==b
,a!=b
,a>b
,a<b
,a>=b
,a<=b
- Boolean logic:
a||b
,a&&b
- Unary minus:
-a
- Parenthesis: e.g.
(a+b)/c
- Ternary
if
:(a?b:c)
- Functions:
floor(a), ceil(a), round(a), random()
- Access to contextual variables:
[<name>]
- Arithmetic:
- You can test the expressions yourself by entering a command
expr <expression>
in the console. - Later on, along with parameters, expressions will be a key part in doing advanced maths within the configuration files.
- A few events which happen in the game already have some parameters.
- Sphere destruction sets four expression variables:
length
- How many spheres have been destroyed.comboLv
- The level combo level at the moment of sphere destruction.chainLv
- The chain combo level at the moment of sphere destruction.comboBoost
- A boolean. Iftrue
, the player has committed to the destruction by shooting a sphere.
- Both sphere destruction and bonus scarab explosion:
offset
- A distance from the beginning of the path, in pixels.offsetE
- As above, but counted from the end of the path.distance
- A percentage of the path counted from the beginning.
- Sphere destruction sets four expression variables:
- They can be created from a string which is just... well, an expression.
-
Changes in sphere data:
- Added a new field,
nextSpriteAnimationSpeed
.- If set, deternimes the speed of the next sprite animation, in frames per second.
- Added a new optional field,
destroy_collectible
.- When a sphere is destroyed, it will spawn collectibles from that generator, if provided.
- Scarabs use this. Note: crushed scarabs also spawn collectibles. This will be fixed later.
- Added a new field:
type
.- Possible values:
"normal"
,"stone"
.- If
"stone"
, the sphere is a stone sphere.- Stone spheres are spheres which are destroyed upon a neighboring match.
- If
- Possible values:
- Added a new field,
-
Changes in collectible generator data:
- Added a new entry type,
"combine"
.- Evaluates a list of given entries and returns a list of all collectibles generated.
- Syntax in the documentation.
- Added a new entry type,
-
Changes in sphere effect data:
- The fields
can_spawn_coin
andcan_spawn_powerup
have been removed. - Added a new optional field:
destroy_collectible
, which is a collectible generator used when the spheres under that effect are destroyed. - Added a new field:
cause_check
.- When set to
true
, two groups of spheres of the same sphere effect which happen to collide will behave as one, ignoring the "cause" sphere.
- When set to
- The fields
-
Changes in game module:
- The
coinSpawn()
andpowerupSpawn()
methods are no longer used. - Soon, the whole game module system will be removed entirely.
- The
-
Changes in level data:
- The fields
powerupGenerator
andgemGenerator
have been removed.
- The fields
-
Changes in color generator data:
- The
fallback
field can now contain another color generator data. This allows for nesting.
- The
Gameplay
- Changes from the previous release have been reverted.
- Frozen groups will no longer magnetize.
- "Daisy-chained" sphere chains will now stop if the frontmost one has some immobile spheres.
- When two sphere groups join, now both of them have their fragile spheres destroyed.
- During game loading, sounds will now load much faster.
Code
- Sphere Entities now move smoothly between shot spheres and spheres.
- Simplified algorithm for Sphere Chain collision calculation.
- Sphere debug screen (F6) now displays the distance between sphere chains.
Bugfixes
- Buttons on 2nd and further pages in the Boot Screen game list were not highlighted properly.
- Color counters now work properly for non-positive sphere IDs.
- The sphere chains would overlap if invincible scarabs were turned on and the frontmost chain was frozen.
That's it for now. Happy matching!
Beta 4.5.0
It's time for another big release: Beta 4.5.0, which introduces a lot of changes, mostly regarding spheres.
As always, the full list of changes can be found here.
Changelog
Game development
-
Changes in level effects:
- The level effects:
"slow"
,"stop"
and"reverse"
have been removed. - A new level effect has been added,
"speedOverride"
.- It contains the following fields:
speedBase
- A value to be added to the current path speed.speedMultiplier
- A value which the current path speed will be multiplied with.decceleration
(optional) - A different sphere decceleration value to be applied.time
- How long the effect will be.
- Speed overrides do not stack. If one is applied, it overwrites the current one, if exists.
- It contains the following fields:
- A new effect type has been added,
"setCombo"
.- It has one parameter,
combo
. - When executed, the level combo counter is set to the
combo
value.
- It has one parameter,
- The level effects:
-
Changes to
config/gameplay.json
:- In the
gameplay
section:- The fields
slowDecceleration
,slowSpeedMultiplier
andreverseSpeed
have been removed.- Use these values as parameters for the speed override effects instead.
- Added a new field:
invincible_scarabs
.- It's a boolean value. If set to
true
, scarabs cannot be crushed by spheres behind them.- Such daisy-chained trains may behave slightly differently than normal trains, especially in terms of movement.
- It's a boolean value. If set to
- The fields
- In the
bonusScarab
section, new fields,coinGenerator
anddestroyGenerator
have been added.- The first one is spawned periodically depending on
coinDistance
, the second one is spawned when the Bonus Scarab explodes.
- The first one is spawned periodically depending on
- In the
scorpion
section, added a new field:destroyGenerator
.- It is spawned when the Scorpion gets destroyed, but with a hardcoded check, which will be rectified in the future.
- In the
-
Added a new folder:
config/sphere_effects
.- It contains sphere effects, a name of each is their file name.
- Each sphere effect contains the following fields:
particle
(optional) - A persistent particle packet to be assigned to a sphere when under such effect.time
- The duration of the effect, in seconds. Starts counting down when the infection size equals to 0.infection_size
- An initial infection size of this effect.infection_time
- Every how long the sphere under that effect will afflict its neighbors, in seconds.apply_sound
(optional) - A sound event to be launched when a sphere gets the effect.destroy_sound
- A sound event to be played when spheres under that effect are destroyed.- If set to
"hardcoded"
, the match will use a hardcoded collapse sound.
- If set to
destroy_font
- A font used for the score.- If set to
"hardcoded"
, the font used will be picked from amatchFont
field of a corresponding "cause" sphere.
- If set to
level_loss_protection
- If set totrue
, sphere groups which contain spheres under such effect will not cause a level loss if reached the end point.immobile
- If set totrue
, sphere groups which contain such spheres will be unable to move.fragile
- If set totrue
, spheres with that effect upon impact with a shot sphere will be destroyed.destroy_particle
- A one-time packet which is launched when a sphere under that effect is destroyed.can_boost_combo
- Whether a combo counter should be incremented if other conditions are passed.can_boost_chain
- Similar one for chain combo counter.apply_chain_multiplier
- If true, the score will be multiplied by the current chain combo value.can_spawn_coin
- If true, a level-defined collectible generator will be used.can_spawn_powerup
- If true, a level-defined collectible generator will be used.can_keep_combo
- If set totrue
, any shot spheres which have this effect will prevent the combo value from dropping to 0.
- A single sphere cannot have two same effects applied at the same time, but it can have any number of different effects applied at the same time.
- Sphere effects allow powerups like Poison and Freeze to be created.
-
Added a new folder:
config/color_generators
.- It contains shooter color generators. Each generator is one file, and the generator name is the same as the file name.
- Each generator has these fields:
type
- a type of the generator. For now, these types are supported:"random"
- Returns a random color from the list."near_end"
- Selects a random path and selects a color from the group which is the closest to the end point.
colors
- A pool of colors to be generated.fallback
- When the algorithm does not find any spheres or fails, this value is returned instead,colors_remove_if_nonexistent
- If a sphere of a color which is in this list is in the shooter and does not exist on the board, it gets removed.
- The
"random"
type has additionally this field:has_to_exist
- if set totrue
, a color will not appear if it is not already on the board.
- The
"near_end"
type has additionally these fields:select_chance
- A percentage value which determines how likely is the sphere to be picked. If it is not, then a second closest sphere is picked, and so on.paths_in_danger_only
- If set totrue
, paths which are not in danger are not taken into account.- When there are no paths in danger, the algorithm will still try to pick any non-empty path first before giving up.
-
The files
config/collectibles.json
andconfig/spheres.json
have been split intocollectibles
andspheres
folders there, respectively.- Now every collectible/sphere is a single JSON file.
- A name for a collectible file is
X.json
, where X is the collectible name. - A name for a sphere file is
sphere_X.json
, where X is the sphere ID.- The sphere ID still must be an integer number.
- A name for a collectible file is
- The data for both spheres and collectibles remain largely unchanged, however there are new fields described below.
- Now every collectible/sphere is a single JSON file.
-
Changes in UI script:
- Added a new UI callback:
comboEnded
with two parameters:- 1: The combo multiplier.
- 2: The total score from combo.
This can be handled by UI script for example to show big combos.
- Added a new UI callback:
-
Changes in sphere data:
- From the
"lightning"
sphere shoot behavior type, a fieldresetCombo
has been removed. - Instead, a new field has been added to the root sphere data,
shootEffects
. It's optional.- It's a list of effects to be executed when the sphere is launched, similarly to Collectibles.
- The field
generatable
has been removed. - A new optional field,
effects
, has been added into thehitBehavior
object of type"default"
.- It's a list of names of effects to be applied to the shot sphere.
- From the
-
Changes in level data:
- Two new fields have been added,
colorGeneratorNormal
andcolorGeneratorDanger
.- These are the names for a shooter color generator used during normal gameplay and during danger, respectively.
- Added a new field:
matchEffect
.- It's a match effect ID which is going to be used when spheres are matched.
- Two new fields have been added,
-
Changes in font data:
- Added a new field,
type
.- Can have two values:
"image"
- in that case, the rest of the fields stay the same."truetype"
- in that case, the following fields are applicable:path
- A path to the font file. Use afont_files
folder in the root game folder.size
- A size of the font.color
- A font color.
- Example:
{ "type": "truetype", "path": "font_files/unifont.ttf", "size": 36, "color": { "r": 0.95, "g": 0.8, "b": 0 } }
- Can have two values:
- Added a new field,
-
Ordinary color matches/chains now, instead of destroying spheres immediately, apply a sphere effect.
-
Files with extensions other than
.json
will now be ignored in any subfolders located inconfig
. This makes .DS_Store files to be ignored, and therefore saves a crash.
Gameplay
These are temporary changes and will be reverted in the next release.
- Bonus Scarabs drop coins and gems, similarly to Luxor 2.
- After every combo, a score value will appear in the console on the screen.
Code
- Spheres now use sphere entities for rendering.
- This is an internal change; no files are changed.
- JSON parser error now shows the file name. This allows for quicker bug-hunting.
- Rearranged how the colors in the Color Manager are stored.
- Added
_MathIsValueInTable(t, v)
.
Boot Screen
- If the game count exceeds 8, excess games are now put on the next pages instead of overflowing the list.
Bugfixes
- Code: Fixed a bug in
_GetDirListing()
where the extension filter did not work.
That's it for now. Happy matching!
Beta 4.4.0
Time for Beta 4.4.0! It introduces a few changes, mostly regarding collectibles. Enjoy!
As always, the full list of changes can be found here.
Changelog
Game development
-
The
config/powerups.json
file has been renamed toconfig/collectibles.json
. -
A few changes inside that file have been made as well:
- Some new fields have been added:
pickupParticle
- A one-time particle packet which is launched when that collectible is collected.spawnSound
- A sound effect launched when the collectible is spawned.dropEffects
(optional) - A list of effects to be executed when a powerup falls off the board without the player catching it.
- The fields
pickupName
andpickupFont
are now optional. If not set, no label will spawn upon picking that collectible up. - The field
effects
is now also optional.
- Some new fields have been added:
-
A few new level effects have been added:
grantScore
- Adds score to the player. It has one field,score
- an integer value determining how much score to add.grantCoin
- Grants a coin to the player.incrementGemStat
- Adds 1 to the gem stats for the current level.
-
Level format changes:
- A new field,
gemGenerator
, has been added. It contains a reference to the collectible generator which is now used to spawn gems. - The
gems
field has been removed.
- A new field,
-
Collectible generator changes:
- The collectible generators data structure has been completely revamped.
- Each collectible generator is an entry of a certain type.
- Every collectible generator entry evaluates to a list of collectibles.
- That means each generator now returns a list of collectibles, and not either one or nil.
- There are four types of entries, for now:
"collectible"
- Has one field,
name
. - Always evaluates to a single collectible.
- Has one field,
"collectible_generator"
- Has one field, which is also called
name
. - Evaluates to a given collectible generator result.
- Has one field, which is also called
"repeat"
- Has two fields:
entry
andcount
. - Evaluates an
entry
count
times, and returns a list of all collectibles evaluated from each iteration.
- Has two fields:
"random_pick"
- Has a single field:
pool
. It's a list of entries, which have anentry
field and an optionalweight
field, which defaults to 1. - Evaluates all choices from the
pool
, and then picks one randomly.- Empty choices are ignored.
- The choice weights can be modified by giving an appropriate weight value.
- Has a single field:
- A new condition type has been added:
cmp_latest_checkpoint
.- Compares the current player's latest checkpoint value.
- There are three optional fields for this condition:
min
,max
andvalue
. - If the value is greater than
min
, lower thanmax
or not equal to thevalue
, this condition does not pass. - If either of the fields is missing, the corresponding check is not performed.
- Examples:
- This condition will pass if the value is between 1 and 3, both inclusive:
{ "type": "cmp_latest_checkpoint", "min": 1, "max": 3 }
- This condition will pass if the latest checkpoint value is equal to 5:
{ "type": "cmp_latest_checkpoint", "value": 5 }
- This condition will pass if the value is between 1 and 3, both inclusive:
- The collectible generators data structure has been completely revamped.
-
config/gameplay.json
changes:- The field
sphereBehaviour.attractionSpeed
has been split intoattractionSpeedMult
andattractionSpeedBase
.- The old formula for the maximum magnetization speed was
attractionSpeed * max(combo, 1)
. - The new formula is now
attractionSpeedBase + attractionSpeedMult * max(combo, 1)
. - In order to retain current behavior, set
attractionSpeedBase
to0
and renameattractionSpeed
toattractionSpeedMult
.
- The old formula for the maximum magnetization speed was
- The field
-
config.json
changes:- The file now looks like this:
{ "name": "Luxor", "window_title": null, "engine_version": "v0.40.0", "native_resolution": { "x": 800, "y": 600 }, "rich_presence": { "enabled": false } }
- Fields:
name
(optional): The game name to be displayed in Rich Presence and in the game window.window_title
(optional): How the window should be named.engine_version
: Specifies the version a game is for. Not really used at the moment, but mandatory.native_resolution
: The native resolution of the game. Same as above.rich_presence
: An object which contains the following field:enabled
: Should be alwaystrue
, unless you want the game to be a secret.- Loading a game with this flag set to
false
causes Rich Presence to disconnect.
- Loading a game with this flag set to
-
Powerups, both internally and in
runtime.json
, are now stored simply by their names instead of an object withtype
,name
andcolor
fields. -
Bonus scarabs, scorpions and large matches now use the, for now hardcoded,
vanilla_coin.json
collectible generator. -
The level now waits for all collectibles to despawn before firing the level win callback.
Gameplay
- The default coin drop rate has been changed to match the original Luxor game:
# of spheres Old New 3 0% 0% 4 20% 0% 5 40% 50% 6 60% 75% 7 80% 100% 8 or more 100% 100%
- You can still change it manually in modules/game.lua.
Boot Screen
- You can now cancel edits to the settings.
- The version label in the settings is now aligned correctly.
- Fixed a few grammar errors in the outdated game message.
Converter
- The Python conversion script should now work with Mac OS systems.
- The
convert.bat
script will now show an appropriate message when the Python script fails, and will revert all changes if the user chooses to do so. - Converted levels should now land in the correct directory once again.
Bugfixes
- Apparently none!
Beta 4.3.0
After a pretty long time period, it's finally here! Beta 4.3.0 adds a lot of interesting features and fixes some bugs.
As always, the full list of changes can be found here.
Changelog
Outline
- Added Zuma sphere generation!
- Added different parameters for each path in a single level!
- Added Bezier speed transitions!
- Added level order randomizers!
- Added emergency save!
- Added speed shot particles!
- Fixed speed shot beam!
- Changed crash screen!
- Increased stability!
Additions
Game development
Level files
-
Zuma sphere generation!
- A new field, named
spawnRules
has been added. It's an object with the following fields:type
- it can be either"waves"
or"continuous"
. If set to"waves"
, sphere trains will spawn as usual. If set to"continuous"
, there will be only one sphere train per path which would continuously spawn spheres until the win condition is met, like in Zuma.amount
- Required only for"waves"
type. Specifies the amount of spheres to be generated per wave.
- The field
spawnAmount
has been removed.
- A new field, named
-
Per-path level settings!
- A new field,
pathsBehavior
, has been added. - It's a list of objects containing these fields:
colors
,colorStreak
,spawnRules
,spawnDistance
,dangerDistance
,dangerParticle
,speeds
. - The above fields have been also removed from the root object.
- The
pathsBehavior
list can contain any number of these path behavior objects. - Each path is assigned the next path behavior on the list, and the list can wrap around.
- This means you can have one path behavior table and it will be applied to all paths on a map.
- A new field,
-
Smooth speed interpolation!
- In a speed node definition, a new optional field,
transition
, has been added. - It contains an object with a
type
field, which can be set to either"linear"
or"bezier"
. - If set to
"bezier"
, two more fields are required,point1
andpoint2
. These fields define the control points for Bezier interpolation between speeds. - Interpolation between speeds is set in the first node, so it applies between that and the next node.
- In a speed node definition, a new optional field,
-
Additionally, the
name
field has been removed. -
An example showcasing all the changes:
-- "name": "1-1", -- "colors": [1, 2, 3, 4], -- "colorStreak": 0.45, -- "spawnAmount": 30, -- "spawnDistance": 0.6, -- "dangerDistance": 0.75, -- "speeds": [ ... ] ++ "pathsBehavior": [ ++ { ++ "colors": [1, 2, 3, 4], ++ "colorStreak": 0.45, ++ "spawnRules": { ++ "type": "waves", ++ "amount": 30 ++ }, ++ "spawnDistance": 0.6, ++ "dangerDistance": 0.75, ++ "speeds": [ ++ { ++ "distance": 0, ++ "speed": 800, ++ "transition": { ++ "type": "bezier", ++ "point1": 0.9, ++ "point2": 0.9 ++ } ++ }, ++ ... ++ ] ++ }, ++ ... ++ ]
Level sets
- The
levels
folder has been moved toconfig/levels
. - All levels now must have an ID which can be any integer number. It doesn't have to be continuous, too.
- Levels inside the
levels
folder must match the patternlevel_X.json
, where X is the level ID. - The journey-level naming of levels has been scrapped. Once again, now levels are defined by only one number.
- The
config/level_set.json
file has a new syntax. The root objects has three fields:level_order
is a list containing level entries. Levels will be played in this order. More about these later.checkpoints
is a list of integers, containing index numbers corresponding to level IDs in thelevel_order
field.startCheckpoints
is, as before, a list of integers, which are the indices for thecheckpoints
list.- Example:
{ "level_order": [ { "type": "level", "level": 101, "name": "1-1" }, { "type": "level", "level": 102, "name": "1-2" }, { "type": "level", "level": 103, "name": "1-3", "unlock_checkpoints_on_beat": [ 2 ] }, ... { "type": "level", "level": 403, "name": "4-3" } ], "checkpoints": [ 1, 4, 7, 10 ], "startCheckpoints": [ 1 ] }
- Level data, which stores things such as win/lose counts or level records, now is stored per level ID in each profile.
- Level entries are objects which define what levels to load and play throughout the game. It consists of the following fields:
type
: The entry type. Can have either of these values:"level"
- in this case, this entry is a single level, and the following fields must be set:level
: A level ID to be loaded.name
: A level name.
"randomizer"
- in this case, this entry contains a group of levels, played in a random order. The following fields are required:pool
: A list of level IDs to be choosen from.names
: A list of level names. The level names will not be shuffled, and this list should have the same length as thecount
field.count
: Defines how many levels to be picked from the pool.mode
: How the levels will be randomized. There are three possible values:"repeat"
- Every next level is simply drawn at random from the list."no_repeat"
- Same as above, but an entry is removed from the pool once it's been picked."order"
- Choosescount
entries from the pool, without changing their order.- Both
"no_repeat"
and"order"
modes need the pool size to be greater or equal to thecount
.
- The randomizer works dynamically, which means only the next level at the time is generated at maximum. The whole sequence is not known nor stored anywhere, so you can't peek it.
unlock_checkpoints_on_beat
: Applies for both entry types and is optional. A list of checkpoint IDs to be unlocked after this level entry has been beaten.- An example of a randomizer entry, which shuffles levels 201 through 205:
{ "type": "randomizer", "pool": [201, 202, 203, 204, 205], "names": ["2-1", "2-2", "2-3", "2-4", "2-5"], "count": 5, "mode": "no_repeat" }
Changes
Game development
- UI script changes:
- Removed functions:
profileGetNextLevelN()
profileGetJourney()
profileGetJourneyLevelCount(n)
configGetLevelData(n)
configGetJourneyName(n)
configGetLevelPath(p)
- Renamed functions:
configGetLevelData2(name)
->configGetLevelData(name)
configGetCheckpointData(n)
->configGetCheckpointID(n)
- Added functions:
profileGetLevelName()
- Returns the player's current level name.profileGetLatestCheckpoint()
- Returns the nearest passed checkpoint from current level number.profileIsCheckpointUpcoming()
- Returns true if the next level is going to have a checkpoint.configGetLevelID(n)
- Returns the n-th entry fromlevel_order
list in the level set.configGetLevelName(n)
- Returns the name of then
-th level entry in the level order. This does not work for randomizers!configGetCheckpointLevel(n)
- Returns the real level number then
-th checkpoint is pointing to, instead of the level order entry.
- Removed functions:
Gameplay
- Changes to Speed Shot:
- The speed shot beam animation is now always smooth. Previously the beam would rapidly appear or vanish most of the time.
- New keys in
config/gameplay.json
:shooter.speedShotBeamFadeTime
: The speed shot beam fade time.shooter.speedShotParticle
: Speed shot particles! They can be defined there. This field is optional, and should contain a path to a particle packet when defined.
Technical
- The engine is now once again based on the 11.3 version of LOVE2D.
- This is because of very unstable nature of 11.4, with strange glitches and memory leaks being common due to an unpolished LuaJIT 2.1 included in that version.
- This means that now, once again, the engine should be stable as much as it was before Beta 4.2.0.
- Now when trying to load a JSON file which does exist, but it does not contain a valid JSON structure, a proper error will be shown.
- Debug Screen rendering has been greatly optimized.
- Crash screen changes:
- Emergency Save is finally here!
- Fixed a few grammar mistakes in the upper text.
- Error info is now framed.
- Only left mouse button will now work.
- The buttons have been shrinked a bit.
- Added text below the buttons, which displays a description for the hovered item, and emergency save status.
Bugfixes
- Emergency Save now works properly! [#20]
- The converter no longer produces sprite files pointing to nonexistent images. This, in turn, would create errors in the console.
Enjoy!
Beta 4.2.2
Time for another beta version, this time Beta 4.2.2, with another pack of features and bugfixes.
As always, the full list of changes can be found here.
Changelog
Additions
Game development
- Added, changed and removed a few extra parameters to
config/gameplay.json
, insphereBehaviour
:- Added
attractionAcceleration
, which is an acceleration rate used during magnetizing two sphere groups together. It's optional. - The
foulAcceleration
field is now optional. - Added
knockbackSpeedBase
andknockbackSpeedMult
, which replacecollisionSpeed
.knockbackSpeedBase
: Speed induced when a group of spheres crashes into another sphere group behind it. This andknockbackSpeedMult
form a final value together using this expression:knockbackSpeedBase + max(1, chainLv) * knockbackSpeedMult
.- The previous formula used was
collisionSpeed * max(1, chainLv)
. This means, settingknockbackSpeedMult
tocollisionSpeed
andknockbackSpeedBase
to0
will yield the same behavior as before.
- Added
Rich Presence
- The OpenSMCE icon will now appear in Discord Rich Presence status!
Changes
Gameplay
- When launching a game for the first time, the default sound and music volumes have been reduced from 100% to 25% in order to save any headphone users from blowing their ears up.
Boot screen
- Changed the position of version label by just a few pixels, so it's now cent... Eh, why talking about that, no one would even notice...
Appearance
Bugfixes
- Now the engine does not crash when pressing any key in the Boot Screen.
- Crashing the engine deliberately in Boot Screen (who would even do that?!) would yield the same witty message each time. Every. Single. Time.
:)