Make attacks faster than some games load! The Castagne Editor is easy to use when starting out, and unlocks incredible speed once you learn it!
Why limit yourself? Castagne’s flexibility allows you to use it for many action genres! Fighter, Platformer, Beat-them-Up? Go ahead! Want to add a dash of fighting to your TRPG? Use Castagne as a module!
Don’t just make a prototype, make a full game! Castagne has Rollback compatibility at a core level, and support for many game modes and quality of life features!
Castagne is Free and Open Source Software (MPL 2.0 Licence), meaning you will never get locked out. Your game will be your own and in your complete control.
Castagne isn’t a regular game engine: it’s a specialization of any engine. Written in Rust, it’s easy to hook it to general purpose engines like Godot and use the best tool for the job!
Castagne welcomes all. Precision design allows ways to edit code graphically, while still saving it in text for VCS. In a team? Easily define interfaces for your designers to adjust attacks. Experts and beginners alike are delighted.
Castagne’s design allows maximum flexibility within some key, tasteful constraints that allow performance and great tools. Make combo unit tests, analyze your data, and make the best game you can.
Come and talk with other developers and players, and maybe find your next project! Ask for help, give feedback, show your work? We’re currently on Discord!
![]()
Hey! Panthavma here, I'm Castagne's author! The Godot 3 version was a long prototype, and I'm finally making the complete vision of Castagne! I want to make something that is still useful in 10 years, and all those previous tests help do that. That's not to say the Godot 3 version is lacking: commercial games have already been released in it, you can try it out!
The Rust version of the engine is still a work in progress, which I'll release in beta when I'm proud of it and I'm confident it can handle current projects. You can follow development here or on any of my channels. Stay tuned!
Follow castagne's development!
Youtube - Mailing List - Discord - Twitter - Bluesky
2D Fighter / Airdasher
Website - Steam - Bluesky - Twitter - Forum
Complex machines fighting at high speed! Tame each mech’s unique weapons using simple inputs and become an ace pilot!
2D Tag Fighter
Magic and technology intertwine in dynamic teamfights! Level up and call upon your allies to decide the fate of the Ashen Island!
2.5D Tag Fighter / Airdasher
A fast-paced tag fighter with only one attack button! A Fabled curse has swept the world… ordinary teens have begun transforming into characters from their favorite classic stories. Put together explosive team combos at Parable Academy for Fabled Youths!
Platform Fighter
A fast-paced, free-flowing platform fighter with a Shibuya Punk and Y2K aesthetic!
This is a pure banger feature, one of the best usability improvements of the new Castagne. State Calls were a huge feature in the previous version, and you could use it to create behavior either by extending a state or through composition. Interally both were the same, but I added warnings and _Helper() to distinguish between the two. You could alter internal defines, but it was a bit janky.
First off, there’s a new syntax for state names, which immediately distinguishes between the two: StateName is a regular state, while StateName() is a helper state. Both can be called without issues by using !StateName (equivalent to Call(StateName) in the old version), that part doesn’t change. What is new is that you can now add parameters to that, which are treated as local variables! Here’s a long snippet showcasing the new abilities:
:HelperState(var X int(), var Y bool() = true):
# You have access to both X and Y here.
# A is a local variable that you can't set from the outside.
var A int() = 10
V Y:
Add(A, X)
!OtherHelper(A)
endif
:OtherHelper(var Z int = 5):
# This has only got access to Z, even when called from HelperState.
# These are copies, so even if called through !OtherHelper(X), it can't change X
# You can call parent with arguments too
!!(10)
:RegularState:
# You can specify parameters with or without defaults
!HelperState(5)
!HelperState(5, false)
# If there are no parameters, these are equivalent
!OtherHelper
!OtherHelper()
# Hooks also work! The parameter list will resolve when needed.
!SuperState?(10, true)
So now you’re either super hype or super confused. This is a core feature of the engine that allows many mechanics and tools to be made inside of CASP in an efficient manner. Let me illustrate the difference with the old Castagne with some examples:
!AirStep(5000) to make the behavior easily readable and contained!!OnLevelUp?. Compared to before, you don’t need to create the state immediately, it will only be used in the characters that want it.!IMPACT or !IMPACT(120) can now take care of everything!!TransitionIfHeld(M, 6, OverdriveMove) to automatically handle moving to OverdriveMove if M is held for the first 6 frames? Easy QoL on something that’s a bit too niche for the modules!FlagCarryover(F) for example, it’s just FlagNext(F) in an L branch. You could make functions like that for your own use in minutes! It’s not as optimized, but that’s easily done later, and you can get started with it faster.This is already super useful, but when you’ll combine it with the upcoming MechMods (!!? is specifically superb in this context, as it allows needed modularity) and Varspec (which can understand when it’s seen from a state call), it will be incredible. These three features are the ones that will bring the editor to a new level and I can’t wait for that!
Slight design musings to finish, since this post is already super long:
Transition(CoolState(500)) or something, but I think it would be a bit overkill in complexity and we can hold variables in memory for that. Maybe I could add a variable tag for that.var X int is valid. The variable tags are optional (the () in int(), which isn’t used for anything right now nor was it before, always a planned feature), and you don’t need to specify a default. In fact, some variable types don’t accept defaults, such as state or flag (semantic types in general), but you may use them in state calls.AttackParam internally. I don’t think this would be for the best however, as it would complexify the docs and make it more confusing to follow. Allowing the ! to become optional would fix that but introduce confusion instead. Making them as CASP functions would allow overriding module functions, which is another can of worms. I’m probably going to introduce module functions as macros to implement that.What’s next is a bit tricky to choose, but I think I’ll start working on the modules again. Logically, I won’t be actually able to implement the MechMods without having something to put in them! Varspec will probably be the very last core feature to be added, since it’s so dependant on the rest.
New feature alert! Whereas before you could only declare constants in your state, now you can declare variables!
These variables are only available for the state (or most likely, scope, due to how I’ve implemented it but I haven’t tested it at the moment), and get reset when going through it again. This means they are volatile: you can’t store state from one frame to another, and you also can’t reference them from the outside.
For the technical detail, it’s a per-entity memory stack that doesn’t get saved or rolled back. It has no upper limit, but it might need to reallocate. It starts at a reasonable size so it probably won’t come up unless you push it explicitely. Its volatility allows it to not bog down the implementation, as it gets “reset” every time you try to execute CASC code.
While it might not sound like a huge thing in the context of the previous versions, it actually enables a lot of future behavior. If you looked at the Base CASP I already used a proxy for them using the RegA/B/C/D variables you might have seen at times. They are usually used in intermediary computations. One such example that I’ll need to convert is F branches, which use it to handle modulos.
The main usefulness however is coming soon: using State Calls as functions, with their own local variables. Previous versions of this were limited and hard to parse, but this time it will be much clearer and integrated. Another benefit that is already in, is shorter compilation times: helpers don’t get compiled anymore so it removes like 80%+ of states. Unsure how needed that was since the compiler is in a compiled language now, but we’ll see when it gets to a higher level. This will be tricky to implement, but I’ve got a fairly clear idea of how I want to do it.
Incredible, but true! I’ve added structures to the compiler, the first of which is the humble Vector! It’s always a 3D vector, even in the 2D settings. You can use them either as a structure, or as individual components:
var V vec() = [0, 0, 0]
# As a component
Set(V.X, 5)
# As a structure
Add(V, [1, 2, 3])
At the moment, this is the extent of the system, but I’m planning on having 3 types of structures:
Vectors are meant to be used in many places in the engine, especially for anything involving Physics or Graphics. I’ve still got design concerns for the other two, namely if the Arrays should have a fixed length (most likely yes), and how Custom structures are meant to be used (just organisation is a bit weak, but I’m thinking it has great potential to replace Specblock structs). Please note that all structures are just in the compiler, and not an actual type in the runtime itself.
I’ve done a lot of design work for the next parts of the engine, as they link a lot with the upcoming systems for top-tier integration in the Castagne engine: Varspec, a second language in the engine for editors, and MechMods, a simple composable way to add mechanics and system mechanics to your game. Combined with the upcoming State Calls with parameters, this will enable tremendous flexibility. That and a basic implementation of Physics, Attacks, and Graphics is my current objective, as this is where I can start porting projects to it.
Also, the forum is almost ready. I’m still testing out the rollout and managed to put myself on a spamlist thanks to a technical error. I guess it happens lol.
All Progress Updates - RSS Feed
This list is not exhaustive, and can change often. It represents my global progress with this version, which will release in beta when it’s more complete.
Castagne Virtual Machine
Entity Lifecycle
Subentities
Inter-Entity Communication
Module Interface
Castagne Config
Profiling Framework
Memory Stack Rollback
Instanced Data
Castagne Compiler
Semantic Representation
Robust Compilation
Host-Engine Functions
Phases and Events
Basic Branches
Advanced Branches
Structured Variables
Varspec / Gizmo System
Skeleton and MechMod
Basic Structure
Game Streaming
Code Editor
Blocks Editor
Varspec / Gizmo Display
Castagne Config
Tools Framework
Tutorial System
Docs System
Basic Math
Vector Math
Trigonometry
Randomness
State Transitions
Flags
Log / Error
Freeze / Halt Phases
Targetting Functions
Input Layout System
Combination Inputs
State-Derived Inputs
Input Events and Buffer
Motion Inputs
Input Transition / Flag
Fake Press
Input from Config
Replay
Environement Collisions
Expanded Env. Colliders
Colbox Collision
Attack Collision
Expanded Attack Colliders
3D Physics
Battle Init Data Interface
Simple Fighter BID Interface
Simple Level BID Interface
Simple World BID Interface
Rounds and Reset
Custom Exit
Training Mode (basic)
Menus Specification
Host Engine Integration
Options Menu
Input Rebinding
Attack Data Storage
Attack Param Base
Attack Data Optimization
Attack Overrides
Attack Events
Blocking System
CASP Hitstun Management
Basic Attack MechMods
Combo-Awareness MechMods
Attack Cancel Rules
Fighter Flow MechMods
Attack Mechanics MechMods
Movement MechMods
Combo MechMods
Godot Integration
Sprite Sytem & Integration
Shader Modifications
Model Management
VFX System
Godot Integration
Audio Parameters
SFX Definition
SFX Parameters
Background Music Support
Dynamic Audio Support