Skip to main content

A minimalist creative-coding toolkit for Python (homage to Processing/p5).

Project description

kanvas

A minimalist creative-coding toolkit for Python, inspired by Processing and p5.js.

Overview

kanvas provides a simple, educational framework for creative coding in Python. It captures the essence of Processing's setup() and draw() paradigm while maintaining a clean, readable codebase that's perfect for learning how creative coding frameworks work under the hood.

Key Features:

  • Simple setup/draw loop similar to Processing
  • Built on pygame for reliable cross-platform support
  • Clean separation of concerns (model-view-controller architecture)
  • Lightweight and hackable (~200 lines of core code)
  • Beginner-friendly API with educational focus

Installation

pip install kanvas

Requirements

  • Python 3.9 or higher
  • pygame 2.0+
  • numpy 1.23+

Quick Start

from kanvas.core import run

def setup(model):
    """Called once at startup"""
    model.clear(30)  # Set background to gray

def draw(model, frame, dt):
    """Called every frame"""
    x = (frame // 2) % model.w
    for y in range(model.h):
        model.pixel(x, y, 255, 255, 255)

# Run the sketch
run(setup, draw, size=(800, 600), title="My First Sketch")

Save this as sketch.py and run with:

python sketch.py

Press ESC to quit or S to save the current frame as a PNG image.

Examples

Sierpinski Triangle

Generate fractals using the chaos game method:

from kanvas.core import run
import random

def setup(model):
    model.clear(20)

def draw(model, frame, dt):
    # Define triangle vertices
    a = {'x': int(model.w/2), 'y': 0}
    b = {'x': 0, 'y': model.h - 1}
    c = {'x': model.w - 1, 'y': model.h - 1}
    targets = [a, b, c]
    
    # Starting point
    p = {'x': int(model.w/2), 'y': int(model.h/2)}
    
    # Generate 1000 points
    for i in range(1000):
        target = random.choice(targets)
        p['x'] = (p['x'] + target['x']) // 2
        p['y'] = (p['y'] + target['y']) // 2
        model.pixel(p['x'], p['y'], 255, 255, 255)

run(setup, draw, size=(800, 800), title="Sierpinski Triangle")

Ulam Spiral

Visualize prime numbers in a spiral pattern:

from kanvas.core import run

def is_prime(n):
    if n <= 1:
        return False
    if n % 2 == 0:
        return n == 2
    r = int(n**0.5)
    f = 3
    while f <= r:
        if n % f == 0:
            return False
        f += 2
    return True

def setup(model):
    model.clear(20)
    
    # Spiral generation logic
    directions = [(1,0), (0,-1), (-1,0), (0,1)]  # right, up, left, down
    x, y = model.w // 2, model.h // 2
    
    n = 1
    dir_idx = 0
    steps_in_leg = 1
    steps_taken = 0
    legs_done_at_length = 0
    
    while 0 <= x < model.w and 0 <= y < model.h:
        if is_prime(n):
            model.pixel(x, y, 255, 255, 255)
        
        # Move in spiral
        dx, dy = directions[dir_idx]
        x += dx * 4  # Step size
        y += dy * 4
        
        n += 1
        steps_taken += 1
        
        # Turn logic for spiral pattern
        if steps_taken == steps_in_leg:
            dir_idx = (dir_idx + 1) % 4
            steps_taken = 0
            legs_done_at_length += 1
            if legs_done_at_length == 2:
                steps_in_leg += 1
                legs_done_at_length = 0

def draw(model, frame, dt):
    pass

run(setup, draw, size=(800, 800), title="Ulam Spiral")

API Reference

Core Functions

run(setup_func, draw_func, **kwargs)

Main entry point to start a kanvas sketch.

Parameters:

  • setup_func: Function called once at startup, receives model parameter
  • draw_func: Function called every frame, receives model, frame, and dt parameters
  • size: Tuple of (width, height) for window size (default: (640, 360))
  • title: Window title string (default: "kanvas")
  • target_fps: Target frames per second (default: 60)

Model API

The model object provides the drawing surface:

model.pixel(x, y, r, g, b)

Set a pixel at coordinates (x, y) to RGB color (r, g, b).

Parameters:

  • x, y: Integer coordinates (0,0 is top-left)
  • r, g, b: Color values from 0-255

model.clear(gray_value)

Clear the entire canvas to a grayscale value.

Parameters:

  • gray_value: Integer from 0 (black) to 255 (white)

Properties

  • model.w: Canvas width in pixels
  • model.h: Canvas height in pixels

Controls

  • ESC: Quit the application
  • S: Save current frame as PNG image to ./output/ directory

Philosophy

kanvas is designed for learning by doing. The entire codebase is intentionally simple and readable, making it easy to understand how creative coding frameworks work internally. There's no magic - you can trace every function call from user input to pixel output.

This makes kanvas ideal for:

  • Learning creative coding concepts
  • Understanding game loop architecture
  • Teaching graphics programming
  • Rapid prototyping of visual ideas
  • Educational workshops and tutorials

Advanced Usage

Animation Loops

Create smooth animations using the frame counter:

import math

def draw(model, frame, dt):
    model.clear(0)
    
    # Animated circle
    center_x = model.w // 2
    center_y = model.h // 2
    radius = 50
    
    angle = frame * 0.05
    x = center_x + int(radius * math.cos(angle))
    y = center_y + int(radius * math.sin(angle))
    
    # Draw a simple circle by setting pixels
    for dx in range(-5, 6):
        for dy in range(-5, 6):
            if dx*dx + dy*dy <= 25:  # Circle equation
                if 0 <= x+dx < model.w and 0 <= y+dy < model.h:
                    model.pixel(x+dx, y+dy, 255, 255, 255)

Interactive Sketches

While kanvas currently focuses on generative art, you can create interactive elements by using the frame counter and mathematical functions to respond to time-based input.

Contributing

kanvas is an educational project welcoming contributions! The codebase is intentionally simple to encourage learning and experimentation.

Source Code

Visit the project on GitHub: https://github.com/robinoscarsson/kanvas

License

MIT License - see the GitHub repository for full details.

Acknowledgments

  • Inspired by Processing and p5.js
  • Built with pygame
  • Created for educational purposes and creative exploration

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kanvas-0.1.3.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kanvas-0.1.3-py3-none-any.whl (8.3 kB view details)

Uploaded Python 3

File details

Details for the file kanvas-0.1.3.tar.gz.

File metadata

  • Download URL: kanvas-0.1.3.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kanvas-0.1.3.tar.gz
Algorithm Hash digest
SHA256 ed3d3862cf36b5503179de5ad551d6c348eda8a8558664f4a39704231779c85c
MD5 4556c04a4883449fb1121c032863c127
BLAKE2b-256 43d04b960f5ce792937a63a63a33a92cd58f9c1d6fe0283d178954588a7b534a

See more details on using hashes here.

File details

Details for the file kanvas-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: kanvas-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 8.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kanvas-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 956bcbce01c187410022b8253d887c3e36a17a7334bb7d993726fcf7c7f50e6b
MD5 44837fe82604b05b5703d911171853d1
BLAKE2b-256 6047b662566dfdb6e37da37ee56b24192de32258028a6c658547f50dd9863a42

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page