Acknowledged. This will be fixed soon. Thanks
Best posts made by info-creaticode
-
RE: Some avatars aren't shown to select until searched for
-
Wishlist for New Models
If you are looking for a particular 3D model that is not in our library, please reply to this topic. If you can include an example picture of it, it would be more clear what you are looking for. We will try to fulfill these requests as best as we can. Please make sure you do not submit duplicate requests by searching for it first.
Thanks
CreatiCode Support -
RE: Raycasting.
Basically it is drawing some arrows from the object to all directions, and when the arrow touches some other object, it triggers some actions.
More info here:
https://www.forum.creaticode.com/topic/41/checking-for-object-collisions-with-ray-cast
-
Number of Seconds since 2000
Introduction
In MIT Scratch, you can already manage dates using the “days since 2000” block. However, if you need a more granular control of date and time, you can use this new block:
This block will return the number of seconds that have passed between the given timestamp and the beginning of 2000.01.01.
Input Format
The input is a timestamp, which contains the date, a “T”, and then the time. The date is represented as year:month:day. The time is represented as hour:minute:second. Each field has to be 2 digits, except that the year has to be 4 digits.
The timestamp is assumed to be the local time of the computer that’s running this program. If you want to use the UTC time, which is the same across the world, then append a “Z” at the end of the timestamp, such as “2024.01.01T10:00:00Z”.
If the input is left empty, then the current time is used:
Calculating Time Difference
With this new block, you can easily calculate how many seconds are between 2 timestamps. You just need to run this new block for both timestamps, then calculate the difference between them:
Converting to Date
You can also convert the number of seconds back to a Date object. For example, the program below first gets the number of seconds for a specific timestamp, then create a date object using that result, and we get the same timestamp as our input:
-
Shape-Based Particle Emitters
Introduction
You learned about Single-Point Particle Emitter, which generates particles from a single point in the 3D space.
In this article, we will discuss “shape-based” emitters, which generate particles from within a 3D shape like a box. They allow us to produce very different visual effects.
Box Emitters
The box emitter is simply a transparent 3D box, and it can generate new particles from any random point inside this box. We can not see this box since it is transparent, but we can indirectly see its shape by where the particles are generated.
To use the box emitter, we need 2 steps:
- Select the “Box” shape when creating the emitter
- Configure the size of the box by its minimum and maximum X/Y/Z positions
Here is a simple example:
This program creates a box emitter that is 400 units in each dimension. For example, in the X dimension, the minimum is -200 and the maximum is 200, so the x position of new particles can be any random value between -200 and 200. When you run this program, you can see the particles are all confined within this box-shaped region:
Sphere Emitters
The shape of the emitter can also be a sphere. When we configure the sphere shape, we can set its size using the “radius” parameter.
There is also a “range” parameter (between 0 and 1), which controls the range of possible values along the radius. You can think of “range” as “thickness”:
- When “range” is 0, the particles will only be generated on the surface of the sphere, and not inside it.
- When “range” is 1, the particles can be generated at any random point on the surface or inside the sphere.
- When “range” is between 0 and 1, the particles will not be generated near the center of the sphere, but can be generated on the surface or near the surface.
Here is an example program with a range of 0:
As shown, particles are only appearing on the surface of the sphere:
Hemisphere Emitters
Hemisphere emitters generate particles from a half-sphere shape. You can specify its radius and range the same way as the sphere emitters.
One thing special about hemisphere emitters is that we can rotate the half sphere to different directions. As shown below, when we rotate it around X-axis for 90 degrees, the new particles are all generated at the bottom half of the sphere:
Cylinder Emitters
The emitter can also take a cylinder shape. We can control the radius of the circle, and also the height of the cylinder.
The “range” parameter also works for cylinders. You can think of it as controling the “thickness” of the cylinder’s skin. For example, when radius 0.5, the thickness of the cylinder skin is half of the radius:
The cylinder shape also supports an additional parameter of “direction randomness”. This only matters when we set the particles to not face the camera all the time, and we will see the particles facing different random directions when we set “direction randomness” to 100:
Lastly, we can rotate the cylinder emitter as well. For example, we can make it “lie down”:
Cone Emitters
For the cone-shaped emitter, we can console these parameters:
- Radius: The radius of the bottom circle of the cone
- Angle: The opening angle of the cone. Note that the angle and the radius would imply the height of the cone, so we won’t need another “height” parameter.
- Radius Range: This range value applies along the radius direction. When it is 0, the particles will only be generated on the surface of the cone. When it is 1, the particles may come out from anywhere inside the cone or on its surface.
- Height Range: This range value applies along the height of the cone. When it is 0, the particles will only emerge from the bottom of the cone, and when it is 1, the entire height can generate particles.
We can rotate cone emitters as well.
-
RE: "Important Forum Announcement" - Question
@011830-0a42ef84 said in "Important Forum Announcement" - Question:
@info-creaticode am I able to be a moderator/mod helper?
Currently 2 helpers are good enough. If they are overwhelmed we might need to add more. Thanks for the offer.
-
RE: Multiplayer 3D games
We are working on fixing the cloud blocks. Should be within next few days. Sorry about that.
-
3D - A Spinning Earth (Difficulty: 1)
Key Topics Covered
Introduction
In this tutorial, you will learn to create a spinning Earth:
Step 1 - Initialize An Empty Scene
First, create a new project, and load an empty scene using the “initialize 3D scene” block.
By default, it will create an empty scene with nothing but a blue background:
Step 2 - Set the Background Starfield
Next, use the “set sky” block to create a better-looking backdrop:
You should get a starfield with the Sun on the right.
Step 3 - Add a Big Sphere
Next, add a sphere with a large diameter of 10000 to the scene. Don’t worry about its color yet.
The sphere would look brighter on the side that faces the Sun.
Step 4 - Add Earth Texture
Now we need to update the sphere’s texture with the Earth. Add the “update texture” block, click the “Please select” input box, then search for “Earth” in the library window.
Step 5 - Flip the Earth Texture
You might have noticed an issue with the texture: the continents are upside-down. We need to flip the texture vertically to correct this issue. This can be done by changing the vertical repeat count from 1 to -1.
Step 6 - Make the Earth Spin
To make the Earth object spin, we can use the “set speed” block. Note that the Earth needs to be spinning from “left” to "right, so the “Z-rotation” speed needs to be negative.
Now your Earth object should be spinning slowly.
Step 7 - Highlight Around the Earth
Lastly, to make the Earth object glow in blue lights, we can create a new highlight layer, then add the sphere to that layer.
Now your Earth object should carry a blue light around it.
Next Steps
You can try to use a similar method to build other projects. Here are some example ideas:
- A Different Planet: You can change Earth to other planets like Mars;
- A Spinning Trophy: You can try to make a trophy object spin and shine.
-
RE: Suggestions for both the forums and CreatiCode!
@mathew139616-10db496a
Thanks for the suggestions.
For unpublished projects, the authors do not want it to be seen, so we can not let anyone see it, even the original author.
We can look into adding the notifications.
For forum, most of the questions are fairly specific to CreatiCode so ChatGPT can’t answer them well. Don’t worry, we have enough staff to answer questions, and there are also a few active users who often help out.
-
RE: Does saving private data act as like a "secret" or "environment variable"?
It should not be used to store real secrets like passwords. The reason is that this block runs on the “client” side (the user’s browser), so when the data is sent over the Internet to the webserver, it is exposed in the network package.
However, for most games/projects you build for learning, it should be good enough.
The “private” mode is meant to store data specific for one user. Say 100 users are running your shared game. Suppose each of them can specify a secret passcode that can be used to save or load game progress. You can use this block and use the “private” mode, so the data is separated by user ID, and 2 users can’t see each other’s data.
-
RE: Wishlist for New Models
Please check out this new avatar:
Its source is at https://sketchfab.com/3d-models/jotaro-kujo-idle-unity-03309a5dd9bc413fa0105597a7755ae9
The original author is https://sketchfab.com/Maxime66410
-
RE: Hitboxes
That’s also a good option, if the hit box must have an empty square hole inside it.
Here is an example of how to do it using “compound shape”. You just need to draw the costume using 4 boxes:
https://play.creaticode.com/projects/670083d55689190abfe5461f
-
RE: Customizable blocks.
@106809nes
It would be interesting. We can certainly add this feature, but frankly it will be fairly low priority at this point, compared to other features on our list.
-
RE: Some avatars aren't shown to select until searched for
FYI this issue is fixed now.
-
RE: new block ideas
Thanks for the kind offer. It is not easy to open up our code base for external contribution at this point. If you are looking for something challenging to do, it would be very helpful to us and to our user community if you can create more interesting projects that demonstrate the potential of our rich set of blocks, especially the AI, 3D, widgets, 2D physics engine and cloud blocks.
-
RE: Using an AI other than CreatiCode if you can't find what you are looking for
Hi everyone, this is an engaging topic, and it’s great to see a thoughtful and respectful debate from both sides.
From CreatiCode’s perspective, our main goal is to help K-12 students cultivate creativity and logical thinking through coding activities. One common challenge they face is finding or creating quality images that fit the story or game they’re building. Many students struggle with drawing, especially digitally, and often can’t afford professional images online. To address this, we provide AI image tools that allow them to generate or find high-quality backdrops and sprites for their projects.
Additionally, using these tools offers another key benefit: students can hone their AI prompting skills. Generating the perfect image for a project requires giving clear, detailed descriptions and refining prompts based on the results. These skills will be increasingly valuable in a future shaped by AI technology.
There are ongoing philosophical debates about whether AI-generated images infringe on artists’ copyrights or stifle creativity. While we don’t take a definitive stance on this matter, we ensure that all images produced with CreatiCode’s AI tools are fully licensed. Users retain complete copyright over these images, allowing them to use them in their CreatiCode projects without concern.
-
RE: new block ideas
@luna
The widget blocks work in both 2D and 3D projects. There are good and bad videos on Youtube. If anyone uses bad content from Youtube, we will delete the project and ban the author.
-
RE: new block ideas
With regard to the “play sound from URL” block, you can actually use the youtube block instead. You just need to set its width and height to 0.
You can find almost every possible sound or background music you want on Youtube. For example, there are at least 50 videos for horse noise.
-
RE: even when logged in, front page says login
Regarding your feedback below:
The forum and website feel a bit seperate, and the forum has features the site doesn’t, like dark mode themes.
At the top of the navigation bar in the forums, maybe there could also be a link to go back to CreatiCode instead of having to press back in my browser button a million times to get back to CreatiCode.com.
I also think the whole thing where you have to make a forum account using a CC account and all is a bit confusing and unnecessarily complicated. Like you have two different usernames (possibly) and profiles and bios, even though it’s the same site but different subdomain (forum.).
If you’re logged in on CreatiCode, then why can’t that same login session/token/whatever just apply to the forum? I get that the subdomain thing might be an issue but if so then the forums could just be moved to https://app.creaticode.com/forums or wherever within the main domain right?We are aware of this disconnection. It’s mostly because the forum is a third party project that we do not have time to make too much changes yet. We will optimize it over time.
-
RE: 3d avatar style I like
That’s called the “Chibi” style. We will sure add more such avatars when I can source them with proper license.
-
RE: Feature request: a block to make a string backwards and other text stuff
Thanks for the proposals. We can definitely add these blocks, but we would like to see more upvotes before committing to them.
-
RE: Feature request: a block to make a string backwards and other text stuff
Can you explain what kind of project would make use of the “cowsay” block?
-
RE: Feature request: a block to make a string backwards and other text stuff
You know, we should only add blocks that’ll be widely used in many projects, so it doesn’t seem cowsay is a good candidate for that?
-
RE: Feature request: a block to make a string backwards and other text stuff
Agreed. We can put that on our list.
-
RE: ProDetect Module V1
Our solution is the new moderation block that’ll be released soon. Using the ChatGPT block for it may lead to other issues. Sorry.
-
RE: Question
@cattyplayzy
I think you are referring to the Chinese Pinyin input box. That’s not part of CreatiCode.
For widgets, you can learn about them here: https://www.forum.creaticode.com/topic/66/introduction-to-widgets-with-the-label-widget
-
RE: Feature request: a block to alphabetize lists and tables
No problem. All letters are represented by numbers (all things are numbers in computers), so you can compare letters just the same way as letters.
-
RE: Question
@106809nes
It is the Chinese version of this tutorial: https://www.forum.creaticode.com/topic/956/chatgpt-ai-a-quiz-writer-difficulty-3
-
RE: Relay | Online Chatting Platform!
This is a great example of using the multiplayer blocks for chatting.
Not sure if you are aware of this, but all projects with chatting functions must implement content moderation. You can use the “get moderation result for [TEXT]” block in the AI category to check the message before sending it out. If the return value is “Fail”, then that message should be rejected.
Please unshare this project, make this change, then share it again. Thank you.
-
RE: Question
Can you give more context? Where did we talk about custom fonts?
-
RE: Customizing Gradients
@106809-mygccs
Thanks for the suggestion. This is an interesting feature. We will research how to implement it.
-
RE: Viewing Remixes
Good question. We will add a section showing remixes, similar to MIT Scratch.
-
AI - Recognize 0's and 1's (Difficulty: 4)
Key Topics Covered
Introduction
There are many AI applications that can recognize numbers automatically. For example, when we deposit a check, we can take a picture of it on the phone, and the app will recognize the account numbers and the deposit amount written on the check.
In this tutorial, you will build a smart program that can recognize whether a hand-written number is 0 or 1:
Step 1 - Create a New Project
First, please create a new project, remove Sprite1 with Cody, and rename the “Empty1” sprite to “AI”. Please also add an empty sprite named “Pen”.
The "Pen’ sprite will allow the user to draw a number on the stage, and the “AI” sprite will contain code to guess whether this number is 0 or 1.
Step 2 - The Drawing Area
We’ll start with the “Pen” sprite. First, when the program starts, let’s draw a square area to indicate where the user can draw the number. This can be done using the “draw rectangle” block in the “Looks” category. Note that this square will be located at the center, with both width and height of 200. Please set its “fill” color to 100% transparent, and pick any border color you like.
Here is what the square looks like:
Step 3 - Initialize the “Pen” Extension
Next, please add the “Pen” extension, and set the pen’s color to black, size to 10. We will also erase all drawings from the pen.
Step 4 - A Forever Loop To Move the Pen Sprite
We will allow the user to use the mouse pointer to draw. To do that, we need to make the Pen sprite follow the pointer. You can use a forever loop to make the Pen sprite keep going to the position of the mouse pointer.
Now if you move the mouse, you will see the position of the “Pen” sprite changes with it:
Step 5 - Mouse Down to Draw
To use the mouse pointer as the pen, we can check if the mouse is pressed down. Whenever it is, we will put the pen down as well; whenever the mouse is not pressed down, we will lift the pen up.
Now our drawing area is ready for drawing:
Step 6 - The “Clear” Button
To allow the user to clear the drawing and restart, let’s add a “clear” button. Please load the “widget” extension, then find the “add button” block.
Run the program again, and you will see the button at the bottom:
When the button is clicked, we need to erase all the drawings:
Step 7 - The “Guess” Button
Please add another button “Guess” at the bottom right. When it is clicked, we’ll send a message to the “AI” sprite to take a guess of the number.
Step 8 - Prepare the AI Sprite
Now we are ready to work on the AI sprite. First, please draw a small square in the “AI” sprite’s costume, so we can see where it is:
Step 9 - Scan the Middle Row
When the “AI” sprite receives the “guess” message, it should scan the middle row from left to right. We can create a new variable “x”, and use a for-loop to set x to go from -100 to 100 at a step size of 5.
Click the “Guess” button to test it:
Step 10 - Touching Black Before and After Each Move
Now we are going to check whether our AI sprite is touching the black color of the drawing at each step. We will use 2 new variables to keep track: “touching before move” and “touching after move”. They will be set to the value of “touching black color” before and after the “go to” block. To view the values in slow motion, we will add a 1-second wait after each move:
Now let’s test it. When our AI sprite touches the black color for the first time, “touching before move” will still be false, but “touching after move” will become “true”.
Step 11 - Stamping the Strokes
Now we can detect a black stroke using the 2 variables we have created. We will make a stamp whenever the AI sprite finds that it is touching the black color after the move, but not touching it before the move.
Now let’s test it. No matter how many strokes we draw, the AI sprite will make a stamp the first time it touches each stroke:
Step 12 - Counting the Strokes
Now we can count how many strokes our AI sprite is detecting. We will use a new variable named “counter”, and instead of making a stamp, we also increase the counter by 1.
Run the project, and you will find that the counter will tell us how many vertical strokes are there. More specifically, it is telling how many “edges” are there, with each edge defined by going from white to black color.
Step 13 - 0 or 1?
Finally, we are ready to answer the question: whether the user has drawn a 0 or 1?
The insight is that when the user draws a 1, there is only one edge; but if the user draws a 0, there are 2 edges.
Therefore, we can take a guess based on the value of “counter”. If it is 1, then the user has drawn a “1”. If it is 2, then the user has drawn a “0”. Of course, to keep it simple, we are assuming the user can only draw a 0 or 1.
Please test it a few times:
Step 14 - Handling Smaller 0’s
When the user draws a very small or very thin “0”, we can only detect one edge, so we will guess incorrectly.
That is because our AI sprite box is touching both strokes at the same time. So to fix it, we simply need to make our AI sprite much smaller, such as a size of 5:
Step 15 - Speed Up
Lastly, to speed up our AI detector, we can make a new block named “guess”, and run it without screen refresh:
Then we move all the blocks into that block’s definition stack:
Now our program runs much faster:
Challenges
This tutorial shows a very common technique that analyzes an image using edge detection. As a challenge, please try to extend this program to recognize some other numbers. You need some smart ideas to handle them in a robust way.
For example, if you are trying to recognize the number “6”, you will need to scan all rows, not just the middle row. Then you can check if the number of edges is 1 at the top, becomes 2 towards the bottom, and then reverts to 1 at last.
Similarly, if you are trying to recognize the number “8”, you can check if the number of edges is 2 at the top and bottom, but 1 in the middle.
Here is a demo of an enhanced version of the project:
-
RE: Group?
@106809nes
It doesn’t have to be every month or week. We can accept any user into the group who has helped answer at least 5 questions on the forum.
-
RE: Robot?
@mathew139616-10db496a
It is pretty much dependant on the “real life things” you want to interact with. For example, there are a category of “smart devices” that support IoT (Internet of Things) protocols, and you can send commands to those devices. But that’s currently not our focus, as we are more focused on AI related capabilities for now.
-
RE: What does the add 3d video plane block do and how to use?
Yes it is for using video as texture. However, youtube videos are not supported, since it is blocked by CORS of Youtube.
Instead, you can follow these steps to test it:
-
Find or create a mp4 video file (make sure it’s appropriate).
-
Share the file online. One easy way is to use the “My Files” tab in the “My Stuff” page: https://play.creaticode.com/mystuff/files
That page allows you to upload a file and copy its public URL.
- Use the video’s public URL in the video plane block like this:
It will look like this:
-
-
2-Player Online 3D Doom (Difficulty: 6)
Overview Podcast
Here is an interesting podcast of 2 AI hosts discussing this tutorial to unpack some of the most challenging concepts:
Introduction
In this tutorial, you will learn how to build a multiplayer shooter game in 3D similar to the classic game “Doom”. Two players (on two separate computers) can play this game against each other.
Since this project is fairly complicated, the completed project is shared below:play.creaticode.com/projects/66e823b5a634f8ee7d92cc88
This tutorial will go through all the key components of this project step by step so that you can understand it thoroughly.
Note that our multiplayer game server only knows about 2D game worlds, but we can use it to support our 3D game, so long as all the objects are on the same ground level. A simple way to think about it is this: if we look down from above the 3D world, then the game world looks like 2D, and a 3D box in the 3D world will look like a 2D square when we look at it from above.
1 - Overview of Sprites
This project contains six sprites:
- Start: This sprite contains code to display the game’s starting screen so the host player can create new games for the guest player to join. It also initializes the 3D world.
- Player: This sprite allows the players (users) to control the two avatars in the 3D world, including handling key events and managing the health/firepower of the players. This is the most complex sprite in this project.
- Bullet: This sprite represents the bullets fired by the players.
- Wall: This sprite is used to create the walls in the 3D world. Players or bullets can not pass through these walls.
- Powerup: This sprite is used to generate new powerup items for “health” or “firepower”. They will appear randomly in the game world periodically, and they will disappear after a while if not collected by any player.
- Winner: This sprite displays the ending screen of the game when either player wins.
2 - “Start” Sprite: Initial Screen
When the user clicks the green flag, we will show an initial screen, which contains a label, an input textbox, and two buttons:
Here is the code for creating this screen in the “Start” sprite:
Note that each game can only be played between 2 users (host and guest), and it is uniquely identified by its name. The default name is “3D Shooter”. If a name is taken, then the host needs to pick a different game name when they create the game, and the guest needs to use the same name to join that game.
3 - “Start” Sprite: Create New Game
After the host user specifies the game name, he/she will click the “Create New Game” button. We will read the game name, and set the ID of this user to “A”, which represents the host player. We will show an error message if the game name is empty, otherwise we will try to create the game.
4 - “Start” Sprite: Create Game
To create a game, we do the following:
- Initialize the 3D scene on this computer;
- Ask the game server to create a new game with the given game name.
- To keep it simple, we will use the default password of “123” and assume the host user is “Player A”.
- The game capacity is 2, which means it will not accept any join request after one host and one guest are in it.
- The game world is set to be 2000 by 2000. Note that this is a 2D game world, so it only has width and height. We assume every object is at the ground level, so we don’t need to specify the world size in the Z dimension.
- If the game world is created successfully, this computer will be connected to the game. Then we can add the host player to the game (will be discussed later), and then wait for the other player (the guest) to join.
- If we are not connected to the game after a short wait, it means we have failed, and the most likely reason is the game name is already taken, or the game server is too busy. Either way, we can ask the user to change the game name and try again.
5 - “Start” Sprite: Initialize 3D Scene
To set up the 3D world, we create a simple “Grass Land” scene, then add a “rectangle cube” with no cap on top, so it becomes the walls on the 4 borders of the world. The size of the world is 2000 by 2000. We set the height of the border wall to 100, so that half of that (50) is above the ground. The avatars will be 100 tall, so the wall will not block our camera that follows the avatar. After the world is created, we also add the health bar and firepower bar on top using the “add bars” block.
6 - “Start” Sprite: Add Health and Firepower Bars
Each player starts with 3 lives, so he/she will lose when hit by bullets 3 times, but can gain lives by collecting health rewards. Each player starts with firepower of 1, and can increase it up to 5 by collecting firepower rewards. The firepower controls the minimum interval between every 2 bullets fired: interval = 2 seconds / firepower. So when firepower is 1, the player can fire every 2 seconds and no sonner; but when firepower is 5, the player can fire every 0.4 seconds.
The current health and firepower values for both players are displayed on top of the stage like this:
The code to add the player name and the health bars is the following. The health bar is represented by 3 square labels in green, and their names start with “health”, then followed by the player’s ID “A” or “B”, and lastly end with a sequence number of 1/2/3.
The code to add the firepower labels is very similar:
7 - “Start” Sprite: Wait for the guest player to join
After the host player creates the game, he/she needs to wait until the guest player has successfully joined the game. We can repeatedly fetch the player information into a table, then check if the number of players is 2. If that’s true, then we show a “Start Game” button, which allows the host player to start the game.
8 - “Start” Sprite: Join Existing Game
Now, let’s look at the guest player side. The guest player needs to input the same game name as the host player, then click the “Join Existing Game” button.
When that button is clicked, we do the following:
- Save the local player to be “Player B”, which represents the guest player.
- Make sure the game name specified by user is not empty
- Join the game
9 - “Start” Sprite: Join the game
To join the game, we will first create the 3D scene at the guest player’s computer, then send a request to the game server to join the game with the given name. This player will be the “Player B”, which represents the guest player.
After waiting some time, we check if we are connected to the game. If so, we create the gust player (to be discussed later); otherwise, we show an error message.
10 - “Start” Sprite: Start the Game
After the guest player joins the game, the “Start Game” button will appear on the host computer. When the host user clicks it, we will send a new message “start game”:
Note that this message is sent to both computers, but only “Original” sprites can receive it. For example, the Player A sprite on the host computer will receive it, but the clone of it on the guest computer will not. This way, the “start game” message is only received and handled for one time on each computer.
11 - “Player” Sprite: Add Players
Now, let’s switch to the “Player” sprite. This sprite represents the player’s avatar in the game world.
To add the host or guest player, we use simply create a clone of the “Player” sprite with different clone IDs: “A” for the host and “B” for the guest. This way, we reuse most of the code to add a player.
When the clone is created, we do the following:
- We initiate a variable “last fire time” to keep track of the last time a fire is shot, which helps us determine when the player can take another shot
- We use two variables, “health” and “firepower”, to keep track of the number of lives and firepower level of each player, which start at 3 and 1. Note that these variables are “private” to each clone of the Player sprite, so the two players can have their own “health” and “firepower” values.
- We will place the two players at two opposite sides of the game world: x of 0, and y of 800 or -800. Note that we use their clone ID to tell whether this is the host or the guest player.
- We add the player to the game, which means we register this player at the game server. The player is “Dynamic”, which means its movement will be tracked and replicated across the two computers.
- We use a “Circle” shape to represent each player. Although each player is a 3D avatar in the 3D world, in the eyes of our game server, they are both represented by a 2D circle with a diameter of 30.
- We will stop the player avatar from going through the Wall objects
- We will allow the player to collect powerup items, which will trigger a message “collect powerup”.
Behind the Scenes
When we register a player to the game server, what happens behind the scenes? The game server simulates what happens in the game world as we play it. At the beginning of the game, when we register a new player, the game server adds a new circle shape to its simulated game world.
In addition, a copy of that player is created on the other user’s computer. For example, when the host user creates a game, his/her code will create the host player “A”, then a clone of player “A” will be created in the guest user’s computer. Similarly, when the guest user joins the game and creates player “B”, it will be replicated in host user’s computer. As a result, on each computer, there are two clones of the “Player” sprite running.
12 - “Player” Sprite: When a player is added to the game
After we run the “add this sprite to game” block, if it is successful, another block will be triggered: “when added to game”. This is an important “hidden” event, because it gives us a chance to fully initialize the player.
This block is called two times on each computer. On the host user’s computer, after the host player is created, this block is triggered for this player (Player A). Later, when the guest user joins the game, a clone of player B is created on the host user’s computer, and this block is triggered again.
When this block is triggered, we do the following:
- Create a 3D avatar to represent this player. Currently it is Superman for the host and Batman for the guest. The avatars will be moved to the initial positions we have specified earlier: x of 0, and y of 800 or -800.
- Although this block is triggered two times on each computer, we will only add a “follow camera” once, only for the avatar that represents the local player. For example, for the host user, his player ID is “A”, so we will only add the follow camera if the clone ID is also “A”. Note that the follow camera’s direction lock is “Free”, which means the user can turn the camera to point at any direction using the mouse. If you are debugging the game, you can skipping adding the follow camera, so you can use the default camera to look at the entire game world easily.
- Lastly, we will add the “Run” animation to the 3D avatar so it knows how to play that animation later.
13 - “Player” Sprite: Handle Game Start
As discussed above, the “original” player sprite on each computer will receive the “start game” message. Here is what we do when we receive that message:
- Remove the “Start Game” button
- If this is the host player (player “A”), then we also need to trigger 2 events: add wall and add powerup. The wall and powerup objects will be replicated on the guest computer, so we don’t need to create them separately on the guest computer. Also, the “add powerup” message is handled by a forever loop that adds a new powerup periodically, so we are not using “broadcast and wait” for that message.
- We set the current animation of the avatar to “Idle”, so when it changes later, we need to tell the other computer.
- Lastly, we start the “handle keys” block, which is a forever loop that handles key inputs. Note that only at this step can the user start to play the game with the keyboard.
14 - “Player” Sprite: Handle Keys
This is the main loop of the game logic, where we continuously check the keys the user is pressing, and update the player avatars accordingly. Specifically, we do the following inside a forever loop:
- Check if we have disconnected from the game server, and show an error message if so. The player gets automatically disconnected from the server if no updates are received from any player in the last 5 minutes. This will help the game server reclaim the resources allocated to a game in case the players have left the game.
- If we are still in the game, we check the SPACE key and fire a shot if enough time has passed.
- We also check the movement keys to determine the moving speed, direction and animation.
- Lastly, we wait a very short time before entering the loop again. This helps reduce the number of messages we send out on the network and avoid too much “network traffic” that will slow down the game server.
15 - “Player” Sprite: Handle Firing Shot
When we detect the SPACE key is pressed down, we check if the current time is more than the last time we fired a shot plus a waiting period. This waiting period is calculated as (2 / firepower). For example, if firepower is 2, then the minimum wait time is 2/2 = 1 seconds.
If we are allowed to fire a shot, we send the “fire” message, which will be handled by the “Bullet” sprite (discussed later). In this message, we need to specify the clone ID of this sprite (“A” or “B”), the x/y positions and the facing direction of this player, so that the Bullet sprite can create a bullet at the same position and direction.
16 - “Player” Sprite: Get Intended Speed and Animation
To create a fun experience that gives the users full control of the avatar’s movement, we will allow the user to use both the mouse and the keyboard at the same time. The mouse will be used to control the camera, and all movements will be relative to the direction of the camera. For example, if we drag the camera to look to the right, the avatar will immediately turn to face the same direction. So when we press “W” to move forward, the avatar will move in the same direction as the camera:
To achieve this effect and keep our code short and clean, we will divide it into 3 cases:
- When the “a” key is pressed, it means the user wants to move left.
- When the “d” key is pressed, it means the user wants to move right
- When neither the “a” or “d” key is pressed, the user wants to move forward/backward or stay still.
The default assumption is that the intended speed is 300 and the intended animation is “Run”, and we can change them as we check the keys.
17 - “Player” Sprite: Handle Move Left or Right
When only the “a” key is pressed, the user wants to move left horizontally. If the “w” or “s” key is pressed at the same time, then the user intends to move diagonally to the left front or left back. Note that we are just setting the “intended dir” and “intended speed” for now, then we will use them to update the avatar later.
Also, all directions are relative to the camera’s “H-Angle”, which is the direction the follow camera is facing. In addition, when the user presses “a” and “s” at the same time, we set the direction to be forward right, and set the speed to negative.
For the “d” key, the logic is exactly the same, though the angles are reversed:
18 - “Player” Sprite: Handle Move Forward or Backward
If neither the “a” or “d” key is pressed, the avatar will run forward under the “w” key, run backward under the “s” key, and stay still when neither key is pressed.
19 - “Player” Sprite: Update player speed/animation/direction
By this point, we have calculated the intended moving speed, moving direction and animation, we need to update it for 3 entities: the player’s avatar on his/her own computer, its 2D representation at the game server, and its copy on the other user’s computer.
This is done in 3 steps:
-
We first compare the local camera’s facing direction and the avatar’s facing direction. If they are not enough (at least different by 0.1 degrees), then we need to update the avatar’s facing direction. For example, this might happen when the user rotate the camera to a different direction. We are using the “synchronously set direction” block, which not only update the direction of this player’s avatar on his/her own computer, but also update the direction on the game server and the other user’s computer.
-
If the intended moving speed or direction has changed, we will use the “synchronously set speed and direction” block to update these values for all 3 representations as well. Note that the “intended dir” is where the avatar is moving, and it may be different from the camera’s direction. For example, when the user presses “a”, the camera may still facing forward, but the intended moving direction is to the left.
-
Lastly, if the intended animation has changed, we need to update the animation for this player’s avatar on this computer and on the other user’s computer. This can be done by broadcasting a message “update animation” to all sprites, and attaching the clone ID and intended animation with that message. We will discuss how that message is handled next.
20 - “Player” Sprite: Handle the “update animation” message
When any sprite receives this message, we will split the attached information and extract the clone ID. If that ID matches the ID of this clone, then we update this sprite’s animation. Recall from #19 that the “animation_info” attached to the message has two parts joined by “_”: “clone ID” and “intended animation”, such as “A_Run”.
21 - “Wall” Sprite: Add 4 Clones
The “Wall” sprite is fairly simple. You can modify it to design any map inside the borders. As an example, we can have four walls on the four sides of the world like this:
To keep the code simple, all the wall objects are the same shape, except that two of them are rotated 90 degrees. They are all clones of the “Wall” sprite with clone IDs of 1, 2, 3 and 4:
When each clone is created, we need to place it at the desired position and direction based on its clone ID. Then, we need to add it to the game so that the game server can create a rectangle of 400 by 50 to represent it in the 2D simulated world at the server. The same clone will also be created on the guest user’s computer.
22 - “Wall” Sprite: Create the 3D Wall Object
When we add the Wall sprite to the game, it has not yet been added to the 3D scene. As discussed earlier, after a sprite is added, the game server will trigger a new event “when added to game”, and this is where we should add the 3D box that represents the wall in the 3D scene. The reason for this is that this event is triggered on both the host computer and the guest computer, which ensures both players can see the walls in their 3D scenes.
The x and y sizes of the 3D box should match the rectangle shape we specified earlier: 400 by 50. The height of the wall does not matter, since the game server only thinks of the wall as a 2D rectangle. However, to make sure the player can not see above the wall, we should make the wall taller than the player’s height of 100. Therefore, we can set z size to 300, so the top half is 150. Depending on the clone ID, we place each box at the desired position and direction.
That is all that we need to do for the walls. We already specified that when a Player touches any Wall sprite, it will be stopped.You can also add 3D cylinders as walls, and you just need to make sure they are added as circle shapes like this:
23 - “Bullet” Sprite: Handle the “fire” message
Next, let’s look at the Bullet sprite. It is slightly more complicated than the Wall sprite. A bullet is created when the “fire” message is received. Note that the Wall is only added at the host computer, but the Bullet can be fired at both computers.
When the “fire” message is received, we first need to make sure only the original Bullet sprite handles it. We check the clone ID to make sure it is “originalsprite”. Otherwise, a clone of the Bullet sprite may receive the “fire” message as well, which may generate a new duplicate clone.
The “shot info” attached to the “fire” message contains four pieces of information about the Player that has fired the shot: Player ID (“A” or “B”), x position, y position and direction. We store this information in four variables, then move the sprite to the given position/direction. Then, we make a clone of this sprite. Each clone is given a unique ID of two parts: the player ID (“A” or “B”), and a bullet ID that keeps increasing by 1.
24 - “Bullet” Sprite: Add clone to game
When a clone of the Bullet sprite is created, we first need to add it to the game. It will be dynamic since it will move forward in a straight line. It will be added as a circle with a diameter of 40, so the game server will use a 2D circle to represent it in the simulated game world.
After that, we need to make the bullet only hit the opponent player. For example, if the clone ID starts with “A”, then we set the bullet to collide only with Player sprites that has a clone ID of “B”. And when that happens, the bullet will destroy itself, and also send out a new message “bullet hit player”. This message will be handled by the Player sprite to reduce its health (to be discussed below).
Lastly, when the bullet hits a wall or the edge of the world, it will simply destroy itself.
25 - “Bullet” Sprite: When added to game
When we get a notification from the game server that a new Bullet clone has been added to the game, we add the 3D sphere to represent the Bullet in the 3D scene. There are a few steps we need to take:
- We will play an explosion sound.
- Depending on the clone ID starts with “A” or “B”, we add a sphere of red or black color to the scene. Its diameter should be 40, which matches the size we used to represent it at the game server. Again, you can think about it this way: if we look down from the top, the sphere looks like a circle on the ground with a diameter of 40.
- We move the sphere to the starting position, which is the position of the Player that fired the shot.
- We set a speed of 600 for this bullet to move along the starting direction.
26 - “Player” Sprite: Handle “bullet hit player”
When a bullet from the opponent hits a player, that player will receive a “bullet hit player” message. Only the main Player sprite on the user’s own computer will receive this message, not its replicate on the other computer. For example, when Player A got hit, only the Player on the host computer will receive this message. This avoid handling the message two times.
If the Player’s health is still greater than 0, we will reduce that player’s health by 1. Then we broadcast a “update health” message, and attach the clone ID and health of that player.
27 - “Player” Sprite: Handle “update health”
When the Player receives the “update health” message, we will make sure only the original sprite will handle it, not the clones. We do the following steps:
- Extract the player ID and the updated health value
- Use a repeat loop to go through the 3 rectangle labels that represent the health of that player, and set them to either green or black based on the health value
- If the health is already 0, then we send a message of “game over”, with the parameter being the ID of the opponent player. Note that this is the only way to end the game.
28 - “Winner” Sprite: Handle “game over”
When the “game over” message is received, we do the following in the “Winner” sprite:
- Hide the 3D scene, since we will use a 2D costume to show the end screen;
- Play a sound of “Success 7”
- Switch to the costume that shows the name of the winner: A or B
- After 3 seconds, we stop the entire program.
29 - “Powerup” Sprite: Handle the “add powerup” message
When the Powerup sprite receives the “add powerup” message, it will first make sure only the original sprite with clone ID of “originalsprite” will handle this message. Note that this is only done on the host computer, and whenever a new powerup sprite is added, it will be replicated on the guest computer.
The Powerup items can be either for gaining one health point or increasing the firepower by 1. You can fine-tune the parameters that control the type and frequency of the new powerup items based on your preference. Obviously, if there are too many “health” powerup items, then the game may never end, since both players can recover from hits quickly.
Here is how Powerup works currently:
- We wait a random time period between 30 to 60 seconds before adding each new powerup. You can make this time longer to reduce the number of powerups available.
- We pick a random position within the world
- We pick a random type between “health” or “firepower” with 50% probability for each. You can change the probabilities to generate more “health” or more “firepower” rewards.
- We move the sprite to the given position, then create a clone.
- Each clone has a unique ID composed of 2 parts: the powerup type and a sequence number.
30 - “Powerup” Sprite: When a clone is created at the host
When a new clone is created, we add it to the game as a static circle (diameter of 40) at the game server. After a random timeout period between 10 to 20 seconds, we remove this item from the game. This way, if the two players do not try to collect a powerup item quickly, it will disappear soon, making the game more exciting. Of course, if you change this time out period longer, it will become easier to gain power for both players.
30 - “Powerup” Sprite: When added to game
Similar to other sprites, we add the 3D object representing the powerup items under the block “when added to game”. This block is triggered on both computers when the host computer adds a new powerup item to the game.
We do the following to add the powerup item when it is added to the game:
- We play a sound to notify the users a new item has been added;
- We store the position of the item in 2 variables “my x” and “my y”. We need this because when we run the “add model” block, it will reset the sprite’s x and y positions to 0.
- We add the model for a medical box or a thunder icon depending on the Powerup type. Note that it is added as hidden, because otherwise the model will show up at the origin point before we move it;
- We will set a z-rotation to make it spin continuously forever.
- We will move the model to the saved position;
- Lastly, we show the object.
31 - “Player” Sprite: Handle “collect powerup”
When the Player sprite touches a Powerup object, it will trigger the “collect powerup” message. Only the Player clone that is controlled by the user will receive this message. To handle it, we first play a sound to confirm the collection of a Powerup. If it is a “health” type, and this player’s health is still less than 3, we would increase the health by 1, and broadcast the “update health” message, which updates the health value display at the top. Similarly, if this player’s firepower is less than 5, we increase it by 1, and send out the “update firepower” message.
32 - “Player” Sprite: Handle “update firepower”
The way we handle “update firepower” is very similar to how we handle “update health”. We extract the update firepower value from the message’s parameter, then we go through all 5 labels for that player, and set each label to red or black based on the firepower value.
Summary
We have explained all the blocks in this project. Feel free to try to remix and modify the game. Here are some ideas:
-
Adjust game parameters: There are many simple changes you can make to the game, such as player avatars, 3D models/textures used, maximum health/firepower values, time interval before each new Powerup is generated and how long it lasts, movement speed of the players and bullets, keyboard controls of the player movements, size/count/positon of the walls, size of the world, etc. Feel free to change them based on your preference.
-
New Powerup types: You can extend the game by adding new Powerup types, such as speed-up for player or bullet, new types of bullets (double or triple bullets), powerup to allow players to run through walls or see through the walls, etc.
-
2 vs 2 games: You can try to allow four users to play together. You will need to increase the game capacity when you create the game, and add new player IDs like “C” and “D”, etc.
-
AI Players: You can create an AI bot to control one player, so that one user can play against the AI instead of looking for another player, or you can have 2 human players team up to play against 2 AI players.
-
RE: Group?
@106809nes
Sure. Here you go: https://forum.creaticode.com/groups/best-forum-helpers
-
RE: Wishlist for New Models
@2570103-learn-vsb-bc Thanks for the suggestion. We will work on this.
-
RE: What does the add 3d video plane block do and how to use?
For all 3D objects, you can move/rotate them the same way, using the blocks under “3D Action”, like this:
If you have multiple objects, you may need to “select” one object as the “sprite object”, then the move/rotate blocks will be applied to that object.
See this for more details: https://www.forum.creaticode.com/topic/16/names-and-sprite-objects
-
ChatGPT AI: A Quiz Writer (Difficulty: 3)
Introduction
You have learned how to use ChatGPT to build smart chatbots. However, it can be used in many other types of projects, and the interface does not have to be a chat window.
In this tutorial, you will learn to build a smart “quiz writer”. The user can specify any topic, then the program will use ChatGPT to help generate a quiz question and also evaluate the user’s answer. You will also practice building a simple app using buttons and textarea.
Step 1 - An Empty Project
Create a new project, and name it “ChatGPT- Quiz Writer”. Delete the sprite with the dog, and we will just use the “Empty1” sprite for coding.
Step 2 - The Topic Input
First, let’s add a label that says “Topic”, and an input textbox for the user to write the topic. We’ll name these 2 widgets “topiclabel” and “topicinput”.
They will look like this:
Step 3 - Move Widgets Using the “Widget Position” Tool
Now we need to move these 2 widgets to the top row of the stage window, so we can add other widgets below them. This can be easily done using the “Widget Position” tool like this:
You will find the X/Y/Width/Height values of the 2 blocks are automatically changed for us, so the next time you run the program, the widgets will directly appear in the new positions:
Of course, you can still change the position and size numbers manually at any time.
Step 4 - Add a “Go” Button
Next, we will add another button that says “Go”, which will tell ChatGPT to generate the quiz.
By default, the button will appear at the center. Please use the “Widget Position” tool to place it in the top right like this:
Your program should be similar to this afterward:
Step 5 - Add the Question Box
Now we need to add a big textbox to show the quiz generated by ChatGPT. It should allow multiple lines of text but does not allow any user input (“read-only”). Practice using the widget position tool to position this textbox.
Step 6 - 2 New Custom Blocks
Before we add more widgets, it looks like this stack of blocks may be getting too tall. Therefore, it is a good time to define 2 new custom blocks to help organize the program.
Please define 2 new blocks “add question widgets” and “add answer widgets”, and run them in the main stack. We will also move all the existing blocks into the definition of “add question widgets”.
Step 7 - 4 Answer Buttons
Now we will add blocks to add 4 buttons in the definition of “add answer widgets”. Their names are simply A/B/C/D.
They look like this:
Step 8 - The Feedback Box
When we click one of the 4 buttons, we will ask ChatGPT to tell us if we got it correctly. So we need to add another textbox at the bottom to show ChatGPT’s feedback. Please add it as multi-line and read-only.
Now the interface is ready:
Step 9 - Compose Request to ChatGPT
Suppose the user inputs a topic at the top, then clicks the “Go” button. At this point, we need to compose a request and send it to ChatGPT. The request should include what the user wrote as well. We can write our request first, then join it with the user’s input.
To store our request, we can define a variable “request”, and set its value when the “Go” button is clicked:
Step 10 - Send Request to ChatGPT in Streaming Mode
Now we are ready to let ChatGPT do the magic and give us a random question. To show the question as soon as possible, we will use the “streaming” mode. To allow a fairly complex question, we can set the max length to 400.
Also, this should be a new chat, since each time we click “Go”, we do not need ChatGPT to remember the previous questions. If we use the continue mode, then after a few questions, we will reach the token limit of ChatGPT, and have to restart.
We will need to make another new variable “question” to hold the question generated by ChatGPT.
Step 11 - Show the Question
Now we need to show the question as ChatGPT generates it. We will use a “repeat until” loop to keep updating the question box with the value of the “question” variable. You can copy the emoji for the checkmark here (may look different here from the CreatiCode playground):
Now we can test if ChatGPT will generate the question properly:
Step 12 - Handle User Answer
When the user clicks on one of the 4 answer buttons, we need to ask ChatGPT about it. To do that, define a new block named “check answer”, which takes the “answer” as input:
Now we can run this new block when the user clicks the 4 buttons:
Step 13 - Compose the Feedback Request
In the “check answer” block’s definition, we need to compose a new request to ChatGPT: we will tell ChatGPT what’s the question since we are not asking ChatGPT to remember it. We also need to tell it the user’s answer, then ask ChatGPT whether it is correct.
We can compose a 4-part request using the “join” block like this:
Step 14 - Display the Feedback from ChatGPT
The remaining work is very similar to how we get the question from ChatGPT. We send the request, then display the result in the “feedback” textbox. You can duplicate the previous blocks and make some changes to them:
Now we have a working version of the quiz writer!
Step 15 - Highlight the User’s Answer
To make our quiz writer easy to use, we need to improve the user interface a bit. The most important change is to highlight the answer selected by the user.
We can change that button’s background color when it is clicked like this:
Step 16 - Reset Button Colors
When the user generates a new quiz question, we need to reset the color of all the answer buttons back to unselected. We can do it when the “Go” button is clicked:
Step 17 - Testing
Finally, you need to do some more testing to make sure the user experience is smooth. Here is a final demo:
Step 18 - Further Improvements
This quiz writer is a very basic version. There are many areas where you can improve it. Here are some ideas for you to try:
-
Other Question Format: For example, you can change the question format from multiple-choice to short answers. The user would need to write the answer in another textbox.
-
Improve the Prompt: The current request we send to ChatGPT is very simple, so sometimes we may get strange answers from ChatGPT. For example, in this feedback, the answer is wrong, but ChatGPt still says “Great job!” because it is a “great question”. Try to improve the request to avoid such issues.
- Better Colors: You can change the text style/color and background color of all the widgets to make the interface look better.
- Keeping Track of Scores: You can help the user keep track of how many questions were asked, and how many were answered correctly.
- Pre-generated Questions: Sometimes you may not want to generate the questions on the fly, since you have no control over what ChatGPT may ask. If you have a fixed topic, then you can ask ChatGPT to generate 20 questions for you, and store these questions and their answers in a list or table. Then when the user runs the program, you can randomly select the question from your pool of questions.
-
-
RE: Group?
@106809nes
We can create groups if you have good suggestions.