UshFramework Documentation

UshFramework is a lightweight framework for creating 2D games using Lua and SDL2. It’s perfect for beginners and pros, offering tools for graphics, sound, input, physics, animations, and more. This guide covers setup, features, API, and tips for building games on Windows, macOS, and Linux (coming soon).

1. Overview

UshFramework makes 2D game development simple with Lua and SDL2. Create arcades, platformers, or puzzles with minimal setup. Write code in a single main.lua file to handle graphics, input, sound, physics, and scenes.

Why Choose UshFramework?

  • Easy to Learn: Lua’s simple syntax is great for all skill levels.
  • Feature-Packed: Includes graphics, sound, physics, animations, and scenes.
  • Fast: SDL2 ensures smooth performance for 2D games.

What Can You Build?

  • Arcades: Fast-paced games with sprites and sounds.
  • Platformers: Character movement with physics and camera.
  • Puzzles: Interactive menus and text displays.
  • Interfaces: HUDs, scoreboards, and menus.

2. Installation

Download ush-installer.exe from ushland.xyz, install it, and restart your terminal. Type ush to check if it’s working.

Setting Up Your Game

  1. Create a main.lua file.
  2. Add the example code below.
  3. Run with: ush run

Example Game

Move a square with arrows or WASD, press space for a sound, and click to draw a circle:

local x, y = 400, 300
local speed = 200

function init()
    load_sound("click", "click.wav")
    set_volume("sound", 75)
    load_font("arial", "arial.ttf")
    set_font("arial")
    log("Game started")
end

function update(dt)
    if is_pressed("space") then
        play_sound("click")
    end
    if is_pressed("mouse_left") then
        local mx, my = mouse_x(), mouse_y()
        circle(mx, my, 20, red)
    end
    if is_down("left") or is_down("a") then
        x = x - speed * dt
    end
    if is_down("right") or is_down("d") then
        x = x + speed * dt
    end
    x = math.max(0, math.min(x, width() - 50))
end

function draw()
    clear({r=20, g=20, b=40})
    rect(x, y, 50, 50, {r=255, g=100, b=100})
    text("Move with arrows or A/D, space for sound, click for circle", 10, 10, 16, white)
    text("FPS: " .. get_fps(), 10, height() - 20, 16, yellow)
end
        

Files Needed:

  • click.wav in the project folder.
  • arial.ttf in the folder or C:/Windows/Fonts.

Troubleshooting

  • Font issues: Ensure arial.ttf path is correct in load_font.
  • Sound issues: Verify click.wav is WAV format and in the folder. Check volume with set_volume("sound", 75).
  • Game won’t start: Ensure main.lua is in the project folder. Enable debug with show_debug(true).
  • SDL2 errors: Confirm SDL2, SDL_ttf, and SDL_mixer are installed correctly.

3. Features

UshFramework provides a rich set of tools for 2D game development. Explore each feature below with examples.

3.1. Graphics

Draw rectangles, circles, lines, and text with customizable RGB colors for HUDs, menus, and objects.

Capabilities: Clear screen, draw rectangles, circles, lines, and text.

Example: Create a menu button with a circle highlight:

function draw()
    clear({r=20, g=20, b=40})
    rect(300, 200, 200, 50, blue)
    circle(350, 225, 20, yellow)
    line(300, 250, 500, 250, white)
    text("New Game", 320, 210, 20, white)
end
          

Tips:

  • Use color(r, g, b, a) for custom colors (0–255).
  • Minimize draw calls for better performance.
  • Load fonts for text (see Fonts section).

3.2. Input

Handle keyboard and mouse input for movement, actions, and menu navigation.

Capabilities: Detect key holds, presses, releases, and mouse input.

Example: Move with keys and click to interact:

local x = 400
function update(dt)
    if is_down("left") then
        x = x - 200 * dt
    end
    if is_pressed("mouse_left") then
        log("Clicked at: " .. mouse_x() .. ", " .. mouse_y())
    end
    if is_released("space") then
        log("Space released!")
    end
end
          

Tips:

  • Use is_down for continuous input, is_pressed for single events, and is_released for key releases.
  • Mouse keys: mouse_left, mouse_right.
  • Use dt for smooth movement.

3.3. Sound

Play sound effects and background music with volume control.

Capabilities: Load/play WAV sounds and music, adjust volume.

Example: Play a sound and background music:

function init()
    load_sound("click", "click.wav")
    load_music("bgm", "background.mp3")
    set_volume("sound", 75)
    set_volume("music", 50)
    play_music("bgm", true)
end
function update(dt)
    if is_pressed("space") then
        play_sound("click")
    end
end
          

