Functions: Connecting to Game World
Functions are the bridge between Mortar and your game code. Through function declarations, you tell Mortar: “These features will be implemented by my game”.
Why Do We Need Function Declarations?
In Mortar scripts, you’ll call various functions:
text: "Boom!"
with events: [
0, play_sound("boom.wav")
2, shake_screen()
]
But where are these functions? They’re in your game code!
Function declarations are a “contract”:
- You tell Mortar: my game has these functions, what parameters they need, what they return
- Mortar checks types during compilation to ensure you use them correctly
- After compiling to JSON, your game implements these functions
Function Naming Conventions
⚠️ Important: We recommend using snake_case
✅ Recommended naming style:
fn play_sound(file_name: String) // snake_case: all lowercase, words separated by underscores
fn get_player_name() -> String // Clear and readable
fn check_inventory_space() -> Bool // Self-explanatory
fn calculate_damage(base: Number, modifier: Number) -> Number
⚠️ Not recommended naming styles:
fn playSound() { } // Avoid camelCase (that's other languages' style)
fn PlaySound() { } // Don't use PascalCase (that's for nodes)
fn play-sound() { } // Kebab-case not recommended
fn sonido_ñ() { } // Non-ASCII text not recommended
fn playsound() { } // All lowercase hard to read
Parameter naming conventions:
// ✅ Good parameter naming
fn move_to(x: Number, y: Number)
fn load_scene(scene_name: String, fade_time: Number)
// ❌ Bad parameter naming
fn move_to(a: Number, b: Number) // No semantics
fn load_scene(s: String, t: Number) // Unclear abbreviations
Naming suggestions:
- Use English words, all lowercase
- Multiple words separated by underscore
_ - Start with verb, describe function purpose:
get_,set_,check_,play_,show_ - Parameter names should be descriptive
- Keep naming style consistent within project
Basic Syntax
fn function_name(param: Type) -> ReturnType
No Parameters, No Return Value
fn shake_screen()
fn clear_text()
fn show_menu()
With Parameters, No Return Value
fn play_sound(file: String)
fn set_color(color: String)
fn move_character(x: Number, y: Number)
With Return Value
fn get_player_name() -> String
fn get_gold() -> Number
fn has_key() -> Bool
With Parameters and Return Value
fn calculate(a: Number, b: Number) -> Number
fn find_item(name: String) -> Bool
Supported Types
Mortar supports types from JSON:
| Type | Alias | Description | Example |
|---|---|---|---|
String | - | String | "Hello", "file.wav" |
Number | - | Number (integer or decimal) | 42, 3.14 |
Bool | Boolean | Boolean | true, false |
Note: Bool and Boolean are the same, use whichever you prefer.
Complete Example
// A complete Mortar file
node StartScene {
text: $"Welcome, {get_player_name()}!"
with events: [
0, play_bgm("theme.mp3")
]
text: $"You have {get_gold()} gold."
choice: [
"Go to shop" when can_shop() -> Shop,
"Go adventure" -> Adventure
]
}
node Shop {
text: "Welcome to the shop!"
}
node Adventure {
text: "Adventure begins!"
with events: [
0, start_battle("Goblin")
]
}
// ===== Function Declarations =====
// Play background music
fn play_bgm(music: String)
// Get player name
fn get_player_name() -> String
// Get gold amount
fn get_gold() -> Number
// Check if can shop
fn can_shop() -> Bool
// Start battle
fn start_battle(enemy: String)
Using in Events
Call Functions Without Parameters
with events: [
0, shake_screen()
2, flash_white()
]
fn shake_screen()
fn flash_white()
Call Functions With Parameters
with events: [
0, play_sound("boom.wav")
2, set_color("#FF0000")
4, move_to(100, 200)
]
fn play_sound(file: String)
fn set_color(hex: String)
fn move_to(x: Number, y: Number)
Method Chaining
with events: [
0, play_sound("boom.wav").shake_screen().flash_white()
]
fn play_sound(file: String)
fn shake_screen()
fn flash_white()
Using in Text Interpolation
Only functions with return values can be used in ${}:
text: $"Hello, {get_name()}!"
text: $"Level: {get_level()}"
text: $"Status: {get_status()}"
fn get_name() -> String
fn get_level() -> Number
fn get_status() -> String
Note: Functions in interpolation must return String!
// ❌ Error: function has no return value
text: $"Result: {do_something()}"
fn do_something() // No return value
// ❌ Error: return type is not String
text: $"Result: {get_hp()}"
fn get_hp() -> Number // Wrong return type
// ✅ Correct
text: $"Result: {get_result()}"
fn get_result() -> String
Using in Conditions
Functions after when must return Bool / Boolean:
choice: [
"Special option" when is_unlocked() -> SpecialNode
]
fn is_unlocked() -> Bool
Position of Function Declarations
By convention, put all function declarations at the end of the file:
// Node definitions
node A { ... }
node B { ... }
node C { ... }
// ===== Function Declarations =====
fn func1()
fn func2()
fn func3()
But position doesn’t really matter, you can put them anywhere.
Static Type Checking
Mortar checks types at compile time:
// ✅ Correct
with events: [
0, play_sound("file.wav")
]
fn play_sound(file: String)
// ❌ Error: wrong parameter type
with events: [
0, play_sound(123) // Passed number, but needs string
]
fn play_sound(file: String)
This helps you catch errors early!
Implementing Functions (Game Side)
Mortar only handles declarations, actual implementation is in your game code.
The compiled JSON will contain function information:
{
"functions": [
{
"name": "play_sound",
"params": [
{"name": "file", "type": "String"}
]
},
{
"name": "get_player_name",
"return": "String"
}
]
}
Your game reads the JSON and implements these functions.
See Integrating with Your Game for details.
Best Practices
✅ Good Practices
// Clear naming
fn play_background_music(file: String)
fn get_player_health() -> Number
fn is_quest_completed(quest_id: Number) -> Bool
// Reasonable parameters
fn spawn_enemy(name: String, x: Number, y: Number)
fn set_weather(type: String, intensity: Number)
❌ Bad Practices
// Unclear naming
fn psm(f: String) // What does this mean?
fn x() -> Number // What is x?
// Too many parameters
fn do_complex_thing(a: Number, b: Number, c: String, d: Bool, e: Number, f: String)
Recommendations
- Self-explanatory names: Function names should say what they do
- Moderate parameters: Generally no more than 7 parameters
- Clear types: All parameters and return values should have types
- Organize by category: Put related functions together with comments
Common Questions
Q: Must I declare all functions I use?
Yes! Using undeclared functions will cause errors.
Q: Can I write function instead of fn?
Yes! Both are identical:
fn play_sound(file: String)
function play_sound(file: String) // Same thing
Q: Can I declare but not use?
Yes. Declared but unused functions will get compiler warnings, but not errors.
Q: Can functions be overloaded?
No. Each function name can only be declared once.
// ❌ Error: duplicate declaration
fn test(a: String)
fn test(a: Number, b: Number)
Q: Can parameters have default values?
Not currently supported. All parameters are required.
Next Steps
- See Complete Examples
- Learn how to Integrate with Your Game
- Check out JSON Output Format