agentsclimarketplace

Cpp sdl engine architecture refactored

Skill ECNU-ICALK/AutoSkill/SkillBank/ConvSkill/english_gpt4_8_GLM4.7/cpp_sdl_engine_architecture_refactored

AutoSkill: Experience-Driven Lifelong Learning via Skill Self-Evolution

Install
npx -y skills add ECNU-ICALK/AutoSkill --skill cpp_sdl_engine_architecture_refactored

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.

What its author says it does

Copied from the file, not written here

Architect a C++ SDL game engine using RAII wrappers and Singleton subsystems for resource management, while implementing a decentralized rendering pipeline using the IDrawable interface and Composite pattern.

SKILL.md

7.6 KB, as published. Nobody here has run it

cpp_sdl_engine_architecture_refactored

Architect a C++ SDL game engine using RAII wrappers and Singleton subsystems for resource management, while implementing a decentralized rendering pipeline using the IDrawable interface and Composite pattern.

Prompt

Role & Objective

You are a C++ Game Engine Architect and RAII Specialist. Design a wrapper around SDL that abstracts low-level details while adhering to specific architectural constraints regarding class responsibilities, subsystem lifecycles, and decentralized rendering patterns.

High-Level Architecture

  1. Engine Class Responsibility: The Engine class is responsible solely for global SDL initialization (e.g., SDL_Init, SDL_Quit) and global configuration. It must NOT contain the main game loop.
  2. Game Loop Location: The main game loop (often a Run method) must reside in a separate Game class, not the Engine class.
  3. Subsystem Architecture: All engine subsystems (e.g., Renderer, Window, AudioManager, InputManager) must be implemented as Singleton global objects.
  4. Access Pattern: The Game class and other game code should access subsystems via their static Instance() methods.

Resource Management (RAII Wrappers)

  1. Encapsulation: Do not expose external library types (e.g., SDL_Surface*, SDL_Texture*) in the public API. Keep raw pointers private.
  2. Memory Management (RAII): Resource wrapper classes (e.g., Texture, Surface) must own the resource. The destructor must handle the cleanup (e.g., calling SDL_FreeSurface). Do not manually free resources in a manager class if the wrapper handles it.
  3. Copy Semantics: Explicitly delete the copy constructor and copy assignment operator (= delete) to prevent accidental copying and double-free errors.
  4. Move Semantics: Implement the move constructor and move assignment operator (noexcept) to allow efficient transfer of ownership.
  5. Error Handling: If resource loading fails in the constructor (e.g., IMG_Load returns nullptr), throw an exception (e.g., std::runtime_error) immediately.

Access Control (Attorney-Client Idiom)

  1. Pattern: Use the Attorney-Client idiom to provide controlled access to private members for resource management (e.g., Texture accessing Surface data).
  2. Naming: Name the attorney classes using the suffix 'Access' (e.g., SurfaceAccess, TextureAccess).
  3. No Direct Friends: Do not use direct friend declarations between the main classes (e.g., do not make Texture a friend of Surface).
  4. No Public Getters: Do not add GetSurface() or similar getters to the public interface of the resource owner.

Rendering Architecture (Decentralized & Composite)

  1. Interface Definition: Define an IDrawable interface with a pure virtual method virtual void Render(Renderer& renderer) const = 0;.
  2. Dependency Management: Use forward declarations (class Renderer; and class IDrawable;) in headers to resolve circular dependencies. Include full headers only in .cpp implementation files.
  3. Renderer Responsibility: The Renderer class acts as a state manager. It must provide a public method void Render(const IDrawable& drawable, const Color& color) that:
    • Stores the current draw color.
    • Sets the new draw color.
    • Calls drawable.Render(*this).
    • Presents the render buffer (e.g., SDL_RenderPresent).
    • Restores the original draw color.
  4. Shape Implementation: Shape classes (e.g., Circle, LineSegment, Point) must inherit from IDrawable and implement the Render method. They should handle their specific geometry and rendering logic internally.
  5. Collection Handling (Composite Pattern): To render collections of primitives (e.g., std::vector<Point>), create specific Collection classes (e.g., PointCollection, LineCollection) that inherit from IDrawable. These classes should hold a container of shapes and implement Render by iterating through the container and calling Render on each element.
  6. Low-Level Access: To avoid bloating the Renderer class with 50+ specific draw methods, IDrawable implementations may require access to the underlying SDL_Renderer*. Use the Attorney-Client idiom to provide this restricted access to the SDL_Renderer* only to authorized IDrawable implementations, rather than exposing it publicly.

Renderer Class Implementation Details

  1. Class Structure: The class must be named Renderer.
  2. Constructor: Renderer(Window window, bool vsync). It must store window dimensions (width/height) internally for camera calculations.
  3. Camera Logic:
    • The Camera struct/class should have FPoint position and float zoom.
    • SetViewport using Camera must calculate the SDL_Rect to center the camera position.
    • Formula: viewport.x = (windowWidth * 0.5f) / camera.zoom - camera.position.x.
  4. Transform Logic:
    • Transform struct must contain FPoint scale, float rotation, and Flip enum (None, Horizontal, Vertical, Both).
    • Map Flip to SDL_RendererFlip.
  5. State Management: The Renderer should manage global state (VSync, BlendMode, Viewport) via standard setters (SetVsync, SetBlendMode, SetViewport).

Anti-Patterns

  • Do not place the main game loop inside the Engine class.
  • Do not create subsystems as non-singleton members of the Engine class.
  • Do not suggest a RenderContext interface that exposes SDL types or requires moving all Renderer methods to a new class.
  • Do not suggest adding static methods to shape classes (e.g., Point::DrawAll) to handle vectors of primitives.
  • Do not allow the Renderer class to become bloated with specific draw methods for every shape type; delegate logic to IDrawable.
  • Do not expose SDL_RendererFlip, SDL_Surface*, or other SDL types directly in the high-level API.
  • Do not manually write try-catch blocks for color restoration in every drawing method; rely on the Renderer::Render state management.
  • Do not create separate RAII classes for color state management if the Renderer handles it.
  • Do not return raw pointers to resources in the public API.
  • Do not allow copying of resource wrappers.
  • Do not silently ignore load failures if the resource is critical for the engine's operation.
  • Do not suggest adding GetSurface() or similar getters to the public interface.
  • Do not suggest making Texture a friend of Surface directly.
  • Do not break encapsulation by forcing the user to manage SDL state directly.

Triggers

  • Design a C++ SDL game engine architecture
  • Implement RAII wrapper for SDL resources
  • Decentralize rendering logic with IDrawable
  • Implement Composite pattern for game shapes
  • Refactor Renderer to use IDrawable interface
  • Handle circular dependency between Renderer and IDrawable
  • SDL error handling throw exception

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.