Releases: jakubg1/OpenSMCE
Beta 4.10.0
As promised, today we're releasing Beta 4.10.0! This time we've got a lot of new powerups and changes to existing powerups in store, as well as Level Timers in a few variations and more!
Happy matching!
Changelog
Game Development
Changes in gameplay.json
:
- In the
sphereBehavior
section:- Added the following fields:
foulDestroySpheres
- Specifies how the spheres will be destroyed when the level is failed.- Contains a
type
field, which can be one of the following:"atEnd"
- The spheres are destroyed at the end of the path. This matches the current behavior."fromEnd"
- The spheres are destroyed starting at the frontmost one and going back the path, until all spheres are destroyed. Contains the following fields:delay
- The delay between losing and destroying the first sphere, in seconds.subsequentDelay
- The delay between destroying one sphere after another, in seconds.
- Contains a
cascadeScope
- Specifies the scope of cascade combos. Can be one of the following:"chain"
- Default. All Sphere Chains will count their own cascade combo values independently from each other."path"
- All Sphere Chains will count their cascade combo values in conjunction with each other on each path separately. This also matches the vanilla Luxor gameplay."level"
- The cascade combo value is globalized and is shared between all paths, sphere chains and sphere groups.
distanceEvents
- Optional. Specifies a list of Distance Events, which are Game Events that can trigger when any Sphere Group rolls past the specified point on its path.- Each Distance Event contains the following fields:
reference
- Specifies the reference point of the Sphere Group which will be compared with. Either of"front"
or"back"
.distance
- The Path distance (percentage from start) of the path to be compared to.forwards
- Optional. If set, the Game Event will be executed when the reference point rolls forwards past the set point.backwards
- Optional. If set, the Game Event will be executed when the reference point rolls backwards past the set point.event
- The Game Event which will be executed when all conditions of this Distance Event are satisfied. This can be only a path and cannot be inlined untilgameplay.json
is moved to Config Classes.
- Added a new optional section:
levelTimers
.- Defines Level Timers.
- The keys are the timer names, and the values are objects which define these timers.
- All level timers are reset when the level is restarted or has been finished.
- They have the following fields:
countDown
- Optional. If set, the timer will be counting down and will cap at 0. Otherwise, the timer will be counting up.value
- Optional, defaults to 0. The starting value of this timer, in seconds.
- Added a new optional section:
levelTimerSeries
.- Defines Level Timer Series. They can be helpful when tracking the frequency of events which happen over time, for example "make X cascades in Y seconds".
- As Level Variables and Level Timers, they are reset once the level is restarted or finished.
- The keys are the Timer Series' names.
- Each entry is an empty object.
- The
lightningStorm
section has been removed.
How to make Lightning Storms as of this version?
- Instead of the
lightningStorm
collectible effect type, useprojectileStorm
:
{
"type": "projectileStorm",
"projectile": "projectiles/lightning_storm.json",
"count": 10,
"delay": "${0.25 + random() * 0.1}"
}
You can reuse the delay
and cancelWhenNoSpheresToDestroy
fields here.
2. Configure the projectiles/lightning_storm.json
projectile as follows:
{
"$schema": "../../../schemas/projectile.json",
"speed": 0,
"sphereAlgorithm": "lightningStorm",
"destroyParticle": "particles/lightning_beam.json",
"destroySound": "sound_events/lightning_storm_destroy.json",
"destroySphereSelector": "sphere_selectors/dagger.json",
"destroyScoreEventPerSphere": "score_events/sphere.json"
}
Here, you can reuse the remaining fields from gameplay.json
:
particle
->destroyParticle
sound
->destroySound
scoreEvent
->destroyScoreEventPerSphere
- If you haven't already, set up the
sphere_selectors/dagger.json
sphere selector as follows:
{
"$schema": "../../../schemas/sphere_selector.json",
"operations": [
{
"type": "addOne",
"sphere": "${[redirectedHitSphere]}"
}
]
}
Changes in Level data: config/levels/level_X.json
- Added a new objective type:
"sphereChainsSpawned"
- How many sphere trains need to spawn in order to complete this objective.
- In the
trainRules
field:- In the
"waves"
type of level train rules, in thewaves
field, added a new element syntax:- Instead of
"AAABBBCCCAABBCC"
, you can now write"3*3:ABC,3*2:ABC"
and get for example:"AAABBAACCCAACCC"
"CCBBBAAABBBCCBB"
"BBAACCCAAACCAAA"
- This syntax is called a Train Preset Generator.
- It consists of any number of blocks, separated by commas:
x*y:ABC
, where:x
- The amount of groups like this in the train.y
- The size of the group.ABC
- Any number (excluding zero) of keys defined in thekey
field which the generator will evaluate to.
- The blocks are never going to generate with the same key next to each other.
- Not every key is guaranteed to show up.
- The preset generation can be tested with a new
train
command.
- Instead of
- For the
"random"
and"pattern"
types - directly inside the main field list, and for the"waves"
type - inside the key definition, added a new optional field:chainChances
- A list of percentage probabilities for each of the chain levels for any sphere of that key to spawn with.- If one chance is rolled, the subsequent do not roll. For example, for the
[0.25, 0.25]
value:- 25% of spheres will spawn with one chain layer,
- 18.75% (25% of the remaining 75%) of spheres will spawn with two chain layers,
- The remaining 56.25% of spheres will spawn with no chain layers.
- If one chance is rolled, the subsequent do not roll. For example, for the
- In the
- In path behavior:
- Added a new speed node transition type:
"instant"
.- Takes no parameters.
- This means that node's speed will apply all the way to the next node.
- Added new distance types:
offset
- The offset from the start of the path, in pixels.offsetFromEnd
- The offset from the end of the path, in pixels.
- Added a new speed node transition type:
Changes in Level Sequence data: level_sequences/*.json
- Added a new Level Sequence entry type:
"executeGameEvent"
.- Executes a Game Event.
- Contains the following field:
gameEvent
- The Game Event to be executed.
Changes in Collectible data: collectibles/*.json
- Added new Collectible Effect types:
"projectileStorm"
- Starts a storm of Projectiles.- Has the following fields:
projectile
- The path to the Projectile which will be spawned.count
- The amount of the Projectiles which should be spawned. Can be an Expression.delay
- The delay between projectile spawns. Can be an Expression.cancelWhenNoTargetsRemaining
- Optional. Iftrue
, if a strike is wasted, the entire storm is cancelled. Otherwise, the projectiles continue to spawn regardless.
- Has the following fields:
"collectibleRain"
- Starts a rain of Collectibles falling from the top of the screen.- Has the following fields:
collectibleGenerator
- The path to the Collectible Generator which will draw the Collectibles.count
- The amount of collectibles which will be spawned in total. Can be an Expression.delay
- The delay between powerup spawns. Can be an Expression.
- Has the following fields:
"colorSort"
- Starts a color sorting procedure for all Sphere Trains.- Has the following fields:
sortType
- One of the following:"instant"
- The colors will be sorted instantly."bubble"
- The colors will be sorted using the bubble sort.
delay
- The delay between consecutive sorting steps, in seconds.stopWhenTampered
- If set, the sorting process will be halted when the sphere train is tampered with. Doesn't work yet.
- Has the following fields:
- Changed some Collectible Effect types:
- For the
"multiSphere"
type:- The
count
field is now optional. - Added three new optional fields:
time
- The amount of time the multi-spheres will be available for, in seconds.removeWhenTimeOut
- If set, the multi-spheres will be removed from the shooter when the time expires.holdTimeRate
- How fast should the multi-sphere timer go when the left mouse button is held. Works best with spheres which have theautofire
property set totrue
.
- The
- For the
"removeMultiSphere"
type:- Added a new field:
removeSpheres
- If set, the multi-spheres will be removed from the shooter.
- Added a new field:
- For the
"destroySpheres"
type:- Added two new optional fields:
gameEvent
- A Game Event which will be executed when the spheres are destroyed.gameEventPerSphere
- A Game Event which will be executed once per destroyed sphere.
- Added two new optional fields:
- For the
- Renamed the
"setCombo"
collectible effect type to"setStreak"
.- Its parameter has been renamed from
combo
tostreak
.
- Its parameter has been renamed from
- The
lightningStorm
Collectible Effect type has been removed.
NEW! Projectile data: projectiles/*.json
- Projectiles are Meteor Storm-like entities, which target a particular sphere, spawn in a distance around it and strike, destroying spheres and executing a score event.
- They can be set up to spawn exactly on top of the targeted sphere and activate instantly, which is the new and only way Lightning Storms will work.
- Th...
Beta 4.9.0
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:
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
andbutonHoverSound
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.
- A new optional field has been added,
- In the
sphereBehavior
section:- Added three new optional fields:
invincibleScarabFrontMatters
- When theinvincibleScarabs
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
- Iftrue
, 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
andnoScarabs
fields are now optional.
- Added three new optional fields:
- In the
lightningStorm
section:- A new optional boolean field has been added:
cancelWhenNoSpheresToDestroy
- Iftrue
(default), the entire lightning storm batch will be cancelled if there are no spheres to strike. Iffalse
, only this particular strike will not happen and the storm will carry on.
- A new optional boolean field has been added:
- 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 atest
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
- Iftrue
, the sequence will wait until thelevelContinue
function is executed on the UI script side. Otherwise, the sequence will immediately move on to the next step.retriggerWhenLoaded
- Defaults totrue
. 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 tofalse
, 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
andspawnRules
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
andforceDifferentColor
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"
.
- It specifies the train length. If omitted, the spheres will spawn continuously, like with the
- 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 }
- Before:
- The
- 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
.
- This example will spawn trains with 30 spheres, and they will always spawn like this:
- 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
orkeys
- 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 thekey
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 ...
- This field unifies the
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 alr
10000
eady, 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 alr
10000
eady, 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
G 8000 ame 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
10000
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!