This lesson is a continuation of previous lessons in Roblox programming. If you are not familiar with how to create the genericShapes module, please review the other Roblox lessons first. For this lesson, you should start a new project. You will need to create two (2) module scripts in the ReplicatedStorage area. First, create a genericShapes module in your ReplicatedStorage area. Then copy-and-paste the code from the website into the genericShapes module. The source code for the genericShapes module is linked below. Then create a "drones" module script also in the ReplicatedStorage area. Rename the module script: "drones". The link to the code for that module is shown below.
2 Module Scripts
genericShapes Module (genericShapes-ModuleScript.htm) Copy the code from this page into the genericShapes module in your program.
drones Module (drones-ModuleScript.htm) Copy the code from this page into the drones module in your program.
The next step is to go to the Workspace in Roblox and add a Script. Rename that script: startingScript and paste the code in the example below.
We will be working with this starting script.
Vectors
The direction of a vector indicates where it points in space. This direction can be represented by an arrow or a line segment. For example, if you imagine an arrow pointing from the center of a circle to some point along the edge of the circle, the direction of the vector corresponds to the degree on the circle that the arrow points towards.
The Compass
The drone module includes a compass to help visualize different vectors. This compass will appear below the Avatar and will move with the Avatar as it moves in the 3D world. Two lines of code (below) are needed to turn the compass on.
The Drone
In this drone module, the drones will be portrayed using a design similar to a quadcopter. A quadcopter drone has 4 small helicopter blades at each corner of the drone. In this example, the helicopter blades will be represented by 4 discs. I tried to get the discs to be transparent. But the transparency was lost when they were joined together as a single model.
A Drone Collection
Most of the examples in today's lesson only use 1 drone. However, it is possible for you to add multiple drones to your Roblox world. The drones are stored in an array identified as: d.collection[]. The code below shows how a for loop is used to store the new drones in the array known as d.collection. The variable i is being used as the array index. So, as the for loop loops through the numDrones, a new drone is added to the .collection using the coordinates of a circle around the origin (spawn) point.
If you decide to create multiple drones, please be advised that you will need to create one or more algorithms to control the drones. You should probably just try to master controlling one drone before you embark on a mission to control a dozen drones.
The example code below shows how to add a drone to the collection. Even if you are using just one drone, you still need to add it to the collection. This is because the "collection" of drones is moved at the same time (though not necessarily in the same directions or speed).
If you recall from the earlier lesson that drew the Colosseum, the math.sin() and math.cos() functions require input as radians. In this example, we will convert the degrees into radians by multiplying by math.pi/180. That's why the above example includes math.pi/180 in the two trig function arguments above.
Combining the Code Examples
To create a single drone in your Roblox world, use the following as your startingScript.
Driving Straight
This drone will only drive straight or turn. It does not have a "backward" function. You can create that one on your own if you want. To get it to move forward, you simply have to tell it the speed you want it to travel.
If you want the drone to travel for a specific distance, you will need to use an additional function: d.encoderValue() to check how far the drone has moved. The combination of setting the speed and monitoring the distance is shown in the example below.
Try getting the drone to move various distances. Check the distances moved. The squares on the baseplate grid can be used to measure distance. Try getting the drone to fly at different speeds as well as distances.
In the above example, the d.resetEncoder() function will reset the encoder of the drone. Since we are only working with one drone at this time, you do not need to specify the drone index for this function. But, if you have created 10 drones and you want to reset the encoder for just drone #6, you would use the following: d.resetEncoder(6) to specify that you want the encoder for drone #6 to be reset. If you don't specify a drone index, the computer will use the default index value (which is 1 for drone #1).
If you examine this function in the drones module, you will see the following:
As you can see from this code, the targetDroneIndex will be the default value of 1 unless an argument was passed. If an argument was passed, then the targetDroneIndex will be whatever value was passed.
The d.encoderValue() is a function that returns the current value of the encoder. Each drone has an "encoder" which keeps track of how far the drone has traveled since the last "reset".
The d.stopMoving() function will stop the drone. If you have multiple drones, you can pass the drone index as an argument for this function. If no argument is specified, then the default drone will be stopped. The default drone is drone #1.
Accuracy in Distance Traveled
Did you notice that the drone travels farther than expected when traveling faster. This is because there is a lag in processing. It takes a few hundred milliseconds to process each action. Therefore, if you are traveling very fast, the command to stop the drone will not be completed exactly where you think it should be completed. The best way to deal with this is to slow the drone down as it gets nearer to the target value.
Write an algorithm that will slow the drone down when getting near to the criteria you are using to exit the while loop. For example:
Now add a brick wall to the startingScript and see how close you can get the drone to the wall without touching it. See example below.
Currently the drone will pass through the wall if you want. I have not been able to get the drone to crash into the wall. Nor have I been able to get the .Touched:Connect(function()) to work with the interaction between drone and wall. Sorry.
I'm still trying to figure this out.
Turning
One function will make the drone turn: d.rotateBy(). This function sets the speed of the turning. The speed of the turning is passed as a number (or numeric value) into the function. For example, a larger number will make the robot turn faster than a smaller number. The basic usage of the function is shown below. Please note that "n" in the example below will need to be replaced by a number.
Positive and Negative Values for Turning
Try entering positive values and negative values. What difference does the sign of the number make?
Asynchronous
Both the d.moveForward() and the d.rotateBy() are asynchronous functions which means that the program flows immediately to the next statement without waiting for the movement of the robot to commence or cease.
Because they are processed asynchronously if you have two d.rotateBy() functions next to each other in the program, only the second one will be executed because the value used for the second statement will overwrite the value of the first statement.
As with the previous example of driving straight, you can use the d.stopMoving() function to get the drone to stop moving.
What do you think will happen in the example code below? Remember, the d.moveForward() and the d.rotateBy() function are processed asynchronously.
Try this example code above. What does the drone do? Why?
What should we place after the d.rotateBy() to get the drone to rotate?
Sleeping for a specified amount of time will get the drone to turn. But how can we get it to turn a specific number of degrees?
There are several ways to do this. For example, you could reset the gyroSensor using d.resetGyroSensor() and then enter a while loop checking if the d.gyroSensorValue() has exceeded some criteria.
Today, we will be exploring a method of turning that uses vectors. Our goal will be to tell the drone to turn itself toward a vector that we specify. The drone will decide for itself whether it needs to turn one direction or the other to make the shortest turn necessary to achieve its goal.
For this exercise, we will create a function called: turnTowardVector(). The purpose of this function will be to give the drone a goal and allow the drone to determine the direction and the speed that it needs to turn in order to move toward the goal.
Creating this function will take a few steps which will be outlined in the next examples.
This is the beginning of the steps to create the function. It doesn't do much at this point. We have created a comment to describe the function and created the function definition called: turnTowardVector() which receives a single number passed as the "target" vector (labeled: v) in the example.
Notice that a local variable g is assigned the value of d.vectorValue(). This is the vector that the drone is currently pointed in.
If you remember from earlier in this lesson, the Avatar has a compass which can be displayed using: d.showingCompass(true). The compass shows the vector values for different directions. As the Avatar turns around, you will see the different vector values which range from 0 to 360. The drone has a similar "built-in" compass that returns the same values. The drone's vector value (i.e., the vector that the drone is point towards) is returned with the function d.vectorValue().
So now we know the vector that we want the drone to turn toward (v) and the vector that the drone is currently pointing toward (g). Eventually we will be calculating the difference between these two vectors. However, before we do that, we need to get the drone to figure out which direction is the shortest. Consider the example below:
If the drone is currently pointing to the vector 90-degrees and we want to turn it toward the vector 60-degrees, we will need to turn the drone clockwise just 30 degrees. Or, we could turn the drone counter-clockwise 330 degrees. Obviously it would be better to just turn the 30 degrees.
What if the drone was pointed toward the 60-degree vector and we wanted to turn it toward the 90-degree vector? What direction should the drone turn and how much?
Both of these vectors are in the same quadrant of the compass.
But what if the vectors appear in different quadrants? For example, what if the drone is pointing toward the 10-degree vector and we want the drone to rotate toward the 350-degree vector?
The drone needs to figure out whether turning toward the right or turning toward the left is the shortest distance.
To determine the shortest distance we will calculate the absolute value of the difference between the two vectors. This will be done using: math.abs(v - g)
See example below:
If you look at the example here, you will see two vectors: 20-degrees and 160-degrees. The absolute value of their difference will not include the zero point (shaded in orange). The other area is 360 - the first area. This second area does include the zero point (shaded in blue).
At this point, the drone knows the size of the two areas. In this example, one of the areas is 140 (which is abs(20-160)) and the other area is 220 (which is 360-140). The drone now knows which of these is the shorter distance between the vectors.
The function will test this in an if statement:
As an exercise in calculating these values.
Use the compass to determine which distance is shorter (with or without the zero point).