Wumpus for PicoSystem v0.0.1 Released

The first function release my Wumpus for Picosystem game is available now. It’s a variant of the classic Hunt the Wumpus game played on a grid with the display and controls designed for the Pimoroni PicoSystem. The GitHub release contains both the source code and the compiled binary UF2 file. While this isn’t yet what I’d consider a fully playable game, there are enough pieces implemented that it may benefit others looking for examples or inspiration.

The key functionality implemented is:

  • Movement – the player can navigate a 10 x 10 grid using the directional pad.
  • Shooting – the player can
    • Switch between movement and shooting modes using any of the X, Y, A, B buttons.
    • Shoot an arrow using the directional pad when in shooting mode.
  • Bats – two caves contain bats which will randomly relocate the player.
  • Pits – two caves contain pits, which will end the game if the player enters those caves.
  • Wumpus – one cave contains the Wumpus, which will end the game if the player enters that cave.
  • Animations – certain activities are animated:Movement between caves
    • Shooting arrows
    • Falling into a pit
    • Being carried by a bat
    • Being eaten by a Wumpus

The key pieces of infrastructure implemented are:

  • States – the game is implemented as a finite state machine (E.G. FELL_IN_PIT_STATE, SHOOTING_STATE)
  • Custom Sprites – custom spritesheet converted using sprite-converter-for-picosystem
  • Win/Lose – the game does handle the notion of being over and restarting

Standard

Hello World for PicoSystem

Having gotten to the point of compiling the snake example in my previous post, it is time to move on to the hello world example in the guide on Pimoroni. The only initial change I made was naming my project hello_world instead of ourproject. After setting up the example code, I found I had some warnings and an error when trying to run cmake.

PicoSystem running Hello World

The first warning:

  No project() command is present.  The top-level CMakeLists.txt file must
  contain a literal, direct call to the project() command.  Add a line of
  code such as

    project(ProjectName)

  near the top of the file, but after cmake_minimum_required().

  CMake is pretending there is a "project(Project)" command on the first
  line.

I addressed this by adding the following line (based on looking at the PicoSystem SDK CMakeLists.txt file):

project(hello_world C CXX ASM)

The second warning:

CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 3.16)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".

I addressed this by adding the following line (again, based on looking at the PicoSystem SDK CMakeLists.txt file):

cmake_minimum_required(VERSION 3.12)

Finally, the error:

CMake Error at CMakeLists.txt:14 (pico_add_extra_outputs):
  Unknown CMake command "pico_add_extra_outputs".


-- Configuring incomplete, errors occurred!

I addressed this by doing three things. First, I copied pico-sdk/external/pico_sdk_import.cmake to my project directory hello_world. Second, I added these lines to my CMakeLists.txt file:

# Pull in PICO SDK (must be before project)
include(pico_sdk_import.cmake)

# ...

find_package(PICOSYSTEM REQUIRED)

Finally, I used the following cmake command:

cmake -DPICOSYSTEM_DIR:PATH=~/picosystem ..

This got me to a point where I can run cmake without warnings or errors; however, running make does result in errors:

/vagrant/hello_world/hello_world.cpp: In function 'void draw()':
/vagrant/hello_world/hello_world.cpp:12:3: error: 'pen' was not declared in this scope; did you mean 'picosystem::pen'?
   12 |   pen(0, 0, 0);
      |   ^~~
      |   picosystem::pen
In file included from /vagrant/hello_world/hello_world.cpp:1:
/home/vagrant/picosystem/libraries/picosystem.hpp:49:15: note: 'picosystem::pen' declared here
   49 |   void        pen(color_t p);
      |               ^~~
/vagrant/hello_world/hello_world.cpp:13:3: error: 'clear' was not declared in this scope; did you mean 'picosystem::clear'?
   13 |   clear();
      |   ^~~~~
      |   picosystem::clear
In file included from /vagrant/hello_world/hello_world.cpp:1:
/home/vagrant/picosystem/libraries/picosystem.hpp:57:15: note: 'picosystem::clear' declared here
   57 |   void        clear();
      |               ^~~~~
/vagrant/hello_world/hello_world.cpp:16:3: error: 'text' was not declared in this scope; did you mean 'picosystem::text'?
   16 |   text("Hello, world!", 0, 0);
      |   ^~~~
      |   picosystem::text
In file included from /vagrant/hello_world/hello_world.cpp:1:
/home/vagrant/picosystem/libraries/picosystem.hpp:78:15: note: 'picosystem::text' declared here
   78 |   void        text(const std::string &t);
      |               ^~~~
