When we run it, we got this at the end:
The retry button looks fine. Can you give some more details on the issue?
BTW it’s an interesting game.
CreatiCode
When we run it, we got this at the end:
The retry button looks fine. Can you give some more details on the issue?
BTW it’s an interesting game.
CreatiCode
Hi, can you please share your project and post a link here? We will look into the issue.
CreatiCode
@flores-yorkshireacademy said in Emitter with model:
My students are learning to code in 3D. They want to use the emitter as a sonar for an ROV; is this possible?
Hi Kathleen,
It is not clear what your students are trying to do. If you can share an example project, we can try to help modify it.
For a generic explanation, to make anything glow, it has to have emission colors. By default the models don’t have emission colors (they only have diffusion colors), so they won’t glow. However, we can update the models to add emission colors to them.
Note that the “update color” block requires you to specify an “area”, which can be up to 4 parts of the model, and the meaning of each area is different depending on the specific model (you will have to try them to find out). Here is more information on that block:
https://forum.creaticode.com/topic/136/update-object-colors
Here is an example project:
https://play.creaticode.com/projects/662725062f96f8f32bf469d8
CreatiCode
Can you please ask your friend to email his/her email login to info@creaticode.com? We will check why.
CreatiCode
To most people, quizzes are not fun: they can be too easy or too hard, and we may have to take them before we are ready. However, quizzes are one of the most effective tools for reinforcing what we have learned and identifying gaps in our understanding.
With XO, you can get quizzes that are much more fun: you can customize the theme of the quizzes and choose the difficulty level.
If you are a teacher, you can also use XO to generate quizzes for your entire class.
For an important note: XO can not accurate evaluate all quizzes yet, especially coding challenges. That is because currently, XO can not run the program, so it has to rely on reviewing the code. Also, XO is not smart enough to recognize all coding issues yet (though it is catching up fast!). To be safe, teachers may still need to review the final answers.
In the most basic format, you can ask XO to generate a random quiz by saying “give me a quiz on [TOPIC] with difficulty [LEVEL]”. The LEVEL can be 1, 2, 3 or 4, with 1 being the easiest. For example, when you say “give me a quiz on variables with difficulty 1”, you may get a response like this:
Now you can simply answer the quiz in the chat and get the result:
By default, XO will randomly select from these 3 formats: coding challenge, multiple-choice question and short-answer question. However, you can specify the format if you have a preference. For example, you can ask “give me a coding challenge on variables with difficulty 2”:
After implementing the solution, we can ask XO to check out solution by saying “check my code” or “check my answer”. If there is an issue, XO will point it out:
After fixing the issue, we can ask XO to check again by saying “check again” or “how about this new answer”:
Quizzes can be made fun when we add some “flavors” to them. Specifically, we can ask XO to generate quizzes with a given background story, character or theme. XO will be happy to do so. For example, you can pretend to be any character, like an Alien:
Below are some more examples that you can try:
XO can follow our instructions very well, so we can feel free to add more details to our request. Here are 2 examples.
Since XO may not know which blocks we already know, it may generate a quiz that uses some blocks that we are unfamiliar with. To avoid this issue, we can specify which blocks can be used like this: give me a coding challenge on clones. difficulty 1. note that I am new to Scratch and I can only use motion and event blocks
Since XO can read the code in the playground, you can ask Xo to use that as a reference when creating the quiz. For example, you can open the Explore page and find an interesting game, then ask XO this: I’m a 5th grade teacher. I just explained this project to my class, and now I hope to test their understanding. Give me a multi-choice question of level 1 about how this project works.
If you have found any interesting way to prompt XO to generate quizzes, please feel free to reply to this post below with the request you used and XO’s response.
This tutorial is designed primarily for K-12 educators, though students may also find it insightful.
As educators, one of our key goals is to provide students with constructive feedback that acknowledges their efforts and guides them towards improvement. Effective formative assessment is crucial in this process, as it helps highlight both strengths and areas for growth.
Nevertheless, crafting thoughtful and comprehensive feedback can be quite demanding. It requires a careful review of each element of a student’s work and a considered choice of words to ensure the message is both encouraging and instructive.
To address this challenge, XO has been developed to provide feedback on any given project when we provide it with a rubric. Here is how it works:
The key advantage of this approach is that it offers students instant, personalized feedback, significantly enhancing both the efficiency and engagement of the learning process.
Let’s consider a scenario where a teacher has recently introduced the concept of the “broadcast message” block in class. Here’s an example of how an assignment using this concept might be structured along with its rubric:
Create a project that effectively demonstrates the use of message broadcasting between sprites.
Rubric:
1. The project must include at least two sprites, each with appropriately descriptive names.
2. At least one sprite should broadcast a message that another sprite receives and responds to.
3. All message names used should be clear and meaningful.
4. The project should narrate a coherent story, such as a dialogue between two people or an interaction between two animals.
5. [Extra credit] Implement a broadcast message that triggers simultaneous actions in two or more sprites.
Suppose a student creates an initial version of the project with 2 sprites like this:
Sprite “Sprite1”:
Sprite “Crab”:
Note that the Sprite1 is missing the “broadcast” block.
Now, suppose the student asks XO for feedback. He/she needs to ask XO to “review the project for the given assignment”, then paste the assignment/rubric into the chat. Don’t worry about the format, as XO will still understand the request even if it is all in one line:
Note that XO has gone through every requirement in the rubric thoroughly, and it has correctly pointed out some issues, especially that “message1” is not sent out.
Next, suppose the student has updated the program to broadcast the message, and also renamed the message name like this:
Sprite1:
Crab:
Now, the student can ask for another review by saying “review again” or “how about now”:
Note that the review has been updated to confirm the changes the student has made, and also encourage student to focus on the remaining issues.
The student can keep improving the project continuously until he/she is happy about it.
It’s important to understand that XO is capable of evaluating only the code blocks within each sprite. This means that XO is unable to assess several aspects of the project:
Given these limitations, XO is best utilized for static analysis of the programming elements of a project.
If you’re uncertain about how to write effective rubrics for XO, you’ll be pleased to know that XO can assist in writing the rubrics itself. Who doesn’t love an AI that can write instructions for itself?
For best results, here are some tips for asking XO to write rubrics:
Here is an example request:
I'm teaching fifth grade students how to use repeat loops in combination with variables.
Write an assignment with rubric. It should cover variable initialization and variable
updates inside the loop.
And here is an example output from XO:
CreatiCode extends MIT Scratch by introducing a variety of new block categories including 3D game engines with physics capabilities, 2D physics, artificial intelligence, app widgets, multiplayer online games, augmented reality, and table variables. These additions allow for the creation of a much broader range of projects beyond what is possible with standard MIT Scratch.
Starting a new project can sometimes be daunting if you’re unsure of where to begin. This is when you can ask XO for help. XO has seen many different types of projects, so it can often make some suggestions on how to design a new project.
It’s important to remember that XO is primarily an assistant. While it can provide helpful tips and guidance, it cannot create an entire project on its own. XO is optimized for short, specific responses, and its performance may decline when tasked with generating lengthy replies. Moreover, as a coding learning tool, XO aims to enhance learning by encouraging students to engage more deeply with the programming process. Providing full code solutions would be counterproductive to this educational goal.
Also, XO can not generate original ideas: everything XO says is a response to your idea based on other existing projects that XO has seen before. For a project to truly stand out, your own creativity and vision are key. XO’s role is to assist in bringing your unique ideas to life, offering support and suggestions based on its vast database of project insights.
In this tutorial, you will learn how to use XO to design new projects.
Whenever you come up with an idea, you can ask XO how to build it. XO would give you an outline of the project. You are use this as a baseline to estimate the complexity of the project, and whether you are ready for it.
For example, you can ask, “how to build a 3D platformer game?”, and here is an example response:
It typically follows this format:
If you simply provide a few words for your project idea, XO will respond with a fairly generic outline. To get more original results, you would have to provide more details. As a basic rule, as you provide more details, XO’s response will also become more unique.
For example, here is an updated request:
Tell me how to design a 3D platformer game, where the player controls an Alien that can both jump and change direction in the air, and the platforms are moving themselves, and there are enemies that fire lasers at the Alien. The Alien can also pick up awards to run faster or jump higher.
Here is what XO says about it. As explained before, the originality has to come from your input.
Since XO can generate outlines for any project idea, it’s easy to be ambitious and aim for a project that might be too complex to manage effectively. For instance, numerous students have contemplated building “Minecraft in 3D” only to realize that such a project exceeds the typical scope of school assignments.
A key principle to follow is “don’t bite off more than you can chew.” This means you should aim for projects that are challenging yet still within your capabilities. As you develop your coding skills through continuous practice, you’ll be equipped to tackle increasingly complex projects over time.
Sometimes you run out of ideas on what to build, you can also ask XO to give you some suggestions. For example, you can say: I want to build a project to practice how to use ChatGPT blocks, can you give me some ideas for small projects?
You will get a list like below, which may inspire you to find your own idea:
After getting a project outline, most people are tempted to say this: “give me all the code!”. However, XO can’t simply convert the project design to a fully working project. Most likely, you will get a “disappointing” response like this:
So, what’s the right way to proceed? We simply need to focus on individual steps/features. For example, if we focus on the first step to set up the 3D scene, XO will be happily working with us again:
One area where every Scratch programmer needs help is debugging. When we say a Scratch program has a “bug”, we are really saying the program is doing something unexpected. This usually happens because what you expected to see isn’t what actually appears on the screen. Most of the time, the project is doing exactly what you told it to do through your code—it’s just not what you wanted.
Think of debugging as being a detective in your own computer game. Your mission is to find the clue—a specific part of your code or a single piece of information you’ve entered—that’s causing the unexpected behavior. You can look at each part of your code closely, or you can play detective by watching what the project does and making smart guesses about what might be wrong.
Now, you might be wondering, how does XO fit into all of this? Think of XO as your trusty sidekick in this detective game. In this tutorial, you’ll discover several strategies for debugging with XO’s support.
Important Note: Do not rely solely on XO to detect all problems in your code. XO does not execute your code but reviews it statically, which is challenging even for experienced programmers. Additionally, XO’s capabilities in logical reasoning and error detection are limited. Consequently, the primary responsibility for identifying issues rests with you, and XO should serve merely as a supporting tool.
The biggest mistake in using XO for debugging is asking questions that do not clearly explain the problem, such as “it is not working!”, “what’s wrong?” or “help me debug!”.
XO doesn’t know what you are expecting to see. Also, XO can only look at your code, and it can not run it, so it does not know what you observe when the program runs. When it is not clear what’s the issue, XO will ask for clarification:
The recommended format to ask XO to debug is to include these 2 parts:
Here are some good examples:
Sometimes, the expected behavior is obvious from the description, so you may omit it. For example:
For commonly made coding errors, XO can spot them right away. It will only report one or two such problems each time to avoid overwhelming you. Also, the problem it reports may not directly resolve the issue you are facing. Yet, you should still fix the reported problem first, then ask XO for more suggestions.
For example, here is a simple program with a variable initialization bug. XO can not only point out the issue, but also suggest how to fix it.
Note that XO understands all the new blocks used in CreatiCode, and can point out issues associated with their usage. For example, here is a common issue in 3D programs about initializing 3D scenes:
For more complex issues and larger projects, XO may not have the immediate answer. In these situations, it’s important to first figure out where the problem might be coming from by focusing on specific parts of your project. You can often determine the most important parts to look at by thinking about how your program is supposed to work. For instance, if your character isn’t moving when you press a button, you should check the parts of your code that are supposed to respond to button presses and make your character move.
If you’re not sure which parts of your code to look at first, you can get XO’s help. If you explain the problem well, XO can help figure out the best place to start looking.
As a practice, please open the following project and remix it:
https://play.creaticode.com/projects/6616a1a7564fc287b0e9b879
Next, modify this block to set the y speed to -450 instead of 450, which will be the bug we try to find.
Then you can ask XO to help locate the issue, and it will suggest a few relevant places:
Another commonly used debugging technique is called “Rubber Duck Debugging”. The idea is to describe your code to a rubber duck toy that will listen to you. This process often helps us rethink the logic of the program and identify flaws. In addition, it forces us to pay attention to every block and every input as we describe the code. It sometimes helps us spot small mistakes we have overlooked.
XO can serve a similar role as a rubber duck. You can simply tell XO to serve as your rubber duck, or you can click the question mark button directly:
After this, XO will enter a special mode: it will respond with short sentences, assist you in walking through your code, and point out any potential mistakes as you talk.
For example, with the issue of wong y speed above, XO will suggest that issue as we discuss with it:
To exit this “rubber duck” mode, you can simply clear the chat to restart the conversation:
Yes, please feel free to post in the tutorial category: https://www.forum.creaticode.com/category/17/tutorials
Thank you
It should be able to write code for you and display them visually. As shown above, when you ask “how to use the ‘for’ block”, it would show you an example program as visual blocks, and you can directly copy that into your playground.
If that doesn’t work for you, please share the prompt you are using, and we will investigate why.
Thank you
Bin
Hi Lucie,
You are right. Only users who have signed in can use the ChatGPT blocks. That’s partly because we need to monitor any users who abuse this feature and take action.
Any user can easily sign up for free with a valid email address, or they can log in directly using Google login.
You can also create a class with new student accounts for free, and then assign them to your students: https://www.forum.creaticode.com/topic/547/teacher-only-how-to-manage-students-in-the-my-class-page
CreatiCode
CreatiCode preloads much more code and data than the original MIT Scratch to provide a richer set of capabilities, but that also consumes more memory and CPU power. That might lead to some slowness on some computers.
Paper Minecraft is a huge project, so it might indeed have some loading issue on some computers. We are constantly optimizing our platform, and hopefully it will cause less such issues over time.
CreatiCode XO is a coding assistant running in the CreatiCode playground. It is an AI chatbot trained to help K-12 students learn Scratch programming. It can help students and teachers in many tasks, such as answering questions and writing code.
The key benefit of using XO is to get personalized and timely help. You no longer need to wait for your turn to ask your teacher your own question. Instead, you can ask XO to help you anytime and get a response right away.
In addition, learning to code with XO isn’t just about coding; it’s about developing essential skills for the future. You’ll learn how to ask precise questions and thoughtfully analyze the responses you get. As AI assistants become a part of everyday life and work in the future, these skills will be invaluable.
There are many ways to use XO, and in this tutorial, we will focus on how to ask XO to explain things to us.
When you wonder how to use any block, you can ask XO like this:
Note that XO will not only explain what the block does but also give you a simple example. You can directly copy the example code into the playground to run it and observe the result.
Note that you should make sure XO understands exactly which block you are referring to. For example, if we ask “how to use the touching block?”, then XO will not know whether you are referring to the “touching Sprite” block or “touching color” block.
When you are not sure what block to use, you can simply ask XO how to do something, such as how to implement a feature or how to make the sprite do something. For example, this is the response you get for “how to draw a star?”:
Note that your request should be as specific as possible, since XO may make mistakes if it has to write a lot of code at once. As a rule of thumb, your request should not require more than 10 blocks to implement.
XO is also really good at making coding ideas clear, especially when you ask questions starting with “what is xxx?” So, if you were to ask, “what is a clone?”, here’s how it would explain it:
There are times when you’re exploring someone else’s project and might not grasp everything about how it functions. This is a great opportunity to seek XO’s assistance. You can inquire about broader aspects, such as the interaction between sprites, or delve into more detailed queries about the purpose of a particular block or sequence of blocks. For instance, here is how to ask about user input handling in the “ChatGPT - Chat with Einstein” project:
XO isn’t all serious when answering your questions. If you throw in a fun twist, XO often comes back with unexpected and enjoyable answers. For example, if you ask, “Explain what is a loop. I’m a pirate.”, here’s how it would respond:
The possible ways to twist your questions are endless. Here are some fun examples:
In traditional MIT Scratch, we can broadcast a message that all sprites running on the stage can receive and handle. For multiplayer network games, this capability is extended so you can broadcast a message to all players’ computers.
The message will be sent to the game server first, which then relays the message to all other players. Therefore, there might be some delay before all players receive that message.
To broadcast the message, you can use the following block in the multiplayer category:
It accepts these inputs:
Message Type: you can define any message type using the “when I receive” block, then choose that message type in this dropdown.
Parameter: you can optionally attach a parameter to this message
Receiver Scope: you can choose between “All Sprites” or “Original Sprites”. If “All Sprites” is selected, all sprites on all players’ playgrounds will be able to receive this message using the “when I receive” block. If “Original Sprites”, then only the original sprites added to the game will be able to receive this message, and the copies made by the game server on other computers/tabs will not receive this message, neither would the local sprites. For example, if a message is about giving a reward to a sprite, then it should only be handled once by the original sprite (not the copies).
This block is an easy way to do almost anything synchronously across all the player computers. For example, to make a sprite change its costume, you can broadcast a message to all players, and then change the sprite’s costume when the message is received by each player’s computer.
The only exception is that you should not change the speed or position of sprites using this method, since the game server takes full control of the motion and position of every sprite added to the game network.
In this demo project, we repeatedly broadcast a message to all sprites, with the current timer value as the parameter. And for every sprite, when it receives this message, it will “say” it on the stage.
https://play.creaticode.com/projects/6607f888b57a3da838c32b3f
To run it, follow these steps:
2. In another computer or an incognito tab, run the project as the guest, and add the obstacle sprite to the game network. Also, add a handler for the event of “greeting” that prints out the parameter briefly:
3. Switch back to the host player, and run the repeat loop to broadcast the “greeting” message to all sprites on all computers every 2 seconds:
As a result, all sprites on both computers, we will see both sprites saying the timer value every 2 seconds:
For the same project, let’s change the broadcast target to “Original Sprites”:
As a result, only the original sprites (ball on left and square on right) will receive this message:
In traditional Scratch games, we can detect whether one sprite is touching another using the “touching” block in the sensor category, and trigger a message when that occurs. You can use the if block or when block like this:
We can do something very similar in multiplayer network games using one block, which helps detect such events and broadcast a message.
To enable collision detection, we can ask the game server to check if this sprite is touching another sprite using the following block:
This is probably the most complex and powerful block in the multiplayer category since it needs to instruct the game server to do a few things. The inputs are:
Sprite Name: This is the target sprite. We are asking the game server to continuously check if this sprite (where the above block is running) is touching the target sprite. Whenever that happens, we will ask the game server to take some actions and maybe also send a message. Note that if the target sprite has clones, they are all counted as potential targets.
 . This input also takes a special value of “Edge”, which represents the 4 borders of the stage. To avoid confusion, you should not name your own sprites as “Edge”.
