Navigation

    CreatiCode Scratch Forum

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • CreatiCode

    3D - Bloxorz Game (Difficulty 6)

    Tutorials
    2
    2
    1313
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • info-creaticode
      CreatiCode last edited by admin

      Introduction

      In this tutorial, you will learn to reproduce a classic puzzle game called “Bloxorz”. In this game, the player rotates a box on a platform to reach the target hole:

      fall.gif

       
      You will practice using parenting to make objects rotate around any point, using a table for level design, and also a little bit of the 3D physics engine.

       
       

      Step 1 - A Starfield Scene

      To get started, please create a new project on the CreatiCode playground, remove the Sprite1 with the dog, and rename the “Empty1” sprite as “Main”.

      In the Main sprite, add the following blocks. They will create an empty 3D scene, display the 3D axes, and add a nice skybox as the background with stars in space.

      7561605b-ba9c-4563-ba62-083705f51f16-image.png

       
      This is what you should get:

      sky.gif

       
       

      Step 2 - Add a New Camera

      By default, when you add the skybox, it will also zoom out the camera. However, in this game, we are going to use objects that are very small. Please use the following block to add a new camera, which will replace the existing camera:

      16e94b95-37a2-410e-b8e8-965a2d174331-image.png

       
      This camera will have a distance of 10 from the center of the world. In addition, we have disabled user input for the keyboard and the mouse pointer. This way, the user can not change the view of the camera, and all key presses will be used to rotate the player’s box.

      You should get an output like this. Do you see any issues here?

      908441da-e634-45be-ab8e-4faf2ad07fe7-image.png

       
       

      Step 3 - Configure the Camera

      You have probably noticed a problem: we can no longer see the beautiful starfield in the background. That’s because the background is too far away. To fix the problem, we need to change the camera’s setting to make it view objects within a distance of 1000000:

      6521c64b-38f8-466b-a726-866831ed1594-image.png

       
      Now we can see both the 3D axis near us and the starfield that’s very far away:

      ae40d7ab-30be-40fa-814f-ab0145d938c0-image.png

       
       

      Step 4 - Add the Player Box

      Now let’s add the box that the player controls. It should be 1 by 1 by 2, and given the name of “p”. You can pick any texture you like. We need to move it to the position of x = 1, y = 1, and z = 1. Since its height is 2, and z position is 1, its bottom will be at the level of z = 0 exactly.

      82968ef8-723d-46d5-befe-f34f3deee47c-image.png

       

      It should look like this:

      4b751523-3895-4183-b713-d3d8a0b26743-image.png

       
       

      Step 5 - Add the “Platform” Sprite

      Now please add a new empty sprite named “Platform”, which will be used to manage the platform boxes.

      To initialize it, send a message from the Main sprite to “add platform”,

      75e1ad21-7dcf-4acc-a168-ab54b2a45f65-image.png
       
      then receive it in the Platform sprite:

      6def194e-ca22-4acc-9cdc-dcb24beb23b9-image.png

       
       

      Step 6 - Add the First Brick for the Platform

      The platform will consist of many bricks (boxes). To keep it efficient, we will use a common technique: we will add one brick, then make many copies of it.

      Here are the blocks for adding the first brick. To keep our level design simple, we will make each brick 1 unit by 1 unit in the x and y dimensions. It should be fairly thin, with a thickness of 0.1. Give it a name like “g”, and feel free to pick any texture for it.

      8d965861-a611-4acf-b780-d22ad5e243b7-image.png

       
      This brick will look like this when we zoom in on it:

      7e2bf8ca-4d00-4fc2-9764-bcc5fc9d77bf-image.png

       
       

      Step 7 - Move the First Brick Away

      Now we will move this brick away by setting its z position to a very large value, so our camera does not see it. This way, we can place all the copied boxes according to our level design map.

      edd863a3-74d3-4fc7-9c6c-3b8ad71b2696-image.png

       
       

      Step 8 - Use a Table to Represent Box Positions

      To build up the platform, we will need to add a lot of boxes, and place them in different positions. Ideally, we would like to be able to view the map visually, so it is easy to create or change the map. For that reason, we will use a table to represent the map.

      For example, the following is a table with 3 columns named “1”, “2” and “3”, which represent x positions of 1/2/3. It also has 3 rows, which represent y positions of 1/2/3. This way, each item in the table can be used to represent whether there should be a brick box at that position. For example, for column 1 and row 1, if we put the letter “b” there to represent “brick” (you can choose to use any letter), then it means we would like to place a box at x = 1 and y = 1. The 7 items in the table with “b” in them will translate to 7 bricks that form the letter “H”.

      3b061819-a0ca-4001-87d5-cdc8d1f6eb97-image.png

       
      Now please create a new table named “map”.

       
       

      Step 9 - Add 20 Empty Columns to the Table

      Although we can manually add new columns to the table, it is much faster to do it using blocks. First, create a new variable “x”, then add the following for-loop to insert 20 columns. It will insert a column named “1” at column 1, then insert a column named “2” at column 2, etc.

      54b4ee87-be1b-47fc-8bb3-bac6af01506b-image.png

       

      You will get 20 columns with no rows in the table:

      sky.gif

       
      Note that if anything goes wrong, you can use the following block to delete all rows and all columns in the table to restart, but make sure you don’t run this block by accident.

      e4975d26-1392-49a2-a118-af3a8278f07a-image.png

       
       

      Step 10 - Add 20 Empty Rows to the Table

      We can also quickly add some empty rows to the table using blocks. Create a new variable “y”, and then use a for-loop like this to add 20 rows:

      7e9a52f6-4f7f-4747-a53f-3978eca1c645-image.png

       
      Now there are 20 empty rows in the table:

      sky.gif

       
       

      Step 11 - Add Some Data to the Table

      Now let’s add some letters to the table to represent 3 rows of boxes, with 5 boxes in each row. You can click on any table cell to edit it, and you can also press the TAB key on your keyboard to jump to the next cell on its right.

      ttt.gif

       
       

      Step 12 - Define the “Add Box” Block

      Now let’s define a new block for adding a new box at a given x/y position. It should take 2 inputs of x and y. In its definition, we will first select the first brick we added named “g”, and then make a copy of it. Note that we need to share data between the original box and the copied boxes, which will save a lot of time and computer memory when we copy many boxes.

      We will name each copy using its x and y positions. For example, if x is 5 and y is 6, then the box’s name will be “5_6”. We would be able to manipulate this box later using its name (such as moving or removing it).

      Lastly, we will place this box at the given x/y position. Its z position should be -0.05, because its height is 0.1, and we want the top face of the box to be at z position of 0.

      7e3b2e18-978f-4fff-aaf3-65f2d177d511-image.png

       
       

      Step 13 - Add Boxes Based on the Map Table

      Now we are ready to add the boxes for the platform. The idea is that we will read the type of each item in the table, and use a new variable “type” to store this information. Whenever we find an item’s type is “b”, we add a box at that position. Note that we are making use of the fact that the value of “x” is both the column name and the x position, and the value of “y” is both the row number and the y position.

      0f7023ad-6848-4dc4-ac69-62bab0e09739-image.png

       
      15 boxes will be added as a result:

      8369317f-5455-4a72-b585-d0de3ffa93eb-image.png

       
       

      Step 14 - Change the Camera’s Position

      To view the platform more clearly, let’s go back to the Main sprite, and change the camera’s view distance to 9, and change its target position to x of 3 and y of 2:

      0a0d94cc-aaf5-4ac8-a931-1089a2b7240f-image.png

       
      Now we get this view:

      58f9275b-076e-4753-8436-33fc9d95a326-image.png

       
       

      Step 15 - Add Some Gaps Between Boxes

      Currently, it is a bit hard to tell the boundary between the boxes of the platform. We can add a small gap between them by shrinking the boxes a little bit. In the Platform sprite, we can change the first box’s size from 1 x 1 to 0.96 by 0.96:

      0fb13838-3690-4ba0-9308-bd1b6a6cf306-image.png

       
      As a result, we can see a clear gap between the boxes:

      0c9dc477-2dc0-4017-9e63-8f186fa96d7e-image.png

       
       

      Step 16 - Add an Anchor for Rotation

      Now we are ready to make the player box rotate on the platform. The challenge here is that we can not simply rotate the box around its own center point. Instead, we need to rotate it around one of its edges. The solution is to use a parent object as the rotation “anchor”. When the parent rotates, the player box will be rotated around the parent’s position.

      To add the anchor object, we can use a transformer object named “a”:

      4cb83400-862d-4cc2-b42b-23fd21d5c350-image.png

       
       

      Step 17 - A Loop for Handling Key Presses

      We will allow the player to press keys to rotate his box. Let’s define a new block named “handle keys”, and use a forever loop to check for key presses. We will start with the “d” key:

      fdb14464-8e24-47ae-9616-2b417255c226-image.png

       
      Note that we are always selecting the player’s box “p” as the sprite object first, since the sprite object might have changed.

       
       

      Step 18 - Define a “Rotate Box” Block

      When the player presses “d”, we need to make the player’s box rotate around its bottom right edge. To do that, we first need to move the anchor object to this point, and then rotate the anchor object around the Y-axis.

      ttt.gif

       

      To implement this change, we will first define a new block named “Rotate Box”. It will accept 4 inputs, which allow us to specify the x and y position of the anchor object, and also how many degrees to rotate around the X axis and the Y axis:

      da78cc1d-f1b2-4d4b-a589-de8a26348cca-image.png

       
       

      Step 19 - Rotate to the Right

      To rotate the player’s box to the right, let’s determine the 4 inputs we should use.

      Suppose the player’s box’s center is at x = 1 and y = 1. Then the anchor point’s x position is 0.5 from the center, which is x + 0.5. The anchor point’s y position is the same as the center point’s y position. The anchor point’s z position should be the z position of the bottom of the box, which is 0.

      We will rotate the box -90 degrees around the Y-axis. Since we are not rotating it around the X-axis, we can set it to 0.

      Therefore, this is how we should use the new block:

      33b238aa-e9dd-4d36-bf66-5a430b349419-image.png

       
      Note that since the player box “p” is selected as the sprite object at the moment, the motion blocks "x position’ and “y position” represent the position of the center point of “p”.

       
       

      Step 20 - Move the Anchor Object

      Now it’s time to implement the definition of “Rotate Box”. First, we need to select the anchor object to move it to the given x and y position. Next, we will select the player box, and then set the anchor object as its parent.

      8b8ca618-be91-4805-a4d3-e0264ea0f2e0-image.png

       
      Note that the 2 “select” blocks are very important. They tell the 3D engine which object you would like to work with.

       
       

      Step 21 - Rotate the Anchor Object

      Next, we’ll rotate the anchor point. We can check the values of “x degrees” to see if we are rotating around the X-Axis or the Y-Axis. If it is not 0, that means we are rotating around the X-Axis. Note that we need to select it before rotating it.

      2fddd3fa-3fd7-415f-9af7-d0ea4df60f93-image.png

       
       

      Step 22 - Unlink the Anchor Parent

      After rotating the anchor object, the player box will be rotated to the new position. We need to unlink it from the parent anchor object, otherwise, its position information will not be accurate.

      6315d7e2-fa7e-4853-800a-8ff29ee32fc2-image.png

       
      Now we can give it a try. When we press “d”, the player’s box will be rotated correctly to the right.

      ttt.gif

       
       

      Step 23 - Rotate Right Again

      When we try to rotate the box to the right by pressing “d” again, we get an incorrect result.

      ttt.gif

       
      This is because when the box is lying down, the right edge is not 0.5 units away from the box’s center point, but 1 unit away.

      So how do we know if the box is lying down? We can check the z position of the player box. If it is standing up, its Z position should be 1; when it is lying down, its Z position is 0.5.

      b6b02199-178b-4fa4-bb8a-efe826e4ba40-image.png

       
      Now we can keep rotating the box to the right:

      ttt.gif

       
       

      Step 24 - Rotate Forward on “w”

      Next, let’s make the box rotate forward when the “w” key is pressed. We can duplicate the blocks for handling the “d” key, and modify it in a few places:

      • When we rotate the box forward, the anchor point will be at the front bottom edge instead of the right bottom edge. That means we need to move the anchor object to the same x position as the box, but a large y position.
      • We need to rotate the box around the X-Axis instead of the Y-Axis.

      ca619aae-e0f5-4059-a381-1c872ef2a345-image.png

       
      Now we can rotate forward as well:

      ttt.gif

       
       

      Step 25 - Reset the Anchor Object’s Direction

      When we rotate the box to the right 2 times, then forward, we have a problem:

      ttt.gif

       
      This is a tricky problem. We can see that the anchor object’s position is correct, but it is rotating the box backward, not forward. The reason is that after we rotate the anchor object to the right 2 times, it is upside-down. So when we tell it to rotate forward, it rotates backward.

      The fix this issue, we simply need to reset the anchor object’s direction every time we use it:

      47a5ceef-bcaf-44de-b852-f9c358768984-image.png

       
      And we can confirm this problem has been fixed:

      ttt.gif

       
       

      Step 26 - Rotate Sideways

      There is another edge case we have to fix. When we rotate right once, then rotate forward, the box ends up in the air:

      ttt.gif

       
      This time, the issue is not in the rotation direction, but the position of the anchor point. When the box is lying down, it can be heading forward or sideways. We only handled the former case so far.

      When the box is lying sideways, to move it forward, the anchor point’s y position should only be 0.5 units away from the box’s center point, not 1 unit.

      However, how do we know if the box is lying forward or sideways? We can check its y position. If the box is lying sideways, its y position is a whole number like 1, 2, etc; if it is lying forward, its y position is halfway in between 2 positions, like 1.5, 2.5, etc. So we can check if the y position rounds to itself: whether round (y ) is still equal to y.

      701ddf7f-e538-4976-9d27-237ebf6594da-image.png

       
      And the problem is now fixed:

      ttt.gif

       
       

      Step 27 - Rotate Forward Then Sideways

      We need to apply the same logic for handling the “d” key: if the box is lying forward, and we roll it to the right, we need to adjust the x position of the anchor point.

      e4ad0511-53b5-47e5-b8f0-4a3af996542c-image.png

       
      And we can test it like this:

      ttt.gif

       
       

      Step 28 - Handle the “a” Key

      Now let’s copy the logic for “d” key to handle the “a” key. The anchor point’s x position will be to the left of the center of the box, and the rotation angle is 90 instead of -90:

      b6c2a1ca-5c81-4bf1-ac83-6ef6aded0ba3-image.png

       
       

      Step 29 - Handle the “s” Key

      Lastly, let’s duplicate the logic for “w” key to handle the “s” key. The anchor point will have a smaller y position than the box’s center, and the rotation angle is -90:

      cae64b3e-073d-4d1b-883a-9e9a5bb66219-image.png

       
      Make sure you test all 4 directions thoroughly:

      ttt.gif

       
       

      Step 30 - Specify the Goal Position

      Now let’s specify where is the goal position on the map. We can use a different letter “g” to represent the position of the goal, and there should be only one “g” in the entire map. For example, we can put it in column 4, row 2:

      113ade8c-f1e2-48fe-af45-2d7743d09116-image.png

       
       

      Step 31 - Add a Box at the Goal Position

      In the Platform sprite, when we create the boxes for the platform, we will walk through every item on the table. If we find the item’s type is “g”, we should create a new box to represent the goal position. It will have the same size as the other boxes except for a different color (such as purple).

      f18d2960-48b6-4e1d-8513-3c0a7abbeadf-image.png

       
      ca2e1fc0-0ed1-4722-a02f-22a23807093d-image.png

       
       

      Step 32 - Make the Goal Box Glow

      To make our goal box prettier, we can make it glow. We will need to update its emission color, then create a glow layer for it:

      57dd830e-dc92-4832-b2c5-0514dd375453-image.png

       
      Here is the glow effect:

      1782fb47-d967-439c-9f18-0d5d9d6b652a-image.png

       
       

      Step 33 - Check Player Box Position

      Now our game is set up for play, and every time after we rotate the player’s box, we need to check its position, and determine if the box should fall or the level is completed.

      Let’s start by creating a new block named “Check Position”, which will run at the end of the “Rotate Box” block.

      4dbdd884-a0e8-452b-af14-d77086a08349-image.png

       
       

      Step 34 - Get Position Type When the Player’s Box is Standing Up

      The player’s box is made of 2 cubes. We need to know whether there is a platform box below each cube, or the goal box is below these cubes. We can read this information from the “Map” table.

      When the player’s box is standing up (its z position is 1), this is fairly simple. Both cubes of the player box share the same x and y positions as the player box itself. Let’s make 2 new variables “type 1” and “type 2” to represent the item type underlying each cube, and we can set their values this way:

      361cf42f-ece3-472b-b207-84a7e8af786f-image.png

       
      For example, when the player box’s x position is 1 and y position is 2, then we will set “type 1” to the value of the item at row 2 column 1 of the table, which will be “b”. “type 2” will be the same, since the second cube of the player box is also at the same x and y positions.

      c15c17f5-2c89-4fb1-b553-ad701219f54b-image.png

       
       

      Step 35 - When the Player’s Box is Lying Left to Right

      When the player box’s z position is not 1, that means it is lying down. If it is lying left to right, its y position would be a whole number. In this case, the 2 cubes of the player box would have the same y position as the box itself, and their x positions would be 0.5 units away from the box’s center.

      70b4faa6-39ef-4b4b-a316-9bb65d94d277-image.png

       
      For example, if the box is lying at y of 2 and x of 2 to 3, we would find their position types will both be “b”:

      86d648b3-722d-44e1-b838-5b13de097690-image.png

       
       

      Step 36 - When the Player’s Box is Lying Front to Back

      In the last case, the player’s box is lying front to back. The 2 cubes would have the same x position as the box, and their y positions would be 0.5 units away from the y position of the box.

      ac96749f-6c96-4858-9a16-be1ff3fd58a2-image.png

       
      For example, in this picture, the 2 cubes are at x of 4, y of 2 and 3. So the types of bricks below them are “g” and “b”:

      aa07f5f1-4dec-4105-b73e-2b47a8e37f88-image.png

       
       

      Step 37 - Enable Physics

      So far we have not used the physics engine at all. So long as the player’s box is landing on the platform properly, we only need the rotation animations. However, when the player’s box should fall off the platform, we would need to use the physics engine to make the fall look real.

      To use the physics engine, let’s make a few changes:

      • Enable physics for the scene in the Main sprite:

      • In the Platform sprite, attach a physics body to the first box we create. This way, all copies of it will have a physics body automatically. Note that the “mass” has to be 0 to ensure these bricks do not fall.

       
       

      Step 38 - Make the Player’s Box Fall

      When the player box is standing up, it has to be on top of a platform brick. If the player’s box is lying down, then both cubes of it have to be on top of some platform bricks.

      Therefore, when we review “type 1” and “type 2”, if at least one of them is empty, then we know the box should fall. To make the box fall, we simply need to attach a physics body to it.

      4834a692-c64d-43ab-ac34-5b45c8fff1c6-image.png

       
      Now we are getting a good falling effect:

      fall.gif

       
       

      Step 39 - Checking for Level Completion

      How do we know when the player has completed the challenge? The box should be standing over the goal area, which means both “type 1” and “type 2” should be “g”.

      When that happens, we should also make the box fall by attaching a physics body to it.

      cd637d35-113a-4107-9c03-7032afaa7bf8-image.png

       
      Now the box will fall through the goal area:

      fall.gif

       
       

      Step 40 - The Level Complete Message

      When the box falls through the goal, we should also show a message for “level complete”. We can use a label to do that:

      4c6ae414-3904-440d-973f-7d1ed2e09999-image.png

       
      It will pop out like this:

      fall.gif

       
       

      Creative Ideas

      Although this game is very simple, you can extend it in many ways. Here are some ideas worth trying:

      • Change the Level Map: You can change the map of the platform very easily by changing the “Map” table. You can add more rows and columns if you need to.

      • Multiple levels: when the user completes a challenge, you can reset the platform to a more difficult map.

      • Buttons: You can add buttons on top of some bricks, and when the player’s box lands on those bricks, it triggers some bricks to be added or removed, such as a bridge between 2 parts of the platform. To implement this idea, you would need to dynamically change the content of the Map table.

      • Blockers: You can use a different color for some bricks of the platform, and when the player’s box lands on any of these bricks, it will bounce back to the previous position.

      • Leaderboard: You can keep track of the number of moves made by the player to complete the level, and show that in a leaderboard.

      • On-screen Buttons: You can add some buttons for rotating the player’s box to the stage so that the game can be played on touchscreen devices.

      Below is a game that demonstrates some of the ideas above:

      https://play.creaticode.com/projects/77083f9840c1f919563357ff

      H 1 Reply Last reply Reply Quote 0
      • Pinned by  info-creaticode info-creaticode 
      • H
        hayden @info-creaticode last edited by

        @info-creaticode said in 3D - Bloxorz Game (Difficulty 6):

        Below is a game that demonstrates some of the ideas above:
        https://play.creaticode.com/projects/77083f9840c1f919563357ff

        1 Reply Last reply Reply Quote 0
        • First post
          Last post