HOW DO I DELETE THIS
NOTICE: I'm not doing this anymore. I'd rather write smaller tutorials rather than big catch-all guides like this one. I don't even know where I;m going with this. Do whatever you want with this, I don't care. ~slacker'
The Graphic Screen. It draws lines, points, and circles, but is it that useful?
That's what this tutorial is about.
In short, yes, it is that useful, but how do we make animations, special effects, or anything that isn't a static line? Let's find out.
In the Beginning...Edit
It is important to note the following points:
- There is a lot of math in here, but prior knowledge to things like sine isn't necessary, because you will mostly be copying down/memorizing the equations I force-feed you anyway.
- If you don't like arrays or loops, get used to them. I use them A LOT.
- You will be doing things my way for most of the tutorial, but this code can be adapted into virtually anything given enough effort.
..and here's an overview of what we will be covering:
- Drawing shapes through a set of n points
- Compacting code and data
- 2D geometry concepts
The commands GBOX, GFILL, GPAINT, and GCIRCLE won't be mentioned in this tutorial (at least not in Vol. 1), so pretty much everything we do is made up of lines.
So, without further ado...
I: Coordinates, and their purposeEdit
When you need to draw some shape, storing every separate coordinate value as it's own variable is a bad idea. It makes code longer, messier, and harder to deal with. How do we remedy this problems? Arrays of course.
The array's importance to this tutorialEdit
In this tutorial, arrays are aguably the most important thing. Instead of using some messy, loosely-put-together set of variables to store a shape's coordinates, putting them all in an array makes them neat and easy to deal with.
Arrays should be set up like this;
|0||x coord||y coord||z coord|
|n||x coord||y coord||z coord|
Assuming an array A(n,3) (n being the total amount of points), the rows are points, and the columns are the coordinates of said points.
NOTE: z-coords were included as a just-because. They are beyond the scope of this tutorial and will not be used.
Use of arraysEdit
Sound confusing? Yes? Good, because I was just about to put it into code form and stop confusing you.
Using the above table example, arrays should be defined as so:
and they should be written to and read from like so:
'Writing to A(row,column)=variable 'Reading from variable=A(row,column)
The following array demonstrates a shape of 4 points (a square in this case) with x and y coords (no z coords):
DIM SQUARE(4,2) 'Array definition 'Definition of first point SQUARE(0,0)=0 'Definition of x coord SQUARE(0,1)=0 'Definition of y coord 'Rinse and repeat SQUARE(1,0)=4 SQUARE(1,1)=0 SQUARE(2,0)=4 SQUARE(2,1)=4 SQUARE(3,0)=0 SQUARE(3,1)=4
In this example, A(0,column) corresponds to the first point, and A(row,0) is the point's x coord (replace 0 with 1 for the y coord).
These points correspond to the square like so:
When defining points, be sure they are defined in the order you want them to be drawn, or you will have an ugly suprise when you draw them...in the next section.
II: Actually Drawing Something FinallyEdit
...the game the musical the movie the book.
So you put your points into arrays? That's nice. But they're useless without some drawing routines. We are going to jump right in, so hold on to your seats.
These drawing routines will be used to draw pretty much everything discussed here, so remember them well.
Drawing Points in a LoopEdit
The big problem with spaghetti languages like SmileBASIC is that much of the routines are hard-coded and non-expandable. That won't be a problem for us. We just need a FOR loop and our point array.
The FOR loop is very simple:
- Draw the point at A(I,0),A(I,1)
We will be using that SQUARE array in the previous section for this example.
FOR I=0 TO MP GPSET SQUARE(I,0),SQUARE(I,1),15 NEXT
This routine plots every point in the array in order. You can use an array of any size, just define the array size in the variable MP (remember: zero-order counting. 4 points would be MP=3, ect).
Drawing Points into a (2D) PolygonEdit
So you think "Huh, I can see the points now. If only they were a shape". Well, looks like I read your mind. Here, we will modify the routine to draw lines through all of the points.
The modification is as simple as changing one line and adding two others.
FOR I=0 TO MP IA=I+1 IF IA>MP THEN IA=0 GLINE SQUARE(I,0),SQUARE(I,1),SQUARE(IA,0),SQUARE(IA,1),15 NEXT
Let me walk you through this routine, step by step.
First, a variable IA is defined as I+1, I being the variable used in our FOR loop. The value of I represents the first point in the line, and IA represents the second point of the line: the point right after point I.
Our IF statement is used to set the value of IA to 0 if it becomes greater than MP. This is done for 2 reasons:
- To close off the shape and form a polygon when the last point is reached
- To prevent the loop from accessing a point that doesn't exist, which would result in a range error and a crash
The GLINE command actually draws the lines. Let's imagine our array as a table again:
On the loop's first run, the GLINE command reads the coordinates for points 0 and 1, and draws a line through them. The second run is through points 1 and 2. The third run is through points 2 and 3. The fourth and final run is through points 3 and 0, thanks to our IF statement. This results in a closed square polygon (think 2D). Like before, any set of points can be used with this routine, just be sure to set MP accordingly.
III: Transformations - Doing Cool Drawing StuffEdit
NOTICE: Section contains a lot of math-related topics So, now that we have drawn up a shape from an array of points, it's time that we make that shape do something.
There are many ways to do this, however, some ways are significantly easier.
Translations of PointsEdit
The first thing we should learn to do is translate points, because it's easy. Let's say that point A is on a grid at the coordinates (1,8). Now, imagine that point A slides from (1,8) to the coordinates (3,12). This is a translation; when a point moves from one place to another.
How do we put this into code? Well, there are many methods, and most of them will be covered.
What is a vector? How do I use them? Why am I asking all these questions?
A vector is a quantity of two or more numbers having magnitude and direction, expressed as a tuple.
In simpler terms, vectors are used to express some kind of change, and by how much. Tuples are essentially just sets of numbers that all relate to one another. You've probably seen them before, like an RGB color tuple: (255,0,127). So, how do we use vectors to represent translation? Using our previous example, point A moved from (1,8) to (3,12) on the grid. To express this as a vector, we simply have to subtract the starting coordinates from the end coordinates, like so:
(3,12) - (1,8) ========== <2,4>
Notice that the vector is placed inside angle brackets instead of parentheses. This is done to differentiate between vectors and other tuples (but you won't need to know that). This vector is read as "Right 2 units on the x-axis, up 4 units on the y-axis". How do we know up from down, left from right? Well, moving down on the y-axis would be a negative, while up is positive, and moving left on the x-axis would be a negative, while right is positive.
At least it would be, in a perfect world.
You see, computer displays invert the y-axis. Y-values increas as you go down, not up. So, we just need to flip negatives around. Up is negative, down is positive. Simple.
Can we code now?
Yes, yes we can.
So how do we represent vectors in code? Again, multiple ways. But we'll ignore those and just focus on one. We'll store a vector in 2 variables, VX and VY. Let's use our first example again.
DIM PA(1,2) DIM PT(1,2) PA(0,0)=1 PA(0,1)=8 VX=2 VY=4 MP=0
Per usual, we store our point in an array (though not really necessary because it's only one point), and assign variables VX and VY in accordance to the vector in our example. We will use the array PT(1,2) to store our translated point.MP is the variable that remembers the amount of points, as mentioned earlier. Next, we need code to actually move our points.
Now, we set up another loop, this time altering the points instead of drawing them. Here it is:
FOR I=0 TO MP PT(I,0)=PA(I,0)+VX PT(I,1)=PA(I,1)+VY NEXT
This array is very simple. All it does is add the contents of the vector to our point and store the result in array PT.
But why can't we just store the result in PA?
More often than not in computer graphics, you need to use the same data multiple times. We store the result in a separate place in order to keep the old data for later use. Next, we just adapt our point-drawing code to this example:
FOR I=0 TO MP GPSET PT(I,0),PT(I,1),15 NEXT
Running this code will just show up as a dot. That's OK, because that's all it does.
As a whole program, the code should look like this:
DIM PA(1,2) DIM PT(1,2) PA(0,0)=1 PA(0,1)=8 VX=2 VY=4 MP=0 FOR I=0 TO MP PT(I,0)=PA(I,0)+VX PT(I,1)=PA(I,1)+VY NEXT FOR I=0 TO MP GPSET PT(I,0),PT(I,1),15 NEXT
Congrats, you translated a point! It doesn't seem very exciting now, but it will when you try these self-check objectives!
-Make the point move across the screen.
-Translate multiple points, or even shapes
Rotation of PointsEdit
This next transformation is the big, bad rotation. It's cool, it's math-y, and it's even cooler when it's animated.