Changes to Kaleidoscope
Since the prior post, we added an option for the player to see instructions when Kaleidoscope starts as shown in the screenshot below.
Button B (cancel) causes Kaleidoscope to proceed without instructions. Button A causes Kaleidoscope to present a sequence of instructions. With each Button A press, advances to the next instruction until at the final message, Kaleidoscope starts cycling through patterns.
Overall Code Flow
The three main sections of Kaleidoscope are shown in the screenshot below. The initialization code is to the left. The main loop is in the middle and the player interface code is to the right.
Each of the above program sections will be explained in this post. The functions shown in the screenshot above are those necessary to understand the big-picture operation of the program. Additional functions are used by the code and will be described towards the end of this post.
The On Start block does the initialization that is done only once in each run of the Kaleidoscope. In addition to setting maximum and minimum values of parameters settable by a player, it calls the function initialize and make_new_field which together set up a new rectangle for patterns. These two functions are also called when a player changes Kaleidoscope settings. The variable B_paused is used to assure that no other code runs at the same time On Start is running.
The make_new_field function (middle above) is called by the On Start bock. It is also called at certain other times (e.g., when the player changes settings). It is comprised of the following four steps:
- set_sprites_and_background — does needed calculations to determine width and height then defines the background sprite. The default width and height are set in On Start, but may also be set by the player and when random size fields are generated.
- set_origin — sets the pattern origin at the center of the background sprite. Patterns are drawn from the origin to a point on the background sprite perimeter. The origin can be changed by the player using the arrow buttons.
- init_perimeter_arrays — defines the two arrays Ax and Ay to hold the x and y points of all pixels on the perimeter of a background (field).
- set_output_sprites — creates the sprites that are used for messages to the player.
Main Loop Overview
The main loop is a Forever block that runs over and over again. Depending on the player’s use of A and B buttons, it may pause before continuing. While paused, the field dimensions might change either because the player changes settings or the random field feature is in use.
The Forever loop performs the following steps:
- Initializes by setting the number of palette colors to 2 and the palette to empty.
- A palette is generated for each number of colors starting at 2. Additional colors are added up to a total of 15 with the restriction that the number must be a factor of the number of points in the perimeter of the pattern field. For each new qualifying number of palette colors, a randomly chosen color will be added with the restriction that no color will be the same as its neighbor. From each palette, a pattern generated. The program always pauses after a pattern is drawn; otherwise, the patterns (depending on the computer) might go by so fast they are a blur. The pause wait time can be changed by the player within limits.
- If the player has previously pressed the A button, the program will pause after the pattern is drawn waiting for the player to clear the pause by pressing the B button.
- After the While loop, if the player has selected the random field option, the program randomly generates new field dimensions and makes a new field.
The wait_until_not_paused function loops and pauses until the variable b_paused is set to false, which the player does by quick pressing the B button. This feature is useful if the player want to view patterns for a longer time, perhaps to select those for saving (screenshot).
The do_pattern function is the heart of Kaleidoscope. It generates a pattern on the background sprite image by looping through all the points in the perimeter arrays Ax and Ay. It also cycles sequentially through the palette colors. Patterns are drawn one line at a time from the origin to a perimeter point. The first line drawn is to the upper left corner. The lines advance to the right around to the line before the beginning line. The screenshot below shows a pattern in the process of being drawn.
Player Input Overview
The prior post Kaleidoscope in MakeCode Arcade describes the use of Arcade’s buttons. The code that processing button presses is sown below.
Arrow keys are used to move pattern origin, for example, as shown in the pattern below with the origin moved towards the upper left corner.
Origin and Sprites
A 1×1 pixel sprite is used for the origin. Lines of the pattern are drawn from the origin to a point on the perimeter of the background sprite. The sprite can be moved by the arrow buttons. The function set_sprites_and_background creates a new sprite for the background depeding on the width and height variables. Any previously created sprite are first destroyed.
Initialize Perimeter Arrays
Perimeter arrays Ax and Ay are used to store all the points of the perimeter of the background sprite. A point consists of one element from the array Ax, which is the x coordinate of the point, and the corresponding y coordinate in Ay. These are used in drawing lines from the Origin sprite to the perimeter. This array is used to make cycling through the points smoother than if logic were used to determine the line end points during drawing a pattern. Once initialized for a field size, these arrays never change.
Get Color and New Palette
The function get_this_color sets the variable Color after selecting it from the array Palette. When the last color is used, it starts over at the beginnin. This is done by using remainder. The variable this_line is the index into the perimeter arrays for the end point of the line being drawn.
The function set_next_palette (above) adds a color to the palette array. The number of colors in the palette is set in the Forever block above. This routine assures that no tow adjacent colors are the same.
Palette colors are displayed at the bottom of each pattern as shown here.
The palette of a pattern is displayed at the center bottom of the pattern. The colors are displayed on a checkboard background. When Kaleidoscope is paused, the A button will eliminate the palette display.
The function do_checker takes three arguments: the sprite on which to create the checker pattern and the two colors to be used in the checker pattern. This function can be used to color a checkerboard of any size with any two colors. We made it a nice little function with parameters so that we can easily use it in another program.
Random Field Dimensions Functions
One of the settings options that can be elected by a player is the random width and height option. With this option, for a randomly selected width and height, a pattern will be generated after which a new width and height will be randomly chosen. Width and height must be odd numbers so that there can be a pixel that is the exact center of the pattern.
A pattern with a randomly generated width and height is shown below.
Player Input Main Function
When the player presses and holds Button A, the player is asked a series of questions that will change Kaleidoscope’s settings, for example, width of pattern.
Player Input Support Functions
Get Width and Height
These two functions get the width and height of the pattern from the player. They set the appropriate default values if the player input is invalid.
Get Wait Between Patterns
This function gets a number from the player and tests that it is within proper limits. If it is not, a message is presented to the player and the default value is used.
Get Odd Integer and Get Integer
This function returns an odd integer as N_return, subtracting 1 if necessary to make the number odd.
Get N within Limits
This function has three parameters: this_s (the text of a number), a minimum value and a maximum value. It returns N_return, the number, and b_is_OK depending on whether this_s is a number and within the two limits.
If the function is_decimal sets B_N_OK, then the parameter “text” is a valid decimal number consisting of digits 0-9 or space. It uses a MakeCode Split block to break the parameter into an array of either 1 or 2 elements. It calls is_digits for each element to verify that it contains only digits 0-9 or spaces.
We have found the sprite say block is handy for displaying messages to the player. We prefer thse, to other methods (e.g., show long text) because this does not require a response from the user. Rather, the message can be displayed for a settable time period, then disappear.
say_msg_default and debug_say_and_wait Functions
The say_and_wait function is called from several places in the functions that enable the player to change settings, e.e., width and height. The parameter “text” is as message concerning limits.
For more general messages, especially those used in debugging, the function debug_say_and_wait is provided. In the published version of Kaleidoscope, this function is not used; however, we found it very useful in debugging so have included it here.
When destroying a sprite, one must be sure it exists; otherwise, problem. This function was created because there are several places in the program where sprites must be destroyed in situations where they may not have yet been created; for example, when the first background sprite is created.
The Instructions functions is call once if the player presses Button A on startup when asked “instructions?’