All chapters
Cookbook · Chapter 1

Getting started

The shape of every sketch, the coordinate system, math helpers, and reacting to the mouse and keyboard.

Umfeld is a C++ environment with a Processing-style API. A program is built from the same three functions you know from Processing — only the language underneath is C++.

The sketch skeleton

settings() configures the window, setup() runs once, draw() runs every frame.

#include "Umfeld.h"

using namespace umfeld;

void settings() {
    size(1024, 768);   // set the window size here, not in setup()
}

void setup() {
    // runs once
}

void draw() {
    background(216);    // clear to light grey each frame
    circle(mouseX, mouseY, 80);
}

Two lines do the bridging: #include "Umfeld.h" pulls in the API, and using namespace umfeld; lets you write circle() instead of umfeld::circle(). Build it with CMake — see Build and run at the end, or the install guide.

Note for Processing users: there is no PDE and no “modes”. You edit .cpp files in any editor (VS Code, CLion, …) and build with CMake. Because this is C++, types are explicit — you write int, float, and const where a sketch language would let you leave them out.

The coordinate system

The origin (0, 0) is the top-left corner. X grows right, Y grows down. width and height hold the window size, so the centre is always (width / 2, height / 2).

line(0, 0, width, height);          // corner to corner
circle(width / 2, height / 2, 100); // centred

Printing to the console

println() and console() both take several comma-separated values:

println("frame:", frameCount, " mouse:", mouseX, mouseY);

Math functions

The Processing math helpers are all here:

float m = map(mouseX, 0, width, 0, 100);  // remap one range to another
float c = constrain(m, 0, 50);            // clamp into [0, 50]
float r = random(width);                  // 0 .. width
float r2 = random(-1, 1);                 // a range
float d = dist(x1, y1, x2, y2);           // distance
float a = atan2(dy, dx);                  // angle of a vector
float n = noise(xoff);                    // Perlin noise (1D / 2D / 3D)

Angles are radians. Convert with radians() / degrees(), and reach for the constants PI, HALF_PI, QUARTER_PI, TWO_PI.

Responding to the mouse

mouseX / mouseY track the cursor; isMousePressed is true while a button is held. Override the callbacks for one-off events — the names match Processing:

void mousePressed()  { /* a button went down */ }
void mouseReleased() { /* came back up        */ }
void mouseDragged()  { /* moved while pressed  */ }

Responding to the keyboard

void keyPressed() {
    println("pressed:", (char) key);
    if (key == ' ') saveFrame();
    if (key == '1') background(255);
}

void keyReleased() {
    println("released:", (char) key);
}

The global key holds the character; isKeyPressed is true while any key is down. To stop the OS auto-repeating a held key, set this in settings():

void settings() {
    size(1024, 768);
    config.ignore_key_repeat(true);
}

Build and run

Each sketch is a folder with one application.cpp and a CMakeLists.txt. The only line you change is the path to the Umfeld library:

cmake_minimum_required(VERSION 3.12)
project(my_sketch)                                              # your app name
set(UMFELD_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../umfeld")  # path to the umfeld library

# --------- no need to change anything below this line ---------
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include_directories(".")
file(GLOB SOURCE_FILES "*.cpp")
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
add_subdirectory(${UMFELD_PATH} ${CMAKE_BINARY_DIR}/umfeld-lib-${PROJECT_NAME})
add_umfeld_libs()
cmake -B build       # configure (once, or after editing CMakeLists.txt)
cmake --build build  # compile
./build/my_sketch    # run