Skip to content

karl-zylinski/Bowtie

Repository files navigation

Bowtie

My 2D engine, built from the ground up using C++ and OpenGL.

  • Remove render target ctor and free texture in renderer.cpp

    • During rw cleanup, look at rw dstr and the texture stuff there.
  • Create an entity component system

    • Rectangle rendering component
      • Updating / creating needs support for updating / creating many resources at once
      • Make on-demand creation of geometry support multiple rects
      • Material
    • Transform component
      • Iterate over dirty transforms before rect renderers and copy the updated transform to the rects belonging to same entity. What to do if the entity is missing rect? Check? Reverse lookup?
      • Copying to rect will make that one dirty, and trigger a update to renderer.
      • Parenting
    • Sprite rendering component
    • Remove Component suffix from script interfaces
    • Add world ptr to entity and thus bind them to world... Or???
    • GC of components
    • Convert old stuff to this new thingmajing
  • Redo console as external application

  • Fix fonts, maybe as entity component or as some kind of gui thing... Not sure. Maybe have the renderer agnostic of the CPU impl?

  • Fix sorting of batches so that it breaks on not only material, but also on uniform permutations

  • Turn engine into namespace of functions which operates on engine struct.

  • Turn font into namespace of functions which operates on font struct.

  • Turn render_interface into namespace of functions which operates on render_interface struct.

  • [/] Rename resource_manager to resource_store and have functions which operate on it in namespace

    • Optionally remove load functions and add auto-load enum
  • Convert view

  • Convert game

  • Convert window

  • Convert render_world

  • Auto size from sprite renderer material texture. Maybe not hack in directly, but rather as a layer outside...

  • Fix adding and removal of components as well as unspawning of renderer side stuff, maybe toss out the "new" block in the component header and do it all explicitly.

  • Convert callstack capturer to struct of function ptrs

  • Convert render_material

    • Have uniforms on main thread as well and keep them in a flat index-based list in renderer? Otherwise we cannot know what type uniforms are before sending update messages and we cannot fetch the values from lua.
  • Convert resource_lut

  • Go a pass over all struct defs and see how they can be inited as 0 (as valid state). For example, maybe make 0 the not inited value for most stuff instead of -1? Can we make writer function init on demand instead of explicit init step?

  • Convert renderer to struct + namespace and ditch irenderer for struct of func ptrs.

  • Rewrite allocators, throw out construct / destroy

    • Add page allocator?
  • Array -> Vector, also shape up Vector to match new allocator shizmajings

  • Make reflection message data for 1 array into soa

  • Write a data compiler by moving all the loading code from resource_manager to a compiler file. Have reasource manager open compiled resources and throw the data into memory.

  • Replace load functions in resource manager with only getter (maybe add auto load feature?). Introduce packages which specify which resources should be loaded. Have a boot package and then have levels/other types of packages do the rest. Or maybe specify default package from main.lua?

  • Move all struct defs into _type.h files?

  • Rename foundation to base

  • Move geometry generation to renderer

  • Deffered / heightmap lighting

  • Replace PNG with homebrew DDS loader

  • Proper assert() and error()

  • Make engine, game and renderer into dlls. Load them dynamically and fetch func ptrs which are called.

  • Move all platform related stuff such as creating and waiting for mutices and conditionals to funtion ptrs whicha send along with the memory from the platform layer. Should be able to remove os layer after that.

  • Remove lua, turn game project into an empty c game project.

  • Move any static or dynamically allocated chucks of memory to permanent memory.

  • Look over temp allocator, make it possible to somehow push the head forward more often? Requires one temp allocator per thread? Might be good though, because of mutex perf. issues

  • The tough one! What to do about the component allocations? Make entity into a regular index and have gaps in component collections? That would be ok if it wasn't for two things: bad locality and marking one entity dirty forces you to move all entities. You could have an indirection table though. It's only the touched ones that are updated and those are at the front so that's ok.

      entity index -> transform index table
      mark dirty by moving transform index to front
      the gc stuff might be non-needed, just remove stuff?
    

Entity can be turned into struct:

struct Entity { unsigned id; World* world; }

entity::set_position(Entity* e, const Vector2* pos) { transform_component::set_position(e->world->transform_components, e.id, pos); }

etc

Have x preallocated entities and the same amount of components of each type. That's no memory anyways.

  • Maybe change world loading a bit to be "after" the systems in the memory map. This goes in line with loading a level and then just rewinding memory the to where the systems left off.

Memory layout:

| - Systems | - Level v - Game << maybe have this one separately or before level as a system with a predefined heap allocator which the game can use to it's leisure?

  • Reload dynamically loaded dlls whenever they're touched. Might need to move debug memory load to platform layer so resources don't die?

  • For allocators:

    Not saying that we should do this everywhere. Pretty pleased with the global temp memory stuff, but where we want two different allocation strategies, for example for resource loading (autoloading for writing an editor vs permanent memory loading).

    struct Allocator { void* memory; void* (*alloc)(uint64 size, uint64 align); void (dealloc)(uint64 size, uint64 align); void (alloc_with_memory)(void memory, uint64 size, uint64 align); void (dealloc_with_memory)(void memory, uint64 size, uint64 align); }

void* bowtie::alloc(Allocator* allocator, uint64 size, uint32 align = memory::default_align) { return allocator->memory != nullptr ? allocator->alloc_with_memory(allocator->memory, size, align) : allocator->alloc(size, align); }

void bowtie::dealloc(Allocator* allocator, void* p) { return allocator->memory != nullptr ? allocator->dealloc_with_memory(allocator->memory, p) : allocator->dealloc(p); }

Style

  • Only do dumb data assignment for structs in constructors
  • Prefer namespaces of functions which operate on structs
  • Prefer splitting things into separate arrays of similar data to monolithic things
  • Prefer enums to bools
  • Templates are only used for collection classes.

Old todo

  • Renderer on separate thread
  • Resource manager for loading stuff
  • Shader loading
  • Image loading
  • Sprite rendering
  • Correctly scale sprites
  • Render world
  • State reflection of sprites
  • Implement Lua support
    • Create a C++-side world which has a handle to the render world
    • [/] Make it possible to specify dependencies (later to be dependencies on a level). I need a texture to load a sprite, and I'm not sure when or where to get that texture.
    • Create a world script interface which returns a world ptr
    • [/] Create a view script interface which returns a view ptr
    • Create sprite script interface
    • Make sprite SI take a world an manipulate that
    • Create a rendering interface which takes a world, view and all that jazz and then sends rendering commands using the rendering handles of those
  • Materials w/ shaders
  • Split engine and renderer into two
  • Text rendering
    • Create geometry for text
    • Update geometry when text or font changes
  • Make sure to remove hacks from combine_rendered_worlds and split it into multiple methods. Seems to be some haze with arrays of textures...
  • Change render resource handles in render_world to drawables
  • Make ResourceHandle::handle -> RenderResourceHandle (uint32 typedef ?). RenderResourceHandle -> RenderResource (remove render_ prefix). Move void* in ResourceHandle to Resource struct.
  • Shader refreshing
  • Remove bad lambdas
  • Depth sorting
  • Parenting with local transform and all that jazz
  • Break engine and gameplay script and resources apart. Make exe load a settings file which specifies lua boot file, or just always load main.lua or something. Also provide a command line option for specifying where the exe is (so you can debug from vs when devving).
  • Move game code to separate repository.

About

Old, dead, 2D engine in C++. Multi-platform and not really finished. Used for game "raket".

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published