Clone ID Prefix: The second input is optional and you can leave it as blank. You can use it to specify the target sprite’s clone ID should start with some text. For example, if the sprite name is “Ball” and the prefix is “A”, then the game server will only look for target sprites that are clones of the “Ball” sprite, and only if their clone ID starts with “A”, such as “A1”, “A_20”, etc. This is useful since we often create clones of the same target sprite for different players or teams, and we may only want to trigger the touch event with a subset of those clones.
Action Type: The game server will only check for touch events when this sprite is moving, and this is the action to take when this sprite touches the target sprite in its movement.
https://play.creaticode.com/projects/66142a83564fc287b0e8ebc5
In this demo project, we make the blue ball move left and right repeatedly, and it will stop at the obstacle and broadcast a message.
To run it:
2. Join the game from another account (in an incognito browser tab) using the “Obstacle” sprite and add the sprite as a rectangle. When it receives the “touching message”, print out the parameter as well.
3. In the “BlueBall” sprite, repeatedly set the ball’s speeds to go left and then right:
4. As a result, the blue ball will stop whenever it hits the obstacle, and both the blue ball and the obstacle will say the parameter values:
You can change the project above this way: go to the “BlueBall” sprite, and modify the action type from “Stop” to “Stop and Collect”:
Now if you run the 2 players again, the obstacle will be deleted upon the first hit:
You might notice a small delay before the square obstacle was deleted, since we need to wait for the game server to determine the collision has occurred and the obstacle should be deleted, and then that decision has to be sent to the player’s computer.
We can also change the action type to “Continue”, so the blue ball will continue its movement when touching the obstacle:
Note that the message is received repeatedly while the blue ball and the obstacle are touching each other.
Next, we can choose the “Continue and Collect” action type, so the obstacle will get deleted the first time the blue ball touches it:
Now we can try to change the action to “Self-Destruct”, and the blue ball will disappear when it touches the obstacle:
Lastly, when we use the “Self-Destruct and Colelct” option, both sprites will be deleted when they touch:
In most multiplayer network games, each player would control a sprite to navigate the game world. For example, in a pong game, each player would move their own bouncing board up and down.
Although we can set the position of a sprite synchronously for all players, a much more common way of moving sprites in a network game is to set its x and y speeds. This will ensure the sprite moves smoothly through a continuous path, which is critical for handling collisions between sprites.
To set a sprite’s speed synchronously, we can use the following block:
This block takes 2 inputs, which are the speed in x and y directions. The x speed controls how many steps the sprite would move per second horizontally, and if it is negative, that means the sprite is moving to the left. Similarly, the Y speed controls how fast the sprite moves vertically, and negative Y speed means the sprite will be moving downwards.
Note that the sprite will stop at the world boundary or when it collides with another sprite.
In this demo project, we repeatedly set the ball’s speed randomly, and its copy on the second computer will move with the same speeds in sync.
To run it:
In the “YellowBall” sprite, run the same blocks
As a result, both balls will be moving to random positions, and the 2 tabs will be in sync all the time:
Note that there might be some delay before the copy sprite changes its moving speed. That’s because the speed update message needs to travel to the game server first, and then it is sent to the guest player’s computer.
Here is the project URL: https://play.creaticode.com/projects/6606029025dc753d5b67bc62
In a multiplayer network game, sprites are still the key building blocks, just like any ordinary Scratch project. However, sprites can be either “network sprites” or “local sprites”.
Local sprites are just ordinary sprites, same as what we have in MIT Scratch. A local sprite will only live in one player’s playground, and other players in the game will not see it. Also, the game server will not know about these sprites.
Network sprites are managed by the game server. When player A creates a network sprite, the game server will start to keep track of this sprite, and a copy of this sprite will be created in all other players’ playgrounds. When player A moves this network sprite, the game server will make sure all the copies of this sprite also move the same way on other players’ computers.
For example, suppose we are creating a multiplayer space-shooter game. How do we determine which sprites are “network sprites”?
For a simple rule-of-thumb, all sprites that interact with other sprites should be network sprites, such as spaceships, shells, asteroids, powerups, etc. For example, when a spaceship sprite is created, it should be added as network sprite, so that the game server keeps track of its position, and manages its copies on other players’ computers.
On the other hand, the local sprites would be sprites used for decoration or information, such as stars in the background that don’t interact with any other sprites, or healthbars/scores displayed on top of stage. For example, for the stars, they should be created on each player’s computer when they start the project.
In general, local sprites are created by every player on their own computers, and the game server doesn’t know about them. Network sprites are created by one player’s computer, and the game server manages its copies on other players’ computers.
Clones are an excellent tool for reusing code. Imagine we are creating a 4-player network car-race game, where each player controls one car from his/her computer.
A naive way to create this game is to use 4 sprites, such as “car A”, “car B”, “car C”, “car D”. Most of the code in these 4 sprites would be identical, except for the player name or costume of the car.
A much better solution is to only use one “car” sprite, and whenever a player creates or joins the game, create one new clone of this car sprite, and the game server will create clones of this sprite on all other players’ computers (the “remote copies”).
To add a sprite (clone) to the game network, you can use the following block:
The first input can be “Dynamic” or “Static”: dynamic sprites can move during the game, while static sprites will stay at the same position.
The second input is the shape of this sprite’s “collider”. It is either “Circle” or “Rectangle”. This is used to approximate the shape of the sprite for collision detection. When a sprite moves, the game server needs to check if it is colliding with other sprites or the world boundary. To make this calculation fast, we simply assume the sprite is a circle or a rectangle, like this:
When this block runs, a copy of this sprite will be created on other players’ computers at the same position.
When we no longer need a sprite or clone, we can tell the game server to remove it from the game, so that the game server will no longer keep track of its movement, and its copies on other computers will be deleted as well. This can be done using the following block:
In this demo project, one player controls a blue ball and the other controls a yellow ball. The first player repeatedly creates clones of the blue ball, which is placed at a random position, and then added to the game network. When that happens, a copy of the blue ball will appear on the second player’s stage. Similarly, the second player repeatedly creates clones of the yellow ball, which are added to the game server, and copies are created on the first player’s computer.
After each clone is created, we wait some time, then remove the clone, and its copy on the other player’s computer will be removed as well.
To run it:
Here is the demo project:
https://play.creaticode.com/projects/6604dcdd25dc753d5b677537
In multiplayer games, multiple users can play the same game together over the network. All players run the same project on their own computers. One player is the host who creates a new game, and the other players are the guests who join the game.
A game server is provided by the CreatiCode platform, which helps to keep track of the games and the players in each game. The game server will also help relay messages between the players over the computer network.
Multiplayer game programming is a very complex task. However, it has been greatly simplified by CreatiCode, so you can build most types of multiplayer games using a dozen blocks.
To create a new game as the host, you can use the following block in the “multiplayer” extension:
It accepts the following inputs:
Game Name: the host player needs to specify a unique name for the game, so that other players can easily find the game to join from a list of games
Password: the host player can specify a password, which defaults to “123”, and other players will be required to provide this password to join this game. This allows the host to make sure only players he knows can join the game he creates.
Display Name: the host player can specify a name for themselves that will be displayed in the game.
Role: the host player can also specify a role for themselves. The role can be freely defined by the game creator, and its meaning should depend on the type of game. For example, for a 2-player chess game, the roles can be “black” and “white”. For a 2 vs 2 shooting game, the roles can be “red team” and “blue team”.
Server: the host needs to specify a server to be used to run the game. The host should pick a server that is closest so that messages can be transferred quickly between the player computers and the game server.
Capacity: the maximum number of players can play the game together. If this number is reached for a game, new players won’t be able to join that game.
Game World Width and Height: The host can specify the width and height of the game world, and player sprites will not move outside this boundary. By default we can use the stage’s width and height, but if a game has a larger map, you can specify it here.
Note that each host user can only host one game at any given time for a given project. So, if a user tries to create a second game using the same project, the first game will be destroyed.
Also, if the game has been idle for at least 180 seconds (no messages sent from any player in the game), then it will be destroyed to release the server resource.
To find out all the existing games created by the current project, we can use the following block:
The first input is the server specified when the game was created.
The second input is the name of a table, which will store the information on the games currently running.
For example, suppose 2 games have been created by 2 host players using the same project, you should see 2 games listed in the table like this:
Each row represents one game, including the display name and game name specified when the host creates the game, and also how many players are currently in the game (including the host).
To join a game created by another host player, we can use the following block:
It takes the following inputs:
Note that the game name and host name can both be read from the games table written by the “list multiplayer games” block above, so usually the program should allow the user to choose from a dropdown list instead of typing them manually.
The password should be input by the user manually, and the host user should tell that to the user.
We can also find out which players are in a game, using the following block:
It takes the following inputs:
For example, when 2 players are in a game, the result table may look like this:
After creating or joining a game, you can use the following boolean block to check if this computer/tab is properly connected to the game server:
If for any reason this game is no longer running at the game server, or if this user’s computer is no longer connected to the game server via the Internet, this block will become false.
To test a multiplayer project, you will need at least 2 user accounts. Here are the detailed steps:
Log in to CreatiCode in your default browser tab. Create the multiplayer project, and share it. You can use the “share unlisted” option so that only you would see it, as only you have the URL of this project.
Click the 3 dots on the top right of the browser (Chrome browser), and open a new browser window in the “incognito” mode:
In the new browser window, log into CreatiCode using your second account.
In the new browser window, open the shared project.
After these steps, you can start testing the project. For example, one browser tab can be used as the host user, and the other as the guest user.
You can use the following project to test the 4 blocks explained above:
https://play.creaticode.com/projects/6604937325dc753d5b676424
Run the first stack of blocks in the first account, and then run the second stack of blocks in the second account. Observe the content of the tables for the games and players.
In this tutorial, you will learn to build a space-shooter game that 2 players can play on their own computers.
Each player will control a spaceship that can move around within the left or right half of the stage, and they can shoot laser bullets toward each other. Both players start with a health value of 4, and whoever drops to 0 health first will lose the game.
Random asteroids (rocks) will fly down from the top, and if they hit a spaceship, that ship will lose 1 point of health. Spaceships can also shoot at the rocks using lasers, and when a rock explodes, it might leave a random power-up item for a health boost or firepower boost. With more firepower, a spaceship can shoot out lasers more frequently.
The game looks like this:
Note that to work on this project, you must be familiar with clones and message passing.
This starter project contains all the game assets you need, so please remix it in your playground:
https://play.creaticode.com/projects/6612868fc7d2146705bf1aee
Here is the content of this project:
Also, all the variables to be used below have been defined in this template, so you won’t have to define them again.
First, we will go to the “Ship” sprite, and add code to create 2 buttons (from Widgets category), one for creating a new game by player A, and one for joining the game by player B. We should also hide the ship sprite, as we will only be using its clones.
They will look like this when you click the green flag button:
When the “create game” button is clicked by the host player, we will remove all buttons, and then create a multiplayer game:
The game is named “space shooter”, and it is protected by the password “123”. You can change them to any other value.
The display name of the host player will be “Player A”, with a role of “A”.
The game will be hosted by the game server named “US East”. It has a capacity of 2, which means it will only have 2 players. The dimensions of the game world are 720 by 360, which is the size of the stage. This means all sprites will not move outside this boundary.
In summary, when this block runs, a game session will be created on the given server under this project’s ID, the game name and the host player name, waiting for the second player to join.
The second player (on another computer) can run the same project and click the “Join Game” button to join the game created by the first player.
The second player needs to use the same game name, host name, game server and password specified above. Otherwise, the game server will not find the given game session. The second player’s display name is “Player B”, with a role of “B”.
Note that we are hardcoding the game name/password/display name in this project for simplicity. For a real game project, there can be many game sessions running at the same time, and they will need to have different game names and passwords. So a more common solution is to ask the host player to input the game name and password, and ask the guest players to choose from a list of all existing games to join.
After this block runs, both players will be connected to the same game session.
In this game, each player controls his own spaceship locally. In other words, player A controls a Ship sprite running on his/her computer, and player B controls another Ship sprite running on his/her computer. To make sure they also see each other’s ships, the game server will create a copy of player A’s ship on player B’s computer, and a copy of player B’s ship on player A’s computer:
The copies are often called “remote copies”, since they run on a different computer, while each player’s own sprite is called the “original sprite”.
Although we can create one sprite for each player, it would be highly inefficient, since most of the code blocks for the 2 players, such as keypress handling and collision detection, are exactly the same. Therefore, a much better solution is to have all players use the same sprite, but each player has a different clone. The clones can have different positions, costumes and clone IDs, which will help us implement different behaviors.
We can add these 2 blocks to create the clones for both players:
The 2 clones have clone IDs of “A” and “B”, which allow us to run different code blocks later depending on the ID.
When the clone is created for either player, we will show the sprite, since the original sprite is hidden. Then depending on the clone ID is “A” or “B”, we move the clone to the left or right, and switch to the right costume.
As a result, when the first player clicks “Create Game”, he/she will see the yellow spaceship on the left; when the second player clicks “Join Game”, he/she will see the red spaceship on the right:
The clones we create are the “original sprites”, since they run on each player’s own computer. The game server doesn’t know about them yet. Now we add them to the game using this block:
This block tells the game server to treat the ship sprite as dynamic, so it will be moveable if we specify its moving speed. Also, we will assume the ship has a circular-shape collider, which will be used to detect collision between the ship and other sprites. The circle is invisible, but you can assume they wrap around the ships like this
After this block runs, the game server will create the remote copies of each spaceship, so we see both sprites on both computers:
Note that there are 2 ways to build and test multiplayer games:
You can work with another student as a group. One of you will create the project and run it as the host. Share this project so that the other student can run it on his/her computer as the guest player. This is a perfect setup for pair coding, as the 2 students can switch roles by switching seats or computers. Also, on some computers, it might be slow to run 2 playgrounds at the same time.
You could also test the program as both players on your computer, using 2 browser tabs. The second tab needs to be in the “incognito” mode, which allows you to log in to CreatiCode using a different account on the same computer. Then, you can run as the host player in one tab and as the guest in the other, as shown above.
After both players have joined the game and added their sprites, the host player can click a button to start the game. We can add this new button after the “Create Game” button is clicked:
In a more complete game, we should not show this button until we see there are 2 players in the game. However, for simplicity, we will add this button right away, even if the second player has not joined. We will rely on the player to wait until he/she sees the second spaceship to press this button.
When the host player clicks the “Start Game” button, we need to broadcast a message to both playgrounds. When each spaceship receives this message, it will start the game logic. For now, we will simply remove all the widgets when we receive this message in the Ship sprite:
Note that at this point, there are 3 “Ship” sprites in each player’s playground:
When we click button 3, all 3 sprites may respond to it. But we only want to handle the button click once, so we should use the “clone ID” to ensure only the original sprite handles it:
Note that the word “original” might be confusing as it is used for 2 meanings:
In this example, we first make sure the original Ship sprite would respond to the button click, then send the message to the “Original Sprites” only, which is the Ship clone created by each player in their playground.
Next, we will add progress bars for the health and firepower of each ship. For each ship, health starts at 4, and a player loses if his/her ship’s health drops to 0. The firepower starts at 1, and it can increase to up to 4 when the ship picks up powerup rewards.
So we will need to add 4 progress bars, 2 on each side of the stage:
Note that we use the letters “A” and “B” in the name of these progress bars so that we can easily use the ship’s clone ID to determine which bar to update.
The bars will look like this:
Note that you can also use a sprite with 4 different costumes to replace the progress bars.
Now let’s make a new block “handle keys” to allow the players to control their ships:
To keep track of the vertical movement speed intended by the player, we can create a new variable “intended y speed”, and update its value based on the key “w” and “s” in a forever loop:
Similarly, we can use another variable “intended x speed” to keep track of the horizontal movement speed:
In this game, we do not want the players to cross the middle of the stage. We can define the minimum and maximum x positions for each spaceship using 2 variables:
With that, we can then set the ship’s x speed to 0 when it is already at the left or right bounds in the “handle keys” block:
Now we are ready to set the moving speed of the spaceship using this block:
Note that this block not only changes the original sprite’s speed in this player’s playground, but also informs the game server of this change in speed, and the game server will make sure the copies of this sprite on other players’ computers also move at the same speed.
The solution above would send the intended speeds to the game server repeatedly in the forever loop, which may not be necessary. On computers with slow Internet connection, too many messages may cause the program to overwhelm the network and cause loss of messages. To reduce the number of messages we send to the game server, we can change it to only update the speed when it changes.
To do that, we can define 2 new variables of “actual x speed” and “actual y speed”, and only set the speed if they are different from the intended speeds:
Now both players can control their spaceships using w/a/s/d keys after the host player starts the game:
You might notice a small lag between the original sprites and their remote copies. This is expected, since it takes some time for the game server to update the remote copies with the change in speed. The good news is that this is acceptable for most games, since the players won’t observe both computers at the same time, so they won’t see this small difference.
Next, we will add 3 new variables to each ship:
Now we can add the logic in the “handle key” block for the SPACE key. We will first check if the required minimum time has passed since the last time the player fired a shot. We can use a new variable “last fire time” to keep track of the time when the last laser was fired, and check if the required time span (2 seconds divide by the ship’s firepower attribute) has passed by:
If the required waiting time has passed, we will broadcast a message to the “Laser” sprite to fire a new shot. Since we are reusing the same Laser sprite for both players, we need to tell the Laser sprite which player is making the shot, and also the starting position of the laser.
The message type is “fire”, and the parameter contains 3 parts separated by a space letter:
Note that we are just sending the message from the “Ship” sprite to the “Laser” sprite on the same computer at this point, and we don’t need to use the game server yet.
Now we switch to the Laser sprite.
First, we will hide this sprite when the green flag is clicked. We will be creating clones for each laser shot, so the original Laser sprite will remain hidden. We will also use the variable “next laser ID” to keep track of the ID of the next laser to be fired.
When the Laser sprite receives the “fire” message, we will first make sure only the original sprite handles it. Otherwise, a clone of the Laser sprite may receive this message as well, which may generate a duplicate laser shot.
We will need to split the parameter attached to this message into 3 parts by the space letter. The first part will be stored in the “Player ID” variable, which will be “A” or “B”. The next 2 parts are stored in “start x” and “start y”, which are the starting positions for the new laser.
Now we can create a clone of the Laser sprite to represent the new shot. We first move the original sprite to the starting position of the new shot, and then create a clone of it at that position. The clone ID of that new clone will be “Player ID” joined with “next laser ID”. For example, for player A’s lasers, its clone ID will be “A 1”, “A 2”, etc.
When the clone of the Laser is created, we will first unhide it, since the original sprite is always hidden. Then we will switch to the correct costume based on whether the clone ID contains “A” or “B”.
So far the game server doesn’t know anything about firing the shot or the clone of the Laser. Now it is the time to add this clone to the game:
The Laser is dynamic since it will be flying across the stage. We will use a rectangle shape to approximate the shape of this Laser for collision detection. After this step, the game server will know about this clone, and will also create a copy of it (another clone) on the other player’s computer.
Next, we will make the Laser fly left or right based on its clone ID:
After this step, both players can start to fire lasers by pressing the SPACE key:
Currently, the laser would stop at the edge. We should make it disappear. This can be done very easily using the “when touching” block:
We are using the special value of “Edge” for the first input, which represents the 4 borders of the stage. The action to take is “Self-Destruct”, which makes the laser delete itself. Since we don’t need to do anything else when a bullet hits the world edge, we won’t need to broadcast any message here.
Here is the result:
When the laser hits the opponent player’s spaceship, it should not pass through it. Instead, it should explode, and the opponent should lose one point in health.
First, we should go to the Ship sprite, and add a message receiver block for a new message type “laser hit ship”:
Next, switch back to the Laser sprite, and set up the touch event using these 2 blocks:
The first input is the Ship sprite. For the second input, we are passing in the letter “A” or “B”, so that player A’s laser would only hurt player B, and vice versa. The action type is “Self-Destruct”, which removes the bullet when it hits the spaceship. Next, we choose to broadcast the “laser hit ship” message, so that we can reduce the spaceship’s health when that message is received.
Here is the result:
Note that the “laser hit ship” message will ONLY be received by 2 sprites: the ship clone that’s being hit, and the laser clone that’[censored]ting it. No other sprites will receive this message. So for the next step, we just need to handle this message in those 2 sprites.
When the Laser clone receives the “laser hit ship” message, it should tell the Explosion sprite to show a new explosion animation. To do that, we first create a new message type “new explosion” in the Explosion sprite:
Next, back in the Laser sprite, we broadcast this message when we receive “laser hit ship”:
The parameter is the x and y positions of the laser, so that we can create the explosion at the same location. Note that we are broadcasting to “All” sprites. This ensures all sprites on all players’ computers can receive this message. We won’t need to add the Explosion sprite to the game at all. The Explosion sprite on each player’s computer will receive this message and show an explosion.
Now, switch to the Explosion sprite. As usual, we should hide it when the game starts, since we only need to use its clones for each explosion:
When the Explosion sprite receives the “new explosion” message, it should create a clone of itself at the given location. The parameter is stored in “explosion info”, which contains 2 parts that can be separated by the SPACE character. Note that we need to check that only the original Explosion sprite would do so, since there may be existing explosion clones, and we don’t want them to handle this new explosion message.
When the clone is created, we will make sure it is at the front layer, play an explosion sound, switch to the first costume, and display it. Then we repeatedly rotate to the next costume. Lastly, we remove this clone.
Now we will get a nice explosion effect:
In the Ship sprite, when the clone receives the “laser hit ship” message, it should reduce its health by 1. We can add a guard to check its health is greater than 0 before doing that. The reason is that a ship with health of 1 may receive 2 hits before we stop the game.
Next, this ship needs to tell all players to update the displayed health bar for this player. We can first add a new receive block to define the message type “update health”:
Then we can broadcast this message to “All” sprites:
The parameter will include 2 parts: the clone ID of this ship, which is “A” or “B”, and the updated health value of it.
To update the health bar value, we first need to make sure only the original Ship sprite on each computer handles this message, so the update is not done in duplicate. We can extract the ID of the ship (“A” or “B”) and its health value from the parameter “info”, then we update the progress bar widget for that ship with the new value:
Now we will see that the health bar of the red ship will be updated from 100% to 75% (4 down to 3) on both playgrounds when it is first hit:
When we update the ship’s health, it’s also a good place to check if the ship’s health has dropped to 0 and announce it is “game over”. We will broadcast a local message to the “Winner” sprite to handle game over, with a parameter that’s the ID of the winning player.
In the Winner sprite, we will need to hide it when the green flag clicks.
When the “game over” message is received, we will play a short sound clip, and show the correct costume of the winning player. After 3 seconds, we stop the entire program.
Here is what it looks like:
By now, the game is fully playable! You have completed a full multiplayer game. Congratulations!
For the remaining steps, you will learn to add rocks and powerups to make the game more fun.
In the Ship sprite, when the player clicks the “start game” button, we will send out the “add rocks” message, so that the Rock sprite can start adding rocks:
In the Rock sprite, we will hide the rock at the game start, and also receive the “add rocks” message:
The Rock sprite will add a new clone of itself every 2 seconds. Each time it will first go to a new random starting position along the top edge of the stage. Each new clone has an ID of “nextRockID”.
When the clone of the Rock is created, we will show it on the stage. Then, we add it to the game, so the game server would create a copy of it on the other player’s computer. We will also assign a random speed for this rock, so it falls down at a random speed and direction:
When the rock hits the edge of the stage, it should be deleted. We can use the “Self-Destruct” action to do so, similar to the Laser sprite:
Now the game looks like this:
When a rock hits a spaceship, it should reduce its health by 1, similar to the effect of a laser shot. This will force the player to dodge the rocks.
First, we handle the message “rock hits ship” in the Ship sprite:
Then, in the Rock sprite, we trigger this message whenever the rock hits the ship:
When the rock hits a ship, it will self-destruct. We can also show an explosion at that location. This can be done by broadcasting the “new explosion” message:
Now the game looks like this when a rock hits a spaceship:
The players can also shoot at the rocks. When a laser hits a rock, the rock should explode. We can set this up in the Rock sprite first:
Then in the Laser sprite, we set up the touch event:
Now we can shoot out the rocks:
When a laser hits a rock, we should reward the player with a power-up item sometimes. For example, in the Rock sprite, we can broadcast the “add powerup” message 50% of the time, along with the x and y positions of the rock as parameters:
Now switch to the Powerup sprite. We will hide it at game start, and set the ID of next powerup to 0. Then we will receive the “add powerup” message:
To handle the “add powerup” message, we will first make sure only the original Powerup sprite on each computer will process that message, and not any of its clones. This sprite will go to the location specified in the parameter, and then choose between 2 types of powerups randomly: “firepower” or “health”. It will then set the costume according to the powerup, then create a clone of itself. It will also update the next ID by 1:
When the powerup clone is created, we will add it to the game session, so a copy of it appears on the other player’s computer. After 6 seconds, we will remove this clone, if the players haven’t picked it up by then.
Now the game runs like this. The powerup items will be added and then removed in 6 seconds.
Next, in the Ship sprite, we will enable the Ship sprite to pick up the power-up items.
First, we receive a new message type of “ship collects powerup”:
Then, we can trigger this message when the Ship touches the Powerup sprite:
The action is “Continue and Collect”, which means the Ship itself will continue its current movement, but the powerup item will be removed.
When the Ship receives the “ship collects powerup” message, if the powerup type is “health”, then we should increase this ship’s health value by 1 if it is not 4 (the maximum):
On the other hand, if the powerup type is “firepower”, we need to increase the ship’s firepower value.
First, we will add a new message handler in the Ship sprite for “update firepower”, which is similar to “update health”. We extract the ID of the ship and its updated firepower value, then update the corresponding progress bar:
Now we can update the ship’s firepower value and send out this new message when the ship collects a firepower reward:
By now the game is working with rocks and power-ups. It can still be further enhanced in many ways, and here are some suggestions:
Can you check out this demo project and compare with your code?
https://play.creaticode.com/projects/aba9b9ae5cbc8ab971511a4e
Yes, here is more information on model animations: https://forum.creaticode.com/topic/107/model-animations
And here is a running fox as an example:
https://play.creaticode.com/projects/66045e93b57a3da838c258b8
Thanks for reporting the issue. Can you please confirm how to reproduce this issue? For example, in this format:
Thanks
If the avatar is halfway in the air, then most likely its Z position is not set correctly.
For example, to make an avatar stand on the ground, its Z position should be 0.
There was a temporary issue with the server loading the project list. Sorry about that.
We always back up all projects, so your projects are always safe. But sometimes the indexing service we use would encounter an error that makes the list empty. This issue shouldn’t happen going forward anymore.
Hi, sorry for the delay. We haven’t determined the proper rate limit on the cloud variables yet. So currently there is no limit, but we will update that when we see load issues.
In terms of multiplayer game, we strongly suggest using the multiplayer blocks, which would handle most of the common tasks for multiplayer games. The tutorial will be posted in a few days.
If you want to shoot from the camera in first person view, you can check out this example:
https://play.creaticode.com/projects/377563a0134456c0ce412fc6
The curators are allowed to add projects to a studio. It is not for permission control on individual projects. We are working on a feature to allow multiple users to work on the same project. We will let you know when that’s released.
After you click the “Add by URL” button in your account, you need to ask your friend to open the same studio. You can give him the URL of the studio, which should look like this: https://play.creaticode.com/studios/6fedgYsFGLMJAgD7m/curators
Hi, the message is a bit confusing. We’ll rephrase it.
Basically you just need the invited user to log in and accept the invitation. He/she can open this studio, and click the button that says “Click to accept”. It looks like this:
You can go to the dashboard at https://app.creaticode.com/dashboard/, and click on the profile picture to change it.
The projects are still there, but the project list is having some issues with out database. We are restoring the index right now. Will be restored soon.
Sorry about that.
Hi, you can click the “invite by URL” button, then the “Add by URL” button, to specify the URL of the user you want to add as the curator:
You can also try to create a new class, and create a curator for that class. All students in that class will become curators for that studio automatically.
On the other hand, the premium account will cost some money, which will give you a much higher rate limit on many premium blocks. These are blocks or features that we have to pay out for third-party services, such as XO Copilot, ChatGPT API, DALL-E image generator AI, text-to-speech, database, multiplayer, etc. Usually schools purchase premium accounts in bulk to ensure smooth learning experiences during classes.
You might want to try the CreatiCode XO to help you brainstorm. It is not perfect but might give you some suggestions to explore. You can ask any question:
Can you be more specific? What kind of game is this? How to play and how to win? What does the ‘money system’ do?
Let’s discuss about this. Usually, the expected behavior is that the user can still type while waiting for the AI response, instead of not allowing the user to input at all, right?
Maybe it’s better to allow the programmer to disable the ‘send’ button so the user can type but can not send it out in that mode?
We will make a new release for the multiplayer blocks soon, and also release a game with tutorials. Stay tuned!
Hi there, you don’t have to have the paid version to create classes. Please follow this tutorial:
https://www.forum.creaticode.com/topic/547/teacher-only-how-to-manage-students-in-the-my-class-page
If you have any problem following those steps, please let us know, and we will be happy to help you out.
CreatiCode
It looks like this project was only saved partially so it couldn’t be correctly p[censored]d. We’ll investigate how to recover it. Sorry about that.
CreatiCode
We have streamlined the Google Login interface, and it will also help avoid the automatic logout that happens sometimes. Please test to see if that solves the issue for your account.
Thanks
CreatiCode
Hi Dawn, sorry about the issue. We’ll contact you separately to discuss how to resolve it.
CreatiCode
Hi, thanks for checking with us. In general, you can only use the assets within the CreatiCode platform. If you have a specific asset in mind, please let us know which one it is, and we will check if you can use it elsewhere.
Thanks for reporting this issue. We will look into it.
CreatiCode is a coding platform, not for model creation. You can look into platforms like https://www.tinkercad.com/ for creating models, then you can import these models into your 3D scene (see https://www.forum.creaticode.com/topic/413/3d-using-a-tinkercad-model-difficulty-2)
We would suggest you start with the ChatGPT blocks in the AI category. You can follow through the “ChatGPT AI” tutorials to learn how to use them.
In a previous tutorial, you learned how to teach ChatGPT new knowledge by semantic search (search for questions with similar meaning to the user question).
The performance of such a chatbot mostly depends on the quality of the knowledge data we provide to the model. This process is often very time-consuming, involving collecting, cleaning, and formatting the data.
In this tutorial, you will learn to prepare the knowledge data for a new chatbot, which will answer questions about the VISIONS organization. The basic idea is to download data from its website and generate questions/answers using that data. This is a common use case: most businesses and organizations already have websites but need to build their chatbots to provide a better user experience.
You will need first to complete this tutorial: ChatGPT AI: QA Bot Using Semantic Search (RAG) (Difficulty: 4)
Save a copy of that project and rename it as “Chatbot Using Web Data.”
As a baseline, we must test what ChatGPT knows about the VISIONS organization. If it can answer most questions without help, it is unnecessary to inject additional knowledge.
To run the test, we can use the plain ChatGPT assistant in this project:
https://play.creaticode.com/projects/6531b7e60fdce080a4481c1d
For example, we can see that ChatGPT already knows about the VISIONS organization:
However, if we try to get more specific information, it would fail:
This proves that ChatGPT needs our help to answer more specific questions about the VISIONS organization, even though such information is readily available on their website.
ChatGPT does not memorize any sentences. Instead, it memorizes the probabilities of the next words. If some words appear together very often in the training data, that pattern gets stored inside the model.
For example, if a lot of websites contain the sentence like “The phone number of VISIONS is 1.888.245.8333”, then the next time ChatGPT sees “The phone number of VISIONS is”, it will predict the correct phone number as the next word.
However, since that sentence is not commonly seen in the training data, the next word with the highest probability is probably “sorry” or “I”, and the actual phone number has a much lower probability.
Now, let’s look at the VISIONS organization website. Open this URL https://visionsvcb.org in a new tab, and you should see the following:
This web page contains a lot of information and links to other web pages. To download the information, we can run the following block (click the green ‘Add Extension’ block on the bottom left and select the ‘Cloud’ category):
Note that this block does two things for you:
The Markdown format is very simple. It is almost the same as the text you see on the web page, but additional information is included, such as the URL of the links on the web page. This will be very useful in the next step.
Note that the content for the URL is cached, so if you run fetch from the same URL repeatedly on the same day, it will be very fast after the first time.
Also, the website’s content will go through a moderation process, so if any inappropriate content is found, this block will reject the fetch request.
Like most websites, the VISIONS page we have downloaded contains many links, such as these:
...
[Home](https://visionsvcb.org)
[About Us](#)
[Annual Reports and Financials](https://visionsvcb.org/about/annual-report)
[Board of Directors](https://visionsvcb.org/about/board-of-directors)
[Management Team](https://visionsvcb.org/about/management-team)
[Mission Statement](https://visionsvcb.org/about/mission-statement)
[VISIONS History](https://visionsvcb.org/about/visions-history)
...
Each link leads to a new page, which may link to other pages. Some of these links may be duplicates as well. For example, page 1 may contain a link to page 2, and page 2 may contain links to both page 1 and page 3. With more pages, they will form a web with many links between the links:
In the next few steps, we will write code to p[censored] the links on each page and put these links into a queue with no duplication. We will visit each link in this queue to get more content and extract more links.
To store all the links we will visit, please create a new list named “URLs”. The first URL will be the main URL of the site: “https://visionsvcb.org.” Note that we are deleting all items from the list first, which ensures we always start with the main URL.
Next, we use a for-loop to visit every URL in the list. Since the list will grow as we discover more links on the pages we visit, we don’t know how many URLs there will be. We will use 1 for now to ensure our code works for 1 URL.
We will also add a guard to ensure the URL Index is never greater than the length of the list so we will always get a valid URL.
Next, we will fetch the content from the URL at the current index and store it in the “result” variable:
Since the logic to extract all the links from the page’s content is fairly standalone, it’s better to define a new block dedicated to it: “extract links”. It will take the result from fetching the content and add all the URLs on that page to the “URLs” list.
To find all the links in the page’s content, we need to look for a certain pattern. In the markdown format, all the links are wrapped inside a pair of ( ) starting with “https://”. Therefore, we can use regular expression to find all the text that matches this pattern and store them in a new list named “links”.
You can copy the exact regular expression from here: \(https?:\/\/[^\)]+\)
Now, if we run the program, it will fetch the content from the main site and extract all the 60 links on that page into the “links” list:
To clean up this list of links, we need another for-loop to process each link. We will store each link in the “link” variable:
Each link contains a pair of parentheses. To remove them, we need to extract the substring of the link text from the second letter to the second but last letter. The result will be stored in a variable named “URL”.
Now, we can add the new URL to the list of URLs, but we need to ensure the list doesn’t already contain this new URL.
There is still one small issue. Some links on the page are not from the same domain, such as “(https://accessibility-helper.co.il)”. Note that we should only download the data from the same main site. Otherwise, the list of URLs may grow exponentially as we visit more and more websites. Therefore, we need to add another condition: we only add a URL to our list if it contains “visionsvcb.org”. (Note that when you use this project for other websites, this main URL also needs to be changed.)
After this, run the program again, and the “URLs” list will grow to 42 items:
For a test, let’s try to fetch from the first 3 URLs in the list:
After we run this program again, we find the “URLs” list grows to 61 items:
We also find a new problem. A lot of the URLs are PDF files. That might be useful if we are creating a document-retrieval app, but for this project, we should exclude them since we only need web content. We can add an additional condition in the “extract links” block like this:
Now, if we rerun the program, the URLs list will only have 42 items in total. That means no new links have been discovered when we visit the second and third URLs.
Now we can go through all the pages in a website, the next step is to generate questions and answers from each page. Let’s focus on generating them using the first page. Please define a new block “generate QA” and call it in the repeat loop. We will pass in the “result” variable, which is the text of the current page.
Next, we will feed the page content to ChatGPT to generate pairs of questions and answers. Note that we can not simply give all the content to ChatGPT in one request because that might exceed ChatGPT’s limit on the request length. Instead, we will have to cut the content into chunks.
For example, suppose we limit each chunk to at most 5000 characters. If the content has 12000 characters in total, we will send 3 requests to ChatGPT: character 1 to 5000, character 5001 to 10000, and character 10001 to 12000.
This idea can be implemented using a for-loop like this:
The “start index” is the position of the first character of each chunk, and the last character’s position will be “start index + 4999”. Therefore, the “chunk” variable will contain the content of each chunk of the page’s content.
It is fairly straightforward to ask ChatGPT to generate some questions and answers using each chunk. However, to make it easier to p[censored] the response of ChatGPT, we need to specify the output format as well. For example, we can use a prompt like this:
You will generate questions and answers based on the content of a web page. Start each question with "--QUESTION:" and start the answer with "--ANSWER:". Here is the web content:
Here is the code to compose and send the request:
Note that each request is a new chat so that ChatGPT won’t need to worry about previous messages. Otherwise, ChatGPt may not focus on the current chunk it is handling.
The response we get from ChatGPT will look like this:
Our next task is to put the questions and answers into a table format so that we can use them to build the semantic database later. First, we need to split the response by the special symbol “--” and put the parts into a list named “qa”:
The list will look like this, with questions and answers as individual items:
Since we will accumulate questions and answers and store them in the “data” table, we need to clear the table’s contents at the beginning.
To add all the questions and answers from the “qa” list to the “data” table, we can use a for-loop to go through every item in the “qa” list. We already know the first item of the list is always empty, so we should start with the second item. Also, we will consume 2 items at a time, one for the question and one for the answer, so we should increase the index “i” by 2 each time:
Now we can read the question at the item at index “i”, and its answer at the index of “i+1”. Then we add both of them as a new row to the “data” table:
For example, if there are 3 pairs of questions and answers, we would get 3 rows in the “data” table:
There is a minor issue: the questions contain the prefix of “QUESTION:”, and the answers contain the prefix of “ANSWER:”. We can remove them using the “replace” operator:
Now if we clear the data table (manually remove the existing items) and run the for-loop by itself again, we would get clean questions and answers:
Now our program is ready. Let’s test it with the first 3 URLs:
It will take some time to run this since we need to use ChatGPT to generate the questions and answers from each page. When the run finishes, we will get some questions in the “data” table. The exact number of questions may be different when you run it.
The rest of the process is the same as before: we can create a semantic database using the “data” table (no need to do this repeatedly if the data stays the same), then we can query this database when the user asks a new question, and feed the query result to ChatGPT as reference.
You can now try to change the program to fetch data from any other website, and then publish a chatbot using that data. Note that you will need to specify the new website in 2 places: