Navigation

    CreatiCode Scratch Forum

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • CreatiCode
    1. Home
    2. info-creaticode
    3. Posts
    • Profile
    • Following 0
    • Followers 15
    • Topics 439
    • Posts 1152
    • Best 396
    • Groups 6

    Posts made by info-creaticode

    • RE: New block -- "When stop sign pressed"

      @sonicplushiesc4

      The key is to press the camera button when the stage is showing exactly what you want as the thumbnail.

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: New block -- "When stop sign pressed"

      @sonicplushiesc4

      This project shows a dog saying hello right? So when it says Hello, you can press the button to update the preview. It will become this:

      2357e5f6-674f-4477-9777-e2ee8df5d857-image.png

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: Checking back on notifications progress

      @kirbstyre_63

      Most likely, we will implement a system similar to MIT Scratch’s “messages” (https://scratch.mit.edu/messages). But this is currently behind other more urgent tasks.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: New block -- "When stop sign pressed"

      @sonicplushiesc4

      If it is not working, can you share the project link? And you pressed that button while the project is running?

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: Add a block to point at closest clone/ closest clone of a certain sprite

      @sonicplushiesc4

      You can use this camera button on top of the stage to update the project preview:

      c2513a90-a9cb-4d5d-a2c5-019af75ea0f3-image.png

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: Add a block to point at closest clone/ closest clone of a certain sprite

      @sirbots

      We have added 2 new blocks to make it easier to work with clones. Please check them out there:

      https://www.forum.creaticode.com/topic/2032/2-blocks-to-scan-for-clones

      posted in Feedback
      info-creaticode
      CreatiCode
    • 2 blocks to scan for clones

       

      Introduction

       

      In game projects, clones are commonly used to create objects like enemies, obstacles or powerups. However, it is not easy to scan for them in our code, which is often needed when we need to do something clever, such as “find all the enemies near me”, or “check if I have a clear line of fire”.

      In CreatiCode, every clone has a clone ID, and the original sprite can also be treated as a clone with an ID of “originalsprite”. There are 2 new blocks that can be used to scan for clones of a given sprite: one is simply based on distance from this sprite, and the other based on a scan area.

       
       

      Find Clones by Distance

       

      You can use this sensing block to find clones of a given sprite within the given distance from this sprite, and save their information in the given table:

      e831e32e-e0a6-432e-8007-0f4a6a0b3998-image.png

       
      Notes:

      • You can pick any sprite, even this sprite itself
      • The original sprite can also be treated as a clone, with a clone ID of “originalsprite”.
      • The distance is the direct-line distance between this sprite and each clone of that sprite, calculated using their x and y positions.
      • If any clones are found within this distance, they are listed in the table in order of increasing distance (nearest first). The table will always have at least 4 columns: clone ID, x, y and distance. If the clone has any private variables, they will also be added as additional columns.

       
       

      Example

       

      Here is an example program showing how it works: play.creaticode.com/projects/685e804081a45ef495ae5fdf

       
      In the Tree sprite, we create 5 clones of the tree. Each clone will go to a random position, generate a “secret” that is private to itself, and then say its clone ID to identify itself.

      de3a9b35-fc8d-4d65-9d6d-797ce583e98f-image.png

       
      So on stage, you will see 6 tree objects like this:

      eebfc0d0-71f5-4490-b138-ff65e1035acc-image.png

       
      Now, in the Truck sprite, we can use this sensing block to find trees that are with 100 units distance from the truck:

      5733089a-dea8-4b91-826c-b9f3f49a05f7-image.png

       
      Then we can look at the content of table1:

      dc341578-fed3-42a9-befe-8dc385511c30-image.png

       
      As shown, there are 3 clones whose distance is less than 100 from the truck.

      The nearest clone is the original tree sprite, which is at x of 0 and y of 0. It is about 64.85 units away from the truck.

      The second nearest clone is the one with ID of “clone_3”. It is a bit further away, and its secret is 78.

      You can try to change the distance threshold or drag the trees around, and observe how table1 changes. For example, when the distance threshold is very large, all clones should be listed in the table; and when it is very small, the table should become empty.

       
       
       
       
       
       
       

      Detect Blocking Clones in the Forward Direction

       

      Another very common question we need to ask is whether there are obstacles in front of our sprite, which may block our sprite’s movement or block the shots it fires.

      One way to do this checking is to use the block above to find all clones on the stage, and then check the position of each of them. But the calculation become more complex when the sprite is facing an angle (not straight left/right or up/down).

      Instead, you can use the following block for this task, which defines a rectangle “scan area” in front of this sprite, and list any clone of the given sprite it finds in this area in the given table.

      77abc8c2-dde9-4ebd-bceb-5d54e2459d29-image.png

      Notes:

      • You can pick any sprite, even this sprite itself
      • The original sprite can also be treated as a clone, with a clone ID of “originalsprite”.
      • The distance is going forward along this sprite’s current direction. So if this sprite is facing 45 degrees, you can imagine it moves forward along this direction for 200 units, and check if there are any clones that’s 20 (half of 40) units away on the left or right side.
      • If any clones are found within this distance, they are listed in the table in order of increasing distance (nearest first). The table will always have at least 4 columns: clone ID, x, y and distance. If the clone has any private variables, they will also be added as additional columns.

       
       

      Example

       

      Here is an example program showing how it works:

      play.creaticode.com/projects/685e928081a45ef495ae82c0

       

      The truck is facing -30 degrees (upper left direction). In the Tree sprite, 2 clones are created in a similar way.

      You can drag them to a formation like this:

      4073efa3-a883-42b8-ad09-497a09e283bc-image.png

       
      The original tree sprite is directly on the forward path of the truck. The clone 2 is slightly blocking the path on the right side, and clone 1 should not be a blocker.

       
      Now, suppose we run this block in the truck sprite:

      050c0b67-7a27-4784-8877-e6861b7942e5-image.png

       
      The detection area will be 200 by 70 in front of the truck:

      00d68337-ca4b-489e-b34c-bf0442c7c8d7-image.png

       
      The table1 will contain 2 rows:

      9ab900f3-a6be-4785-b614-c9d1b9611a4c-image.png

       
      Explanation:

      • The center point of both the original sprite and the clone 2 are inside the red rectangle, so they are included in the result table.
      • For clone 1, although its edge touches with the red rectangle, its center point is outside the rectangle. Since we only look at the x/y position of each clone, and not their size, the only thing that matters is their center point’s position.

      Therefore, when deciding the width of the detection area, you need to consider the width of both this sprite and the clones.

      Now, suppose we change the block to use width of 100, then the table will contain 3 rows, because the detection area now includes the center point of the clone 1 as well:

      b147a6c9-6ee4-44bc-9367-fd5737041030-image.png

       
      You can try to play with different truck direction, tree position, distance and width settings to understand how this block works better.

      posted in 2D Blocks
      info-creaticode
      CreatiCode
    • RE: How to find "If Shift key pressed"

      This change has been released. Please refresh your playground to get latest code.

      5576f202-2950-4b07-86a5-36513c1c3985-image.png

      posted in Help
      info-creaticode
      CreatiCode
    • Game AI for <Candy Truck Battle> - Part 2 (Difficulty: 5)

       

      Introduction

       

      In part 1 of this tutorial, we built a basic AI controller for the game. That AI could already move the truck to random locations, and even seek and attack the opponent.

      In this second part, we’re going to supercharge our AI! We’ll add two major new skills: collecting power-ups and avoiding tree obstacles. With these upgrades, our AI will become a much tougher competitor in battle.

      Here is a demo of what we’ll be building:

      detour2.gif

       
       
       
       
       
       
       
       
       
       
       

      Version 4 - Collecting Powerups (Difficulty: 4)

       

      To get our truck to collect powerups, it first needs to know where they are. Then, it has to drive over to them. A key part of the logic will be deciding when to go for a powerup versus when to keep attacking the opponent.

       
       

      Step 1 - Duplicate the Previous AI Code

       

      We’ll be building on the AI controller we made in Part 1 (Version 3). Go ahead and open that project, and then save a copy of it. This way, you’ll always have the original version to go back to if you need it.

       
       

      Step 2 - Check for Powerups

       

      To collect powerups, our AI first needs to know that they’ve appeared on the map. It only makes sense to change the truck’s behavior after a powerup is available. The best spot for this check is right at the start of our main forever loop.

      Let’s create a new custom block and name it check powerups. Important: Make sure to check the box for “Run without screen refresh.” This gives our code a nice little speed boost.

      cbb87297-8004-41a3-a631-2aa8acb22c26-image.png

       
      And we will place this new block at the beginning of the main loop:

      45833864-1dcc-432a-a1e6-ece31fffedb9-image.png

       
       

      Step 3 - Check Our Life Count

       

      Remember, there are two types of powerups in the game:

      • Sugar: Increases our truck’s life count (up to a max of 3).
      • Gas: Boosts our truck’s speed (up to a max of 120).

      It makes sense to prioritize survival. If our truck has fewer than 3 lives, getting a Sugar powerup should be the top priority. Let’s start by adding a check for that.

      6719afe5-2e75-42b8-90b3-9256da7445a2-image.png

       
      Note that the ☁ my lives variable keeps track of the life count for our truck, which is identified by the my team ID. This sensing block is very handy when you need to access any private property of a clone so long as you know its ID.

       
       

      Step 4 - Look for Sugar Powerups

       

      If our truck needs health (meaning it has less than 3 lives), it’s time to scan the area for any Sugar powerups. We can do this using the special find clones of sensing block.

      b4b1e8a3-906c-416f-a351-1fada5611c7f-image.png

       
      This block is incredibly useful. It searches for all visible clones of a specific sprite within a certain distance. Since we want to find Sugar anywhere on the map, let’s use a large distance like 1000. Any Sugar clones it finds will be listed in the table1 variable.

       
       

      Step 5 - Check If Table1 is Not Empty

       

      If the find clones of block successfully located one or more Sugar sprites, it will add them as rows to table1. So, to see if we found anything, we just need to check if the number of rows in table1 is greater than 0.

      c4cdd455-ad89-4022-a13b-8432f10c8804-image.png

       
       

      Step 6 - Update Mode and Target Location

       

      Okay, we’ve found a Sugar powerup! The next step is to drive to it. The table1 is conveniently sorted by distance, meaning the very first row always points to the closest clone. For example, this screenshot shows that one Sugar clone was found. It has a clone ID of 1, is located at X: 160 and Y: -65, and is 96.43 units away from our truck.

      9703166c-6275-4db8-b8bf-1bdf4fa5acb0-image.png
       
      Now, we could create a whole new mode like “collect sugar,” but there’s a clever, simpler way. We can just reuse our existing wander mode! All we have to do is update the target x and target y variables with the location of the Sugar item. The existing code in the wander block will then automatically navigate our truck right to it.

      4e730dc1-66f1-4de3-9955-88612152a8fa-image.png

       
       

      Step 7 - Return from “check powerups”

       

      Once we’ve spotted a Sugar clone and decided to go for it, our job inside the check powerups block is done for this cycle. There’s no need to continue and check for Gas powerups. We can use a return block to exit the custom block immediately.

      1e04af61-9176-4c8e-ad32-c4316474f250-image.png

      Pro Tip: It’s a common misunderstanding that the return block is only for reporter blocks (the ones that return a value). You can also use it in regular stack blocks like this one to simply stop the block from running any further. Its return value is just ignored. This is equivalent of using the stop [this script] block.

       
       

      Step 8 - Look for Gas Powerups

       

      If our truck is at full health, or if there were no Sugar powerups to find, the code continues. Now we can check for Gas powerups. But, there’s no point in grabbing a Gas powerup if our speed is already maxed out at 120. So, let’s first check our ☁ my speed variable.

      a794da49-9c47-4c70-9dd0-9cd7a8a22943-image.png

       
       

      Step 9 - Complete the Rest

       

      The logic for finding and collecting Gas clones is nearly identical to what we just did for Sugar. See if you can build the rest of the code yourself! It’s great practice.

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Here is the complete solution for the check powerups block:

      d2e9237d-676c-4501-b8f7-e548cec0e7d2-image.png

       
       

      Step 10 - Test This Version

       

      Time to test our new powerup-collecting AI! To focus just on this new skill, let’s keep the tree count at 0 for now (you can change this in the Setup sprite).

      It’s also really helpful to make the table1 variable visible on the stage. This way, you can see exactly when the AI finds a powerup.

      One last tip for faster testing: in the Sugar sprite, you can shorten the time it waits before reappearing. For example, try changing the random wait to between 3 and 9 seconds.

      a5d7f091-2195-474d-ad4d-c21cdff56bd8-image.png

       
      Now you can test your AI by opening the project in two browser tabs and letting them battle. It should look something like this:

      collect.gif

       
       
       
       
       
       
       
       
       
       
       
       

      Version 5 - Avoiding Trees (Difficulty: 5)

       

      Now for a real challenge: obstacle avoidance! Right now, our truck will just drive straight into trees and get stuck, completely stopping it from chasing the opponent or grabbing powerups. We’re going to fix this by teaching our AI how to detect when a tree is in the way and then plot a “detour” to get around it.

       
       

      Step 1 - Export Version 4 for Backup

       

      First thing’s first. Let’s make a backup of our working powerup-collecting version. Export your Controller sprite as a file (it will be named something like sprite3). This way, if anything goes wrong, you can easily import this version and start again.

      a8868a00-4c11-4e0d-9e16-769f250b99c2-image.png

       
       

      Step 2 - Define a New Reporter Block

       

      To avoid trees, our AI first needs a way to “see” if its path is blocked. We’ll create a new custom block that can answer a simple question: “Is this direction blocked?”. Let’s name it direction is blocked, and it will take the command as an input. Make sure to select “Run without screen refresh” and define it as a reporter block. A reporter block returns a value; ours will return 1 if the path is blocked and 0 if it’s clear.

      44a2c9ee-ca6a-4c17-9804-997c0ab06b35-image.png

       
       

      Step 3 - Discussion On How to Detect Tree Obstacles

       

      Before we jump into coding, let’s talk strategy. How can our Controller sprite, which only sends commands, know if the Truck sprite is about to hit a tree?

      In standard Scratch, you might try a “ghosting” technique: quickly move the sprite forward, check for a collision, and move it back before the screen refreshes. But that won’t work here, because our Controller sprite and Truck sprite are separate. The Controller can’t directly move the Truck to test for collisions.

      So, we need a different, more clever approach:

      1. We’ll temporarily move our invisible Controller sprite to the exact location of our Truck.
      2. We’ll point the Controller sprite in the direction we want to move.
      3. From that position, we’ll use a new sensing block to scan a rectangular “detection area” in front of the sprite to see if any trees are inside it.

      f4986eed-18f1-4579-bb80-c3b2c3ffc0f1-image.png

       
      Let’s implement this idea in the next few steps.

       
       

      Step 4 - Move the AI sprite to the Truck

       

      First, let’s get the current X and Y position of our truck using its my team clone ID. Then, we’ll use a go to x y block to instantly move our Controller sprite to that same spot.

      175785d7-a156-4a1c-8912-5bf7c015687b-image.png

       
      Remember, the Controller sprite is invisible, so you won’t see anything change on the stage. The whole point of this move is to establish a starting point for our tree-detection scan.

       
       

      Step 5 - Face Upward if Command is 1

       

      If the command we’re checking is 1 (move up), we need to check for trees above the truck. To do this, we’ll point our Controller sprite upwards (direction 0). This step is crucial because the detection area we’re about to create is always relative to the direction the sprite is facing.

      7685dd78-7648-4247-91ed-471070c53c5d-image.png

       
      Again, we’re just using the invisible sprite’s direction to set up our detection area.

       
       

      Step 6 - Handle the Other 3 Directions

       

      Similarly, we’ll handle the other three possible commands (2 for down, 3 for left, and 4 for right), pointing the Controller sprite in the corresponding direction each time.

      fbccfb61-6302-48cd-bf48-84755e14ddb7-image.png

       
       

      Step 7 - Detect Tree Clones in a Rectangle Area

       

      With our Controller sprite now at the truck’s location and pointing in the direction of intended movement, we’re ready to scan for trees. We’ll use the find clones of sprite in rectangle block. Here’s how this powerful block works for our setup:

      c23887b5-3c95-4658-b4dc-95616a62c3ce-image.png

       
      Explanations:

      • We are looking for visible clones of the Tree sprite. The original Tree sprite is hidden, so this check will correctly ignore it.
      • The rectangle is defined relative to the Controller sprite’s forward direction. So if the command is 1 (up), the Controller is facing upward, and the rectangle will extend 60 units forward and expand 90 units wide, like this:
        e53ff571-b6ed-40ee-bf1a-ac615cddc752-image.png
         
      • We will store information about all clones found in the table1 variable.

       
      Feel free to fine-tune the distance and width values. Think of distance as how far ahead the AI can “see,” and width as its “peripheral vision,” or how wide you want to scan.

      If the center of any Tree clone is inside this rectangle (i.e. its center point falls into this rectangle), it will be listed in the table, which includes columns for clone ID, x, y, and distance.

      884533a1-10be-42c5-b409-1fab2058027b-image.png

       
      If more than one clone is found, the table will be sorted by distance, with the closest one listed first.

       
       

      Step 8 - Check If Table is Empty

       

      We don’t need the specific details of the trees, just whether any tree was found. So, we can simply check if table1 has any rows. If the row count is greater than 0, a tree is blocking the path, and our block should return 1. Otherwise, the path is clear, and it should return 0.

      85f2ebe6-6b1d-4a3c-8d31-42ce5156a618-image.png

       
       

      Step 9 - Check if Command Direction is Blocked

       

      Now we can put our new reporter block to use! Back in the main loop, right before we set the new command, we’ll call direction is blocked to check the path.

      Also, to make our AI more responsive and quicker to react to obstacles, let’s reduce the wait time in the main loop to 0.1 seconds. This allows it to check for blockages more frequently.

      dd6c0245-3d1d-4259-bab7-207b0f9a1321-image.png

       
       

      Step 10 - Calculate a Detour Command

       

      If our check finds that the intended direction is blocked, we need to calculate a detour. We’ll create another new custom block, calculate detour, to handle this logic. This block will figure out a new, unblocked detour command which will then temporarily override the new command.

      3fb16588-9fe2-4fb8-b205-ac2716cf1e9c-image.png

       
       

      Step 11 - Discussion on How to Make a Detour

       

      So, how do we calculate a smart detour? There are many complex pathfinding algorithms, but we’re looking for a solution that is effective, fast, and simple to build.

      Imagine the truck needs to get the Gas on the top right, but a tree is blocking the path to the right.

      a412f367-612a-4b1e-b283-0d401eaac2ed-image.png

       
      We have a few command options:

      • new command: The original, blocked command (e.g., move right).
      • alt command: The other direction towards the target. Since the Gas is also above the truck, moving up would be a good alternative.
      • alt command 2: The opposite of the alt command. This is a backup plan if the alt command is also blocked.
      • back command: The opposite of the new command. If all forward and side paths are blocked, our only choice is to back up to escape the “trap”.

      Our strategy will be this: when we’re blocked, we will check these alternatives in order. Once we find a clear path, we’ll execute a two-step detour (e.g., move sideways for 1 second, then move toward the target for 1 second) before returning to our normal logic. This simple strategy will handle most situations very effectively. Let’s build it!

       
       

      Step 12 - Initialize Detour

       

      Inside our new calculate detour block, the first thing we’ll do is set up a couple of variables to manage the detour process:

      • in detour: A “flag” variable. We’ll set this to 1 to signal that the AI is currently executing a detour.
      • detour start time: We’ll record the current timer value here. This will help us time each step of the detour.

      f6ecfbf9-17a3-44ef-b20c-dd5562b93e8e-image.png

       
       

      Step 13 - Calculate the Alt Command

       

      Next, we need to determine the best alternative command (alt command). This command should still move the truck generally closer to its ultimate target.

      If our original new command was vertical (up/down), the alt command should be horizontal (left/right). We can pick the correct horizontal direction by looking at distance x. If distance x is positive, the target is to the right, so our alt command should be 4 (move right).

      3a1a1f08-0484-49ec-a60d-4118f1640434-image.png

       
      Similarly, if the new command was horizontal (left/right), the alt command should be vertical (up/down). We can use distance y to decide whether to move up or down.

      c407b2cf-b9f4-472f-8e39-683bd1184d14-image.png

       
       

      Step 14 - Calculate the Alt Command 2

       

      The alt command 2 is always the opposite of the alt command. We can use a neat little math trick for this: since (left=3) + (right=4) = 7, we can calculate the opposite by subtracting from 7. This logic works whether the new command was vertical or horizontal.

      6d2c1877-59ee-4beb-adb6-64e82dbb4d8c-image.png

       
       

      Step 15 - Calculate the Back Command

       

      The back command is always the opposite of the new command. We can use a similar calculation based on whether the command is vertical or horizontal.

      f3e0c2e3-979f-4070-90bc-3d5acd43ecb2-image.png

       
       

      Step 16 - Take the Alt Command If Available

       

      Now we’ll decide which detour path to take. Our first choice is always the alt command. We use our direction is blocked reporter to check if that path is clear. If it is, we’ve found our detour! We’ll set up a two-step plan:

      1. detour command: Set to the alt command.
      2. detour command 2: Set to the original new command.

      This means the truck will first move sideways, then try to resume its original path. Since we’ve found a plan, we can use a return block to exit the calculate detour script.

      d8dd9db1-4783-496e-9570-1dfe91045fa0-image.png

       
       

      Step 17 - Take the Alt Command 2 If Available

       

      But what if the alt command path is also blocked? This means obstacles are in front of us AND on one side. Our next best option is to try alt command 2 (the other side). If that path is clear, we’ll set our detour plan to use alt command 2 first, followed by the original new command.

      11d44863-29a4-4af4-9391-9e0010c78439-image.png

       
       

      Step 18 - Take the Back Command as a Last Resort

       

      In the worst-case scenario, the paths forward, left, and right are all blocked. The truck is trapped! The only way out is to back up. We’ll set the detour plan to use the back command first, and then follow it up with the alt command to try and steer around the trap.

      bbc8c789-da7f-4c2e-94e8-b7e3486d8d39-image.png

       
       

      Step 19 - Add a New Branch for Detour

       

      Now we need to modify our main loop to actually execute the detour. When the in detour flag is set to 1, we need to bypass all our normal logic (checking powerups, finding the opponent, etc.). Instead, we will run a separate branch of code dedicated to the detour.

      The animation below shows how to restructure your main loop with an if/else block based on the in detour variable. Notice that the block that sends the command to the truck is now outside and after the if/else, so it runs in every situation.

      restructure.gif

       
       

      Step 20 - Stop Detour in 2 Seconds

       

      Inside the new “detour” branch of our if/else block, we’ll manage the two-step detour sequence. The whole detour will last for 2 seconds. By default, the new command will be our detour command. If the timer shows that 2 seconds have passed since the detour start time, the detour is over. We’ll set the in detour flag back to 0, so that on the next loop, the AI will go back to its normal behavior.

      c01a326f-df6f-49de-b426-52a67b4b9c54-image.png

       
       

      Step 21 - Switch to Second Detour Command in 1 Second

       

      The detour itself has two parts. For the first second, the truck will follow detour command. After one second has passed, we’ll switch the new command to detour command 2 for the second half of the detour. This creates the “go sideways, then go forward” maneuver.

      f3fed8c3-0722-4602-82f5-f816c64a6093-image.png

       
      And that’s it! Our detour logic is complete. In short, when the AI “sees” a tree, it will now intelligently try to move sideways or even back up for a moment to get around it.

       
       

      Step 22 - Test This Version

       

      It’s time for the final test! Go to the Setup sprite and set the tree count to 6 (or even more to make it really challenging). Run the project and watch how your AI truck now cleverly navigates around the trees instead of getting stuck. You can also speed up the powerup spawn times again for a more action-packed test.

      Here is a demo:

      detour2.gif

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Further Improvements

       

      This AI controller is already much smarter, but there’s always room for improvement! If you want to take your AI to the next level and win battles, consider these enhancements:

      • Smarter Attack and Dodge: Have you noticed your truck sometimes has a perfect shot lined up but decides to wander off instead? Improve the attack mode to recognize when it’s aligned with the opponent, take the shot, and then immediately move sideways to dodge any return fire.

      • Strategic Powerup Denial: Right now, your AI only grabs powerups it needs. But what if your opponent is low on health and a Sugar powerup appears? A truly smart AI would grab that powerup just to prevent the opponent from getting it! Modify your check powerups logic to consider the opponent’s status, too.

      • Don’t Waste Ammo: Firing donuts into a tree is a waste! Before shooting, you can use a similar detection method to the one we built for avoiding trees. Check if the line of sight to the opponent is clear. If it’s blocked by a tree, hold your fire and reposition.

      • Press the Advantage: When your truck is stronger (more lives, more speed), it should be more aggressive! Instead of firing one shot and then wandering away, why not make it stay in attack mode and keep firing as long as it has the upper hand?

       
      These are just a few ideas to get you started. The best way to improve your AI is to watch it battle. What mistakes does it make? When does it get outsmarted? Every battle is a chance to learn and come up with your own unique strategies to build the ultimate champion

      posted in Tutorials
      info-creaticode
      CreatiCode
    • RE: How to find "If Shift key pressed"

      @rubiired

      That’s the idea. It shouldn’t take long once we finish the other tasks ahead of it in the queue.

      posted in Help
      info-creaticode
      CreatiCode
    • Game AI for Candy Truck Battle - Part 1 (Difficulty: 3)

       

      Introduction

       
       

      Candy Truck Battle is a 2D online shooting game played between two players. Each player controls a candy-themed truck that can move around, collect power-up items like Sugar and Gas, and fire donuts at the opponent.

      Players control the truck using:

      • WASD keys to move in 4 directions
      • SPACE to shoot donuts

      In this tutorial, we’ll build an AI (Artificial Intelligence) that can automatically control the truck in this game. Instead of using the keyboard, the AI will decide when to move and shoot, all by itself.

      We’ll go through a series of increasingly powerful AI versions, each adding more intelligence and strategy.

      Here’s a preview of what happens when two AIs face off after you complete this tutorial:

      attack.gif

       
       
       
       
       
       
       
       
       

      Version 1 - Random Walk (Difficulty: 2)

       

      The first version of the AI will do something very simple: send out random movement commands. It won’t think, aim, or chase. It will just wander around randomly, like a monkey pressing buttons.

      That might sound silly at first, but it’s actually very useful for two reasons:

      1. It helps us set up and test the AI system early, without needing complicated logic. Once we get this working, we can improve it gradually.

      2. It serves as a baseline. Any future AI we build should be able to beat this one. If not, the new AI probably isn’t very smart.

      Let’s get started.

       
       

      Step 1 - Remix the Game Project

       

      Go to the following link and remix the original game project to create your own copy:

      play.creaticode.com/projects/6858d69beb4683fb2ab03c73
       
      If you’re interested in how this multiplayer game was built, you can read the detailed explanation in this tutorial.

       
       

      Step 2 - Understand the Manual Controller

       

      The Controller sprite is responsible for handling user input. Let’s take a look at the script that controls movement and shooting:

      blocks (1).png

      Here’s what the code does:

      • It starts running after receiving the "start game" message.
      • It enters a forever loop, constantly checking if the player is pressing any movement keys (W/A/S/D).
      • If the SPACE key is pressed, it sends out a "shoot donut" message.
      • If one of the W/A/S/D keys is pressed, it sends out a movement command using the "my team" message, with a value of 1–4 (up/down/left/right).
      • If no key is pressed, it sends command 0 (stand still).
      • It only sends a command when it’s different from the last one, to avoid spamming cloud variable updates.

       

      In summary, our AI needs to:

      • Send "my team" messages with movement commands (0 to 4).
      • Send "shoot donut" messages at the right time.

      That’s it! Once we can send those messages, we can fully control the truck without touching the keyboard.

       
       

      Step 3 - Remove the Key Press Related Code

       

      Let’s begin building our AI by reusing the manual controller’s loop, but deleting all the blocks related to key presses.

      We end up with this stripped-down version:

      a9892099-e063-41e4-8c87-7332c49bab8c-image.png

      Now we have a basic framework that can send commands. Next, we’ll let it pick commands at random.

       
       

      Step 4 - Set a random new command

       

      To make the truck move randomly, just pick a number between 0 and 4.
      Each number means:

      • 0 → stand still
      • 1 → move up
      • 2 → move down
      • 3 → move left
      • 4 → move right

      Use the pick random block like this:

      de138734-7a34-424e-984c-f7de5e83e789-image.png

      This alone is enough to make the truck wander.

       
       

      Step 5 - Add a Short Wait

       

      Without a delay, the loop may send hundreds of commands per second, which can overwhelm the cloud server or cause lag.

      Let’s slow it down by adding a wait block. One second is a good starting point:

      02094c89-ddf6-436a-a69c-61f45423525e-image.png

      Now the AI will choose a new move every second.

       
       

      Step 6 - Test the AI By Yourself

       

      Now it’s time to test! You can run two copies of your game in your browser to simulate two AIs playing against each other.

      Here’s how:

      1. Open two browser windows side by side.
      2. Open your remixed project in both windows.
      3. In browser A:
        • Click the green flag
        • Click Create Game
           
      4. In browser B:
        • Click the green flag
        • Click Join Game using the same session ID
           
      5. In browser A:
        • Click Start Game

      Now both trucks will begin moving randomly!

      Here’s what that looks like:

      randomwalk.gif

      This is a working AI. It’s not smart, but it’s alive. And now that you’ve built this, you’re ready to level up and give your truck a brain.

       
       
       
       
       
       
       
       
       

      Version 2 - Random Targets (Difficulty: 3)

       

      In the second version of our AI, we’ll give it a bit more purpose: instead of randomly pressing movement buttons, it will now pick a random target location and attempt to move there.

      This small change makes the AI appear more intentional, even though it’s still completely blind to rewards, opponents, or obstacles. In future versions, we’ll replace the randomness with smarter decision-making.

       
       

      Step 1 - Prepare for the new version

       

      We will duplicate the code from Version 1 and modify it.

      1. Detach the old random command block.
      2. Keep the basic loop and message-sending logic.
      3. Remove the block that picks a random number (0–4).

      The structure should now look like this:

      71ec534b-b736-49c8-9a77-87b1f496b2b5-image.png

       
      Don’t forget to disconnect the existing code from version 1. Otherwise it will keep sending random commands.

       
       

      Step 2 - Initialize with a random target location

       

      We’ll choose a random position on the stage as our target. Use two new variables: target x and target y. These should be initialized before the loop starts.

      Make sure the coordinates are within the stage boundaries:

      fa38b795-4a5b-4da6-a0b8-eb50edb913cc-image.png

       
       

      Step 3 - Calculate X and Y Distances

       

      To move toward the target, the AI needs to compare the truck’s position to the target’s position.

      You can use the following sensing block to get the X and Y coordinates of the truck. Make sure to reference the correct clone ID, which matches the player’s my team value.

      f35740ea-5ea3-4b98-91a0-22ebd7809c30-image.png

      At the start of each loop iteration, calculate and store the horizontal and vertical distances:

      0ebcb715-3054-4c09-8eb5-dc87432509cd-image.png

       
       

      Step 4 - Pick a New Random Target Upon Arrival

       

      If both distances are small (e.g. less than 20), the truck is close enough to its target. In that case, we’ll pick a new random target.

      6cb1da1c-520f-46d2-99b5-077bfaefac29-image.png

       
       

      Step 5 - Compare Distance X and Distance Y

       

      To decide whether to move horizontally or vertically, we compare the absolute value of the distances. Whichever is larger becomes the axis we move along.

      fb8431e1-ab46-4efc-a886-0a0a652cc005-image.png

       
       

      Step 6 - If Horizontal Distance is Larger

       

      If the distance is wider horizontally, then we move left or right depending on whether the truck is to the left or right of the target.

      5f1742f2-4c6a-4237-a40c-10efa05019d7-image.png

      This version of the AI will go horizontally first in this case.

      To decide left or right, check the sign of distance x:

      6b314471-5e49-4e2c-aa52-5eb4b2a480cf-image.png

       
       

      Step 7 - If Horizontal Distance is Smaller

       

      Otherwise, vertical distance is larger, so we’ll go up or down based on the sign of distance y:

      f5d92b4e-08bf-4f7e-b627-b8540e51459b-image.png

       
       

      Step 8 - Test with No Trees

       

      To test if our AI is working properly, we will make some adjustments to the project:

      Remove Trees

       
      In the Setup sprite, change the tree count to 0. This is because our truck can not avoid trees yet, so it would get stuck at a tree forever.

      30fec463-c3e5-420d-ae13-90094e0977d6-image.png

       

      Display variables

       
      Show these 4 variables on top of the stage, so we can check the truck’s movement against these variables:

      a3693fa6-a446-47fc-b850-426a0c14d22f-image.png

       
      Now run 2 instances side by side. You’ll see the trucks moving directly toward randomly chosen spots:

      randomtarget.gif

       
       

      Step 9 - Fix the Deadlock Issue

       

      You might notice that sometimes a truck gets stuck at the target, going back and forth near the target point but never switching to a new target.

      Here’s what that looks like:

      stuck.gif

       
      Can you think about what the reason is?

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      The reason for this issue is the wait time in the loop. Here’s what’s happening:

      • Truck is 30 steps from the target → moves forward
      • The truck moves 80 steps in one second
      • It overshoots → next time it’s 50 steps away, but on the opposite side
      • This repeats endlessly

      ✅ The Solution:

      Lower the wait time. Set the wait block to 0.2 seconds or even smaller. This way, the AI updates its movement more frequently, and doesn’t overshoot as easily.

       
       
       
       
       
       
       
       
       

      Version 3 - Random Targets or Attacking (Difficulty: 3)

       

      In this third version of our AI, we add the ability to switch between two behaviors:

      1. Wandering to a random location (as in Version 2);
      2. Attacking the opponent truck directly.

      This change brings the AI to life. It now uses the second message type, shoot donut, and can actually cause the game to end, unlike before where both trucks wandered forever.

       
       

      Step 1 - Refactor the Code for Random Target

       

      Start by duplicating the AI code from Version 2.
      We’ll extract all the logic related to reaching random targets into a custom block called wander.

      This simplifies the main loop to:

      ad44f943-2bce-4f15-8f45-d05571f345b8-image.png

      And the wander block contains the logic we moved:

      ab3972da-4183-48ba-9918-3262bf8222fd-image.png

       
       

      Step 2 - Define the mode

       

      The AI can now be in one of two modes: "wander" or "attack". We’ll create a new variable mode, and initialize it to "wander":

      1522a61a-205c-4309-8014-e152c279b067-image.png

       
       

      Step 3 - Switch to “attack” mode

       

      Instead of picking a new random target after reaching one, we now switch to attack mode:

      bc4952a3-28c2-4b52-9d22-7b711f58e037-image.png

       
       

      Step 4 - Define the “attack” Block

       

      Define a new block “attack” to contain the logic of attacking the opponent.

      Then, in the main loop, we’ll now check the mode before deciding which behavior to run:

      d6eb7056-676d-4968-af72-c8fb037760c6-image.png

       
       

      Step 5 - Calculate Distance to Opponent

       

      Inside the attack block, we calculate the X and Y distance to the opponent truck using clone ID 3 - my team: For example, if my team is 1, then the opponent’s ID is 3 - 1 = 2.

      5b997cfe-7d12-4452-bad5-e9fb5b76385d-image.png

       
       

      Step 6 - Check If We can make a shot

       

      We are ready to shoot if the opponent is aligned horizontally or vertically with our truck (i.e., the distance in the X or Y direction is less than 15):

      8d3f1204-07fc-4dcf-bca5-4b727537541b-image.png

       
       

      Step 7 - Move to Align with the Opponent

       

      Let’s work on the logic to move to the target first, since we already have code doing similar things.

      We can first duplicate the logic from the “wander” block, which looks at whether the vertical or horizontal distance is larger and turns the truck accordingly:

      a45cb1ae-574f-485e-8b39-91a6d72d5964-image.png

       
      However, we will make one change: when the horizontal distance is larger, we should move our truck vertically, since it is faster to align horizontally to make a shot.

      For example, in this situation below, we should move the yellow truck down, then fire the shot horizontally:

      b2835bde-144f-4e6c-b1a8-8ce4806a259d-image.png

       
      The code change is very simple. We just need to swap the 2 “if-then-else” blocks:

      a78657c0-2af5-459f-89c6-050d8af47d3e-image.png

       
       

      Step 8 - Turn to the Opponent

       

      To shoot at the opponent, we need to first turn our truck towards it. Let’s define a new block turn to opponent. It turns out this is exactly the same logic we used for moving the truck towards the target position:

      67b82d3e-ad4c-4d5c-b19c-1d990ed01d2d-image.png

       
      We will use it in the “attack” logic:

      ccf8541c-9ecd-4537-ae03-07f89d220d3c-image.png

       
       

      Step 9 - Send out the movement command

       

      The turn to opponent block sets the command, but doesn’t send it. So send it now:

      3ecc2613-4a6e-4321-b064-a24e4a8251e1-image.png

       
       

      Step 10 - Take a Shot

       

      After turning, wait briefly so the truck finishes its turn, then fire the shot:

      e6918415-843e-491e-ab54-c1058936572f-image.png

       
       

      Step 11 - Switch back to “wander” mode

       

      After firing, the AI goes back to wander mode and picks a new random location:

      1c398e36-0844-43ac-8619-f8f63ec72210-image.png

       
       

      Step 12 - Testing

       

      Keep trees disabled in the Setup sprite.
      Show the mode variable on screen to visualize what the AI is doing.

      Here’s how it looks in action:

      attack.gif

       
       
       
       
       
       
       

      Improvements

       

      Version 3 completes the core loop of wander → attack → wander, allowing the game to reach an actual ending. But it’s still a pretty weak AI. Let’s look at a few obvious improvements.

      ✅ 1. Smarter Target Switching

      Currently, the AI only switches to attack mode after arriving at a random target. But it may have had a clear shot on the opponent midway through wandering.

      Fix: Constantly check if it’s aligned with the opponent, even during wander, and switch to attack instantly if possible.

      ✅ 2. Dodging After Attacking

      After shooting, the truck just picks a new random target — which might keep it in the line of fire.

      Fix: After firing, pick a target that’s not in the same row or column as the opponent.
      Or define a third mode: escape, and cycle like this:
      wander → attack → escape → wander …

      ✅ 3. Combo Firing

      Once the AI aligns with the opponent, it only fires one shot.
      But it may be better to fire multiple donuts before wandering off.

      Fix: Add a cooldown timer and allow burst fire.


      These enhancements will make your AI more competitive — especially against another AI using the same version.

      In Part 2 of this tutorial, we’ll teach the AI to avoid obstacles and collect power-ups.

      posted in Tutorials
      info-creaticode
      CreatiCode
    • RE: How to find "If Shift key pressed"

      @the_true_odst

      Sure. But it will take a while. Maybe a few weeks.

      posted in Help
      info-creaticode
      CreatiCode
    • Multi-player 2D game <Candy Truck Battle> - Difficulty 6

       

      Introduction

       

      In this tutorial, you’ll build a 2-player game called Candy Truck Battle, where two candy trucks collect rewards and fire donuts at each other. Each player controls one truck on their own computer, but they’ll both see the full game scene on their screens.

      To connect the two players across computers, we’ll use the enhanced cloud variables provided by CreatiCode. Here’s a quick preview of the final result:

      finaldemo.gif

       
       
       
       

      Module 1 - Setting Up the Game Session

       

      In this section, you’ll set up a game session that connects two players running the same project on different computers. We’ll use widgets for the user interface, and cloud variables for real-time communication between the two players.

       
       

      Step 1 - Remix the Starter Project

       

      Start by remixing this project:

      play.creaticode.com/projects/68543e0c23ae1eb9ca386f59

       
      It contains everything you’ll need: trucks, trees, donuts, rewards, and other assets.

       
       

      Step 2 - Display the Game Name Input

       

      Open the “Setup” sprite, which manages the connection between two players.

      Create a new custom block called show setup screen and run it when the green flag is clicked:

      c84d3e16-232a-4353-9eea-465b711736d7-image.png
       

      Inside this block, start by displaying a label and an input box:

      6bf5c536-45f9-4c6e-9ee4-0f02c503228c-image.png

       
      The label has a fully transparent background and 0 border, so we directly see the white text over the green stage. The input box has a default value of 1234 as an example.

      This game name will be used later as a “session ID” to create a new game session. Each pair of players will share a common session ID, so that the cloud variables will only be kept in sync between them. This way, players in different sessions won’t interfere with each other.
       
      Here’s what it looks like:

      d06b0b8a-d4ec-406a-98f8-e524d520a37e-image.png

       
       

      Step 3 - Show 2 Action Buttons

       

      To connect just these two players using cloud variables, one player needs to create the session and the other must join it using the same session ID.

      Under the input box, add a label and two buttons:

      97f1210a-f1c5-4be8-a781-9f2f5da27a2a-image.png

       
      Here are the blocks you’ll add inside the show setup screen block:

      8a3775a1-d738-4602-b67d-fd4bbc4a3891-image.png

       
       

      Step 4 - Handle the “Create Session” Button

       

      When the “create session” button (“button1”) is clicked, we will first set a few key variables:

      1762b11d-8f2d-4604-a3da-0542f6c24eaf-image.png

       

      • Player 1 sets my team = 1 and opponent team = 2.
      • Store the session ID in a variable like session input.

       
       

      Step 5 - Create the Session and Handle Errors

       

      Use the create cloud session block. If it fails (usually because that session ID already exists), show an error and let the player try a different ID.

      5f9a234b-ed1e-42ce-8cbe-01ea925cc7b6-image.png
       
      Here’s the error message shown to the user:

      bb2e38bc-3cf4-490f-8fb8-32e73c4104b1-image.png

       
       

      Step 6 - Show a waiting message

       

      If player 1 successfully creates the session, they’ll wait for the second player to join.

      975c5066-aa8b-4d9e-82f4-38e540b43d3a-image.png

       
      The message looks like this:

      62027797-0808-4fa8-8b64-cab54fe2af30-image.png

       
       

      Step 7 - Wait for ☁ ready2 from Player 2

       

      We’ll use the cloud variable ☁ ready2 to let player 1 know when player 2 has joined. Initially, set it to 0.

      Once player 2 joins, they’ll set ☁ ready2 = 1, and player 1 will detect this change.

      2e26f356-7a3c-410b-a0c8-3c6c5b1ac7b5-image.png

       
      2681b78e-f496-4af3-842b-4aabf26d32f8-image.png

       
       

      Step 8 - Handle Player 2 Joining the Session

       

      When the second player clicks Button 2 (“Join Session”):

      • Set my team = 2 and opponent team = 1
      • Save the session ID
      • Try to join the existing cloud session

      If successful:

      • Show a “Waiting for player 1…” message
      • Set ☁ ready2 = 1 (this triggers player 1’s next step)

      If it fails, player 2 probably used the wrong ID or the session isn’t created yet.

       
      ecea004a-9699-443b-901c-7f95988cbcaf-image.png

       
       

      Step 9 - Show “Start Game” Button for Player 1

       

      Once ☁ ready2 = 1 is detected on player 1’s side, we hide the setup screen and show a new “Start Game” button.

      bfb57002-a68e-44f9-b2e9-653b5d9b71d3-image.png

       
       

      Step 10 - Start the Game

       

      When player 1 clicks “Start Game,” set the cloud variable ☁ game state = 1 to let both players know the game has started.

      Start with ☁ game state = 0 when the project loads:

      1a5818e5-b4c1-4571-801d-45a88bc618cd-image.png

       
      Then update it when the button is clicked:

      3d591b58-9c4f-4cc4-97c9-8da9517c5bd0-image.png

       
       

      Step 11 - Wait for ☁ game state = 1

       

      Once ☁ game state = 1, both players proceed.

      For player 1:

      1c28f136-528f-4164-b8d1-c37791f5e95e-image.png

       
      And for player 2:

      d2286f7d-bd46-4591-b6d8-f2a02a23ee94-image.png

       
       

      Step 12 - Show Life Count

       

      After the game begins, show each player’s life count, starting at 3. Create a block called show life count:

      9a99bf8d-4348-422d-90b0-ecfea1ca4fad-image.png

       

      • Use lives_1 and lives_2 as label names for updates.

      Call this block for both players:

      2f432994-d3f6-4135-b6a6-14b10d54c012-image.png

       
      eb9d5444-49c0-4b2e-a68c-a940563e5520-image.png

       
       

      Step 13 - Recap

       

      Let’s walk through the full connection process:

      1. Player 1 enters a unique session ID (like “1234”) and creates a cloud session. They wait for ☁ ready2 = 1.
      2. Player 2 uses the same session ID to join. If successful, they set ☁ ready2 = 1 and wait for the game to start.
      3. When player 1 sees ☁ ready2 = 1, they get a “Start Game” button. Clicking it sets ☁ game state = 1.
      4. When both players see ☁ game state = 1, they clear the setup screen and display lives.

      To test the setup on one computer:

      1. Save and share the project.
      2. Open a new incognito window, log in to creaticode.com, and open the project link.
      3. Arrange the two windows side by side.

      Or test with a friend on a different device.

       
      Here is what it looks like on 2 browsers:

      setupsession.gif

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Module 2 - Adding Game Objects

       

      In this module, we’ll add the main objects to the game scene, starting with the trucks and trees. To keep both players’ views identical, we’ll rely on cloud variables to make sure these objects are created in exactly the same way on both computers.

       
       

      Step 1 - Broadcast the “add trucks” message

       

      After the life count is displayed on both computers, we broadcast a message called “add trucks”:

      ec50b2dc-4ab9-40d7-a791-1ac8701ce5c2-image.png

       
      484bc863-b60b-4491-8425-56a342499f04-image.png

       
       

      Step 2 - Create Truck Clones

       
      Switch to the Truck sprite.

      Since we only use clones for gameplay, hide the original sprite when the green flag is clicked. When the sprite receives the "add trucks" message, it will create two clones, one for each player:

      43d93ad4-a13e-4bf6-a05d-5f4556771446-image.png

       
      Each clone has a unique clone ID:

      • 1 represents Player 1’s truck
      • 2 represents Player 2’s truck

      In total, there are 4 clones running across both computers: each player controls their own truck locally, and the other player sees a “mirror” clone of that truck on their computer.

       
       

      Step 3 - Initialize the Truck Clone State

       

      Every truck clone will start with a ☁ my state variable with a value of 0. This value indicates which direction the truck is moving:

      • 0: Not moving
      • 1: Moving up
      • 2: Moving down
      • 3: Moving left
      • 4: Moving right

      e907c86f-297a-4f5c-a510-598b575370dd-image.png

       
      Note that the ☁ my state variable is a cloud variable, and each truck clone has its own ☁ my state variable. The value of this variable is synchronized between the 2 clones with the same ID on the 2 computers. For example:

      If Player 1 sets clone 1’s state to 3 on their computer, the state of clone 1’s mirror on Player 2’s computer is also updated to 3, so the clone 1 truck will start moving left on both computers. Meanwhile, clone 2’s state is unaffected.

       
       

      Step 4 - Additional Truck Initialization

       

      Each truck clone should also be initialized with:

      • A life count of 3
      • A speed of 40 (feel free to change the speed)
      • A costume based on its ID (1 for yellow, 2 for red)
      • And it should be shown, since the original Truck sprite stays hidden

      bd3d5356-86db-42fa-9387-c2cb0b6f5337-image.png

       
       

      Step 5 - Set Starting Positions

       

      Now place the two truck clones in opposite corners:

      6ec4b79a-a6e9-417e-ad27-6588a8a67b0c-image.png

       
      After running the project, you’ll see the two trucks appear like this:

      07fe0e07-97e0-4d66-b65d-4b6c3ffb0855-image.png

       
       

      Step 6 - Broadcast the “add objects” message from “Setup”

       

      Back in the Setup sprite, after the trucks are added (on Player 1’s computer only), we send the "add objects" broadcast:

      f5437ada-b0b5-4b21-9c35-08898f321269-image.png

       
      Only Player 1 sends this message. Player 1’s program will decide when and where to add the objects, and then share those details with Player 2 using cloud variables.

       
       

      Step 7 - Configure the Tree Count

       

      Trees are static obstacles that block both trucks and the donuts they shoot. Use the variable tree count to define how many trees to add.

      Set this value in the Setup sprite:

      d07b4906-39d1-44f2-ad5b-3db0a6763287-image.png

       
      Then, in the Tree sprite, when it receives the "add objects" message, it checks if tree count > 0:

      aac7c68b-01a6-4f95-836a-52dc0ee02fb3-image.png

       
      Again, this part of the code runs only on Player 1’s computer after the “Start Game” button is clicked.

       
       

      Step 8 - Generate a Tree List

       

      To ensure trees appear in the same places for both players, we generate their positions on Player 1’s computer, then share them using a cloud variable.

      We use the format "x_y" for each position. A list of 2 tree positions might look like:

      120_-23_100_70
      

      Here’s how to build that list step by step:

      fad951e8-dfb4-4e92-98fd-914c6fecaefc-image.png

       
      The tree list variable starts as empty, and then we repeatedly append a random x position and a random y position to it, all using the “_” separator.

       
       

      Step 9 - Share the List Using ☁ all trees

       

      Once Player 1 has the full list, assign it to the cloud variable ☁ all trees.
      Then both computers will extract the same data and generate trees accordingly:

      2da8c79b-82f0-4f42-9669-8754be44bc89-image.png

       
       

      Step 10 - Create Tree Clones

       

      To create each clone:

      1. Extract the x and y positions from the list using the "part of by" block
      2. Move the Tree sprite to that location
      3. Create the clone

      Each tree takes up 2 entries in the list (x and y). So tree #1 uses part 1 and 2, tree #2 uses part 3 and 4, and so on.

      154735de-dd3e-4c0f-924d-65b936531c69-image.png

      4f58af6c-7060-485f-ae93-4dbd5192a4c0-image.png

       

      Use a loop to process each tree:

      5c5daf47-07c1-4284-a559-e2572533ef01-image.png

       
       

      Step 11 - Hide the Original Tree Sprite

       

      We’ll only use clones for the trees. Hide the original sprite and show each clone when it’s created:

      hide-tree-original.png

      Now, test the game—you should see identical trees on both screens:

      trees-both-sides.png

       
       

      Step 12 - Add Sugar objects

       

      Sugar objects restore a truck’s life when collected.

      Unlike trees, Sugars appear dynamically during gameplay, and may also disappear if not collected. So they’re handled differently.

      In the Sugar sprite, when "add objects" is received:

      • Start a loop to randomly generate Sugar positions
      • Each Sugar gets a unique ID
      • A cloud variable ☁ new sugar info stores "ID_x_y" for the next clone

      sugar-gen-code.png

      Key points:

      • IDs start at 1 and increment
      • Wait a random 30–90 seconds between Sugars
      • This loop runs only on Player 1’s computer

       
       

      Step 13 - Create Sugar Clones

       

      On both computers, whenever ☁ new sugar info changes, split it to get the ID and coordinates, then create a clone.

      69e6217b-8bde-49ff-91de-a34ec224fa30-image.png

       
      Before cloning, check the clone ID is “originalsprite” to avoid duplicate clones from existing ones.

      Use the first part (ID) to uniquely identify each clone.

       
       

      Step 14 - Hide the Original Sugar Sprite

       

      Just like with trees, hide the original Sugar sprite and show only its clones:

      hide-tree-original.png

       
       

      Step 15 - Auto-Delete Sugar Clones

       

      Each Sugar clone will wait 15–25 seconds. If it’s not collected, it deletes itself:

      74fca837-90a1-4927-b23a-b740087c11f7-image.png

       
       

      Step 16 - Add Gas Objects (Speed Boosts)

       

      The Gas sprite works just like Sugar, but boosts the truck’s speed instead of restoring life.

      Just duplicate the Sugar sprite’s code and adjust the variables:

      • next gas ID
      • new gas info
      • Any references to “Sugar” should be changed to “Gas”

      112d7dd6-db6d-4168-90ce-e1ae88d64e3b-image.png

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Module 3 - Keyboard Control of the Trucks

       

      Now that the game world is set up, it’s time to let players control their trucks using the keyboard. But remember, this is a two-player online game. That means when a player presses a key to move their truck, the same movement must happen in real-time on both computers.

      We’ll accomplish this using cloud variables to send and sync movement commands.

       
       

      Step 1 - Broadcast the “start game” Message

       

      Once all objects are added and the game is ready, we need to let both players begin controlling their trucks. In the Setup sprite, broadcast the "start game" message on both computers:

      For Player 1:

      startgame-player1.png

      For Player 2:

      startgame-player2.png

      In the Controller sprite, we’ll listen for this message and begin a forever loop to handle keyboard inputs:

      controller-loop.png

       
       

      Step 2 - Detect Key Press and Set Command

       

      Within the loop, check which arrow key the player is pressing:

      • 1: Up
      • 2: Down
      • 3: Left
      • 4: Right
      • 0: No key is pressed (stay still)

      key-detection.png

      This value is stored in the new command variable.

       
       

      Step 3 - Send the Command Only If It Changes

       

      Since this loop runs continuously (many times per second), it could end up sending the same command over and over. That’s unnecessary and wasteful. So we’ll compare the current command to the last command sent, and only send a new command when it actually changes.

      First, store the command 0 in a current command variable initially:

      set-current-command.png
       
      Then, compare it with the new command. If different, save this new command:

      compare-command.png

       
       

      Step 4 - Send the Command to the Correct Truck

       

      Each player controls one of the two trucks. Player 1 controls truck 1, and player 2 controls truck 2. On both computers, both trucks exist, so we need to ensure that only the correct truck clone receives the command from the player.

      Here’s how we’ll do it:

      • Use the my team variable (1 or 2) to send a message with that same number
      • Attach the new command as the parameter (we have made sure this is different from before)

      So Player 1 will send message "1" with the command, and Player 2 will send "2":

      c49bb7cd-1aaf-4c14-9a8c-a82769961baa-image.png

       
       

      Step 5 - Let the Correct Truck Handle the Command

       

      Switch to the Truck sprite.

      All truck clones (ID 1 and ID 2) will receive the message "1" or "2", but only the clone with the matching ID should actually respond. Use an if block to check the clone ID.

      Then define a custom block called handle command that will process the movement:

      handlecommand-block.png

      So if Player 1 presses a key:

      • On Player 1’s computer, Truck 1 responds and updates its state.
      • On Player 2’s computer, Truck 1’s mirror will also update its state.

      This keeps both trucks behaving identically on both screens.

       
       

      Step 6 - Set ☁ my state Cloud Variable

       

      Inside the handle command block, set the cloud variable ☁ my state to the command value:

      set-my-state.png

      Each truck clone owns its own cloud variable. This variable is not visible to other clones or sprites locally—but because it’s a cloud variable, the value is automatically shared with the other player’s computer.

      So the state of a truck is immediately synced across both computers. That’s how both players see the exact same movement for the same truck.

       
       

      Step 7 - Calculate Travel Duration and Distance

       

      Now we’ll build the movement loop. To ensure that truck speed is consistent across fast and slow computers, calculate how much time has passed between iterations of the loop using the timer.

      Use that to determine how far the truck should travel:

      calculate-timer-distance.png

      For example:

      • On a fast computer, the loop might run 40 times/sec, so travel duration ≈ 0.025
      • On a slower one, maybe 20 times/sec, so travel duration ≈ 0.05

      Multiply speed by time to get consistent movement regardless of computer speed.

       
       

      Step 8 - Move the Truck Up (State = 1)

       

      Now use that travel distance to move the truck in the right direction. Start by handling state 1 (move up)

      391fc6b3-60db-4cce-b52f-980d9651ad12-image.png

       
       

      Step 9 - Move in the Other Directions (States 2–4)

       

      Repeat this logic for states 2 (down), 3 (left), and 4 (right):

      move-234.png

      No need to handle state 0 directly—if no key is pressed, the truck simply doesn’t move.

       
       

      Step 10 - Undo Movement if Hitting a Tree or Edge

       

      If the truck hits a tree or touches the edge, immediately reverse the last movement:

      reverse-hit.png
       
      Put this logic at the top level inside the loop, so it always runs on every frame, regardless of what state the truck is in.

       
       

      Step 11 - Sync Position When Truck is Idle (Command = 0)

       

      Even with identical movement commands, trucks can drift out of sync over time due to slight timing delays. Here’s why:

      Imagine Player 1 moves the yellow truck up, then presses right. The command is instantly executed on Player 1’s computer. But there’s a small delay (maybe 0.1 seconds) before that command reaches Player 2. So on Player 2’s screen, the yellow truck moves slightly farther up before turning.

      To fix this, whenever a truck receives command 0 (no movement), we broadcast its exact position to the other computer using a cloud variable ☁ my x y (formatted like "x_y"😞

      sync-on-idle.png
       
      Then, when the other computer receives this update, the matching truck clone updates its position smoothly:

      receive-sync.png

      This ensures both versions of the truck stay visually aligned.

       
       

      Step 12 - Sync Position When Truck Hits Obstacle

       

      When a truck hits a tree or an edge, it should stop moving—and sync its corrected position to the other computer. You can reuse the handle command block by calling it with command 0.

      But only the truck being controlled locally by the player should do this, because only that version has the accurate position. Add this logic inside the collision detection block, not at the top level:

      sync-on-stuck.png

      Now, both players will always see exactly the same movement, even when a truck hits trees or stop moving.

      Here’s a demo of it in action:

      insync.gif

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Module 4 - Collecting Items

       

      In this module, we’ll enable the trucks to collect Sugar and Gas items, which can increase the truck’s life or boost its speed. When a truck picks up one of these items, we need to make sure the effect happens only once, and that it syncs across both computers.

      This means the item should disappear at the same time on both screens, and the truck’s speed or life must update only on the player’s own truck (not the mirrored one).

      Let’s go step by step.

       
       

      Step 1 - Detect Touching the Sugar

       

      Start in the Truck sprite.

      We’ll use the “when touching [object]” block to detect when the truck touches a Sugar clone. But there’s an important detail: each computer has two trucks (clone ID 1 and 2), and we only want the truck controlled by the local player to handle the collection.

      So first, check that my team matches the truck’s clone ID. That ensures only the player’s truck reacts:

      truck-touch-sugar.png

      If you don’t do this check, both the original truck and its remote mirror might react, and the item could be collected twice incorrectly.

       
       

      Step 2 - Notify Which Sugar Was Collected

       

      When a Sugar item is collected, we want both computers to delete that Sugar clone. Since each Sugar clone has a unique ID, we can use a cloud variable to broadcast that ID.

      Set ☁ sugar being collected to the ID of the clone that was touched:

      set-sugar-being-collected.png

      Once this variable changes, every copy of the Sugar sprite (on both computers) will be notified.

       
       

      Step 3 - Increase Truck’s Life (Max 3)

       

      After collecting a Sugar item, the player’s truck should gain one life—but only if its current life is less than 3.

      Here’s the code to do that:

      increase-life.png
       
      This check prevents the truck from going above the max life limit.

       
       

      Step 4 - Delete the Correct Sugar Clone

       

      Now switch to the Sugar sprite.

      We want only the clone with the matching ID to delete itself when ☁ sugar being collected changes. Use the when [cloud variable] changes hat block, and compare the clone’s ID with the new value:

      delete-sugar-clone.png
       
      This event runs on both computers, but only the matching clone actually deletes itself.

      To make this detection work reliably, set ☁ sugar being collected to an invalid ID at the beginning of the game, like -1 or "none":

      init-sugar-variable.png
       
      If you skip this step, the first clone might mistakenly delete itself before anything has been collected.

      Now test it out: try adjusting the Sugar spawn delay to appear more frequently so you can quickly see the effect during testing:
       
      sugarcollect.gif

       
       

      Step 5 - Handle Touching Gas Objects

       

      Back in the Truck sprite, we’ll use similar logic to handle collecting Gas objects. These do not increase life—they increase the truck’s speed instead.

      Duplicate the Sugar collection code and change it to work with Gas. When touched, increase the speed variable of the truck:

      touch-gas.png
       
      Again, remember to only allow the local player’s truck to trigger the collection.

       
       

      Step 6 - Delete the Gas Clone

       

      In the Gas sprite, add logic similar to Sugar. When the cloud variable ☁ gas being collected changes, compare its value to each clone’s ID. If it matches, delete the clone:

      delete-gas.png
       
      And just like with Sugar, initialize this variable to an invalid value at the start:

      init-gas-variable.png
       
      This avoids accidental deletions or unexpected behavior.

      Once you’ve added this code, try testing the collection of both Sugar and Gas. Make sure:

      • Only one truck can collect the item (not the mirror)
      • The effect applies only to that truck
      • The item disappears on both screens

      This logic is essential for keeping both players’ games perfectly in sync.

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Module 5 - Shooting Donuts

       

      In this module, we’ll let players shoot donuts from their trucks. Donuts travel in a straight line and disappear when they hit a tree, the edge of the stage, or the opponent truck. If a donut hits the opponent’s truck, it will lose a life. As always, everything must stay synchronized between both players’ computers.

      Let’s walk through each part of the shooting mechanic.

       
       

      Step 1 - Detect SPACE Key to Fire

       

      In the Controller sprite, add a condition to detect when the player presses the SPACE key. When that happens, broadcast a "shoot donut" message.

      ca2b8092-5090-4b15-909b-b736e2739c68-image.png

       
       

      Step 2 - Only Original Donut Handles the Message

       

      Switch to the Donut sprite. When the "shoot donut" message is sent out, it will be received by both the original Donut and all its clones. So, add a check to make sure only the original sprite handles it:

      a863f526-6d52-4546-98c2-96f02939cc71-image.png

       
       

      Step 3 - Limit Shooting Frequency

       

      To prevent players from spamming the SPACE key, introduce a cooldown. Create two variables:

      • donut_time: last time a donut was fired
      • donut_interval: minimum wait time between shots (e.g., 1 second)

      Initialize them like this:

      donut-time-init.png
       
      And check the current timer value before allowing a new shot:

      7db53c54-f190-4c4a-bfc2-b9f77239f0e7-image.png

       
       

      Step 4 - Get truck position and direction

       

      A donut should appear at the front of the truck, facing the same direction. Use the sensing blocks to get the x/y position and direction of the truck the player is controlling:

      get-truck-position.png
       
      Use my team to access the truck clone ID that matches the player.

       
       

      Step 5 - Track Donut ID

       

      Each donut clone should have a unique ID. Use a variable next donut ID, initialized to 0:

      init-donut-id.png

      Increase it by 1 with each new shot:

      7925599a-d71d-4c97-a97e-9d27534d9a8a-image.png

       
       

      Step 6 - Create ☁ new donut command

       

      Use a cloud variable ☁ new donut command to let both computers know a new donut was fired.

      Its format will be:

      playerID_direction_x_y_donutID

      Start with the direction 90 (right). Offset the x-position by 35 so the donut doesn’t touch the truck that fired it:

      8b2df66f-6d40-4f73-a2da-5d0189496cbe-image.png

       
       

      Step 7 - New donut commands for the other three directions

       

      Repeat the same logic for directions:

      • 0 (up): adjust y
      • 180 (down): adjust y
      • 270 (left): adjust x

      b11bf926-5d97-4fc4-8539-e5f35880a2dc-image.png

       
       

      Step 8 - Handle updates in ☁ new donut command

       

      When the cloud variable ☁ new donut command changes, both computers will create a new donut clone.

      Make sure only the original Donut sprite handles this:

      c414302c-3fe0-4f77-8ea1-fc07a72bb8d3-image.png

       
       

      Step 9 - Extract Donut Info

       

      Split the command string into 2 parts and store them:

      • owner team: the shooting player
      • my direction: the direction the donut should move in

      c7d9a2d3-551a-4934-a574-abdca16d07d8-image.png

       
       

      Step 10 - Move Donut to Position and Set Angle

       

      Move the original Donut sprite to the target position and direction. The clone will inherit this when it’s created:

      a0e3f559-856b-45f0-808f-962cc39111f4-image.png

       
       

      Step 11 - Create the Donut Clone

       

      Now create the donut clone. Its ID will be a combo of the player’s ID and the sequence number:

      c80015ee-0406-4755-a88d-ec1761887c06-image.png

       
       

      Step 12 - Set Costume by Team

       

      Set the donut costume based on the player who fired it:

      ff0b0c44-15f0-4727-8309-b05718c2078d-image.png

       
       

      Step 13 - Hide the Original Donut Sprite

       

      Only clones should be visible. The original Donut stays hidden:

      fcefe505-18da-4679-93ee-73c26a4ff6cf-image.png

      16aad3ca-23c6-46ef-9a7d-ba7776735fc5-image.png

       
       

      Step 14 - Calculate Travel Distance Based on Timer

       

      Just like trucks, donuts should move consistently across fast and slow computers. Use the timer and a constant speed (e.g. 150) to calculate how far each donut moves every frame:

      donut-travel-distance.png

      Each clone tracks its own prev time and travel distance.

       
       

      Step 15 - Move the Donut

       

      Move the donut in its set direction using the calculated distance:

      e00ba132-02f3-4bb0-8e93-dc61fea43c64-image.png

       
       

      Step 16 - Delete on Tree or Edge (Only on Owner’s Side)

       

      Only the player who owns the donut should check for collisions (to avoid false positives due to lag). If a donut touches a tree or the edge:

      • Set ☁ donut to delete to its ID
      • Both computers delete the clone when this variable updates

      0ab2eef4-235d-496b-8513-303c10da800a-image.png

       
       

      Step 17 - Detect Hitting the Opponent

       

      If the donut hits the opponent truck, do the same thing: set a cloud variable ☁ donut hitting target to the donut’s ID:

      6835d348-d1aa-4586-baf9-d1383f1ebd90-image.png

       
       

      Step 18 - Delete the Donut

       

      In the Donut sprite, when ☁ donut to delete updates, each clone compares its ID and deletes itself if it matches:

      aaa08493-cff5-4532-a8d4-b1230d40729b-image.png

       
       

      Step 19 - Handle Opponent Hit

       

      Similarly, when ☁ donut hitting target changes, the matching clone:

      1. Sends a truck hit message with the opponent truck’s ID. For example, if this clone’s team is 1, then the opponent team’s ID is 2 (3 - 1).
      2. Deletes itself

      99bfd34d-57ce-4346-855a-9ac03c501ac3-image.png

       
       

      Step 20 - Truck Handles “truck hit”

       

      In the Truck sprite, handle this message carefully:

      Only the truck that got hit, and only on its own player’s computer, should reduce its life by 1.

      Use two checks:

      • clone ID = truck being hit
      • my team = owner of this truck

      truck-hit-checks.png
       
      Then update ☁ my lives, which is mirrored on both computers.

       
       

      Step 21 - React to Changes in ☁ my lives

       

      Each truck that shares that cloud variable will react when ☁ my lives is updated.

      Make sure the game has started (game state is 1):

      52292a20-0798-4591-9b81-108863d8ea51-image.png

       
       

      Step 22 - Compare Life Count

       

      Use a separate variable prev my lives (initially 3) to compare the new life count to the previous one:

      5cc07434-3c0a-4e68-8523-ae922d7efbb6-image.png

       

      dfde5a30-496f-4f1f-b4bd-98a0ba752c48-image.png

       
       

      Step 23 - Play Sound Effect

       

      Play different sounds for gaining vs. losing lives:

      93767c74-c89b-47e9-82e8-4fffe51029f2-image.png

       
       

      Step 24 - End the Game if Lives = 0

       

      If the truck’s life count drops to zero, end the game. This check happens on both computers:

      8018a2f8-a3c6-4462-9999-ca5be2402b16-image.png

       
       

      Step 25 - Show the Winner

       

      Before stopping the game, show a message announcing who won:

      If truck ID = 1, then player 2 wins. If it’s 2, then player 1 wins:

      show-winner.png

       
      Here is a full demo of the game:

      finaldemo.gif

       
       
       
       
       
       
       
       
       
       

      Additional Challenges

       

      The game you’ve built so far is a fully functional 2-player battle, but there’s plenty of room to expand and experiment. The main goal of this project was to demonstrate how cloud variables and clones can be used to build a multiplayer game where each player runs the same project on their own computer, and everything stays in sync.

      Once you’ve got the basic mechanics working, here are some ways you can extend and improve the game. These ideas range from simple tweaks to major redesigns—try one or try them all.


      🔹 Firepower Reward

      You’ve already added Sugar and Gas as collectible items. Now try adding a third type of reward that affects the player’s shooting ability.

      What to do:

      • Create a new sprite for a Firepower item
      • When collected, reduce the cooldown time between donuts (e.g., from 1 second to 0.5 seconds)
      • Use a new cloud variable to sync this change across both computers
      • Maybe even show a temporary fire effect or shooting animation

      This reward adds more strategy and makes collecting items more impactful.


      🔹 Shrinking Arena

      To prevent players from hiding or running away forever, you can create a shrinking play area—similar to battle royale games.

      How it works:

      • Add invisible wall sprites that slowly move inward from the edges of the stage
      • These walls can appear every 10 seconds or after a certain time has passed
      • If a truck touches a wall, it loses a life or takes damage

      This forces players toward the center of the stage over time, making the game more intense and guaranteed to end eventually.


      🔹 2 vs. 2 Team Game

      This is a major upgrade: turn your 2-player battle into a 4-player team battle, with two players on each team.

      What changes:

      • Four players will join the same cloud session, each with their own truck (clone IDs 1 to 4)
      • Players 1 and 2 are on Team Yellow, and Players 3 and 4 are on Team Red
      • Each player only controls their own truck, but it has 3 mirror trucks on the other 3 computers
      • Donuts can damage players from the opposite team, but not teammates
      • The game ends when both trucks from one team have lost all their lives

      What you’ll need to update:

      • Session setup screen to support 4 unique player IDs
      • Truck spawning logic to handle 4 clones and assign them to teams
      • Donut logic to check for friendly fire and block it
      • Life tracking and win condition logic to check if both teammates are eliminated
      • Display a win message like “Red Team Wins!” when the condition is met
      posted in Tutorials
      info-creaticode
      CreatiCode
    • RE: "Token Limit Reached"

      @the_true_odst

      Most likely there are too many messages in the chat history or output.

      Please check this document: https://www.forum.creaticode.com/topic/867/ai-openai-chatgpt

      posted in Help
      info-creaticode
      CreatiCode
    • Game AI for Flappy Bird (Difficulty: 2)

      Introduction


      Flappy Bird is a simple and fun game, where the player controls the bird to fly through a few obstacles to reach its nest. There is only one control: press the SPACE key to make the bird flap.

      In this tutorial, you will learn to build a simple AI program to control the bird instead of manually.

      Note that this AI will be based on programming logic, rather than large language models (LLMs). That is due to 3 reasons:

      • LLMs are too slow for such tasks: it usually takes a few seconds for LLMs to respond to each request, but we need to make the bird react and flap with a precision of milliseconds.
      • LLMs are too unpredictable: LLMs are inherently random, and it is often hard to control them to generate precisely the same output every single time. In contrast, programming logic is much more predictable and reliable.
      • LLMs are too expensive: It takes a lot of computation, and hence energy, to generate even a very simple output. To avoid such waste, when we can use programming logic to make a decision, we should do so.

      The same argument also applies in many other situations, and that’s why a significant portion of AI systems will continue to be implemented using programming logic.

      Now let’s get started with this simple AI program.


      Step 1 - Remix the Starter Project


      Open this link and remix the project:

      play.creaticode.com/projects/684dbd401c49cae4509533bd


      Step 2 - Read the Existing Code for “AI”


      In the “AI” sprite, there are 2 stacks of code.

      First, when the green flag is clicked, 3 parameters are set:

      • How many columns (green pipes) are placed before the nest.
      • The gravity for the bird’s falling speed;
      • How much the bird rises up on each flap.

      AI parameters

      Below that, when the “start” message is received, this AI program will simply send out the “flap” message every 0.3 seconds. Each “flap” message will make the bird flap once. This is the most basic AI program, which we will improve in the next few steps.

      Flap loop


      Step 3 - Adjust the Game Settings


      When you click the green flag, you will find that the bird will fall to the ground. The falling speed will depend on your computer, but it will look similar to this:

      Bird falls


      This is because the “gravity” and “flap strength” are not fine-tuned yet. As an exercise, please adjust these 2 values. In general, “gravity” should be a number between 0 and -2 (such as -0.5), and “flap strength” should be a number between 4 and 20. Your goal should be to make the bird fly horizontally with a nice waveform trail like this:

      Wave flight


       

       

      Step 4 - A Shorter Wait Interval

       

      Currently, in the forever loop, we send out the “flap” message every 0.3 seconds, and the bird will stay at the same height. Suppose we want the bird to fly higher, then we need to use a shorter interval.

      Instead of 0.3 seconds, let’s use an interval of 0.03 seconds. This may be necessary if the bird needs to rise up very quickly.

      Change delay

      As a result, when you run again, the bird should reach the ceiling very quickly and stay there:

      Bird at top

       
       

      Step 5 - Skip some flaps

       

      Obviously, the current AI always makes the bird fly too high. A simple solution is to skip some flaps, so the bird will do a free fall to reach nests that are below its level.

      In general, to make smart decisions, an AI needs relevant sensing data. In this case, to determine whether the bird needs to fall a bit, we can compare these 2 variables:

      • The bird’s Y position
      • The Y position of the nest

      Your AI can access these 2 values using these 2 reporter blocks:

      Y sensing
       

      Now, can you change the forever loop so that the bird would not flap if it is already above the nest?

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Here is one way to do it: we put the broadcast block inside an “if-then” block, so only when the nest is above the bird would the bird make a flap:

      If nest is above

      Try to run the program a few times. The nest is placed at random heights, but the bird will almost always rise or fall to its level quickly:

      Bird matches nest

       
       

      Step 6 - Add a few columns

       

      Now let’s move on to the next challenge: make the bird fly through the columns (pipes). Change the “columns” variable to 4, which will add 4 columns:

      Set to 4 columns

      Obviously the bird will crash with the columns and fail. What can we do?

       
       

      Step 7 - Fly through all columns

       

      Similar to above, we need to provide data to the AI. Specifically, here are information about the columns:

      1. Each column has an opening at its center, and the Y positions of these openings are stored in the list named “columnYs”.
      2. The number of columns is given in the variable “columns”.
      3. The upcoming column has an index of “nextColumnIndex” in the list. For example, when the bird is facing the first column, nextColumnIndex is equal 1. After the bird flies through it, nextColumnIndex will automatically increase to 2.

      With these information, can you try to make the bird fly through all the columns? Don’t worry about the nest for now.

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      In fact, all that we need to do is to replace “nestY” with the Y position of the upcoming column:

      Use columnY

       

      The bird should have no problem flying through all columns:

      Success with pipes

       

       

      Step 8 - Fly to the nest after all the columns

       

      For our last step, we need to combine our solution for columns and the nest. When the bird has passed the last column, the nextColumnIndex will be more than the columns variable, and that’s when we should target the nest instead. Can you implement this change?

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Here is an example solution:

      Switch to nest after pipes

      Here is the final demo:

      Final full run

       
       

      Extra Practices

       

      To practice what you have learned, here is an additional challenge for you.

      Currently, the bird would only start flapping if it is below the target height (of the nest or the center of the opening), so it might fall too much below the target. If the target is very low, then the bird might touch the ground before flying back up.

      Bird too low

      To ensure the bird is always safe, it should start to flap if it is too close to the ground (Y of -240).

      posted in Tutorials
      info-creaticode
      CreatiCode
    • RE: Scroll wheel should be use as zoom instead of scroll in Creaticode Create

      @tyller_

      Currently, the playground already supports both:

      • Ctrl + Wheel: zoom in or out
      • Shift + Wheel: scroll left or right

      And these are the same for MIT Scratch.

      posted in Feedback
      info-creaticode
      CreatiCode
    • Introducing the Newly Enhanced Cloud Variables

      Hi all,

      We have made some exciting new enhancements to cloud variables. The description is on this page: https://www.forum.creaticode.com/topic/1997/newly-enhanced-cloud-variables

      We will post new tutorials on multiplayer games using this new feature as well. Please feel free to give us your feedback on this.

      Thank you
      CreatiCode

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: left click should be drag in sprite creating area

      @the_true_odst

      Got it. We’ll check why it happens on chromebooks.

      posted in Feedback
      info-creaticode
      CreatiCode
    • Newly Enhanced Cloud Variables

      Introduction

       

      Cloud variables are a powerful tool in MIT Scratch for creating multiplayer programs. CreatiCode has enhanced them further, making them even more capable. In this tutorial, you’ll learn how cloud variables work in the CreatiCode playground.

       
       

      Basics of Cloud Variables

       

      When creating a new variable, you can check the “cloud variable” box:

      f702479b-a596-4ae5-b146-caf71bb4fce8-image.png

      If the project is shared and opened by other users, the value of that cloud variable will be synchronized across all their computers automatically.

      For example, imagine 10 users are running the same project at the same time. If one user changes the value of a cloud variable, the other 9 users will instantly see the updated value.

      Here’s what happens behind the scenes:

      1. User A changes a cloud variable using a “set variable to” or “change variable by” block.
      2. User A’s computer sends the new value to the CreatiCode server.
      3. The server broadcasts the update to the other 9 users running the same project.
      4. Each of those computers receives the message and updates the cloud variable’s value.

       
       

      A Simple Example

       

      Here is an example project: play.creaticode.com/projects/68473cea3d952dd83a76d160

      It has one dog sprite with this code:

      3306fac4-3758-4577-8c80-213ef1781d5b-image.png

      When the program starts, the sprite keeps saying the value of the cloud variable “counter”.

      Whenever any user clicks the sprite, the value of “counter” increases by 1, and all other users running this program will instantly see the new value.

      You can test this by opening the project in two browser windows (one normal mode and one incognito mode). Make sure you’re logged in, as cloud variables only work when you’re signed in. Of course, you can also try this with a friend on 2 computers.

      Here’s what it looks like across two browsers:

      cloudcounter.gif

       
       
       
       

      The “When Variable Changes” Block

       

      To make working with variables easier, especially cloud variables, CreatiCode has added a new event block:

      005ee1af-8126-487d-ba3c-e0ef2949e773-image.png

       

      This block is triggered whenever the selected variable changes, i.e., when its value becomes different. Note that if you set a variable to its current value (hence no change), then this block won’t be triggered.

      It works with both regular and cloud variables. This means you no longer need a forever loop to constantly check the variable — you can run code only when the value actually changes.

      Here’s how we can rewrite the earlier example using this block:

      122a4880-f6c8-43f7-9021-7a186fdf8f6c-image.png

      1. When the sprite is clicked, increase the counter as before.
      2. When the counter changes, the sprite says the new value.

      You can try it here: play.creaticode.com/projects/684747163d952dd83a76d79c

       
       
       
       

      Number of Cloud Variables

       

      MIT Scratch limits you to 10 cloud variables per project. In CreatiCode, you can use up to 100. This allows you to build much more advanced multiplayer projects.

       
       
       
       

      Accepted Values and Update Frequency

       

      In MIT Scratch, cloud variables:

      • Can only store numbers
      • Can only update any variable at most 10 times per second

      For example, suppose your project has 2 cloud variables, then if within any second, your code updated them more than 10 times, then the extra updates will be ignored.

      These limits were put in place to block users from building chat rooms, but they also make cloud variables harder to use.

      In CreatiCode, cloud variables support any type of value, with some important rules:

      • If the value contains any letters (a–z), it must pass a moderation check to filter inappropriate content. Also, such values can only be updated once per second per user. That’s still fast enough for chat room projects.

      • If the value does not contain letters, and only contains numbers or symbols, like 120 or "1_23_44", it bypasses moderation and can be updated up to 20 times per second per user. This is useful when you want to send multiple numbers in a single update. For example, to send X = 50 and Y = 80, you can combine them into one value of "50_80". Also, CreatiCode does not drop any updates. Instead, these updates are queued and sent out at intervals of 50ms.

       
       
       
       

      Cloud Sessions

       

      In MIT Scratch, everyone running the same shared project receives the same cloud variable updates. For example, suppose you share a multiplayer game, then all users who run this game at the same time will receive the same updates. To isolate groups, you’d have to make separate copies of the project.

      CreatiCode introduces cloud sessions, which limit cloud updates to just the users in the same session. If a user hasn’t joined a session, they’re placed in the default session.

      To use sessions, one user has to create one with a unique name first, then other users can join that session with the same name. Here are the2 blocks from the “Variables” category for doing so:

      6c299aae-5c60-4df2-9b81-9dc492d5d1fe-image.png

       
      The session name is just a string that users agree to use. Only users in the same session will receive each other’s cloud variable updates. These blocks are boolean blocks, since they will return true or false depending on whether the action is successful.

      Here’s an example program that shows how to use these blocks:

      b64c75e1-465d-4b95-ad9d-c68284db34db-image.png

       
      To run this program:

      • First, one user needs to create a session named “579”
      • All other users can then join the same session using the same name.
      • After that, only these users will see each other’s updates to the “counter” variable.

      The project is shared here: play.creaticode.com/projects/6847509b3d952dd83a76dbfb

       
       
       
       

      Private Cloud Variables for Clones (Advanced)

       

      In MIT Scratch, cloud variables are always global: shared across all sprites and clones. This creates problems when you’re working with clones.

      For instance, suppose a car sprite creates 2 clones: Clone 1 and Clone 2. If you use a global cloud variable like “facing direction,” then changing it to 90 will affect both clones, even if you only meant to rotate one.

      To fix this, CreatiCode lets you create private cloud variables for each sprite or clone:

      86ec028f-9c73-4591-8462-e4d99ee35191-image.png
       
      Now, each clone will have its own “direction” variable, separate from the others. For example, when one user updates the direction variable for “Clone 1”, then the direction will be updated for “Clone 1” running on all other computers, yet “Clone 2” will not be affected on any computer.

       
       
       
       

      Example for Private Cloud Variables

       

      Here is an example project: play.creaticode.com/projects/6847575f1c49cae45091d685

      When the green flag is clicked, the original dog sprite hides and creates two clones, with IDs 1 and 2:

      421699f2-f4bc-45e6-9b02-854ecfab8946-image.png

       
      When born, each clone shows itself, says its clone ID, and moves to one side of the stage:

      884f5fda-d4cd-4209-8005-176279dc4986-image.png

       
      Now, when a clone is clicked, it increases its own private cloud variable called “direction” by 15. This triggers only that clone to rotate:

      dcf57267-c6f6-4929-ac99-c27ede0e9f1c-image.png

       
      As a result, when any user clicks on a dog clone, that specific clone rotates on every computer — but the other clone is unaffected:

      cloudcounter.gif





      We hope you enjoy these new features, and we can’t wait to see the amazing multiplayer projects you’ll build with them!

      posted in 2D Blocks
      info-creaticode
      CreatiCode
    • RE: left click should be drag in sprite creating area

      @the_true_odst

      What device/browser are you using? Have you tried to restart the browser?

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: How to find "If Shift key pressed"

      @the_true_odst

      Yes.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: Scroll wheel should be use as zoom instead of scroll in Creaticode Create

      @the_true_odst

      The scroll wheel is used for scrolling up and down to view the blocks, which is similar to the MIT Scratch interface. We strive to be consistent with MIT Scratch, unless there is a compelling reason to improve upon it.

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: left click should be drag in sprite creating area

      @the_true_odst

      The left mouse button is indeed used for dragging the editor area. Are you seeing otherwise?

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: How to find "If Shift key pressed"

      @the_true_odst

      Sure. We can probably add it to this block:

      04cf5932-1b6c-41f0-9367-685b1dd58dba-image.png

      posted in Help
      info-creaticode
      CreatiCode
    • RE: New block -- "When stop sign pressed"

      @the_true_odst

      The stop button is meant to simply stop the program. It would be strange if it doesn’t.

      Probably you can just add a “restart” button for this purpose?

      posted in Feedback
      info-creaticode
      CreatiCode
    • Getting Started with CreatiCode

      Welcome to the CreatiCode Playground

       

      The CreatiCode Playground is a fun online platform where you can create and share projects using Scratch blocks. It builds on the open-source MIT Scratch framework but adds exciting new tools and features to make your projects even more awesome!

      This tutorial will guide you through the basics of using the CreatiCode Playground, perfect for beginners to block-based coding. If you’ve used MIT Scratch before, it is recommended that you quickly skim through and check out what’s different.

      Let’s dive in and get started!


       
       
       
       

      Create a New Account with Email and Password

       

      Good to Know: If you have a Google email, you can sign in directly without creating a new account!

      Here’s how to sign up using an email and password:

      1. Go to creaticode.com.
         
      2. Click the “Join” button in the top-right corner.
        Join Button
         
      3. Choose whether you’re a student or an educator.
        327188b0-f119-4fa0-ba21-bab98e2b7269-image.png
         
      4. Fill out the sign-up form with your details, then click “FREE SIGN UP”.
        Note: The “Full Name” field is your username, and it doesn’t have to be your real name.
        Sign-Up Form
         
      5. If you’re 13 or younger, you’ll need to provide a guardian’s email (like a parent or teacher). Your account won’t work until your guardian approves it.
        Guardian Approval

       
       
       

      Sign In to Your Account with Email and Password

       

      Here’s how to sign in using your email and password (created by you or your teacher):

      1. Visit creaticode.com.
         
      2. Click the “Join” button at the top.
         
      3. On the next page, click “SIGN IN” in the top-right corner to open a dropdown menu.
        Sign-In Dropdown
         
      4. Enter your email and password, then click “Sign In”.

       
       
       
       

      Sign In with a Google Account

       

      If you have a Google account (like a Gmail or school email), signing in is super easy — no need to sign up!

      1. Go to creaticode.com.
         
      2. Click “Join” in the top-right corner.
        Join Button
         
      3. Click “SIGN IN” in the top-right corner, then select the “Google” button in the dropdown.
        Google Sign-In
         
      4. Enter your Google email and password to sign in.
         
      5. Select account type (student or educator) if this is the first time.

      Tip: Always use the same sign-in method going forward (either email/password or Google) to avoid any mix-ups.


       
       
       
       

      Explore Projects from the Community

       

      Scratch — and by extension, CreatiCode — is all about Create → Share → Remix! You can make a project (like a game), share it for others to play and give feedback, and even let others “remix” it to create their own versions. It’s a fun way to inspire each other!

      To check out projects shared by others:

      1. Click the “Explore” link at the top of the page.
         
      2. The top four rows show Editor’s Pick projects — cool demos that highlight what you can build on CreatiCode.
        Explore Projects
         
      3. Below those, you’ll see all community projects. Use the two dropdown menus on the right to sort them:
        • Time Period: Choose a timeframe, like the past month or year.
        • Sorting Method: Pick how to sort projects:
          • Trending: Most likes.
          • Popular: Most views.
          • Recent: Newest projects.
          • Inspiring: Most remixes.
            Sort Options

       
       
       
       

      Understand Project Stats

       

      Each project has a preview image with three key stats below it to give you a quick idea of its popularity and complexity:

      • Love Count: How many users clicked the heart button to mark it as a favorite.
      • View Count: How many times the project has been played.
      • Block Count: How many coding blocks are in the project. A higher number usually means a more complex project.
        Project Stats

       
       
       
       

      Search for Community Projects

       

      With so many projects in the community, searching helps you find exactly what you’re looking for! Here’s how:

      1. Type a keyword (like “car”) in the search box and press Enter. You’ll see projects with that word in their name.
        Search Bar
         
      2. Click the small triangle in the search box to add filters, like finding only 3D projects or projects with a specific number of blocks.
        Advanced Search

       
       
       
       

      Check Out a Project’s Home Page

       

      When you click on a project, you’ll land on its home page, which has everything you need to explore it. Here’s what you’ll see (from top to bottom):

      • Green Flag: Click this to play the project.
      • Remix Button: Make your own copy of the project to edit.
      • See Inside Button: Peek at the project’s code blocks and assets in the editor.
      • !Report: Flag the project for the CreatiCode team if it has anything inappropriate.
      • App Link: Send a link to the project as an app via email.
      • Project Link: Get a direct link to the project.
      • Comments: Share your thoughts (like compliments or ideas) and read what others have said.
      • Remixes: Check out other users’ versions of this project, created by copying and modifying it.

       
      Project Home Page


       
       
       
       

      Remix a Project

       

      Want to put your own spin on a project you like? It’s easy!

      1. Click the orange “Remix” button on the project’s home page.
      2. A copy of the project will appear in your CreatiCode Playground.
      3. Make any changes you want, then share your version with the community!

       
       
       
       

      Share or Publish Your Project

       

      Your projects are private by default, so you can experiment without anyone seeing your work. When you’re ready to show it off, you can share or publish it.

      • Sharing lets others play your project, view its code blocks, and remix it. This is called “open-source” because the code is open for everyone to see and use.
      • Publishing lets others play your project, but they can’t see the code or remix it. This is called “closed-source” and is great for sharing finished projects, like a puzzle game where the secrets in the code must remain hidden.

      When sharing, you can choose who sees your project:

      • Share: Open to all users.
      • Share with friends: Only your CreatiCode friends can see it.
      • Share with password: Only users with the password you set can access it.
      • Share Unlisted: Not shown in Explore or search results — only users with the direct link can see it.
      • Make private: Hide the project from everyone.
         
        Sharing Options

       
       
       
       

      Create a New Project

       

      Here’s how to make a new project:

      1. Click the “Create” link in the top navigation bar.
         
      2. Your new project comes with two default sprites:
        • Sprite1: A cute dog with costumes for walking in all four directions—perfect for animations!
        • Empty1: A blank sprite for your own ideas.
          Default Sprites
           
      3. If you don’t need the dog, just delete Sprite1 and start fresh!

       
       
       
       

      Browse Your Projects in “My Stuff”

       

      The “My Stuff” page is your hub for managing all your projects. To get there:

      1. Click the folder button in the top-right corner or select “My Stuff” from the dropdown menu.
        My Stuff Button
         
      2. You’ll see a list of all your projects, showing each project’s name, last modified date, and view count.
        My Stuff Page
         
      3. Use the menu on the left to filter projects by shared, published, or private.
      4. Click “See inside” on any project to open and edit it.

       
       
       
       

      Search for Projects in “My Stuff”

       

      If you have lots of projects, finding the right one is easy with the search box:

      1. Type a project name in the search box (upper or lower case doesn’t matter).
        My Stuff Search
         
      2. Tip: Give your projects clear, memorable names so you can find them quickly later!

       
       
       
       

      Find Blocks in the Block Palette

       

      The block palette on the left side of the Playground lists all the coding blocks you can use. Here’s how to use it:

      1. By default, the palette is folded to give you more workspace. Click any block category to open it.
         
      2. Want to keep it open? Click the “pin” button.
        Block Palette
         
      3. With tons of new blocks in CreatiCode, use the search box to find specific ones quickly. Clear the search by clicking the “X” button.
        Block Search

       
       
       
       

      Adding Blocks to the Editor

       

      To create a program with blocks, just drag them into the editor area. You can snap them together vertically, much like stacking LEGO bricks:

      drop2.gif

       
      In some cases, you’ll need to insert one block inside another. When doing this, make sure to align the left edge of the new block (not the middle) with the target slot:

      dropblock.gif


       

      You’re now ready to explore, create, and share in the CreatiCode Playground! Have fun building your projects and remixing others’ ideas. If you get stuck, revisit this tutorial or ask a teacher for help. Happy coding!

      posted in Tools
      info-creaticode
      CreatiCode
    • Teacher Only: An Introduction to the CreatiCode AI Curriculum

       

      Why Coding Still Matters

       

      This AI curriculum comes at a time when artificial intelligence (AI) is rapidly transforming every walk of life, with a particularly profound impact on how professional programmers work. In the near future, it’s likely that 90% or more of all code will be written by AI. Our students, when they grow up, will be worse at coding than ChatGPT, just like they are worse at crunching numbers than calculators. All programmers will have to shift into new roles: guiding AI systems, initiating complex tasks, and reviewing what machines produce.

      But that doesn’t mean coding is disappearing from education. On the contrary, we believe it’s more important than ever, and should remain a core component of every student’s education. Coding teaches students how to think logically, solve problems, and bring their ideas to life. It gives them creative agency in a world increasingly shaped by intelligent tools. Just as children will always build with LEGO and explore in Minecraft, they will continue to code; not because they must, but because it’s how they learn, create, and play.

      The key challenge is: how do we keep coding fun, meaningful, and relevant in a world where AI is part of the process? This curriculum is designed to answer that challenge—by showing that the rise of AI isn’t the end of coding, but the beginning of a new way to engage with it.


       

      AI as Assistant and Building Block

       

      In a world where AI will increasingly act as a collaborator, students must learn not just how AI works, but how to work with it. That means learning to use AI tools thoughtfully and building directly with AI-powered components: not as passive consumers, but as creative problem-solvers.

      CreatiCode builds on MIT Scratch, the world’s most widely used platform for teaching introductory computer science. It keeps what makes Scratch great: intuitive design, creative freedom, and a learning journey based on the cycle of creating, sharing, improving, and remixing.

      On top of that foundation, CreatiCode introduces a full suite of classroom-ready AI tools. Students engage with AI coding assistants, generate assets with AI image tools, and use AI coding blocks to build real applications, like chatbots, gesture recognizers, and intelligent interfaces. These aren’t add-ons; they are central to how students learn to build with modern technology.

      By working directly with AI tools in a controlled, educator-guided environment, students gain practical AI literacy. They learn to prompt, evaluate, and debug AI systems. They begin to understand how to collaborate with machines and how to shape what those machines do. In short, they’re not just coding with AI. They’re learning how to think, build, and create in a world powered by it.

      This guide will walk you through everything you need to bring that experience into your classroom: the tools, the teaching strategies, and the core concepts behind each activity.

       
       

      What Guides This Curriculum

       

      This AI curriculum isn’t just a collection of tools and lessons. It’s built around a set of clear principles designed to help students thrive in a changing world, and to support teachers every step of the way.

      First, we believe educators are essential. No AI tool can replace the relationships, insight, and emotional support that real teachers bring to the classroom. Every part of CreatiCode is designed to keep the teacher at the center. Technology should amplify your presence, not sideline it.

      Second, we focus on student engagement within a safe environment. Students learn best when they care about what they’re doing, have agency, and can explore hands-on. At the same time, generative AI introduces real risks. That’s why all AI features on CreatiCode are moderated and controlled, allowing for creative freedom in a safe, school-ready space.

      Instead of banning AI, we believe students should learn how to use it responsibly, like any other powerful tool. With the right support, they can explore what AI can (and can’t) do, reflect on how they’re using it, and become thoughtful users who are ready to shape the future.

      Third, we prioritize doing over memorizing. Many AI curricula focus on abstract theory or concepts. Ours emphasizes building real projects, experimenting with tools, and learning by making. Scratch’s visual format removes coding syntax barriers, so students can focus on design, logic, and problem-solving from the start.

      Finally, we encourage students to work together. After each core lesson, students pair up to extend what they’ve learned. These simple collaborations help reinforce ideas, build communication skills, and make learning social and fun. Working with a partner to build and debug supports deeper understanding and more confidence.

       
       

      Tools That Support AI Learning

       
       
      CreatiCode includes a full set of classroom-ready tools to help students learn AI in hands-on, creative ways while giving teachers the control they need.

      The AI Coding Assistant helps students understand code and answer questions. It includes a Socratic Mode that asks guiding questions instead of giving direct answers, helping students reason through challenges and reflect on what they’re learning. You can choose when to turn this feature on and off, and all interactions are moderated for safety and focus.

      The AI Image Generator lets students create custom sprites and backgrounds using text prompts. This supports visual creativity and brings more personality to their projects. Like all features on the platform, inputs and outputs are carefully filtered to keep things school-appropriate.

      AI Coding Blocks offer easy access to powerful AI features like ChatGPT, text-to-speech, and hand-gesture recognition. These blocks make complex functionality accessible without overwhelming beginners. Students can focus on ideas and problem-solving instead of technical setup.

      Widget Blocks give students the ability to build interactive AI applications using chat windows, buttons, text inputs, and other real interface elements. These tools introduce students to real-world software design by helping them build usable, accessible, and thoughtful digital experiences.

      And most importantly, teachers have full control. Through the class dashboard, you can enable or disable AI features, see what students are generating, and guide the learning experience based on your goals. This makes it easy to support digital citizenship and balance freedom with structure.

       
       

      What to Expect When Teaching AI

       

      Teaching AI can feel different from teaching traditional programming. Here are a few key shifts to keep in mind as you plan your lessons.

      • First, AI isn’t always predictable. Unlike regular code that always behaves the same way, generative AI can produce different answers depending on small differences in context. This means it’s a good idea to use screenshots or saved examples when demonstrating in class. It also opens the door to great discussions about how AI works and why it sometimes surprises us.

      • Second, AI can be surprisingly competent in some areas and completely unreliable in others. Whether used as an assistant or through AI coding blocks, students will encounter tools that excel at certain tasks while failing unexpectedly at others. A key part of learning is developing the judgment to leverage AI’s strengths effectively while recognizing its blind spots. Students must learn to validate AI outputs, question results, and intervene when the system goes off-track.

      • Third, how students access the AI assistant matters. Full access offers lots of support but may lead to over-reliance. Socratic Mode encourages deeper thinking but can frustrate students who are struggling. Sometimes, turning the assistant off entirely is helpful to build independence. A flexible approach is best.

      • Forth, writing becomes a central skill. Communicating with AI is less about code and more about clear, precise language. Students need to learn how to ask thoughtful questions, give instructions, and reflect on results. Prompting overlaps with writing skills like argumentation and technical documentation. Our curriculum includes practice in prompt design to build this ability over time.

      • Fifth, students won’t just be writing code — they’ll be taking on four new roles. As they build with AI, they must think like a creator — deciding what to make and why; a prompter — crafting inputs that guide the AI effectively; an integrator — combining AI-generated output with traditional code; and a tester — reviewing, refining, and improving what the system produces. These roles help students move beyond passive use and into active, reflective creation.

      • Finally, students will be building tools, not just stories. While Scratch has traditionally been used for animations and games, AI projects often focus on building interfaces like chat apps or interactive tools. This shift introduces students to real software design and prepares them for the types of applications they’ll build in the future.


       
       

      Concluding Remarks

       

      AI is changing how we code, create, and learn, but it doesn’t replace the need for coding in education. Instead, it gives us new reasons to teach it. Coding helps students think clearly, solve problems, and build ideas from scratch. When paired with AI, it becomes an even more powerful learning experience. With CreatiCode, students don’t just use AI. They learn how to shape it, question it, and build with it, growing into confident creators in a world increasingly shaped by intelligent tools.

      posted in Tools
      info-creaticode
      CreatiCode
    • RE: Is it possible to attach URL to chat?

      @andis_3cc

      So you are hitting the daily limit for free users. It should reset tomorrow.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: Is it possible to attach URL to chat?

      @andis_3cc

      Here is a short example where it downloads the image from the given URL to the sprite as a costume, then attaches that costume to the chat, and then it asks the LLM to describe this image.

      play.creaticode.com/projects/684340d71c49cae4508fc1ff

      Also, what error message are you getting when you say you have hit the LLM limit?

      posted in Help
      info-creaticode
      CreatiCode
    • RE: How to create a Scrolling platformer on CreatiCode

      Hi,

      These are great questions, but there are no easy answers. CreatiCode is a much more advanced version of Scratch, so you will have to learn the basics before creating complex projects.

      Can you start with the tutorials on this list?

      https://www.forum.creaticode.com/category/17/tutorials

       
      You can build some simple projects by following these examples, and then ask more specific questions about what you would like to do, such as how to modify one of these projects based on your idea.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: Camera stuff

      @jamesa-blackwell-57b383d3

      The simplest solution is indeed using the viewport:

      1. Make the canvas size much larger than the view port
      2. Draw a large backdrop in the stage canvas
      3. Lock the viewport on the key sprite
         

      5b9cc078-5ca0-4999-ba1c-c55453084d13-image.png

       
      Here is an example:

      play.creaticode.com/projects/6842f3d73d952dd83a741d13

       
      If this “does not work”, can you please explain what the problems are? We can either refine this or discuss a completely different solution.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: the ai does not work. i need help. please

      Can you please post a screenshot? We have just tested it and this is what you should get:

      aadaef11-1c59-4d67-9fdf-e9eeb8a355cf-image.png

      posted in Help
      info-creaticode
      CreatiCode
    • RE: Is this the right topic?

      @rubiired

      We have communicated with that user and he/she agreed to remove inappropriate projects. If there is evidence that he/she is sharing new inappropriate projects again, we will take further actions.

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: Is this the right topic?

      @rubiired

      Thank you. We will remove inappropriate projects from that user.

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: the ai does not work. i need help. please

      Hi, you mean the XO chatbot, right? It sometimes get behind a long queue of requests and may time out.

      Can you please try again now? You can reset the chat by clicking the red button, then ask your question again.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: how slow point lock

      OK. You can control the angular speed of the camera using the “configure camera” block’s last input, which is a percentage. For example, when you set it to 100, it is the default speed, but if it is 10, then it will be 10% of the default speed.

      See this project for example:

      play.creaticode.com/projects/68345dcdcf69bbdc83e9472e

      posted in Help
      info-creaticode
      CreatiCode
    • RE: how slow point lock

      Do you mean you want to make the camera rotate less when you move the mouse?

      posted in Help
      info-creaticode
      CreatiCode
    • RE: drop down menu

      You can use the “when widget changes” block.

      Here is a simple example:

      play.creaticode.com/projects/6831f4e759dd9cb676181c93

      posted in Help
      info-creaticode
      CreatiCode
    • RE: [Community Project] Let's Build a CreatiCode Project Packager!

      @jeffreyrb03-gmail

      There are already packagers like Turbowarp, which works well for generic Scratch projects. And since most of the new CreatiCode blocks don’t work offline, most likely this new packager won’t do much more compared to a Turbowarp packager, right?

      So the question is whether it will be justified to dedicate manpower on this feature (as opposed to others) if it is not going to add much additional value.

      posted in Test
      info-creaticode
      CreatiCode
    • RE: fix creaticodg

      @khour_thedeveloper-cc5393d8

      Hi, sorry about that issue.

      You should be able to create many clones with an issue. If you have this problem again, can you please share the project?

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: Cannot save game?

      @notjaldolfyt

      The service has been restored.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: Cannot save game?

      @notjaldolfyt

      Yes, there is an issue saving and loading projects. It will be restored shortly.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: Limit FPS on projects?

      @notjaldolfyt

      Thank you for the suggestion. We will look into how to add this.

      posted in Feedback
      info-creaticode
      CreatiCode
    • RE: queshtion

      @jeffreyrb03-gmail

      No. That question was on the button on top, not the text to speech block.

      posted in General Discussion
      info-creaticode
      CreatiCode
    • RE: Yellow boxes around projects?

      This issue has been resolved.

      posted in Help
      info-creaticode
      CreatiCode
    • AI Tool Use - A Calender Assistant (Difficulty: 4)

      Introduction

       

      Welcome to this tutorial on building an AI-powered calendar assistant! This project is a great example of how AI tools can be extended with new abilities — allowing them to solve more complex, real-world problems.


      🧠 What’s This All About?

       
      Large language models (LLMs), cannot remember information across different sessions — they can only “remember” the messages within the current chat session. That’s a big limitation because most apps need to store and recall information over time. Think about a calendar app: it needs to store all your events so you can see them later!

      To work around this limitation, we’ll use Google Sheets to store data. Then we’ll teach the AI how to interact with that data to manage a user’s calendar.

      By the end of this project, your app will look like this:

      calendar.gif

       

      This tutorial is divided into two main parts:

      • Part 1: Set up a basic AI chat app
      • Part 2: Teach the AI how to manage the user’s calendar using Google Sheets

       
       
       
       
       

      🧩 Part 1 - Setting up the chat app

       

       
       

      Step 1 - Remix the Starter Project

       

      Start by remixing this template, which gives you a basic chat app to build on. We’ll add new logic to it step by step.

      play.creaticode.com/projects/682dad154dba4796824af2a6

       
       

      Step 2 - Prepare the Google Sheet

       

      We’ll use a Google Sheet to store all calendar events. This approach is free, easy to use, and simple to review.

      Here’s what you need to do (or ask your teacher/guardian to help):

      1. Create a new Google Sheet
      2. Set its sharing settings so that “anyone with the link” can edit
      3. Copy the sheet’s link

      6fe532c8-c01a-4dbd-ba03-b15462392d8a-image.png

      If you can’t create your own Google Sheet, you can use this pre-made one:
      https://docs.google.com/spreadsheets/d/1tH9J09laZNl94Qb1smO5LSmDwD_yzungb9d4lmkobxE/edit?usp=sharing

       
      Then, in your app, store the sheet URL in a variable called Sheet URL. You’ll use this later to tell the AI where the calendar lives.

      eae1657b-7a9d-4cf2-a745-4b3637f32d2e-image.png

       
       

      Step 3 - Update the System Prompt

       

      Next, we’ll give the AI a new role by updating its System Instruction.

      This tells the AI what it’s supposed to do. For now, keep it simple and clear:

      197c4ae4-ba5d-4133-9953-3b190e6ec10a-image.png

       
       

      Step 4 - Customize the Welcome Message

       

      Let’s make the welcome message match the AI’s new job.

      667f26d2-e8a1-4297-bed5-0db881b29b55-image.png

       
      📌 Tip: You could make the AI generate a different welcome message every time, but that would slow things down.

       
       

      Step 5 - Add a Tab for Each User

       

      Because different users might use this app, we need a way to keep their data separate.

      The solution: whenever a new user joins, we’ll create a new tab in the Google Sheet just for them. The tab name will be the user’s unique ID.

      ae212509-2bdf-48aa-b854-bd4d886f5597-image.png

       
      📝 If the tab already exists, this block will do nothing — which is exactly what we want.

       
       

      Step 6 - Get the Current Day of the Week

       

      Here’s an important thing to remember: AI models do not know the current date or time on their own. You can test that like this:

      35c1e1ac-c623-4b17-90ee-932e5b1eabfa-image.png

       
      That’s a problem when managing calendars! We’ll fix this by manually sending the current date and time to the AI.

      Let’s start with the day of the week:

      • First, create a new list “weekdays”:
        6298781c-e323-43ba-afd8-21448f235fbe-image.png

      • Then, use the current [day of week] block to get today’s number, and use it to pick the correct item from your list:
        82c8a6e9-d0d6-402e-9fa9-925f23ce4cbe-image.png

       
      📅 For example, if today is Wednesday, the “current day of the week” block will return 4, and item 4 in your list will be "Wednesday".

       
       

      Step 7 - Get the Full Date and Time

       

      We can also get the full date and time using the current block and combine them into a single string:

      6dfcfd51-db40-401c-a5d2-ad253e5d4d66-image.png

       
       

      Step 8 - Send Time Info with Every User Message

       

      Now we’ll attach the time information to each message we send to the AI model.

      bd8c0581-61a3-4da0-bc40-1d5eae91b171-image.png

       
      For example, if the user says “hi”, then what we actually send to the AI will be:

      hi
      (current time: Wednesday 05/21/2025 13:23:43 )
      

      That way, the AI will know exactly when the message was sent!

      You can now test it to make sure the AI sees the correct time:

      392697d0-3618-40dd-a401-0d1d5c871753-image.png

       
       
       
       
       
       
       

      🧩 Part 2 - Managing the Calendar with Google Sheets

       

       
       

      Step 1 -  Plan the Workflow for Adding a New Event

       

      Our entire calendar lives in Google Sheets, yet the AI can’t touch that Sheet directly — it needs help from our helper code. Here’s a sample back‑and‑forth among the user, the AI, and the helper:

      1. User -> AI: I will have a haircut tomorrow at 4pm
      2. AI -> Helper: add a new event for [date] [time]
      3. Helper adds it to the Google Sheet
      4. Helper -> AI: event added successfully
      5. AI -> User: I have added the haircut to your calendar.

       
      From the user’s perspective, the Sheet and helper code are invisible—the AI simply “gets it done.”

      Another way to think about it: the user speaks natural language, the helper speaks code, so the AI acts as the translator between them.

       
       

      Step 2 - Define the “addEvent” Command

       

      To teach the AI to use our helper, we need to define a new command “addEvent” in the system instruction:

      You are an AI assistant that helps manage the user's calendar.
      
      ## Commands
      
      You can use the following tools to manage events through an external service:
      
      * To add a new event to the calendar, you can return this command, which will return its eventID:
      addEvent | [date] | [time] | [event description]
      
      ## Instructions
      
      * If you are using a command, then only return the one line of command and nothing else.
      
      

      Notes:

      • We separated Commands and Instructions with ## headers so the AI can “see” the sections clearly.

      • The addEvent syntax uses pipes (|) — easy for us to split into pieces later.

      • The instruction forces the AI to output only the command line when needed — no extra chit‑chat.

      Testing now shows the AI emitting addEvent lines automatically:

      324814be-e4dd-4867-9c6b-9b5b5925ad71-image.png

       
       

      Step 3 - Standardize Date and Time Formats

       

      The AI currently formats dates like 05/01/2025, which sorts poorly—05/01/2025 appears “larger” than 02/01/2026. Times such as “3 p.m.” sort badly, too.

      Add two lines to the Instructions section to enforce sortable formats:

      You are an AI assistant that helps manage the user's calendar.
      
      ## Commands
      
      You can use the following tools to manage events through an external service:
      
      * To add a new event to the calendar, you can return this command, which will return its eventID:
      addEvent | [date] | [time] | [event description]
      
      ## Instructions
      
      * If you are using a command, then only return the one line of command and nothing else.
      * Use yyyy.mm.dd date format, such as "2025.02.21"
      * Use hh:mm time format, such as "13:30"
      
      

      Re‑run the app and confirm:

      d1eb5487-12ab-4d69-a973-1cfc3adb3217-image.png

       
       

      Step 4 - Intercept the “addEvent” command

       

      Whenever we receive AI output, we’ll check if it begins with "addEvent " (note the trailing space). If so, we execute helper code in “handle add event”.

      ee6922cd-072a-4a8b-a75b-38d00263f53b-image.png

       
       

      Step 5 - Extract the Parameters

       

      The addEvent line has four parts separated by three pipes. Use the “part of” block to pick them apart and trim whitespace:

      b904221b-f61a-44b0-a897-5ae7264f3e73-image.png

       
       

      Step 6 - Read Data from Google Sheets

       

      Our add‑event logic is:

      1. Read the user’s tab into a table called events.
      2. Add the new event.
      3. Write the entire table back.

      To start, we will read the sheet using a “read data” block:

      c9234755-1b23-4d7b-ab29-747080b966df-image.png

       
      In this block, we will use the “read from Google Sheet” block to read the first 10000 rows from this user’s tab, assuming there are less than 10000 events on the calendar:

      333550a9-d29b-4284-8fcc-67a38af3aa7f-image.png

       
      Run this block and remove all the widgets (or save and reload the project), you will find the “events” table looks like this:

      5ed62169-3cac-423a-a4dd-977a5e16ce8a-image.png

       
      That’s because the new tab is still empty, so the column headers are missing. To fix that, we can define the columns whenever there are 0 rows in the table:

      61dffcd1-e3d2-4361-8535-533288186d35-image.png

       
      The first column “id” will be used to store the unique eventID.

       
       

      Step 7 - Add the New Event

       

      Generate a unique ID using row count + 1 (always unique) and prefix it with “E”. Then append a row:

      d3c9015d-d19e-450b-9775-22dfd1a66eca-image.png

       
       

      Step 8 - Sort the Table

       

      Since all the events have date and time, we should keep them sorted in the calendar. We will sort the rows by “time” first, then by “date”. This will ensure all events are sorted by date and then time:

      4d864702-2d7b-4f65-8a59-bab1e3025a9e-image.png

       
       

      Step 9 - Write Back to the Sheet

       

      Overwrite the user’s tab with the updated table:

      05a6e9d1-f1d6-46fe-a66a-7ca12687e8e2-image.png

       
       

      Step 10 - Report Success to the AI

       

      Let the AI know the command succeeded and pass along the new eventID:

      64a7f312-336b-4591-a3ac-840599769b41-image.png

       
      We clarify that this message is from addEvent, so the AI won’t mistake it for user input.

      Test by adding events:

      c49731ea-472d-498f-a385-ae98eb299472-image.png

       
      …and confirm they appear in the Sheet:

      48824007-a8a5-4e7a-9d2a-1ee82f9eb9d8-image.png

       
       

      Step 11 - Define the “removeEvent” Command

       

      Next, let’s work on removing an evnet. We will still start with defining the command in the system instruction:

      You are an AI assistant that helps manage the user's calendar.
      
      ## Commands
      
      You can use the following tools to manage events through an external service:
      
      * To add a new event to the calendar, you can return this command, which will return its eventID:
      addEvent | [date] | [time] | [event description]
      
      * To remove an existing event, after you have found its eventID, you can use this command:
      removeEvent | [eventID]
      
      ## Instructions
      
      * If you are using a command, then only return the one line of command and nothing else.
      * Use yyyy.mm.dd date format, such as "2025.02.21"
      * Use hh:mm time format, such as "13:30"
      

      removeEvent takes just one parameter — the event’s unique ID. If the AI doesn’t already know the ID, it must retrieve it using other commands first (those are defined later).

       
       

      Step 12 - Intercept the “removeEvent” Command

       

      Detect and handle it with a new block:

      fba93dd8-a0af-4516-9c8d-5316582db7f5-image.png

       
       

      Step 13 - Extract the eventID

       

      Pull the ID from the command string:

      0180e05f-19f3-44cf-b351-6589c557a27f-image.png

       
       

      Step 14 - Find and Remove the Event

       

      1. Read the Sheet into events again.
      2. Find the index of the row with the matching eventID.
      3. Delete that row.

      8637a6a4-4f4d-4cba-b236-d265a9214ae6-image.png

       
       

      Step 15 - Clear and Rewrite the Sheet

       

      Before we write the table back, we need to first clear the tab. The reason is that the table has one less row compared to the data in that tab, so if we simply write the table into that tab, there will be an extra duplicate row at the bottom.

      bdd2d179-e0a3-428f-b7cf-ccece0807ecd-image.png

       
       

      Step 16 - Report Removal to the AI

       

      Notify the AI so it can reply to the user:

      7d7a062a-078f-4733-9579-baf1cdda4d44-image.png

      Restart your program, add an event, then remove it. Double‑check the Sheet each time:

      f31330ff-bb58-4ed5-bd82-bb6c399c64cb-image.png

       
       

      Step 17 - Define the “searchEvents” Command

       

      Earlier, the AI already knew the eventID for the dentist appointment, so removing it was easy. But when an eventID is not in the chat context, the AI must search for the event first.

      To keep things simple, we’ll let the AI specify one keyword. Our helper will search that word in the description column and return every matching event (with its eventID).

      Updated system instruction:

      You are an AI assistant that helps manage the user's calendar.
      
      ## Commands
      
      You can use the following tools to manage events through an external service:
      
      * To add a new event to the calendar, you can return this command, which will return its eventID:
      addEvent | [date] | [time] | [event description]
      
      * To remove an existing event, after you have found its eventID, you can use this command:
      removeEvent | [eventID]
      
      * To search for existing events by a **single word**, use this command, which will return all events at that time with their eventIDs (use a generic word to get more likely matches):
      searchEvents | [keyword]
      
      
      ## Instructions
      
      * If you are using a command, then only return the one line of command and nothing else.
      * Use yyyy.mm.dd date format, such as "2025.02.21"
      * Use hh:mm time format, such as "13:30"
      
      

      We instruct the AI to choose one broad word (e.g., “lunch” or “Jon”) so we’re more likely to find the right event—even if we return a few extras, the AI can sort them out.

      Test it:

      cb3181c5-3870-40b9-90d3-8ded030b3ec9-image.png

       
      The AI should pick “lunch” or “Jon” as the word to search for.

       
       

      Step 18 - Intercept the “searchEvents” Command

       

      We will handle this new command using the block “handl search command”:

      a189acb7-0a5b-4cd4-8aa6-cfc1a1109172-image.png

       
       

      Step 19 - Extract the Search Word and Read the Data

       

      Store the keyword in a variable called search word:

      d470f68e-fb62-488c-ae99-73dbb6dfd306-image.png

       
       

      Step 20 - Iterate Through All Rows

       

      Use a for‑loop to walk through each row in events, pulling out the description:

      b1fbb7ed-c0e0-4ffc-af72-d85b4a194889-image.png

       
       

      Step 21 - Build the Search Result

       

      Create a variable called search result. Start it empty, and append every row whose description contains the keyword:

      dd7b8d9b-2dd3-46c0-bc4a-f9d10745b8e6-image.png

       
       

      Step 22 - Send the Search Result to the AI

       

      After the for-loop finishes, the “search result” will either be empty or filled with events. Either way, we will let the AI know the result, so it can generate the response to the user:

      29c74dc2-4960-40b3-883c-56ef07fd5d6d-image.png

       
      To test it, first add another lunch event to the Google Sheet with another person:

      7b4d3776-859e-4f85-9e28-083e63d91b66-image.png

      Then, restart the app, and ask about the “lunch with Jon”:

      9a7d452e-0fa5-4c22-b2e6-224b66743812-image.png

       
       

      Step 23 - Define the “findEvents” Command

       

      Our final command, findEvents, grabs every event between two time points. Perfect for “Am I free next Wednesday morning?” or “What’s on my calendar this weekend?”

      Here is the updated system instruction with the “findEvents” command:

      You are an AI assistant that helps manage the user's calendar.
      
      ## Commands
      
      You can use the following tools to manage events through an external service:
      
      * To add a new event to the calendar, you can return this command, which will return its eventID:
      addEvent | [date] | [time] | [event description]
      
      * To remove an existing event, after you have found its eventID, you can use this command:
      removeEvent | [eventID]
      
      * To search for existing events by a **single word**, use this command, which will return all events at that time with their eventIDs (use a generic word to get more likely matches):
      searchEvents | [keyword]
      
      * To find existing events inbetween 2 time points (they can be the same date or time), you can use this command, which will return all events within the given time interval:
      findEvents | [start date] | [start time] | [end date] | [end time]
      
      ## Instructions
      
      * If you are using a command, then only return the one line of command and nothing else.
      * Use yyyy.mm.dd date format, such as "2025.02.21"
      * Use hh:mm time format, such as "13:30"
      

       
       

      Step 24 - Intercept the “findEvents” Command

       

      We will handle this command using a new block called “handle find events”:

      779b348f-b6c7-4853-9f3c-83d3cf946c74-image.png

       
      The “handle find events” block should be very similar to the “handle search events” block. Can you try to implement it before looking at the steps below?

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Step 25 - Extract Parameters

       

      We will first extract the 4 parameters:

      e2561586-799a-4b27-954b-592d8e8b08d8-image.png

       
       

      Step 26 - Reading Events in a For-Loop

       

      We will still use a for-loop, but this time, we will extract the eventDate and eventTime from each row:

      974f08b8-7ec7-40ea-b506-955b752045b8-image.png

       
       

      Step 27 - Skip Events Before the Start Date/Time

       

      As we check out each row, if we find its date is earlier than the start date, or its time is earlier than the start time, then we will continue to the next row:

      fbb2c495-08cf-43ce-b613-c6b890d109f1-image.png

       
       

      Step 28 - Stop After the End Date/Time

       

      Because events are already sorted, once we reach a row after the end date/time, we can break the loop. Until then, add each valid row to search result:

      413abb89-a679-4f75-9fa0-dbde4e7d29d4-image.png

       
       

      Step 29 - Send these events to the AI

       

      After the for-loop completes, we will give the result list to the AI:

      db5cbeff-0384-4655-991e-88892902fd8c-image.png

       
      Now let’s test it. Suppose this is the calender:

      b6fb265d-d965-4b4e-be6a-b6b90d7ac4d9-image.png

       
      The AI will be able to find all events for next week:

      32bd8a87-72ba-4769-9ba0-48126f9b0a10-image.png

       
       

      Step 30 - Refine the output

       

      The reply above feels a little robotic. Let’s tweak the system prompt so the AI talks more like a human:

      ## Instructions
      
      * If you are responding to the user, then talk like a human
      * If you are sending a command, then only return the **single line** of command and nothing else.
      * Use yyyy.mm.dd date format in commands, such as "2025.02.21"
      * Use hh:mm time format in commands, such as "13:30"
      

       
      Unfortunately, this sometimes makes the AI mix user responses with commands:

      1d59cee0-244b-44b9-9f4c-9283717ac8a7-image.png

       
      Fix: Apply the T.I.R.E. prompting method by adding an explicit Example to the end of the system instruction:

      
      ## Example
      
      [User]: I need to go to Jon's birthday party this Saturday
      [You]: What time is the party?
      [User]: I think it is 2pm
      [You]: addEvent | 2025.05.31 | 14:00 | Jon's birthday party at 2 PM
      [Helper]: addEvent result: successfully added event with ID: E123
      [You]: I have added Jon's birthday party to the calendar for May 30 at 2pm.
      [User]: So what's my schedule next week?
      [You]: findEvents | 2025.05.26 | 00:00 | 2025.06.01 | 23:59
      [Helper]: findEvents result: 
      E99|2025.05.28|18:00|gym class with friend at 6 PM
      E123|2025.05.31|14:00|Jon's birthday party at 2 PM
      [You]: Looks like you have a light schedule next week. You will be meeting with your friend for a gym class next Wednesday at 6, and you will also attend Jon's birthday party on Sunday at 2 o'clock.
      
      

       

      Another problem that might appear in testing is that the AI sometimes think of “next week” as the “next 7 days”, rather than the next calendar week. This can be fixed by adding a new line in the “## Instructions” section:

      * When the user refers to the next week, assume they mean the next calendar week, not the next 7 days.
      

       

      Finally, we are getting a much more human-like response:
       
      be331e0c-680c-49ad-b023-822c792fa45e-image.png

       
       
      Here is a final demo:
       
      calendar.gif

       
       

      Important Note:

       
      When you release your app for other users, you should publish the project instead of sharing it. That is because if you share the project, any user can look inside it to acquire the URL of the Google Sheet, then they will be able to look at other users’ calendars.

       
       
       
       
       

      Additional Challenges

       

      For practice, here are some improvements you can make to this app:

      1. Multiple Commands:
        • Users may combine requests (“My lunch with Jon is cancelled and schedule a dentist at 4 p.m. today”).
        • Rescheduling should trigger a removeEvent followed by an addEvent.

       

      1. Multiple Search Keywords:
        • Allow two or three keywords for searchEvents.
        • “Lunch with Jon” could search for “Jon” and “lunch.”

       

      1. Remove Past Events:
        • When the app starts, delete events more than one month old to keep the Sheet tidy.

       

      1. Recurring Events (advanced):

        • Extend addEvent with a fifth parameter, interval (e.g., “weekly,” “daily”).
        • Add an interval column to the Sheet.
        • When interval is present, auto‑add the event for the next six months.
        • On startup, scan for recurring events and extend them six months into the future.
      posted in Tutorials
      info-creaticode
      CreatiCode
    • RE: Bug?

      @notjaldolfyt

      We just tried, and it seems these comments are not blocked?

      a1f10b9f-8a1a-4179-a12e-aa463cf7954a-image.png

      posted in Help
      info-creaticode
      CreatiCode
    • AI-based Game: Guardian of History (Difficulty 4)

      Introduction

       

      Large Language Models (LLMs) such as ChatGPT can do far more than simply chat or perform text‑processing tricks.

      In this tutorial you will build an artificial‑intelligence‑powered game called “Guardian of History.”

      The AI will act as the Game Master, controlling all interactions with the player. Because the AI responds to the player’s unique choices, every play‑through feels fresh and completely personalized.

      This game is an entirely new game designed by the CreatiCode team. Here are some high-level explanations on how this game works:

      1. Background — A villain has stolen a time‑travel machine and journeyed into the past to tamper with human history. They secretly “hijack” the mind of a historical figure, force that person to act differently, and thereby disrupt a major historical event.

      2. Goal of the Game — The player is a “Guardian of the True Timeline.” To win, they must figure out who was hijacked and what action that person took under mind control. Once identified, the timeline can be repaired.

      3. Helper Tool — The player has access to a time‑travel console named TESSA. TESSA can answer any question about the true or altered timeline — but it does not know the identity of the hijacked person either. That detective work is up to the player.

       
      Here is a preview of the game play:

      Peek 2025-05-19 19-48.gif

       
      Besides being fun, this game strengthens historical knowledge, logical reasoning, and debugging skills as the player searches for clues in the altered past.

       
       

      Tutorial Structure

       

      This project leans heavily on widget blocks to build the game’s user interface (UI). Because coding the complete UI step‑by‑step would be extremely long, and our focus is really on the AI portion, you will start from a template project that already contains all non‑AI code.

      The tutorial is split into two large parts:

      • Part 1   A rapid walkthrough of the provided UI code. You will see how every sprite and block fits together so you can customize the visuals later if you wish.
      • Part 2   A detailed, step‑by‑step guide for adding the AI logic. Here you will write and fine‑tune the complex prompts that power the game.

       
       

      Part 1 - Starting Project Explained

       

      This part will help you understand the code given in the starting project, so you can easily change it or extend it, and also you will understand how the AI related code fit into the flow.

       
       

      1 - Remix the project template

       

      You can find the project at this link:

      play.creaticode.com/projects/682bc7628baa30c98a62551a

      Please remix it into your own.

       
       

      2 - The Stage and 3 Sprites

       

      There are 4 components in this project:

      1. Stage: A static backdrop for the game.
      2. “Initial Screen” Sprite: Displays the initial screen when the game starts.
      3. “Game Screen” Sprite: Manages the in‑game chat window and buttons used during play.
      4. “AI” Sprite: Holds all the code that uses AI to run the game. This will be the focus of part 2.

       
       

      3 - The Stage Backdrop

       

      The stage only has one backdrop, which is composed of 3 layers:

      • Background image — You can generate one with any AI image tool. After importing, convert it to vector mode.
      • Title — A bold heading at the top reading “Guardian of History.”
      • Semi‑transparent dialogue area — A see‑through rectangle in the middle where text will appear.

       
      53f6d403-c44d-4f84-b8c9-7b863dcd0c0c-image.png

       
       

      4 - Initial Screen Sprite - Show 3 Main Buttons

       

      Now let’s look at the “Initial Screen” sprite. When the green flag is clicked, this sprite:

      • Loads any saved game so the player may replay a previous mission.
      • Shows an “Instructions” button that explains the rules.
      • Shows a “New Game” button that asks the AI to create a brand‑new plot.
      • Displays a “Replay Game” button only if a prior game was loaded successfully.

       
      ae11ccbb-1997-4ddd-b6c9-534127141913-image.png

       
       

      5 - Initial Screen Sprite - Handle the “Instructions” Button

       

      When Instructions is clicked:

      1. A read‑only rich‑text box appears as an overlay.
      2. Its text is pulled from the variable instructions, which is easy to fill with multi‑line content.
      3. A Back button is added under the text.
      4. Clicking Back removes both the overlay and the button.

       

      0a88cd65-97f1-4e15-b6f8-e65f60ee5584-image.png

       
       

      6 - Initial Screen Sprite - Handle the “New Game” Button

       

      When New Game is pressed:

      • The player sees a label and a text box asking for an interesting historical event. This lets them tailor the adventure to any topic — maybe the French Revolution or the Space Race.
      • For example, we might enter Invention of the Spinning Jenny (UK) in 1764.
      • A “Generate New Game” button then appears. Clicking it instructs the AI to craft a unique plot using the chosen event.

       

      956adf49-c6de-41a4-8886-bcba810e0f47-image.png

       
       

      7 - Initial Screen Sprite - Handle the “Generate New Game” Button

       

      When the player clicks “Generate New Game”:

      1. Saves the typed event in event input.

      2. Clears every widget on screen and shows a single label that says “Creating game …”.

      3. Broadcasts “generate new game” to the AI sprite and waits. The AI will eventually populate 3 key variables:

        • true history – contains the list of people involved in the given event in history.
        • altered history – contains a list of events that lead to a different outcome in the altered history.
        • game intro – a welcome paragraph that sets up the mission.
           
      4. Stores true history, altered history, game intro, and event input so the game can be replayed later.

      5. Removes all widgets because we are switching to the main game screen.

      6. Broadcasts “start game” to let the “Game Screen” sprite take over.

       
      f481e2b7-19eb-41f6-8bbf-c3578ed6a286-image.png

       
       

      8 - Initial Screen Sprite - Load the Saved Game Info

       

      The “load saved game” block (run at project start) works like this:

      1. Retrieves event input, true history, altered history and game intro from local storage.
      2. Extract the first line of altered history into the variable hijacked person. This will be used as the final answer for checking against the player’s guess.

      A real AI‑generated example of altered history looks like this, with the hijacked person’s action in the first line, followed by a series of chain reactions that lead to the disruption of the historical event:

      
      1.  Thomas Highs, instead of employing Hargreaves, decided to focus on improving his own weaving business and invested heavily in new loom technology.
      2.  Without Highs's support or workshop, James Hargreaves lacked the resources and collaborative environment to develop the spinning jenny efficiently.
      3.  Robert Kay's flying shuttle still increased yarn demand, but without the spinning jenny, the pressure fell on existing spinning methods, leading to yarn shortages and price increases.
      4.  John Wyatt and Lewis Paul's earlier spinning machine designs remained largely unexploited, as no other inventor stepped forward to significantly improve upon them.
      5.  Daniel Defoe's advocacy for textile innovation went unheeded, as the focus shifted to optimizing existing hand-spinning techniques rather than pursuing radical mechanization.
      6.  The textile industry experienced slower growth, with weaving outpacing spinning. This imbalance led to economic inefficiencies and delayed the onset of the Industrial Revolution in textile production.
      7.  Ultimately, the invention of the spinning jenny was significantly delayed, potentially allowing other countries or inventors to develop alternative solutions for increasing yarn production first.
      
      

       
       

      9 - Initial Screen Sprite - Handle the “Replay Game” Button

       

      Because the variables were already loaded, pressing Replay Game simply removes the current widgets and broadcasts “start game.” No AI call is necessary.

       
       

      10 - Game Screen Sprite - Responding to “start game”

       

      Now let’s switch to the “Game Screen” sprite. When it receives the “start game” message:

      • Clear the “messages” list, which keeps a running log of player/AI chat.
      • Run the “add chat” block to add a chat window.
      • Run the “add command buttons” block to insert three action buttons below the chat.
      • Run the “add input box” block to prepare a hidden overlay for player text entry.

       
      The finished game screen initially looks like this:

      294a55cc-9bb0-46ae-819d-c223b468c627-image.png

       
       

      11 - Game Screen Sprite - “add chat”

       

      Within add chat the sprite:

      1. Adds the chat window.
      2. Covers the chat’s own input area with a blank label. (We supply our own input dialogue later, which is more reliable than asking the AI to guess each message’s purpose.)
      3. Inserts game intro as TESSA’s very first message.
      4. Saves that same message in the messages list.

       
      If you run only add chat, the screen would appear like this:

      087d25c1-c241-4c9d-a91e-d82d26a62b7a-image.png

       
       

      12 - Game Screen Sprite - “add command buttons”

       

      This block simply drops three buttons onto the bottom edge:

      9f830627-21da-404c-80b4-4be5fe5a82bf-image.png

       
       

      13 - Game Screen Sprite - “add input box”

       

      This custom block creates—but immediately hides—a reusable overlay dialogue. It contains:

      • A purple label that darkens the background.
      • A read‑only textbox that shows a short instruction.
      • A second textbox where the player will type their command.
      • Two buttons: Cancel and Send.

       

      If you displayed them without hiding, they would look like this:

      f1ee0fc7-3611-4fcf-92f9-c9bd20f10498-image.png

       
       

      14 - Game Screen Sprite - “show command input”

       

      This helper toggles the visibility of the overlay input box:

      • If visible = 1, every widget is shown and the input textbox is cleared.
      • If visible = 0, the five widgets are hidden.

       
       

      15 - Game Screen Sprite - Handling the “True History” Button

       

      Clicking True History (factbutton) does three things:

      1. Sets a variable current mode to “check true history.”
      2. Changes the instruction text so the player knows they should ask about the original timeline.
      3. Calls show command input (1) to reveal the overlay.

       
      It would look like this:

      951ca70b-8b5c-4604-a62e-a4d6318abcaf-image.png

       
       

      16 - Game Screen Sprite - Handling the “Altered History” Button

       

      Clicking Altered History (querybutton) follows the same logic, but the instruction now asks about the altered timeline:

      b6dae638-b30c-4f3d-b43e-7da279a84cf8-image.png

       
       

      17 - Game Screen Sprite - Handling the “Guess” Button

       

      Pressing Guess changes the instruction to tell the player they must name the hijacked person and the altered action:

      0da0d319-8997-4365-91f6-390e4d480152-image.png

       
       

      18 - Game Screen Sprite - Handling the “Cancel” Button

       

      If a player opens the overlay but clicks Cancel, show command input (0) hides the dialogue box. Nothing else happens.

       
       

      19 - Game Screen Sprite - Handling the “Send” Button

       

      When Send is clicked the sprite:

      1. Calls show command input (0) to hide the overlay.
      2. If the input box is blank, it exits — identical to pressing Cancel.
      3. Otherwise it appends the player’s message to the chat.
      4. Inserts a placeholder response “…” from TESSA so the user knows the AI is thinking.
      5. Broadcasts “handle command” to the AI sprite and waits.
      6. Replaces “…” with whatever text the AI stores in the variable command result.
      7. If command result reads “You won”, then the player guessed correctly. The three command buttons are hidden so the conversation ends.
      8. If the player has not won, both the player’s message and TESSA’s answer are appended to the messages list.
      9. If the “messages” list becomes too long (more than 31 messages logged), then trim it by removing the 2 oldest messages at the beginning.

       
       

      20 - AI Sprite - Placeholders for Now

       

      Finally, let’s peek at the AI sprite. It currently reacts to only two broadcasts:

      1. “generate new game” – It must invent a full storyline (hijacked person, true history, altered timeline) based on the historical event the player typed. It also needs to compose the introductory game intro.

      2. “handle command” – Depending on current mode, the sprite will run exactly one of three blocks:

        • query true history – Answer a question about the original timeline.
        • check altered history – Answer a question about the sabotaged timeline.
        • submit a guess – Judge whether the player’s guess is correct.

      We will build these blocks — complete with robust prompts — in Part 2.

       
       
       
       
       
       

      Part 2 - Step‑by‑Step Guide for Adding the AI Logic

       

      Now that you have a solid grasp of the player experience and the template code, it is time to fill in the missing AI pieces.

      Throughout this section, we will iteratively craft long, detailed prompts and apply best‑practice techniques (including the T.I.R.E. prompting method) so the AI consistently produces correct and interesting replies.

       
       

      Step 1 - Generating the “true history”

       

      When the AI sprite receives the broadcast “generate new game,” it must invent an entirely new plot.

      The only input available is the player’s event input, for example — “Invention of the Spinning Jenny (UK) in 1764” or “The Declaration of Independence.”

      From that single line, the AI must output 2 items: what happened in the true history and how that’s disrupted in the altered timeline.

      Let’s focus on the true history first. It is simply a list of key historical figures closely related to the event specified by the player. For some events, these people might be well documented. However, if the player has specified a less well-known event, the AI might have to “invent” some people to create a complete story.

       
      For a simple start, we can try this:

      a87d10ec-0b47-4876-82f1-418db216e06c-image.png

       
      Note: Use the LLM reporter rather than ChatGPT — the LLM block is more suitable for complex tasks.

      And here is a likely output in the console panel:

      Okay, here are some people whose actions were important leading up to the invention of the Spinning Jenny in 1764:
      
      *   **John Kay:** His invention of the flying shuttle in 1733 significantly sped up the weaving process. This created a demand for more yarn, which, in turn, spurred innovation in spinning technology.
      
      *   **Lewis Paul and John Wyatt:** They patented a roller spinning machine in 1738 and 1748. Although their inventions weren't commercially successful, they demonstrated the potential for mechanized spinning and inspired later inventors.
      
      *   **James Hargreaves:** As the inventor of the Spinning Jenny, he is the person most directly responsible for its creation. His personal experience as a weaver likely informed his understanding of the need for a better spinning solution.
      

      Before continuing to the next step, try running these blocks a few times to observe any issues. You should try different “event input” as well.

       
       

      Step 2 - Adding Some Instructions

       

      Here are some issues with the blocks added above:

      1. There are often unnecessary sentences before or after the list, such as “OKay, here are …” or “If you need anything else, let me know …”. These are often called “pleasantries.” They are meant to make a chat message more natural, but since we are not in a chat, they become unnecessary.

      2. The output list often only contains 3 to 4 people. We need more people to create a rich story.

       
      Now, can you try to refine this prompt by adding some instructions for the output?

      For a hint, you can build a longer prompt by joining 2 or 3 variables like this:

      27b28366-f8e2-4380-ad22-06d3739f6eb5-image.png

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Here is an example of a refined prompt in 3 parts:

      • Part 1:
      ## Task
      
      Generate a list of 6 most important people in history whose actions directly led to this event:
      
      

       

      • Part 2: The variable event input (note that you need to run the game at least once to populate this variable with an event)

       

      • Part 3:
      
      ## Instructions
      
      * If historical records are incomplete, invent plausible figures to fill gaps in the story.
      * Briefly explain each's role in the event.
      * You must assign a name in English for each person.
      * Avoid all pleasantries. Only return the list and say nothing else.
      
      

       
      Here are the blocks:

      f2e02411-dfb7-421c-ba36-98b06e101495-image.png

       
      Important observations:

      • We are asking the AI to list exactly 6 people to ensure the true history is not too short or too long.

      • We encourage the AI to “invent” some people if the event is not well-documented.

      • The ## headings make it easy for the AI to locate relevant instructions.

      • The event input is a dynamic component that will be provided by the player, which makes the game highly customizable. For this tutorial, please keep using the default value of “Invention of the Spinning Jenny (UK) in 1764” as an example.

      • We require the AI to “avoid all pleasantries” and only output the list. If you did not include this, most likely you will get unnecessary sentences before or after the list.

       
      When you test run this script, the output in the console may look like this:
       

      *   **James Hargreaves:** Inventor of the Spinning Jenny.
      *   **Thomas Highs:** Possible early inventor of a similar spinning machine.
      *   **Robert Kay:** Inventor of the flying shuttle, which increased demand for yarn.
      *   **John Kay (of Bury):** Improved upon the carding process, preparing cotton fibers for spinning.
      *   **Daniel Defoe:** Writer whose observations highlighted the existing domestic system of textile production and the need for efficiency.
      *   **Lydia Bancroft:** A skilled weaver whose efficiency highlighted the disparity between yarn production and weaving capacity.
      

       
      Try to run this new stack a few times, and observe how the list changes. You will find that people on top of the list usually don’t change much, but the remaining people may change between runs.

       
       

      Step 3 - Generating the “altered history”

       

      Next, we need to generate an altered history based on the true history above. The idea is to randomly pick a person from the list as the person to be “hijacked”, and ask the AI to change that person’s action to disrupt the historical event. We will need a list of chain reactions that lead to the disruption of the historical event.

      Now try to add code to generate this altered history. You can use the LLM block to “continue” the conversation above, so you don’t have to repeat the event or true history again.

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

       
      Here is an example implementation:

      c0cffd47-4055-4caf-abf7-b0101f772e2f-image.png

       
      We start by asking the AI to “imagine person X from the list was hijacked by a time traveler to disrupt the event”, and X can be a random number between 2 and 6. We did not include the first person, since that’s almost always the main character of the event, and it would be too easy to guess.

      Next, we specify the task and instructions. The complete text for prompt2 is:

       from the list was hijacked by a time traveler to disrupt the event.
      
      ## Instructions
      
      * Only output a list of chain reactions, starting with that person's action and continuing with how other people may react and how the event was disrupted.
      * The first line must be what the hijacked person did
      * Never mention what happened in the original history. Describe the updated events as if they actually happened in history.
      * Avoid any pleasantries and say nothing else except the list of chain events
      
      ## Output Format Example
      
      1. Isaac Newton walked away from the apple tree, so he ignored apples falling from trees.
      2. ...
      
      

       
      A few important details:

      • The text starts with a SPACE before “from the list”, so that there is a space after the random number when they are joined.

      • We emphasize that the first line must be about the hijacked person since we are extracting that into the variable hijacked person, which will be the game’s final answer.

      • We also include an example output to further make sure the output starts with the action of the hijacked person. This is the “E” part in the T.I.R.E. method.

       
      Here is an example output:

      1. John Kay sabotaged the carding machines in his region and spread misinformation about their reliability.
      2. Textile producers became wary of using carding machines, preferring manual methods of preparing cotton fibers.
      3. James Hargreaves struggled to find a reliable supply of prepared cotton for his Spinning Jenny prototype.
      4. Robert Kay's flying shuttle was not as effective due to the uneven quality of hand-carded yarn.
      5. Daniel Defoe documented the continued inefficiency of textile production, blaming the unreliable fiber preparation methods.
      6. Lydia Bancroft's weaving speed was limited by the inconsistent quality of yarn, reducing overall output.
      7. The Spinning Jenny's adoption was slowed by the lack of efficiently prepared cotton, hindering its impact on textile production.
      

       
      Again, run this part of the code a few times, and notice when different people are chosen as the hijacked person, the timeline varies quite a lot.

       
       

      Step 4 - Generating the Opening Message (“game intro”)

       

      TESSA’s first message should greet the player, summarize the danger, and invite questions—no more than ~80 words. We again build a three‑part prompt:

      • Part 1 — fixed text introducing TESSA and the disrupted event (see below).
      • Part 2 — the dynamic event input.
      • Part 3 — instructions demanding a concise, markdown‑formatted greeting.

      For example:

      • Part 1:
      You are TESSA, a robot in a time-travel detective game. A rogue time traveler has gone back to the past to secretly take over a real person. This person was not famous, but they did something different, changing history in a big way.
      
      The player is a guardian protecting the actual history. With your help, the player will discover which person was taken under control and what they did.
      
      Through you, the player can ask about what happened in the original and altered history, so that the player can discover the rogue traveler.
      
      So far, you know the rogue agent aims to sabotage this event:
      ---
      
      • Part 2: the “event input” variable

      • Part 3:

      ---
      
      Now, please generate a short greeting message within 80 words to the player explaining the situation and ask the player to ask questions to catch the rogue traveler.
      
      Use a markdown format to emphasize key information.
      
      

      Note that we are asking the AI to use the markdown format, which usually makes the output easier to read. This is important, since this game is mostly presented by chat messages, it will be exhausting if the player has to read big chunks of text.

      Below is the code for composing this 3-part prompt and send it to AI:

      4e2a809b-03e0-4c6d-b333-eb87d2bad196-image.png

       
      Note that we are using a “new chat” session type. Since all the information is included in the current prompt, the AI does not need any previous messages to generate the new message.

      After this step, when the player generates a new game, they will be greeted with a new message like this:

      2cb75199-b8b3-44d6-80e4-49595eff8c3a-image.png

       
       

      Step 5 - Handling Query on the True Timeline

       

      Next, let’s address the player’s question about what actually happened. This will be a complex prompt that we can develop in a few steps.

      For an initial version of the prompt, let’s keep it relatively simple:

      • Explain how the game works and the key event
      • Tell the AI that its task is to answer the player’s question

      Please add code to “query true history” to compose the prompt above and query the AI. You can test with this question: “Who invented the Jenny?”

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Based on the discussion above, this prompt will contain 5 parts:

      • Part 1:
      You are TESSA, an AI time machine in a time-travel detective game: a bad time traveler has gone back to the past, secretly taken over a real person to alter their action. The player's job is to guess which person was hijacked and what change in action was made.
      
      Specifically, the current game plot is about protecting the truth of this event:
      
      
      • Part 2: the variable “event input”

      • Part 3:

      
      ## Task
      
      Your current task is to answer a question about the true history from the player:
      
      • Part 4: the variable “player input”, which contains the question.

       
      Below is the code to compose these 4 parts into the prompt and query the AI:

      8365d52f-8187-4487-871d-6243d88a61ff-image.png

       
      Here is an example response we get:

      0ad2951f-91b6-4ab4-9186-7fcac3b00d6d-image.png

       
       

      Step 6 - Adding Recent Messages for Context

       

      When answering player questions, we are doing something very different: we always choose the “new chat” session type instead of “continue”.

      Here is why. When we use the “continue” type, the CreatiCode server will help save all the messages between the user and the AI, and automatically attach them to the next request, so the AI model understands the context.

      However, for this project, there may be hundreds of messages between the player and the AI, so soon there will be too many messages in the context, and the AI model won’t be able to handle them anymore.

      Therefore, we are going to use the “new chat” type and provide the most recent messages ourselves in each request. The benefit is that the player can keep chatting forever if they want to. However, since only the most recent conversation is saved, the AI model will not “remember” earlier messages, though the player can still check them in the chat window themselves.

      To insert the recent messages into the prompt, we can insert another section into our prompt:

      40ba36bb-d4e4-455c-b60e-c4261cc2cc1c-image.png

       
      Note that when we use “messages” as a reporter, it will join all the items in that list as one text.

      The value of “prompt2” above is the following:

      
      ## Recent Messages
      
      For context, here is the most recent conversation between you and the player:
      
      

      We can test it by asking 2 questions one by one:

      1. “Who invented the Jenny?”
      2. “How old was he in 1764?”

      Because we are inserting the messages into the prompt, the AI model can infer “he” refers to “James” in the second question:

      0fb06357-4cdf-486b-83d7-beb39edcd729-image.png

       
       

      Step 7 - Adding the True History as Refrence

       

      Although we can simply make the AI answer these questions based on its existing knowledge of the actual history, it is better to “ground” it with the “true history” we have generated earlier. This way, it will generate consistent answers, and it will automatically include these key people in its answers, which can serve as clues for the player.

      To do that, we can insert these blocks when composing the prompt for the true history:

      64ad405c-6862-467b-ab1f-2590ec045b7c-image.png

       
      The content of the “prompt2” is the following:

      
      
      ## Reference
      
      Some additional details related to the event that you can use as reference:
      
      

       
       

      Step 8 - Output Instructions

       

      Although our code works for basic questions, there are a few issues that need to be addressed:

      • It may include unnecessary pleasantries.
      • It might be “too eager to help” and leak the secret identity of the hijacked person.

      Therefore, we need to add a new section “Output Instructions” to improve the output. This prompt can be refined over time, but here is a good starting point:

      
      
      ## Output Instructions
      
      Now return the answer as if you are talking to the player directly.
      
      * Always assume the player is asking about the true history.
      * Try to include other people from history in your answer besides the reference to make it harder to guess who are important.
      * Be concise. No need for pleasantries. Just answer directly.
      * If the player's question is not clear, you can ask a clarifying question instead. 
      * Use markdown format to organize your answer to make it concise and easy to understand.
      * For any questions on the rogue traveler, say they have no impact on the true history.
      * For questions on who was hijacked or what was changed, say you have no information.
      * Reject inappropriate inputs.
      

       
      This section can be inserted like this:

      e528a2b1-60dd-48d1-b468-731f49257d8b-image.png

       
       

      Step 9 - Handling Questions about the Altered History

       

      The logic for answering questions about the altered history is actually very similar to that for the true history.

      Can you give it a try first? Duplicate the blocks from the “query true history” block into the “query altered history” block, then make all necessary changes.

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
      Here are the blocks you need:

      a3b71374-6562-4ed3-9159-c68337d50a53-image.png

       
      The changes are:

      • For “Task”, it needs to be updated like this:
      ## Task
      
      Your current task is to answer a question about the altered history from the player:
      
      
      • For “Altered History”:
      
      ## Altered History
      
      The following events happened in the altered history. You should base your answers on these events instead of the actual history:
      
      
      
      • For “Output Instructions”, you need to specify that the answers should be about the altered history:
      
      
      
      ## Output Instructions
      
      Now return the answer as if you are talking to the player directly.
      
      * Always assume the player is asking about the altered history.
      * Use the reference to help you answer, and fill in more details and bridge any gaps to make your answer logical and consistent as if they really happened. You can add additional people in the explanations, so long as they make sense.
      * Be concise. No need for pleasantries. Just answer directly.
      * If the player's question is not clear, you can ask a clarifying question instead. 
      * Use markdown format to organize your answer to make it concise and easy to understand.
      * For questions on the rogue traveler, who was hijacked or what was changed, say you have no information.
      * Reject inappropriate inputs.
      
      

       

      Try a few questions on the altered history. Do you see any issues?

       
       

      Step 10 - Enhancing the Output Instructions

       

      One obvious and serious issue is that the AI is “too eager to share”. For example:

      54a2c2d4-59a9-41b8-be2c-8519713d1ae6-image.png

       

      This is a critical issue. If the AI keeps spilling out clues like this, the game will be boringly easy to play.

      To make the game more challenging, we need to force the AI to say less. Here are some new instructions we can add:

      
      
      ## Output Instructions
      
      Now return the answer as if you are talking to the player directly.
      
      * Always assume the player is asking about the altered history.
      * * Use the reference to help you answer, and fill in more details and bridge any gaps to make your answer logical and consistent as if they really happened. You can add additional people in the explanations, so long as they make sense.
      * Be concise. No need for pleasantries. Just answer directly.
      * If some event did not occur in the altered history, say it did not happen without explaining why.
      * Avoid explaining why some event happend and avoid offering extra facts unless you have to. 
      * Be secretive and respond with the **minimum info**. Make it hard for the player to guess the hijacked person.
      * If the player's question is not clear, you can ask a clarifying question instead. 
      * Use markdown format to organize your answer to make it concise and easy to understand.
      * For questions on the rogue traveler, who was hijacked or what was changed, say you have no information.
      * Reject inappropriate inputs.
      

      After this change, the answer is less helpful (which is good):

      b5134a91-f61a-4f5c-8c74-232235ffc3d6-image.png

       
      Of course, this prompt can still be improved over time as you test with more events and questions.

       
       

      Step 11 - Evaluating Player’s Guess

       

      For the last part, we need to check if the player’s guess is correct. To do that, we need to explain the game to the AI, and ask the AI to compare the player’s guess against the secret information on the hijacked person. To avoid leaking any information by accident, we will simply make the AI respond with one word: “correct”, “partial” or “wrong”.

      You can start by duplicating the blocks from “handle altered history”, and then updating the blocks/variables:

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       

      Here is an example solution:

      2ee9f2b3-17f9-414d-912e-327dc0c04df1-image.png

       
      The changes:

      • The Task is different:
      ## Task
      
      Your current task is to check if the player has guessed correctly who the hijacked person is and what they did to sabotage the event above. Here is the player's input:
      
      
      • Some information on the hijacked person is inserted

      • The output instructions emphasize that only one word should be returned:

      
      
      ## Output Instructions
      
      Return a single word "correct", "partial" or "wrong" by comparing the player's input and the secret information below.
      
      * Return "correct" if the player guessed the hijacked person's name, and is pretty close on what that person did to sabotage the key event.
      * Return "partial" if the name was guessed correctly, but the action description is missing or far off.
      * Return "wrong" if the name was not guessed correctly.
      
      

       
       

      Step 12 - Converting the One‑Word Verdict into Friendly Feedback

       

      Players deserve a human‑readable reply. In the Game Screen sprite, intercept the raw AI verdict and swap it for a nicer message:

      75aa67cd-be5d-430b-8239-026fa0970f86-image.png

       
       

      Demo

       

      That’s all the steps needed to complete a basic version of the game. Here is what it looks like in action:

      Peek 2025-05-19 19-48.gif

       
       

      Additional Challenges

       

      Below are some creative extensions you can try to make the game more advanced, interesting, or accessible. These tasks are optional but highly recommended as practice to deepen your understanding of AI behavior and game design.

      • Refine the Prompts: Thoroughly test the game and look for bugs, inconsistencies, or loopholes. Then refine the AI prompts to fix those issues. For instance, if the player can easily trick the AI into revealing the correct answer, that would ruin the challenge, so make sure the prompts explicitly tell the AI not to leak any secret information unless asked directly.

      • Add Difficulty Levels: Let players choose a difficulty level when starting a new game. You can increase the challenge by having the AI generate more people involved in the event, so instead of 6 possible suspects, you might have 10 or even more. This adds complexity and makes guessing correctly much harder.

      • Add a Hint Button: For players who are younger or not familiar with history, the game may be too difficult. To help them out without spoiling the answer, you can add a fourth button labeled “Hint” on the game screen. When clicked, the AI can provide a small clue—such as a general time range, region, or a short list of suspicious individuals—that nudges the player in the right direction while still preserving the mystery.

      • Enable Conversations with Historical Characters: Currently, the player can only talk to TESSA to ask questions about the timeline. A major upgrade would be to allow the player to “mentally travel” into the timeline and speak directly with people from that era. You can implement this by asking the AI to role-play historical figures based on the time period and context. This will make the investigation more immersive, like interviewing eyewitnesses in a mystery story.

      posted in Tutorials
      info-creaticode
      CreatiCode
    • RE: Really sad about this

      @notjaldolfyt

      This issue is fixed now.

      posted in Help
      info-creaticode
      CreatiCode
    • RE: [Community Project] Let's Build a CreatiCode Project Packager!

      @tyller_ @Neurotex000-ed114c41

      Thank you for bringing this up.

      We have considered this before. The main issue is that the new extensions, like 3D and AI, all rely on our server to work, so an “offline” version won’t do much.

      If the goal is to generate a package to run a project online, such as embedding it in a webpage, then the “share link” tool already makes this possible.

      We would like to hear more about whether this new packager would be really useful for CreatiCode. If there is a strong use case, we are open to working on it ourselves or with the community.

      posted in Test
      info-creaticode
      CreatiCode