Skip to content

Creating a demo

At its core, using the SSS is meant to be a learning experience. Anyone who wants to know more about computer engineering and the Internet of Things can go through the demos and learn quite a bit by experiencing the end result. However, the SSS is also designed to be an educational tool for designers. Anyone with the desire can make a demo themselves without needing to understand the entire system! In this article, we will discuss the template for making one of these demos by looking at the template’s basic structure and its required subcomponents.

Template Format

All of the demos for the SSS are located in the demos folder in the seven_segment_sign repo that you clone from GitHub. If you take a look at the contents of demos, you’ll notice that each demo has its own folder with a main.py file inside of it:

demos
├── breakout
   ├── high_score.txt
   └── main.py
├── breakout_ai
   └── main.py
├── checkerboard
   └── main.py

.... 

Notice that all of the folder names are lowercase and that all of the programs are named main.py. If you don’t follow this convention, the system won’t see your demo and it will fail to load when you run the program.

But what goes inside of your main.py is what really counts. The following format must be observed for your demo to run correctly. If you want to use this example as a boilerplate to get you started, you can always copy it from demos/template/main.py.

class Template:
    """This is a boilerplate class for creating new demos/games for the SSS platform. It needs to include definitions for the following functions: init, run, stop.
    The init function needs to at least have the things shown below. Frame rate is in frames per second and demo time is in seconds. Demo time should be None if it is a game.
    The run function yields a generator. This generator will be called a specified frame rate, this controls what is being pushed to the screen.
    The stop function is called when the demo/game is being exited by the upper SSS software. It should reset the state for the game"""

    # User input is passed through input_queue
    # Game output is passed through output_queue
    # Screen updates are done through the screen object
    def __init__(self, input_queue, output_queue, screen):
        # Provide the framerate in frames/seconds and the amount of time of the demo in seconds
        self.frame_rate = 10
        self.demo_time = 300  # None for a game

        self.input_queue = input_queue
        self.output_queue = output_queue
        self.screen = screen
        # init demo/game specific variables here

    def run(self):
        # Create generator here
        while True:
            self.screen.draw_text(self.screen.x_width // 2 - 5, self.screen.y_height // 2 - 4, "HELLO THERE", push=True)
            yield

    def stop(self):
        # Reset the state of the demo if needed, else leave blank
        pass

When creating your class object, name sure that the first letter of its name is capitalized. If you have a demo with two words (i.e. breakout_ai) make sure you capitalize the first letter of every word (i.e. Breakout_Ai). Failure to do this will cause your demo to not load or execute properly into the SSS system. You’ll also notice that apart from the normal Python __init__() method for a class, there is also a run() , stop() , and get_input_buff(). Implementing these functions is crucial to making sure that your demo will execute correctly at runtime. An explanation of what each one does is included below.

__init__()

This function allows you to set up some initial values for your demo. For example, if you were creating a game and wanted to include the initial amount of lives or the amount of ammo in a shooter, __init__() is the perfect place to set that up! Apart demo-specific variables that could be initialized, there are also a few SSS specific variables which must also be initialized which will affect how your demo runs and interacts with the rest of the system.

frame_rate

This variable determines how fast your demo runs (i.e how many frames are rendered in a second). If your game is intended to have a buttery experience higher values will be more suited to your needs.

NOTE: setting the frame_rate too high can result in too quick of a game on the simulator or undefined behavior on the actual SSS due to hardware limitations.

demo_time

If you are creating a non-interactive demo (i.e. a shape bouncing around the screen or some other concept that does not require input), you will need to set a demo_time. This value will determine how long your demo will run for when the SSS is in kiosk/screensaver mode (i.e. cycling through demos when no one is actively using it). If you are planning on developing an interactive demo/game, set this value to None.

input_queue

If you are creating a demo which requires active user input, you will need to keep track of the values are are coming in through the input queue. Regardless of what controller is connected to the SSS, the supported inputs are:

Value Description
LEFT_P Left arrow pressed
LEFT_R Left arrow released
RIGHT_P Right arrow pressed
RIGHT_R Right arrow released
UP_P Up arrow pressed
UP_R Up arrow released
DOWN_P Down arrow pressed
DOWN_R Down arrow released
START_P Start button pressed
START_R Start button released
SEL_P Select button pressed
SEL_R Select button released
PRI_P Primary action button pressed
PRI_R Primary action button released
SEC_P Secondary action button pressed
SEC_R Secondary action button released

By setting self.input_queue = input_queue you link the input_queue for your demo to the system’s input buffer. All input information can be retrieved directly through this object or by using the get_input_buff() function as explained below.

NOTE: This object is a Python Queue object. Any functions found here can be used on this object.

output_queue

If your demo needs to communicate information that will not be seen on the screen back to the user (i.e. a score or number of lives), this can be accomplished by using the output_queue. You can link your demo’s output_queue to the system output_queue by using self.output_queue = output_queue. At the current moment there are a limited amount of topics that you can send output through:

Value Description
SCORE Sets the score of a game.
LIVES Keeps track of the amount lives of a player

To send data through one of these channels, you will put the name of the topic and the value you wish to send:

self.output_queue.put("SCORE " + str(self.score))

NOTE: This object is a Python Queue object. Any functions found here can be used on this object.

screen

This object controls what will be drawn on the screen. Any functions as described in this API doc will work on this screen object. The demo screen is connected to the SSS system screen as follows:

self.screen = screen

run()

This function is what causes your actual program to run. Everything inside of this demo will be executed at runtime. Notice that in our boilerplate we surround the contents of this function with a while True loop ending with a yield. This special organization will cause whatever is inside the loop to be repeated until the system indicates that it is time for your demo to stop. By placing a yield keyword at the end of the loop, this converts the function from a blocking function to a non-blocking function (for the purposes of the system). If yield is not provided at the end of a frame rendering, the program will have no way to release control back to the SSS to actually draw anything or process any inputs and outputs that the demo. For a simple example of how a demo works with this non-blocking functionality, take a look at the template demo. For more complex examples, demos such as game_of_life , snake, or breakout which include multiple yields for multiple cases.

stop()

Code in this function will be exited right as soon as your demo is ended by the SSS or user. If you need to reset state or do any sort of cleanup, that code belongs here. If there is nothing fancy like that in your demo, no worries! Just leave a pass and be on your merry way.

Handling Input in Your Demo

Most games on the SSS are pretty simple and are only meant to handle one keypress at a time. However, if you are feeling ambitious and want to keep track of multiple keypresses at a time (i.e. holding up and left to jump diagonally), this function will help you catch that by returning all keypresses waiting in the queue as a list. Below is a snippet from breakout which illustrates this functionality:

# Include this at the top of your demo
from demos.utils import get_all_from_queue

# Put this part in your while True loop 
for keypress in get_all_from_queue(self.input_queue):

    if keypress == "LEFT_P":
        # Some action
        pass
    if keypress == "LEFT_R":
        # Some action
        pass
    if keypress == "RIGHT_P":
        # Some action
        pass
    if keypress == "RIGHT_R":
        # Some action
        pass 

Conclusion

By following the template format, you learn about and are accountable for most of the key components of a demo! If you are still feeling overwhelmed and don’t know where to start in your demo creation journey, take a look at some of the existing ones and try to modify them bit by bit, taking note of what changes you caused. If there are any clarifications that need to be made, please feel free to reach out by opening an issue on the GitHub repo or taking a look at how to get support so we can help you and also update our docs. We’re excited to see what you create!


Last update: August 24, 2023
Created: July 13, 2022