Tips:

  • Load sounds/music in init.
  • Use WAV for sounds, MP3/WAV for music.
  • Verify file paths if audio fails.

3.4. Fonts

Load and display TTF fonts for text in menus and HUDs.

Capabilities: Load TTF fonts, set active font.

Example: Show a score:

function init()
    load_font("arial", "arial.ttf")
    set_font("arial")
end
function draw()
    text("Score: 100", 10, 10, 16, yellow)
end
          

Tips:

  • Load fonts in init.
  • Verify font paths (e.g., C:/Windows/Fonts/arial.ttf).
  • Use common fonts for compatibility.

3.5. Scenes

Organize game states (menu, gameplay, end screen) with separate Lua files.

Capabilities: Register, switch, and get scenes.

Example: Start with a menu:

function init()
    register_scene("menu", "menu.lua")
    set_scene("menu")
end

-- menu.lua
function draw()
    rect(300, 200, 200, 50, blue)
    text("Play", 320, 210, 20, white)
end
function update(dt)
    if is_pressed("space") then
        set_scene("game")
    end
end
          

Tips:

  • Ensure scene files are in the project folder.
  • Scenes need init, update, draw functions.
  • Avoid duplicate scene names.

3.6. Camera

Move and zoom the camera to follow objects or create effects.

Capabilities: Move camera, set zoom level.

Example: Follow a player:

function update(dt)
    camera_move(player_x - 400, player_y - 300)
    camera_zoom(1.5)
end
          

Tips:

  • Use camera_move to center on objects.
  • Zoom >1 enlarges, <1 shrinks.
  • Check boundaries to avoid empty views.

3.7. Resources

Load and display BMP textures for sprites.

Capabilities: Load textures, draw sprites.

Example: Show a player sprite:

function init()
    load_texture("player", "player.bmp")
end
function draw()
    sprite("player", 200, 200)
end
          

Tips:

  • Load textures in init.
  • Use BMP format for textures.
  • Optimize texture sizes for performance.

3.8. Physics

Create physics bodies with collision detection for objects like players or walls.

Capabilities: Create/destroy bodies, set velocity/position, detect collisions.

Example: Player collides with a wall:

local player_id
function init()
    player_id = create_body(400, 300, 50, 50, "player", true)
    create_body(600, 300, 100, 100, "wall", true)
end
function update(dt)
    set_velocity(player_id, 200, 0)
    local collision_id = get_collision(player_id, "wall")
    if collision_id then
        log("Collided with wall ID: " .. collision_id)
    end
end
          

Tips:

  • Use unique tags for collision detection.
  • Destroy unused bodies with destroy_body.
  • Enable show_debug(true) to see body outlines.

3.9. Animations

Use timers for animations or timed events.

Capabilities: Create one-time or repeating timers.

Example: Animate a sprite:

local frame = 1
function init()
    timer(0.2, "next_frame", true)
end
function next_frame()
    frame = frame % 4 + 1
    log("Frame: " .. frame)
end
          

Tips:

  • Timers use seconds (0.2 = 200ms).
  • Use unique timer function names.
  • Reset timers when switching scenes.

3.10. Debugging

Monitor FPS, frame time, and physics bodies for optimization.

Capabilities: Enable debug visuals, get FPS.

Example: Show debug info:

function init()
    show_debug(true)
end
function draw()
    text("FPS: " .. get_fps(), 10, 10, 16, white)
end
          

Tips:

  • Disable show_debug in final builds.
  • Use FPS to optimize draw calls.
  • Logs appear in console or file.

3.11. Utilities

Manage window size, time, save data, random numbers, and more.

Capabilities: Get window size, time, save/load data, generate random numbers, exit.

Example: Resize window and save score:

function init()
    set_window_size(1024, 768)
    local score = load("score", "0")
    log("Score: " .. score)
end
function update(dt)
    if is_pressed("s") then
        save("score", "100")
    end
end
          

Tips:

  • Use width(), height() for dynamic positioning.
  • Save only essential data.
  • Use exit() for clean shutdown.

4. API

Complete API reference with parameters and examples.

