In our last project, we created a basic Minecraft game controller and wrote the code to allow us to map the buttons and accelerometer to specific functionality related to Steve, our Minecraft character.

In this project, we will implement the same functionality as we did previously, but we will revise the code to use a Dictionary to map the button inputs to functionality, making the program much more simple and straightforward. This will be the foundation of our future Minecraft programs.

Our goal with this project is to greatly simplify the button controls we implemented in our Minecraft Controller 1 project. This will make future controller projects easier to write and will also make the code easier to read and debug.

As a reminder, here is the code from the previous project that we're going to focus on changing:

Specifically, in this project, we're going to make two major changes to the code above:

  1. We will use a Dictionary to define the button controls and use a for loop to reduce the large number of if/else loops

  2. We will greatly simplify the remaining if/else statement in our code

Implement a Dictionary and a for loop

The first thing we're going to do to simplify our code is to use a Python Dictionary to enumerate (create a list of) our button controls.

If you recall, a Dictionary maps a set of keys to their values. In this case, the set of keys will be the buttons and their respective GPIOs, and the values will be the specific control commands for each:

Now that we have our button control definitions in a Dictionary, we can replace the large number of if/else statements (one set for each button) with a for loop and single set of if/else statements:

Simplify the if/else statement

In our code above, we use a four-line if-else statement to check each controller button (to see if it was being pressed) each time through the game loop:

While this works just fine, using four lines of code to complete this task is more cumbersome than necessary.

NOTE:You may notice that in the Minecraft Controller 1 project and in the above step, we did not include release=False in the first action statement. That's because this is the default assumption of the function, and therefore it's not needed. We include it above, as it will make the next part of this discussion more understandable.

As you can see, the first line of the code above tests whether the button is being pressed. If so, the second line of code takes specific action; if not, the third and fourth lines of code stop the specific action.

Those four lines of code can actually be condensed into the following single line of code, which does the exact same thing:

WHY DOES IT WORK?

If it's not clear why the single line of code above is equivalent to the original four lines of code, let's break it down in a little more detail.

You'll notice that the original four lines of code essentially accomplish the following two things:

  • If button.is_pressed()=True, then action(release=False)

  • If button.is_pressed()=False, then action(release=True)

In other words, the result of button.is_pressed() is changed to the opposite and inserted into the action(release=...) statement.

The not keyword is referred to as a "boolean operator," and it is used to flip False to True (0 to 1) and True to False (1 to 0). The statement:

action(release=(not button.is_pressed()))

simply takes the result of button.is_pressed(), flips it and inserts the result into the release=... statement.

We can now replace the if/else statement in our for with the single statement:

Full Code

Here is what the full code for this project should look like. The functionality is equivalent to the functionality in the Minecraft Controller 1 project, but the code is much more compact and readable:

  1. Add another button (or remap an existing button) to allow Steve to crouch at the press of the button. Notice how easy this is to add now compared to in the project.

  2. Invert your controller — make it look down when you tilt up and up when you tilt down.