Cute Framework (CF)

repository·master·Indexed 21 days ago

https://github.com/randygaul/cute_framework

A portable, lightweight 2D game framework for C/C++ designed to run on Windows, MacOS, iOS, Android, Linux, and Browsers without heavy dependencies. It provides a C API with C++ wrappers and uses CMake for building. Key functionality includes application lifecycle management via make_app(), app_update(), and app_draw_onto_screen().

Tokens
52.6K
Snippets
157
Records
240
Agent score
73%

What's inside Cute Framework

  1. Explore Cute Framework interactive samples

    master

    The Cute Framework provides a wide range of interactive samples to demonstrate its features. These samples cover various domains including rendering, UI, physics, and input handling. You can use these samples to understand how specific framework components work in practice.

    Key Feature Areas in Samples:

    • Rendering & Graphics: 9-Slice, Basic Indexed Rendering, Basic Instancing, Basic Shapes, Basic Sprite, Blend Modes, Custom Shapes, Custom Sprite, Draw Lists, Draw to Texture, Easy Sprite, Glitch, Hello Triangle, Import Spritesheet, Outline (Stencil), Polygon, Recolor, Stencil Pie Chart, Tile Performance, Vector Paths, and Waves.
    • UI & Text: Clay UI, Clay UI Animations, Dear ImGui, Dear ImGui Texture, Font Debug, IME Text Input, Text Drawing, and Vector Text.
    • Camera & View: Basic Camera, HiDPI, Pivot, and Window Resizing.
    • Physics & Simulation: Fluid Sim, Metaballs, Rainbow Liquid, and Shallow Water.
    • Input & Audio: Input Binding, Joypad, and Sound Pan.
    • Game Mechanics & Logic: Platformer, Space Shooter, Timestep, and Mandala.
    • Utilities: Fetch Image, Noise, and Vector Paths.
  2. Understand the Low Level Graphics API in CF

    master

    The Low Level Graphics API in CF is intended for implementing custom rendering or advanced rendering techniques. It wraps several 3D rendering backends, including Vulkan, DirectX 11, DirectX 12, Metal, and OpenGL ES.

    To use this API, you must work with several core primitives:

    • CF_Canvas: A texture that can be rendered to.
    • CF_Texture: Stores image data on the GPU for drawing onto the screen.
    • CF_Mesh: Stores vertex data (triangles) for the GPU to process.
    • CF_Shader: A GPU program that transforms mesh vertices into pixels.
    • CF_RenderState: Configuration for rendering settings like stencil or blend states.
    • CF_Material: A collection of shader inputs, including uniforms and textures.
    // Typical rendering loop flow:
    for each canvas {
        cf_apply_canvas(canvas);
        for each mesh {
            cf_mesh_update_vertex_data(mesh, ...);
            cf_apply_mesh(mesh);
            for each material {
                cf_material_set_uniform_vs(material, ...);
                cf_material_set_uniform_fs(material, ...);
                for each shader {
                    cf_apply_shader(shader, material);
                    cf_draw_elements(...);
                }
            }
        }
    }
  3. What is a CF_Coroutine and when to use it

    master

    A CF_Coroutine is a function that can be paused and resumed multiple times before finally exiting. This abstraction is ideal for implementing complex state machines, cutscenes, or any logic that requires performing actions sequentially over multiple game frames.

    Key Benefits:

    • Clean State Machines: Replaces complex switch or if-else chains with linear, readable code.
    • Local State Management: Instead of storing persistent variables in external structures (like an editor_t or global state), you can use standard local variables. The coroutine's own stack preserves these variables across yields.
    • Chronological Logic: Code reads like a script (e.g., "Do A, then B, then C") rather than jumping between disconnected state blocks.
    void my_coroutine_function(coroutine_t* co) {
    	// Local variables persist across yields
    	int local_state = 0;
    	
    	// Do something
    	local_state = 1;
    	coroutine_yield(co); // Pause here
    
    	// Resume here with local_state still being 1
    	local_state++;
    }
  4. Configure the VFS Search Path

    master

    The search path is a list of directories associated with a virtual alias. When you mount multiple physical locations to the same virtual path with append_to_path = true, the VFS searches them in order.

    If multiple files exist at the same virtual path across different mounts, the most recently added file is the one returned by the VFS. This mechanism is ideal for implementing downloadable patches or mod support, as you can mount a patch archive onto an existing alias to 'hide' the original files.

  5. How Connect Tokens work for server security

    master

    Connect tokens are used to authenticate clients before they can connect to a game server. This allows developers to control access (e.g., ensuring only players who purchased the game can connect) and protect expensive dedicated server resources.

    The Connection Workflow:

    1. Authentication: The client makes a REST call (typically over HTTPS) to a secure Web Service.
    2. Token Retrieval: The Web Service validates the client and returns a Connect Token.
    3. Connection Attempt: The client uses the token to attempt a connection to a game server via cf_client_connect.
    4. Handshake: The server validates the token and the security handshake. If a connection fails, the client can use the token to try the next available server in the list provided by the token.
  6. Mount archives (ZIP, 7Z, PAK, etc.)

    master

    The VFS treats archives exactly like normal directories. You can mount various archive formats using cf_fs_mount, and the framework will allow you to access the files inside them using standard virtual paths. Supported formats include:

    • .ZIP (pkZip/WinZip/Info-ZIP)
    • .7Z (7zip)
    • .ISO (ISO9660)
    • .GRP (Build Engine)
    • .PAK (Quake)
    • .HOG (Descent I/II)
    • .MVL (Descent II)
    • .WAD (DOOM)
    • .VDF (Gothic)
    • .SLB (Independence War)
  7. Packet Structure and Encryption

    master

    Most packets in the Cute Protocol are encrypted. The connect token packet is the only exception, as it is pre-encrypted by the web service.

    Encrypted Packet Format

    All encrypted packets follow this structure:

    • packet type: 1 byte
    • sequence nonce: 8 bytes
    • signature: 64 bytes
    • encrypted bytes: variable length (up to 1207 bytes)

    Total packet size is capped at 1280 bytes.

    Decryption Validation Steps

    When receiving a packet, perform these checks in order. If any fail, ignore the packet:

    1. Check if length < 45 bytes.
    2. Check if packet type > 7.
    3. Role Filtering:
      • Server ignores: challenge response, connection denied, connection accepted.
      • Client ignores: challenge request, connect token.
    4. Verify encrypted bytes size matches the expected range for the packet type.
    5. Verify replay protection.
    6. Verify AEAD decryption success.
    packet type       1 byte
    sequence nonce    8 bytes
    signature         64 bytes
    encrypted bytes   <variable length>
  8. Understand Texture UV-coordinates

    master

    Textures store image data (texels). In shaders, data is fetched from a texture using UV-coordinates.

    UV-coordinates consist of two floats, typically in the range [0, 1].

    • (0, 0) usually maps to the top-left of the texture.
    • (1, 1) maps to the bottom-right of the texture.

    Each vertex in a mesh typically carries a unique UV coordinate to determine which part of the texture is mapped to that vertex.

  9. Prevent tunneling with swept collision (Time of Impact)

    master
    Discrete collision detection can fail if an object moves too fast, causing it to 'tunnel' through another object between frames. To prevent this, use swept collision via the cf_toi function. This calculates the Time of Impact (TOI) for two linearly moving shapes (no rotation), allowing you to detect collisions that occur during a movement step.
  10. How to override the default allocator in Cute Framework

    master

    For advanced performance optimization or to reduce memory fragmentation, you can replace Cute Framework's internal memory management with a custom allocator. This is achieved by providing a CF_Allocator struct containing function pointers for allocation operations to cf_allocator_override.

    To implement an override, you must provide implementations for the following four operations:

    • alloc_fn: Handles basic allocation.
    • free_fn: Handles memory deallocation.
    • calloc_fn: Handles allocation with zero-initialization.
    • realloc_fn: Handles memory reallocation.

    Each function receives a void* udata parameter. This is a user-provided pointer that is passed back to your functions, allowing you to access external state (like a pointer to your specific allocator instance) without using global variables.

    typedef struct CF_Allocator
    {
    	void* udata;
    	void* (*alloc_fn)(size_t size, void* udata);
    	void (*free_fn)(void* ptr, void* udata);
    	void* (*calloc_fn)(size_t size, size_t count, void* udata);
    	void* (*realloc_fn)(void* ptr, size_t size, void* udata);
    } CF_Allocator;
  11. Understand shader resource set layouts

    master

    Shaders in CF must follow strict rules regarding resource sets (sets and bindings). If you violate these, the shader will not function correctly across different backends.

    Resource Set Rules:

    • Vertex Shaders: Use sets 0 and 1.
    • Fragment Shaders: Use sets 2 and 3.
    • Compute Shaders: Use sets 0, 1, and 2.

    Uniform Block Naming:

    • For standard shaders: The single available uniform block must be named uniform_block.
    • For Draw-API compatible shaders (created via cf_make_draw_shader): Uniform blocks must be named shd_uniforms.
  12. How the Virtual File System (VFS) works

    master

    The Cute Framework (CF) uses a Virtual File System (VFS) to provide a layer of indirection between actual physical file paths and virtual paths used within your game code.

    Instead of using absolute paths (like C:\Games\MyGame\content\music\song.ogg) or relative paths (which are disallowed for security), you mount physical directories to virtual aliases. Once a directory is mounted to a virtual path like /, you access assets using that virtual path (e.g., /music/song.ogg).

    Key Benefits:

    • Portability: Virtual paths do not use Windows-specific drive letters (C:) or backslashes (\), making code cross-platform.
    • Security: Relative paths like . and .. are disallowed. You can only access folders that have been explicitly mounted.
    • Versatility: You can reorganize your physical folder structure without changing any asset loading code, as long as you update the initial mounting logic.