4.1. Graphics

  • clear(color): Clear screen with color.
    • Params: color{r, g, b, a} or predefined (e.g., blue).
    • Example: clear({r=20, g=20, b=40})
  • rect(x, y, w, h, color): Draw rectangle.
    • Params: x, y — position; w, h — size; color{r, g, b, a}.
    • Example: rect(300, 200, 200, 50, blue)
  • circle(x, y, r, color): Draw circle outline.
    • Params: x, y — center; r — radius; color{r, g, b, a}.
    • Example: circle(350, 225, 20, yellow)
  • line(x1, y1, x2, y2, color): Draw line.
    • Params: x1, y1, x2, y2 — endpoints; color{r, g, b, a}.
    • Example: line(300, 250, 500, 250, white)
  • text(str, x, y, size, color): Display text.
    • Params: str — string; x, y — position; size — font size; color{r, g, b, a}.
    • Example: text("Score: 100", 10, 10, 16, yellow)
  • color(r, g, b, a): Create custom color.
    • Params: r, g, b, a — 0–255 (a optional).
    • Returns: Table with r, g, b, a.
    • Example: color(255, 165, 0, 255)
  • Predefined Colors: white, black, red, green, blue, yellow, cyan, magenta, gray, orange, purple, brown, pink.

4.2. Input

  • is_down(key): Check if key is held.
    • Params: key — e.g., "left", "a".
    • Returns: true/false.
    • Example: if is_down("left") then x = x - 200 * dt end
  • is_pressed(key): Check single key press.
    • Params: key — e.g., "space", "mouse_left".
    • Returns: true/false.
    • Example: if is_pressed("mouse_left") then log("Clicked") end
  • is_released(key): Check key release.
    • Params: key — e.g., "space", "mouse_right".
    • Returns: true/false.
    • Example: if is_released("space") then log("Released") end
  • mouse_x(), mouse_y(): Get mouse coordinates.
    • Returns: Number.
    • Example: local mx, my = mouse_x(), mouse_y()

4.3. Sound

  • load_sound(name, path): Load WAV sound.
    • Params: name — string; path — file path.
    • Returns: true/false.
    • Example: load_sound("click", "click.wav")
  • play_sound(name): Play sound.
    • Params: name — string.
    • Returns: true/false.
    • Example: play_sound("click")
  • load_music(name, path): Load music (MP3/WAV).
    • Params: name — string; path — file path.
    • Returns: true/false.
    • Example: load_music("bgm", "background.mp3")
  • play_music(name, loop): Play music.
    • Params: name — string; looptrue/false.
    • Returns: true/false.
    • Example: play_music("bgm", true)
  • set_volume(type, volume): Set volume.
    • Params: type"sound"/"music"; volume — 0–100.
    • Example: set_volume("music", 50)

4.4. Fonts

  • load_font(name, path): Load TTF font.
    • Params: name — string; path — file path.
    • Returns: true/false.
    • Example: load_font("arial", "arial.ttf")
  • set_font(name): Set active font.
    • Params: name — string.
    • Example: set_font("arial")

4.5. Scenes

  • register_scene(name, file): Register a scene.
    • Params: name — string; file — Lua file path.
    • Example: register_scene("menu", "menu.lua")
  • set_scene(name): Switch to a scene.
    • Params: name — string.
    • Example: set_scene("menu")
  • get_scene(): Get current scene name.
    • Returns: String.
    • Example: local current = get_scene()

4.6. Camera

  • camera_move(x, y): Move camera.
    • Params: x, y — coordinates.
    • Example: camera_move(400, 300)
  • camera_zoom(zoom): Set camera zoom.
    • Params: zoom — number (1 = normal).
    • Example: camera_zoom(2)

4.7. Resources

  • load_texture(name, path): Load BMP texture.
    • Params: name — string; path — file path.
    • Returns: true/false.
    • Example: load_texture("player", "player.bmp")
  • sprite(name, x, y): Draw sprite.
    • Params: name — string; x, y — coordinates.
    • Example: sprite("player", 200, 200)

4.8. Physics

  • create_body(x, y, w, h, tag, solid): Create physics body.
    • Params: x, y — position; w, h — size; tag — string; solidtrue/false.
    • Returns: Body ID (number).
    • Example: local id = create_body(400, 300, 50, 50, "player", true)
  • set_velocity(id, dx, dy): Set body velocity.
    • Params: id — body ID; dx, dy — velocity.
    • Returns: true/false.
    • Example: set_velocity(id, 200, 0)
  • get_velocity(id): Get body velocity.
    • Params: id — body ID.
    • Returns: dx, dy or nil, nil.
    • Example: local dx, dy = get_velocity(id)
  • set_body_position(id, x, y): Set body position.
    • Params: id — body ID; x, y — coordinates.
    • Returns: true/false.
    • Example: set_body_position(id, 400, 300)
  • get_body_position(id): Get body position and size.
    • Params: id — body ID.
    • Returns: x, y, w, h or nil, nil, nil, nil.
    • Example: local x, y, w, h = get_body_position(id)
  • get_collision(id, tag): Check collision with tag.
    • Params: id — body ID; tag — string.
    • Returns: Collided body ID or nil.
    • Example: local cid = get_collision(id, "wall")
  • destroy_body(id): Destroy body.
    • Params: id — body ID.
    • Returns: true/false.
    • Example: destroy_body(id)

