### Initialize the Main function Source: https://easel.games/docs/learn/tutorial-astroblast/backdrop Clear the Main function to prepare for game world setup. ```easel pub game fn World.Main() { } ``` -------------------------------- ### Setup AbilityGallery Source: https://easel.games/docs/learn/tutorial-mechanics/abilities Initializes the AbilityGallery and adds it to the UI layout within the unit's ability system. ```easel pub prop unit.SelectedAbility pub gallery unit.AbilityGallery pub fn unit.AbilitySystem([owner]) { SelectedAbility = Subspawn ability { LaserAbility } Subspawn ability { BombAbility } CommandBarRight { HStack(padding=1) { AbilityGallery } } } pub fn AbilityIcon(image, keycode, isSelected, tooltip?, [ui]) { // ... } ``` -------------------------------- ### Verify setup completion with Spawn Source: https://easel.games/docs/learn/language/behaviors Illustrates that code inside a Spawn block executes fully before returning control to the caller. ```Easel let x = Spawn { this.name = "Bob" } Transmission { "My name is " + x.name } // Displays "My name is Bob" ``` -------------------------------- ### Define identifiers and namespaces Source: https://easel.games/docs/learn/language/syntax Examples of identifier naming conventions and the use of colons for namespacing. ```easel pub const MyConstant = 456 // global identifiers must begin with an uppercase letter pub fn Movement:MoveFast() { // colons are allowed in identifiers to help with namespacing let myVariable = 123 // local identifier must begin with a lowercase letter } ``` -------------------------------- ### Define project configuration in easel.toml Source: https://easel.games/docs/learn/configuration Example of a standard easel.toml file structure including project, author, engine, graphics, and player settings. ```toml [project] name = "Acolyte Fight!" domain = "acolyte.easel.games" [authors] "u1z.DHAVSGw" = "raysplaceinspace" [engine] edition = 17 [graphics] resolution = "max" minResolution = "low" minAutoResolution = "high" [players] defaultPrefix = "Acolyte" selfColor = "#00ccff" colors = ["#f58c81", "#b69cf6", "#54c794", "#e09f47", "#e08747", "#e58cc5", "#a9b852", "#6eb2fd"] ``` -------------------------------- ### Define and use a preference Source: https://easel.games/docs/learn/players/preferences A complete example showing the declaration of a preference and its usage within a function to handle player input and display state. ```Easel pub preference owner.LikesCarrots pub fn owner.Example() { Transmission { "Do you like carrots, Y/N?" } on ButtonDown(KeyY) { LikesCarrots = true } on ButtonDown(KeyN) { LikesCarrots = false } Transmission { with LikesCarrots { if IsUndefined(LikesCarrots) { "We don't know yet if you like carrots" } else if LikesCarrots { "You like carrots!" } else { "You don't like carrots!" } } } } ``` -------------------------------- ### Declare role-based system signatures Source: https://easel.games/docs/learn/thinking/roles Example function signatures and properties that operate on the 'animal' role. ```Easel pub fn animal.HungerSystem() { ... } pub fn this.WalkToTarget([animal]) { ... } pub fn CalculateHayRequired([animal]) { ... } pub prop animal.IsSleeping = false pub field animal.HungerLevel = 100 pub signal animal.Hurt = 100 ``` -------------------------------- ### Output Function Usage Source: https://easel.games/docs/learn/sounds/esfx/reference Examples demonstrating how to route oscillator signals to the final output or specific input keys. ```text Output(into) ``` ```text Oscillator(freq=500) Envelope(attack=0.1s) Output Oscillator(freq=1250) Envelope(attack=0.5s) Output ``` ```text Oscillator(freq=500) Output(into=$abc) Oscillator(freq=1250) Output(into=$abc) Input(key=$abc) Envelope(attack=0.1s) ``` ```text Oscillator(freq=500) Output(into=[$abc, $def]) Input(key=$abc) Delay(0.1s) Output Input(key=$def) Output ``` -------------------------------- ### Implement Team Selector System Source: https://easel.games/docs/learn/players/teams/team-selector Creates a UI system for players to join teams and start the game, utilizing signals for state updates. ```easel pub signal World.TeamsChanged pub fn owner.TeamSelectorSystem() { Subspawn { OverlayContent { H1 { "Choose Your Team" } HStack { with TeamsChanged { await Paint // in case two players change team in the same tick, only rerender once for index, team in Teams %%{ Panel(width=30, minHeight=20) { H2 { "Team " + (index+1) } if team == Team { RaisedButton(backgroundColor=Color:Primary, opacity=0.5) { "Joined" } } else { RaisedButton(PressIntent(index), backgroundColor=Color:Primary) { "Join" } } for player in QueryPlayers(team=) %%{ P { %(player.PlayerName) } } } } } } RaisedButton(PressIntent, backgroundColor=Color:Primary) { "Start Game" } } on Pressed index { Team = Teams[index] TeamsChanged } on Pressed { CommenceGame } once AfterGameCommenced { Expire } } } ``` -------------------------------- ### Signal Declaration Syntax Source: https://easel.games/docs/learn/entities/signals Examples of declaring signals with specific object parameters, public visibility, and parameter lists. ```Easel signal owner.Celebrate ``` ```Easel pub signal owner.Celebrate ``` ```Easel pub signal owner.PayRespects(message, [color]) ``` -------------------------------- ### Defining Static Variables Source: https://easel.games/docs/learn/language/statics Example of declaring mutable and immutable static variables and functions that interact with them. ```text let NumBananas = 0 const DesiredBananas = 5 fn AddBanana() { NumBananas += 1 } fn RemoveBanana() { NumBananas -= 1 } fn HasEnoughBananas() -> boolean { return NumBananas >= DesiredBananas } ``` -------------------------------- ### Execute concurrent logic with behavior blocks Source: https://easel.games/docs/learn/language/behaviors Starts a concurrent block of code that runs alongside the main program flow. ```Easel pub fn World.Example() { behavior { // Starts a concurrent block of code loop { Transmission { "Jump!" } await Tick(5s) } } Transmission { "Simon says:" } } // Outputs "Simon says:" once, and "Jump" every 5 seconds ``` -------------------------------- ### Declare a preference Source: https://easel.games/docs/learn/players/preferences Preferences must be associated with an owner object and start with an uppercase letter. Use the pub keyword to make them accessible across files. ```Easel preference owner.LikesCarrots ``` ```Easel pub preference owner.LikesCarrots ``` -------------------------------- ### Configure Oscillator frequency Source: https://easel.games/docs/learn/sounds/esfx Examples of setting a fixed frequency versus a linear frequency ramp over the sound duration. ```esfx Oscillator(freq=300) ``` ```esfx Oscillator(freq=[300,500]) ``` -------------------------------- ### Trigger Game Start via Laser Fire Source: https://easel.games/docs/learn/tutorial-astroblast/multiplayer Updates the ship's click handler to trigger the CommenceGame signal, allowing players to start the game by shooting. ```Easel pub fn unit.Ship([owner]) { // ... on ButtonDown(Click) { CommenceGame while IsButtonDown(Click) { Spawn projectile { Laser } await Tick(0.5s) } } // ... } ``` -------------------------------- ### Declare Accumulator with Initial Value Source: https://easel.games/docs/learn/players/accumulators Sets a starting value for the accumulator upon declaration. ```Easel accumulator owner.Rating = 1000 ``` -------------------------------- ### Initialize the Game World Source: https://easel.games/docs/learn/quickstart Sets up the initial game environment including the background, camera, and viewport. ```Easel pub const BoundaryRadius=25 pub game fn World.Main() { SolidBackground(#222233) Camera(body=@(0, 0), radius=BoundaryRadius) Viewport(aspectRatio=1) } ``` -------------------------------- ### Declare constant variables with const Source: https://easel.games/docs/learn/language/locals Constant variables cannot be reassigned after initialization and can start with any case letter. ```text pub fn Example() { const NumBots = 7 NumBots = 8 // Compilation error: Cannot assign to a constant variable } ``` -------------------------------- ### Demonstrate depth-first execution order Source: https://easel.games/docs/learn/language/behaviors Shows how control switches between behaviors and returns upon hitting an await statement. ```Easel pub fn Example() { Transmission { "1" } behavior { Transmission { "2" } await Tick(1s) Transmission { "4" } } Transmission { "3" } } ``` -------------------------------- ### Envelope Usage Examples Source: https://easel.games/docs/learn/sounds/esfx/reference Demonstrates various ADSR envelope configurations for different sound characteristics. ```text Play(duration=2s) { Oscillator(freq=500) Envelope(attack=0.1s) } ``` ```text Play(duration=2s) { Oscillator(freq=500) Envelope(attack=0.01s, decay=0.05s, decayTo=0.2) } ``` ```text Play(duration=2s) { Oscillator(freq=500) Envelope(attack=0.1s, sustain=true) } ``` -------------------------------- ### Using context parameters Source: https://easel.games/docs/learn/language/functions/subblock Shows how parameters marked with use are automatically filled from the current context. ```Easel fn FunctionWithSubblock() |use name, use age| { use name="Augustus", age=25 delve() // name and age are passed in from context } ``` -------------------------------- ### Define PolygonCollider with ID Source: https://easel.games/docs/learn/upgrading/collider-isolation Example of a collider definition that will now trigger both global and specific collision events. ```text PolygonCollider(...) ``` -------------------------------- ### Define and use callbacks Source: https://easel.games/docs/learn/language/types/callback Demonstrates block and expression syntax for defining callbacks and their usage in functions like OrderBy. ```Easel // Block syntax let callback1 = |name| { return "Hello, " + name + "!" } let greeting = callback1("world") // assigns "Hello, world!" to greeting // Expression syntax let callback2 = |name| "Goodbye, " + name + "!" greeting = callback2("Fred") // assigns "Goodbye, Fred!" to greeting // Callbacks can be used to customize certain functions let players = QueryPlayers.OrderBy(|x| x.PlayerName) ``` -------------------------------- ### Configure the World Main function Source: https://easel.games/docs/learn/tutorial-astroblast/spaceship Sets up the game world with a backdrop and a camera with a specific zoom level. ```easel pub game fn World.Main() { ImageSprite(body=@(0, 0), image=@backdrop.png, radius=7, repeatX=100, repeatY=100, layer=-100) Camera(@(0,0), radius=20) SpawnEachPlayer owner { Subspawn unit { Ship } } } ``` -------------------------------- ### Peaking Filter Usage Source: https://easel.games/docs/learn/sounds/esfx/reference Examples and syntax for applying a peaking filter to boost or dampen specific frequencies. ```text Peaking(freq, db, q?) ``` ```text Peaking(freq=220, db=6) ``` -------------------------------- ### Route sound signals Source: https://easel.games/docs/learn/sounds/esfx Examples of standard sequential routing and complex routing using Input/Output keys. ```esfx Play { Oscillator(freq=500) Oscillator(freq=750) LowPass(freq=1000) // receives the sum of the two oscillators above } ``` ```esfx Play { Oscillator(freq=500) Envelope(attack=0.01s) Output(into=$abc) Oscillator(freq=750) Envelope(attack=0.5s) Output(into=$abc) Input(key=$abc) LowPass(freq=1000) // receives from the two Outputs above } ``` -------------------------------- ### Define teams and main game loop in main.easel Source: https://easel.games/docs/learn/players/teams/team-selector Initializes team constants and manages player spawning and game commencement. ```easel pub const Team1 = Spawn pub const Team2 = Spawn pub const Teams = [Team1, Team2] // put the teams in an array for easy access pub game fn World.Main(maxHumanPlayers=10) { SpawnEachPlayer owner { Team = Teams.MinBy(|team| CountPlayers(team=)) TeamSelectorSystem await GameCommenced Subspawn hero { Hero } } } ``` -------------------------------- ### Managing Components with IDs Source: https://easel.games/docs/learn/tutorial-mechanics/lives Demonstrates how to create, replace, and delete a component using a specific ID. ```Easel ImageSprite(@hero.png) await Tick(1s) ImageSprite(@hero-smiling.png) await Tick(5s) delete ImageSprite ``` -------------------------------- ### Initialize a physics-enabled game world Source: https://easel.games/docs/learn/physics Sets up a basic game world with a player ship, physics body, collider, and collision event handling. ```Easel pub tangible category Category:Ship pub game fn World.Main() { SpawnEachPlayer owner { Subspawn ship { use body=ship, radius=1, shape=Equilateral(numPoints=3) Body(pos=20*RandomVector) PolygonCollider(category=Category:Ship) PolygonSprite(color=#0f0) } on BeforeCollide that { Print { "Hero collided!" } } } } ``` -------------------------------- ### Remove legacy firing logic Source: https://easel.games/docs/learn/tutorial-mechanics/abilities Replaces the old manual firing logic with a simple game start trigger. ```easel pub fn unit.Ship([owner]) { // ... on ButtonDown(Click) { CommenceGame while IsButtonDown(Click) { Spawn projectile { Laser } await Tick(0.5s / RateOfFireFactor) } } // ... } ``` ```easel pub fn unit.Ship([owner]) { // ... once ButtonDown(Click) { CommenceGame } // ... } ``` -------------------------------- ### Defining and Calling Functions with Default Parameters Source: https://easel.games/docs/learn/language/functions/defaults Demonstrates how to assign default values to parameters and how they behave when arguments are omitted or explicitly set to undefined. ```Easel fn Function1(x=1, y=2) { } fn Example() { // Set x to 123, but leave y to its default expression, which is 2 Example(123) // This will have the same effect as the above Example(123, undefined) } ``` -------------------------------- ### Use context variables with use Source: https://easel.games/docs/learn/language/locals Context variables are automatically passed into functions and must start with a lowercase letter. ```text pub fn Example() { use color=#ff8800, density=15 // Context variables DoSomething("Bob", radius=1.5) // This is identical to: MakeACharacter("Bob", radius=1.5, color=#ff8800, density=15) } // This is a function that takes `name` directly and `radius`, `color` and `density` from context fn DoSomething(name, [radius, color, density]) { // ... } ``` -------------------------------- ### Declare mutable variables with let Source: https://easel.games/docs/learn/language/locals Mutable variables allow reassignment after declaration and must start with a lowercase letter. ```text pub fn Example() { let x = 123 x = 456 Transmission { "x=" + x } // Outputs: x=456 } ``` -------------------------------- ### Register UpgradeSystem in Main Source: https://easel.games/docs/learn/tutorial-mechanics/upgrades Integrates the UpgradeSystem into the player spawning logic within the main game function. ```Easel pub game fn World.Main(maxHumanPlayers=5) { // ... SpawnEachPlayer owner { ScoreSystem UpgradeSystem await Subspawn unit { Ship } Subspawn dialog { GameOverDialog } } // ... } // ... ``` -------------------------------- ### Defining components and spawning entities in Easel Source: https://easel.games/docs/learn/key-concepts Demonstrates how components attach to the current entity and how the Spawn block shifts the current entity context. ```Easel pub fn ship.Spaceship() { // the current entity is `ship` inside this block ImageSprite(@sparkles.svg, radius=5) // Attaches a sprite to the current entity, `ship` Spawn projectile { // `projectile` is now the current entity inside this block ImageSprite // Attaches a sprite to the current entity, `projectile` } } ``` -------------------------------- ### Execute code immediately and repeatedly with with Source: https://easel.games/docs/learn/key-concepts Runs the block once immediately upon initialization, then repeatedly whenever the condition updates. ```Easel with Health { let proportion = Health / MaxHealth ImageSprite(@hero.svg, color=proportion.Mix(#f00, #0f0)) } ``` -------------------------------- ### BandPass Filter Definition and Usage Source: https://easel.games/docs/learn/sounds/esfx/reference Defines a band-pass filter and provides an example of usage for a 220 Hz frequency. ```text BandPass(freq, q?) ``` ```text BandPass(freq=220) ``` -------------------------------- ### Example of Duplicate Arguments Source: https://easel.games/docs/learn/upgrading/no-duplicate-args A function call where the 'glaze' parameter is defined twice, causing the first value to be ignored. ```Easel Spark(color=#ff8800, glaze=0.5, radius=2, bloom=3, glaze=1) ``` -------------------------------- ### Sequential Level Execution Source: https://easel.games/docs/learn/thinking/asynchronous Demonstrates using await to execute a sequence of game levels one after another. ```Easel pub game fn World.Main() { // ... await PlayLevel1 await PlayLevel2 await PlayLevel3 await ShowCredits } ``` -------------------------------- ### Displaying the AbilityGallery Source: https://easel.games/docs/learn/ui/galleries How to instantiate and display an AbilityGallery within a Panel. ```APIDOC ## AbilityGallery ### Description Displays the gallery component. The gallery inherits the layout properties of its parent container. ### Usage Content { Panel { AbilityGallery } } ``` -------------------------------- ### Declare context parameters Source: https://easel.games/docs/learn/language/types/callback Prefix parameters with the use keyword to treat them as context variables passed implicitly. ```Easel fn DisplayGreeting(firstName, [age]) { Print { "Our friend " + firstName + " is " + age + " years old." } } fn Example() { let callback1 = |firstName, _, use age| { // the age parameter is passed implicitly through context DisplayGreeting(firstName=) } callback1() } ``` -------------------------------- ### Define WaitingForPlayersDialog Source: https://easel.games/docs/learn/tutorial-astroblast/multiplayer Defines a dialog component that displays a start button and listens for the startGame intent to trigger the game commencement. ```Easel pub game fn World.Main() { // ... SpawnEachPlayer owner { // ... } AsteroidFieldSystem } fn dialog.WaitingForPlayersDialog { BottomContent { Panel { VStack { H3 { "Waiting for players..." } HStack { RaisedButton(PressIntent, backgroundColor=Color:Primary, expand=true) { "Start Game" } } } } } once Pressed { CommenceGame } once GameCommenced { Expire } } fn dialog.GameOverDialog([owner]) { // ... } ``` -------------------------------- ### Signal with Parameters and Context Source: https://easel.games/docs/learn/entities/signals Demonstrates passing explicit parameters and implicit context-based parameters to a signal. ```Easel pub signal owner.PayRespects(message, [color]) pub game fn World.Main() { use color=#8800ff SpawnEachPlayer owner { Transmission { P { "Press F to pay respects" } } on ButtonDown(BtnF) { PayRespects("F") } on PayRespects message color { Transmission { P(color=) { "You paid respects: " + message } } } } } ``` -------------------------------- ### Implement a live ranking gallery Source: https://easel.games/docs/learn/ui/galleries Displays a gallery within a panel and populates it with content from each player. ```Easel pub gallery World.PlayersGallery pub game fn World.Main() { // Display the PlayersGallery in a Panel Content { Panel { PlayersGallery } } // Each player gives their own content to the gallery SpawnEachPlayer owner { give PlayersGallery { %(PlayerName + " is here!") } } } ``` -------------------------------- ### Defining and using a Buff Source: https://easel.games/docs/learn/upgrading/buffs-obsolete/buffs Example of declaring a buff property and using it within an entity's logic to manage temporary effects. ```Easel pub buff owner.Boost ~ |boosts| boosts.Sum pub fn owner.Example() { Transmission { P { "Press X to boost!" } } on ButtonDown(BtnX) { Subspawn { // create a new entity to represent the temporary effect Boost(1) // this entity contribute a value to the buff once Tick(5s) { Expire } // the entity and its contribution expire after 5 seconds } } with Boost { Transmission { P { "Your current boost: " + Boost } } } } ``` -------------------------------- ### Assign the 'this' subblock parameter Source: https://easel.games/docs/learn/language/functions/subblock Use 'use this =' to map a parameter to the 'this' variable within the subblock, useful for entity setup. ```Easel fn this.DrawMe() { } fn SpawnProjectile() |use this = projectile| { Spawn projectile { delve(projectile) } } fn Example() { SpawnProjectile fireball { DrawMe // the object parameter `this` is assigned from context } } ``` -------------------------------- ### Define and use a minimap camera Source: https://easel.games/docs/learn/graphics/cameras Demonstrates spawning a secondary camera and assigning specific sprites to it using the camera parameter. ```Easel pub const Camera:Minimap = Spawn camera { Viewport(width=10, height=10, anchor=@(1, 1), offset=@(-1, -1)) SolidBackground(#fff1) } pub game fn World.Main() { SpawnEachPlayer owner { Subspawn hero { use body=hero, radius=1 Body(pos=@(10, 10)) PolygonSprite(shape=Circle, color=#f00) // renders to the main camera by default PolygonSprite(shape=Equilateral(numPoints=3), color=#0f0, camera=Camera:Minimap) } } } ``` -------------------------------- ### Implement AsteroidFieldSystem Source: https://easel.games/docs/learn/tutorial-astroblast/asteroids Create a system that spawns asteroids at random boundary positions when the count falls below 20. ```easel pub fn this.AsteroidFieldSystem() { on Tick(1s) { if QueryCount(filter=Category:Asteroid) < 20 { let radius=5, pos=RandomBoundaryPos(radius=) if pos.QueryAnyWithinRadius(radius=) { continue } Spawn unit { Asteroid(pos=) } } } } fn RandomBoundaryPos([radius]) -> vector { return @(BoundaryRadius + radius, SignedRandom*BoundaryRadius).Rotate(Random.Quantize(0.25) * 1rev) } ``` -------------------------------- ### Start a party with PartyIntent Source: https://easel.games/docs/learn/multiplayer/parties Use PartyIntent within a Link component to open the party dialog, adjusting text based on the IsPartying state. ```Easel P(fontSize=0.9) { if IsPartying { "Invite more friends to " Link(PartyIntent, bold=true) { "this party!" } } else { "Invite your friends to " Link(PartyIntent, bold=true) { "party!" } } } ``` -------------------------------- ### Implicit Parameter Injection with Context Source: https://easel.games/docs/learn/key-concepts Demonstrates how the 'use' keyword makes variables available to child function calls automatically. ```Easel pub fn ship.Spaceship() { use color=#8800ff // The `use` syntax puts `color` into the context // Both the function calls below require a `color` but it has not been given explicitly. // Easel will automatically pull in the `color` parameter from context. PolygonSprite(Circle(radius=5)) Spark(radius=1) } ``` -------------------------------- ### Defining and calling functions with object parameters Source: https://easel.games/docs/learn/language/functions/objects Demonstrates explicit object parameter definition and invocation. ```Easel fn vegetable.FunctionThatTakesAnObject() { } fn Example(carrot) { carrot.FunctionThatTakesAnObject } ``` -------------------------------- ### Define and Spawn an Entity Source: https://easel.games/docs/learn/language/types/entity Demonstrates declaring properties and behaviors, and spawning an entity with specific initial values and hooks. ```Easel prop projectile.MyProperty pub fn behavior this.MyBehavior() { } Spawn projectile { // create an entity called 'projectile' MyProperty = 123 // this property will be stored on the projectile MyBehavior // this behavior will expire when the projectile expires on MyProperty { // this 'on' hook will be terminated when the projectile expires // do something whenever MyProperty changes } } ``` -------------------------------- ### Use body context for physics functions Source: https://easel.games/docs/learn/physics/best-practices Define a body context at the start of a block to avoid passing the body parameter to individual physics functions. ```Easel Subspawn ship { use body=ship Body(pos=20*RandomVector) // finds `body` from context PolygonCollider(category=Category:Ship, shape=Equilateral(radius=1, numPoints=3)) once Tick(5s) { Velocity = @(20,20) // finds `body` from context } } ``` -------------------------------- ### Implement walking movement with Move Source: https://easel.games/docs/learn/physics/how-to-movement Use the Move command within a BeforePhysics behavior to apply a one-off force for discrete movement steps that respect collisions. ```Easel Subspawn hero { use body=hero, radius=1, shape=Circle Body(pos=20*RandomVector) PolygonCollider(category=Category:Hero) PolygonSprite(color=#0f0) on ButtonDown(ArrowRight) { behavior on BeforePhysics { // Take on step to the right Move(@(10, 0)) } } on ButtonDown(ArrowRight) { delete behavior } } ``` -------------------------------- ### Public Static Variable Declaration Source: https://easel.games/docs/learn/language/statics Use the 'pub' keyword to make static variables accessible across files. Public variables must start with an uppercase letter. ```text pub let NumBananas pub const DesiredBananas = 5 ``` -------------------------------- ### Register AsteroidFieldSystem in Main Source: https://easel.games/docs/learn/tutorial-astroblast/asteroids Add the AsteroidFieldSystem to the World entity in main.easel to initiate continuous spawning. ```easel pub game fn World.Main() { ImageSprite(body=@(0, 0), image=@backdrop.png, radius=7, repeatX=100, repeatY=100, layer=-100) Camera(@(0,0), radius=BoundaryRadius) Viewport(aspectRatio=1) SpawnEachPlayer owner { Subspawn unit { Ship } } AsteroidFieldSystem } ``` -------------------------------- ### Spawn player ship entities in main.easel Source: https://easel.games/docs/learn/tutorial-astroblast/spaceship Use this snippet within the World.Main function to initialize the player and their associated spaceship entity. ```Easel pub game fn World.Main() { ImageSprite(body=@(0, 0), image=@backdrop.png, radius=7, repeatX=100, repeatY=100, layer=-100) SpawnEachPlayer owner { Subspawn unit { Ship } } } ``` -------------------------------- ### Integrate ScoreSystem into Main Source: https://easel.games/docs/learn/tutorial-astroblast/scoring Adding the ScoreSystem to the player spawn logic within the main game loop. ```easel pub game fn World.Main() { // ... SpawnEachPlayer owner { ScoreSystem await Subspawn unit { Ship } Subspawn dialog { GameOverDialog } } // ... } // ... ``` -------------------------------- ### Using Assert Statements Source: https://easel.games/docs/learn/language/debugging Demonstrates how to use Assert to validate program state, noting that the error message parameter is optional. ```Easel pub fn Example() { let a = 2 + 3; Assert(a == 5, "'a' should be 5!") Assert(a == 5) // error message is optional } ``` -------------------------------- ### Spawn the Game Over Dialog Source: https://easel.games/docs/learn/tutorial-astroblast/game-over Integrate the dialog into the main game loop by spawning it alongside the player's ship. ```Easel pub game fn World.Main() { // ... SpawnEachPlayer owner { Subspawn unit { Ship } Subspawn dialog { GameOverDialog } } // ... } fn dialog.GameOverDialog([owner]) { // ... } ``` -------------------------------- ### Enable experimental features in easel.toml Source: https://easel.games/docs/learn/experimental/experimental-toml Add the [experimental] header and specific feature flags to your configuration file. ```toml [experimental] regionAffinity = true ``` -------------------------------- ### Implement Team-Based Entity Logic in Easel Source: https://easel.games/docs/learn/players/teams Demonstrates spawning entities with owner context and checking team membership during collision events. ```easel // main.easel pub game fn World.Main(maxHumanPlayers=10) { SpawnEachPlayer owner { // `owner` is the player being spawned Subspawn hero { Hero // `owner` is passed into `Hero` from context } } } // hero.easel pub fn hero.Hero([owner]) { // `owner` is received from context // ... setup your hero here on ButtonDown(KeySpacebar) { Subspawn projectile { Fireball // owner is passed into `Fireball` from context } } } // fireball.easel pub fn projectile.Fireball([hero, owner]) { // `owner` is received from context // ... setup your fireball here on BeforeCollide that { if that.Category.Overlaps(Category:Hero) && that.Team != owner.Team { // Only apply damage to enemies, not allies that.Health -= 10 } } } ``` -------------------------------- ### Implement a basic HealthSystem Source: https://easel.games/docs/learn/thinking/systems A simple system that initializes health and uses a with block to monitor the value, expiring the entity when health reaches zero. ```Easel pub prop unit.Health pub fn unit.HealthSystem() { Health = 100 with Health { if Health <= 0 { Expire break } } } ``` -------------------------------- ### Format statements and line continuation Source: https://easel.games/docs/learn/language/syntax Shows how to structure statements, use line continuation for long expressions, and separate multiple statements on a single line using semicolons. ```easel pub fn MyFunction1() { CallAFunction("This is a statement") CallAnotherFunction("This is another statement") CallFunction3( "This statement continues onto multiple lines" + "because the brackets have not been closed yet" + "and the lines end with a + operators which need a right hand side value" ) CallAFunction("This line has statements"); CallAFunction("separated by a semicolon") } ``` -------------------------------- ### Configure Edition in easel.toml Source: https://easel.games/docs/learn/upgrading/no-implicit-use Sets the project edition to 13 or higher to enable the new behavior. ```toml [engine] edition = 13 ``` -------------------------------- ### Configure Engine Edition Source: https://easel.games/docs/learn/upgrading/multiple-cameras Set the engine edition in the easel.toml file to enable multiple camera support. ```toml [engine] edition = 15 ``` -------------------------------- ### Define and use a prop Source: https://easel.games/docs/learn/entities/props Demonstrates declaring a prop and using it within a function with a transmission block. ```text pub prop hero.Health pub fn hero.Example() { Health = 100 with Health { Transmission { "Health: " + Health } } Health = 75 } // Outputs "Health: 100" then "Health: 75" ``` -------------------------------- ### Listen Directly to Input Source: https://easel.games/docs/learn/thinking/for-object-oriented Eliminate unnecessary abstractions by having entities listen directly to input events. ```Easel pub fn weapon.LaserWeapon([owner]) { on ButtonDown(Click) { Spawn projectile { Laser } } } ``` -------------------------------- ### Define Upgrade Properties Source: https://easel.games/docs/learn/tutorial-mechanics/upgrades Initialize the upgrade factors in a dedicated upgrades file. ```easel pub prop owner.DamageFactor = 1 pub prop owner.RateOfFireFactor = 1 ``` -------------------------------- ### Configure World Camera and Viewport Source: https://easel.games/docs/learn/tutorial-astroblast/boundaries Updates the main game loop to align the camera view with the defined world boundaries. ```easel pub game fn World.Main() { ImageSprite(body=@(0, 0), image=@backdrop.png, radius=7, repeatX=100, repeatY=100, layer=-100) Camera(@(0,0), radius=BoundaryRadius) Viewport(aspectRatio=1) SpawnEachPlayer owner { Subspawn unit { Ship } } } ``` -------------------------------- ### Defining Implicit Parameters with use and Signatures Source: https://easel.games/docs/learn/key-concepts Shows that function parameters and 'use' declarations act as implicit parameters, while 'let' variables remain local. ```Easel pub fn ship.PlasmaBolt(color, [owner]) { // ship, color and owner are all implicit parameters use radius=10 // implicit parameter let x = 5 // not an implicit parameter // Equivalent to `ship.DoSomething(color=color, owner=owner, radius=10)` // `x` is not passed from context because it is declared with `let` DoSomething } pub fn ship.DoSomething([color?, owner?, radius?, x?]) { /* ... */ } ``` -------------------------------- ### Declare Fields and Props Source: https://easel.games/docs/learn/key-concepts Basic syntax for defining entity fields and properties. ```Easel pub field shield.PreviousShield pub prop unit.Health = 100 pub prop ability.Cooldown = 0 ``` -------------------------------- ### Define project metadata Source: https://easel.games/docs/learn/publishing/project-toml Configures the project name and hosting domain. ```toml [project] name = "Acolyte Fight!" domain = "acolyte.easel.games" ``` -------------------------------- ### Implement respawn loop with lives Source: https://easel.games/docs/learn/tutorial-mechanics/lives Wraps the ship spawning logic in a loop that checks the remaining lives and triggers a game over dialog upon exhaustion. ```easel pub game fn World.Main(maxHumanPlayers=5) { // ... SpawnEachPlayer owner { ScoreSystem UpgradeSystem loop { await Subspawn unit { Ship } if NumLivesRemaining <= 0 { break } NumLivesRemaining -= 1 await Tick(2s) } Eliminated = true Subspawn dialog { GameOverDialog } } // ... } // ... ``` -------------------------------- ### Integrate UpgradeSystem Dialog Logic Source: https://easel.games/docs/learn/tutorial-mechanics/upgrades Triggers the waiting dialog within the UpgradeSystem and handles the lifecycle until all players have finished upgrading. ```easel pub fn this.UpgradeSystem([owner]) { on TriggerUpgradeMode { await Subspawn dialog { give PlayersStillUpgrading(owner) UpgradeDialog } await Subspawn dialog { WaitingForPlayersToUpgradeDialog while !PlayersStillUpgrading.IsEmpty { await PlayersStillUpgrading } Expire } } } ``` -------------------------------- ### Receiving subblock parameters Source: https://easel.games/docs/learn/language/functions/subblock Illustrates parameter matching by name and position, allowing for flexible argument ordering. ```Easel pub fn Spray() |index, headingOffset| { // ... } pub fn Example() { Spray headingOffset, index { // Notice the parameters `headingOffset` and `index` are received in a different order than declared. // This still works because in this form, parameters are matched by name where possible. } Spray i { // In this case, `i` will be bound to the declared parameter `index` // because there is no parameter named `i` } } ``` -------------------------------- ### Create a Spectate Button Source: https://easel.games/docs/learn/multiplayer/spectating Attach a SpectateIntent to a Button to allow users to access the live game feed. ```Easel pub page fn owner.HomePage() { Button(SpectateIntent) { "Spectate" } } ``` -------------------------------- ### Implicit and Explicit UI Parameter Usage Source: https://easel.games/docs/learn/ui/under-the-hood Demonstrates how the 'ui' parameter is passed implicitly to subblocks or explicitly defined for clarity. ```Easel pub fn Example() { Transmission { SayHello } // implicit ui parameter Transmission ui { SayHello(ui=) } // equivalent, but with explicit ui parameter } pub fn SayHello([ui]) { %("Hello, world!") } ``` -------------------------------- ### Displaying a Gallery Source: https://easel.games/docs/learn/ui/galleries Basic implementation of an AbilityGallery within a Panel. ```Easel Content { Panel { AbilityGallery } } ``` -------------------------------- ### Input(key) Source: https://easel.games/docs/learn/sounds/esfx/reference Routes the output of a previous Output function to a later function. ```APIDOC ## Input(key) ### Description Allows you to route the output of a previous Output function to a later function. ### Parameters - **key** (string) - Required - The key of the Output function that you want to route the output from. ``` -------------------------------- ### Handle prop changes Source: https://easel.games/docs/learn/entities/props Use the with keyword to execute logic when a prop changes. ```text with Health { Transmission { "Health: " + Health } } ``` -------------------------------- ### Define and call an await function Source: https://easel.games/docs/learn/language/await Demonstrates declaring a function with the await fn specifier and invoking it using the await keyword. ```Easel await fn WaitThenGiveMeANumber() -> value { // wait for 10 ticks before returning await Tick(10) return 123 } fn Example() { let x = await WaitThenGiveMeANumber } ``` -------------------------------- ### Configure Automatic Colors in easel.toml Source: https://easel.games/docs/learn/players/player-colors Configures player colors globally via the easel.toml file, which is useful for MOBA-style perspective-based coloring. ```TOML [players] selfColor = "#0000ff" # blue for yourself colors = ["#ff0000"] # red for your opponents ``` ```TOML [players] selfColor = "#0000ff" # blue for yourself allyColor = "#33bbdd" # if you like, include a different shade of blue for allies colors = ["#f58c81", "#b69cf6", "#54c794", "#e09f47", "#e08747", "#e58cc5", "#a9b852", "#6eb2fd"] ``` -------------------------------- ### Initialize a map for multiple subentities Source: https://easel.games/docs/learn/entities/how-to-subspawn-once Use a map to track multiple subentities, allowing for conditional spawning based on a key. ```text pub field hero.HeroShields = {} ``` -------------------------------- ### Dynamic UI Updates with Magic UI Parameters Source: https://easel.games/docs/learn/ui/under-the-hood Shows how the compiler uses the 'ui' parameter to replace content dynamically within the same slot index. ```Easel pub fn Example() { Transmission { H1 { "The great counter" } P { let counter = 0 on Tick(1s) { counter += 1 "We have waited " + counter + " seconds" // the above text replaces the previous text every second // because it is written to the same index within the slot } } } } ``` -------------------------------- ### Define WaitingForPlayersToUpgradeDialog Source: https://easel.games/docs/learn/tutorial-mechanics/upgrades Creates a UI component that displays a list of players who have not yet completed their upgrade selection. ```easel fn PrintUpgradedMsg() |use ui| { // ... } fn dialog.WaitingForPlayersToUpgradeDialog([owner]) { BottomContent { InsetPanel { P(fontSize=0.9) { "Waiting for players: " with PlayersStillUpgrading { for use index, owner in PlayersStillUpgrading %%{ if index > 0 { ", " } PlayerNameDisplay } } } } } } ``` -------------------------------- ### Spawn Heroes for Players Source: https://easel.games/docs/learn/quickstart Uses SpawnEachPlayer and Subspawn to create a hero entity for every connected player. ```Easel pub const BoundaryRadius=25 pub game fn World.Main() { SolidBackground(#222233) Camera(body=@(0, 0), radius=BoundaryRadius) Viewport(aspectRatio=1) SpawnEachPlayer owner { Subspawn hero { OverlayContent { "Hello world, I'm " + PlayerName + "'s hero!" } } } } ``` -------------------------------- ### Create buttons with different widths using the same frame image Source: https://easel.games/docs/learn/ui/frame-images Demonstrates how 9-slice scaling allows the same frame image to be reused across buttons of varying dimensions. ```Easel ImageButton(frameImage=@panel.png, width=10, height=5) { } ImageButton(frameImage=@panel.png, width=20, height=5) { } ImageButton(frameImage=@panel.png, width=30, height=5) { } ``` -------------------------------- ### Configure Project Name in easel.toml Source: https://easel.games/docs/learn/tutorial-astroblast/project Update the project name field within the configuration file to identify the game. ```toml [project] name = "Astroblast!" [authors] # ... ``` -------------------------------- ### Simulate keypresses with Keycode Intents Source: https://easel.games/docs/learn/language/types/intent Provides alternative inputs for touchscreen users by simulating keycode presses. ```Easel with TouchscreenMode { if TouchscreenMode { BottomRightContent { HStack { Pip(KeySpacebar, borderRounding=true, backgroundColor=#bb00ff, shadow=0.5) { Image(@shipFire.svg, height=6) } Pip(Click, borderRounding=true, backgroundColor=#ff8800, shadow=0.5) { Image(@shipThrust.svg, height=6) } } } } } ``` -------------------------------- ### Defining and accessing public and private functions Source: https://easel.games/docs/learn/language/visibility Demonstrates the difference between private and public function visibility across different files. ```easel // file1.easel fn PrivateFunction() { } pub fn PublicFunction() { } // file2.easel fn Example() { PrivateFunction() // Compilation error: PrivateFunction is not defined PublicFunction() // This is fine } ``` -------------------------------- ### Implement Tagging Logic in main.easel Source: https://easel.games/docs/learn/quickstart Add a tick handler to automatically assign a tagged player if none exists, ensuring the game state remains valid even if players leave. ```Easel pub const BoundaryRadius=25 pub prop World.TaggedHero pub game fn World.Main(maxHumanPlayers=10) { SolidBackground(#222233) Camera(body=@(0, 0), radius=BoundaryRadius) Viewport(aspectRatio=1) SpawnEachPlayer owner { // ... } on Tick { if !TaggedHero.Exists { TaggedHero = QueryAny(filter=Category:Default) } } } ``` -------------------------------- ### Open a URL with a Link component Source: https://easel.games/docs/learn/language/types/intent Uses a string intent to open a URL in a new tab when the component is clicked. ```Easel Link("https://discord.gg/EJfzutBSz8") { "Join our community on Discord! " Icon("fab fa-discord") } ```