Project 2 – Random Walk Variant Overview
For this project, you are going to implement 2 variations on the previous assignment. Overall the concept will be the same, but instead of individual points/pixels, you will take steps using 2 different kinds of shapes: squares and hexagons.
Description
For this assignment you are going to create a program that looks something like the following:
The layout of this program will have two main parts:
- The UI, which consists of a variety of controls, detailed in the next section
- The viewable area, which will contain the rendered shapes as the algorithm progresses
Example Images
~5000 squares with terrain coloring vs 1200 squares with smaller size and spacing of 1.45
~2300 hexagons with and without stroke and terrain coloring, using the seed value
UI Specifications
The UI for this project is not complicated, but there are a fair number of components that will need implementation. The details for these are described below. The background of the UI is a simple rectangle with a width of 200. You could draw any number of these “panels” anywhere you like within the application’s window to create multiple sections, or groups of tools. Each of those sections could have their own size and location variables if you wanted to be able to customize the interface, but that goes beyond this particular assignment.
- Where the magic happens, the start button. You can change the background color by using the setColorBackground() function.
- A DropdownList object. The following functions will be helpful:
- addItem() – Adds and item to the list
- setItemHeight() – set the height of entries in the list
- setBarHeight() – set the height of the “selected” item on the
top
- getValue() – retrieve the 0-based index of whatever is
selected
- A Slider for the maximum number of steps, with a range of 100 to
50,000. The text above it is a Textlabel. To disable the text on a Slider, you can call getCaptionLabel().setVisible(false), or just pass an empty string to the setCaptionLabel() function.
- A Slider to indicate how many steps to take in a single frame, with a range of 1 to 1,000
- A Slider indicating the size of a single step. This will be represent the length of a square’s side, or the radius of a hexagon. The range of this should be 10 to 30.
- A Slider representing an additional modifier to the length of a step from one position to the next. This is a multiplier ranging from 1.0 to 1.5.
- A Toggle indicating whether or not the walking process should remain bound to the viewable area or not. To access the on/off value of a Toggle object, simply catch the return of the getState() function.
- Another Toggle representing if the drawing process should color the steps to give a rough approximation of terrain elevation, or instead use a fixed color for each space.
- A toggle to indicate whether shapes should be drawn with a stroke outline or not.
- A toggle to indicate whether a specific value should be used to seed the random number generator or not.
- A Textfield to let you specify a seed value. Some helpful functions for this control:
- setInputFilter() – Pass ControlP5.INTEGER to this function to limit input to integers
- getText() – This retrieves the data stored in this control, as a string. In order to use this as a
number, you will have to convert it.
Class Structure
You should create at least 3 classes for this project:
- A class to control the square walk
- A class to handle the hexagonal walk
- An abstract class to serve as the base for both of them
Class Features
On a basic level, your classes should do two things:
Update() – Generate a random number, figure out where to move, and move to that location
Draw() – Draw the specific shape according to the relevant properties: location, size, color, with or without a stroke, etc
Based on the UI controls and program layout, your base class will need to store information regarding the following:
- The maximum number of steps
- The number of steps already taken
- The distance of each step
- The scale for each step, to add borders/padding around each shape
- Whether or not to use color
- Whether or not to use a stroke when drawing a shape
- The boundaries of the viewable area. Normally it would be width and height, but you will need
to take the side panel into account
Color Details
The program approximates the idea of building up elevation depending on how many times a particular location is “visited.” How you do you store each of these visits? You would need to associate a particular location with a count. A HashMap<> is perfectly suited to this scenario. A PVector with the current x and y location serve as a key, with the count stored as the value.
Based on the number of visits, the arbitrarily chosen formula and colors used for this is as follows:
If the number of visits is less than 4, fill with the color 160, 126, 84
If the number of visits is less than 7, fill with the color 143, 170, 64
If the number of visits is less than 10, fill with the color 134, 134, 134
Otherwise, fill a color equal to the number of visits * 20, capping at the maximum value of 255Random Walk – Squares
The square version of this is largely the same as walking with pixels. Generate a random number between 1 and 4, and then move in that direction. The amount of the move will depend on the size of the step, which represents the length of a side of the square, as well as the step scale variable. Be sure to take into account whether the shapes should be constrained to the viewable area or not.
If you want to modify this formula, improve upon it in any way (adding more colors, a finer level of granularity between levels of “elevation”), feel free to do so!
Typically with any sort of grid or arrangement of shapes, we think of those shapes as being centered on some point. The rect() function defaults to drawing the shape from its top-left corner. You can call the rectMode() function to specify that a rectangle should be drawn relative to its CENTER, instead of the top-left corner.
Random Walk – Hexagons
Drawing a hexagon is a bit more complex, as is determining where to move it.
To update it, generate a random number from 1 to 6, and based on that number, move in a particular direction. For this assignment you should draw your hexagons such that they have flat tops, which means your movement would look something like this:
5
6
4
3
0 degrees
2
Why is the 1 different? Because a 0 degree rotation would be straight along the positive X axis, and from there to the first adjacent side is only a 30-degree rotation. From there, it is a 60-degree rotation to the next side, 150 to the next, and so on.
With knowledge of the angle, and the radius, translating that into an X/Y offset is easy using the sin() and cos() functions. There’s a small catch, however! The radius is that of the circle which circumscribes the hexagon. If you were to step by just the radius, you would have overlapping shapes.
Instead… the distance between two regular hexagons set adjacent to one another is: √𝟑 ∗ 𝒓𝒂𝒅𝒊𝒖𝒔. This derives from the relationship between the vertical and horizontal distance between the centers of each hexagon, which form a 30-60-90 triangle. For everything you ever wanted to know about hexagons: https://www.redblobgames.com/grids/hexagons/
Drawing a hexagon can be done using the beginShape(), endShape() and vertex() functions. Take a look at the examples on the Processing website, or in some of the class demos. Like the squares, other details of this shape (the color and stroke) should be stored already and used accordingly.
1: a 30 degree rotation, 60 degrees for each past this
Submissions
Create a .zip file with any code files you created for this project (in Processing they are files with the extension .pde), and name the file LastName.FirstName.Project2.zip. Submit the .zip file on the Canvas page for Project 2.
Where could you take this next?
This could be used as the start of a terrain generator, or a level generator for a video game. The data created could be saved to a file for later use, or fed into another system to further refine the shapes that were created.
Tips
- Use the reference page! Processing has a very thorough reference at https://processing.org/reference/
- Ditto for ControlP5. The reference and example pages are very thorough. Using a new tool or library can initially be a bit overwhelming, but step by step you’ll learn more about it.
- Points are colored by the stroke() function, not the fill() function. Fill() is used for shapes (i.e. something with area).
- Tackle one thing at a time. Even in a small project such as this, breaking it into smaller pieces can help you to make sense of the larger application.
- When rendering things with different properties, it’s helpful to have each thing be self- contained—each thing should set its own rendering properties, to ensure it will still work if something else changed those properties
Grading
Item |
Description |
Maximum Points |
UI |
Components present and functional |
10 |
Squares |
Squares positioned properly according to all size and step scale properties |
10 |
Hexagons |
Hexagons positioned properly according to all size and step scale properties |
20 |
Color |
Buildup of color implemented based on number of “visits” to a particular location |
20 |
Constraints |
Steps are constrained to the drawable area if this option is turned on |
10 |
Code Structure |
Main functionality broken into separate classes: abstract base class, and two derived classes for the square and hexagonal walks |
20 |
Random seed |
Reproduction of particular patterns possible with a specific random seed value |
10 |
Total |
100 |