4.9. Animations

  • timer(time, func, repeat): Call function after time.
    • Params: time — seconds; func — function name; repeattrue/false.
    • Example: timer(0.2, "next_frame", true)

4.10. Debugging

  • show_debug(bool): Toggle debug info (FPS, frame time, physics outlines).
    • Params: booltrue/false.
    • Example: show_debug(true)
  • get_fps(): Get current FPS.
    • Returns: Number.
    • Example: local fps = get_fps()

4.11. Utilities

  • width(), height(): Get window dimensions.
    • Returns: Number.
    • Example: local w, h = width(), height()
  • set_window_size(w, h): Set window size.
    • Params: w, h — width, height.
    • Example: set_window_size(1024, 768)
  • time(): Get time since game start.
    • Returns: Number (seconds).
    • Example: local t = time()
  • rand(min, max): Generate random number.
    • Params: min, max — numbers.
    • Returns: Number.
    • Example: local n = rand(1, 100)
  • log(msg): Log message to console.
    • Params: msg — string.
    • Example: log("Game started")
  • save(key, value): Save string value.
    • Params: key, value — strings.
    • Example: save("score", "100")
  • load(key, default): Load string value or default.
    • Params: key, default — strings.
    • Returns: String.
    • Example: local score = load("score", "0")
  • exit(): Exit game.
    • Example: exit()

5. Tips and Tricks

Maximize your use of UshFramework with these practical tips.

5.1. Creating Interactive Menus

Build menus with scenes and mouse input.

function init()
    register_scene("menu", "menu.lua")
    set_scene("menu")
end

-- menu.lua
function draw()
    rect(300, 200, 200, 50, blue)
    text("Play", 320, 210, 20, white)
end
function update(dt)
    if is_pressed("mouse_left") then
        local mx, my = mouse_x(), mouse_y()
        if mx >= 300 and mx <= 500 and my >= 200 and my <= 250 then
            set_scene("game")
        end
    end
end
          

Tips:

  • Use rectangles for clickable buttons.
  • Check mouse_x, mouse_y for clicks.
  • Create separate scenes for menus and gameplay.

5.2. Animating Sprites

Use timers to cycle through sprite frames.

local frame = 1
function init()
    load_texture("frame1", "frame1.bmp")
    load_texture("frame2", "frame2.bmp")
    timer(0.2, "next_frame", true)
end
function next_frame()
    frame = frame % 2 + 1
end
function draw()
    sprite("frame" .. frame, 200, 200)
end
          

Tips:

  • Use sequential texture names (e.g., frame1, frame2).
  • Timers of 0.1–0.3s work well for animations.
  • Monitor performance with many animations.

5.3. Handling Physics

Use physics bodies for collisions and movement.

local player_id
function init()
    player_id = create_body(400, 300, 50, 50, "player", true)
    create_body(600, 300, 100, 100, "wall", true)
end
function update(dt)
    if is_down("right") then
        set_velocity(player_id, 200, 0)
    else
        set_velocity(player_id, 0, 0)
    end
    local collision_id = get_collision(player_id, "wall")
    if collision_id then
        set_velocity(player_id, 0, 0)
    end
end
          

Tips:

  • Store body IDs for manipulation.
  • Use get_collision to handle interactions.
  • Enable debug to visualize bodies.

5.4. Saving Game Progress

Save and load data like scores or levels.

function init()
    local level = load("level", "1")
    log("Level: " .. level)
end
function update(dt)
    if is_pressed("l") then
        save("level", "2")
    end
end
          

Tips:

  • Save only when needed (e.g., on level complete).
  • Use unique keys for data.
  • Ensure save file is writable.

5.5. Performance Optimization

  • Graphics: Reduce rect, circle, line, and text calls.
  • Physics: Limit active bodies and destroy unused ones.
  • Sound: Load sounds/music in init.
  • Debugging: Disable show_debug in release builds.
  • Resources: Use optimized BMP textures.

5.6. Common Errors

  • Text not shown: Check font loading and color contrast.
  • Sprites missing: Verify BMP paths and coordinates.
  • Collisions not detected: Ensure correct tags and solid bodies.
  • Low FPS: Optimize draw calls, check with show_debug(true).

Conclusion

UshFramework, powered by SDL2, makes 2D game development fun and accessible. With tools for graphics, physics, sound, and more, you can create games quickly. Use this guide to get started and explore the API for advanced features.

Start with the example in "Installation," use log for debugging, and check file paths for resources. Happy coding!