make[2]: *** [CMakeFiles/hello_world.dir/build.make:63: CMakeFiles/hello_world.dir/hello_world.cpp.obj] Error 1
make[1]: *** [CMakeFiles/Makefile2:1544: CMakeFiles/hello_world.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

I addressed this by adding the following to hello_world.cpp (based on snake.cpp):

using namespace picosystem;

Which got to the next error:

/usr/lib/gcc/arm-none-eabi/9.2.1/../../../arm-none-eabi/bin/ld: CMakeFiles/hello_world.dir/home/vagrant/picosystem/libraries/picosystem.cpp.obj: in function `main':
picosystem.cpp:(.text.startup.main+0xf8): undefined reference to `update(unsigned long)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/hello_world.dir/build.make:852: hello_world.elf] Error 1
make[1]: *** [CMakeFiles/Makefile2:1544: CMakeFiles/hello_world.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Which I addressed by changing the signature of the update method like so:

void update(uint32_t tick) {
}

At this point, I was able to compile and produce a uf2 file. I’m including the current working version of my files below in case they are useful to others:

CMakeLists.txt

cmake_minimum_required(VERSION 3.12)

# Pull in PICO SDK (must be before project)
include(pico_sdk_import.cmake)

project(hello_world C CXX ASM)

find_package(PICOSYSTEM REQUIRED)

add_definitions(-DPIXEL_DOUBLE)

add_executable(
  hello_world
  hello_world.cpp
)

target_link_libraries(hello_world picosystem)

pico_add_extra_outputs(hello_world)

hello_world.cpp:

#include "picosystem.hpp"

using namespace picosystem;

void init() {

}

void update(uint32_t tick) {

}

void draw() {
  pen(0, 0, 0);
  clear();

  pen(15, 15, 15);
  text("Hello, world!", 0, 0);
}
Standard

Compiling for the PicoSystem

I recently purchased a PicoSystem by Pimoroni with the intention of immediately diving in and programming a game; but, I have to admit I got distracted by how much fun Super Square Bros. is to play right out of the box. The overall system feels great as a small portable in the style of the 80s portable LCD based game systems. I’m noticing that the form factor of the system is a bit small for me from a purely functional perspective; but, again, I really like the overall aesthetic and the case is absolutely stellar.

Snake example running on the PicoSystem

As much fun as I’m having playing the shipped game, I decided the weekend was definitely the time to get a small hello world up and running. I’m using Vagrant in order to keep my dev environment consistent and source controlled. Starting from the guide on Pimoroni, I ran into this issue:

CMake Error at examples/snake/CMakeLists.txt:10 (find_package):
  By not providing "FindPICOSYSTEM.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "PICOSYSTEM", but CMake did not find one.

  Could not find a package configuration file provided by "PICOSYSTEM" with
  any of the following names:

    PICOSYSTEMConfig.cmake
    picosystem-config.cmake

  Add the installation prefix of "PICOSYSTEM" to CMAKE_PREFIX_PATH or set
  "PICOSYSTEM_DIR" to a directory containing one of the above files.  If
  "PICOSYSTEM" provides a separate development package or SDK, be sure it has
  been installed.


-- Configuring incomplete, errors occurred!

Which has a workaround listed in issue 4 on the PicoSystem SDK project of providing the path to the PicoSystem SDK via PICOSYSTEM_DIR like so:

git clone https://github.com/pimoroni/picosystem.git ~/picosystem
mkdir ~/picosystem/build
cd picosystem/build
cmake -DPICOSYSTEM_DIR:PATH=~/picosystem ..
make

The next error I hit was:

    default: CMake Error at CMakeLists.txt:2 (project):
    default:   No CMAKE_CXX_COMPILER could be found.
    default: 
    default:   Tell CMake where to find the compiler by setting either the environment
    default:   variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path
    default:   to the compiler, or to the compiler name if it is in the PATH.
    default: 
    default: -- Configuring incomplete, errors occurred!

This was addressed by revisiting the initial package installs and adding build-essential like so:

    apt-get -y install build-essential \
                       cmake \
                       gcc-arm-none-eabi \
                       libnewlib-arm-none-eabi \
                       libstdc++-arm-none-eabi-newlib

At this point, the snake example built and I was able to transfer it to my PicoSystem in DFU mode. I’m including the current working version of my Vagrantfile below in case it is useful to others:

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get upgrade -y

    # pico requirements
    apt-get -y install build-essential \
                       cmake \
                       gcc-arm-none-eabi \
                       libnewlib-arm-none-eabi \
                       libstdc++-arm-none-eabi-newlib
  SHELL

  config.vm.provision "shell", privileged: false, env: {"PICO_SDK_PATH" => "~vagrant/pico-sdk"}, inline: <<-SHELL
    # pico sdk
    git clone https://github.com/raspberrypi/pico-sdk.git ~/pico-sdk
    echo 'export PICO_SDK_PATH="~vagrant/pico-sdk"' >> ~/.bashrc
    cd ~/pico-sdk && \
      git submodule update --init

    # pico system
    git clone https://github.com/pimoroni/picosystem.git ~/picosystem
    mkdir ~/picosystem/build

    cd ~/picosystem/build && \
      cmake -DPICOSYSTEM_DIR:PATH=~/picosystem .. && \
      make

  SHELL
end
Standard

Generating Towns for Townscaper in Processing

I’ve been playing Oskar Stålberg’s Townscaper recently and enjoying seeing how the algorithms react to changes. While looking for information on how garden paths are calculated, I stumbled across Chris Love’s article on the Townscaper file format. Using that as a starting point, I decided to try building up town maps in processing using Perlin noise to determine height, color, and distance above waterline.

My first attempt iterated the map while incrementing a 1D vector in Perlin noise space to determine these attributes. This gave a nice wavy pattern; but, wasn’t quite what I was trying for.

Continue reading
Standard