Coder Social home page Coder Social logo

pulcher's Introduction

Pulcher

pulcher

2D cross-platform (Windows/Linux) game inspired by Quake. This is the source-code repository, pre-built binaries exist at https://github.com/AODQ/pulcher-binaries , which provides rolling-release updates for every code commit.

The game is processed at a logical 90 frames per second, with 1 frame of latency to allow for interpolation to render at 90+ frames. The engine is built "from scratch", though it mostly just ties multiple libraries together. The engine is basically not seperable from the game, or, a different perspective, they are the same entity. However, it's not some hard-coded nightmare, and in the future it is definitely possible that the two are seperable.

Sokol is used to render OpenGL3.2 & EnTT is used for the entity-component system. These both drive the majority of Pulcher functionality. ImGui is used for development to allow prototyping of functionality to be very fast, which combined with hot-reloadable plugins make developing Pulcher very painless & easy.

physx

Code Philosphy

Code should be simple and data-oriented. There should be minimal implicit behavior, including hidden heap allocations. OO patterns like polymorphism & inheritance are also discouraged. It should be fast to compile code, so headers should generally avoid including other headers, favoring forward-declarations. Also dependencies should be minimal & carefully chosen, and built along-side the project. All code, with an exception to files that exist to hold data, should be 80-character width.

Some definitions of ambigous terminology;

  • 'size' in consts will usually refer to the number of bytes, whereas 'length' will refer to the number of elements. Though I have recently decided to stick with 'byteSize' to avoid confusion with std::vector::size.

Layout

Applications directory contains directories of every executable built by Pulcher. Right now it is just the client, but in the future it could be a server, launcher, etc. They provide minimal code, mostly just setting up environment from command line, initiating plugins, then using library/plugin code to process logic/graphics/etc.

Assets directory is private, if you want to create your own assets the structure is;

  • assets/base/config.json ; json file for pulcher configurations, not meant to be modified by user (optional)
  • assets/base/controller.config ; json file for controller input (meant to be modified by user)
  • assets/base/map/*.json ; Tiled maps
  • assets/base/spritesheets/data.json ; json list of files that contain spritesheet information

Docs directory provides documentation on the codebase, game-related documentation goes to https://github.com/AODQ/pulcher-binaries/wiki .

Libraries directory contains code to build static libraries that are useful to Pulcher in a generic manner;

  • libraries/animation contains the structure of the animation system
  • libraries/audio provides a system to allow multiple places of the codebase to trigger audio
  • libraries/controls parses controller configuration and performs controller logic
  • libraries/core provides core Pulcher functionality, such as entity structs for EnTT useage, configurations, enums, scene-bundle to pass Pulcher data around, etc
  • libraries/gfx provides useful utilities for GLFW, OpenGL, Sokol, spritesheets, etc
  • libraries/enet provides network utilities that are shared for client/server communication
  • libraries/physics provides a generic interface for physics interactions
  • libraries/plugin gives plugin information, such as function pointers, along with being able to load, reload, and free plugins
  • libraries/util provides generic non-Pulcher specific functionality

Plugins directory contains dynamic libraries that provide known C-ABI functions to Pulcher, which allows for hot-reloading and quick prototyping. Right now there is one single base plugin, which provides functionality for the base engine; extensions can be created by modders in the future to create their own plugins, which I assume will grab assets from assets/plugin-name/. See Creating Plugins section for more details;

  • plugins/base/animation contains the implementation of the animation system, which is very flexible & drives most of the animated components of Pulcher.
  • plugins/base/audio contains implementation of audio
  • plugins/base/entity contains implementation of Pulcher entities (weapons, players, etc)
  • plugins/base/map contains implementation of the Pulcher map, including loading & rendering.
  • plugins/base/ui contains DebugUiDispatch function, that along with containing some ImGui behavior (diagnostics, controls, etc) will dispatch every plugins DebugUiDispatch

The scripts directory contains generic scripts, mostly to quickly set up a development environment, updating the binaries repository, & testing that each binary launches.

third-party ; submodule repository of third-party libraries; some point to other submodules. Many of them have modifications.

Building

The build system uses only CMake. It relies on pulling from a lot of third-party repos, even if the library already exists on the system, which is not the best way to handle CMake in the majority of usecases. However, since Pulcher plans to be released in binary-form, it's most convenient for developers/modders IMHO that the libraries under third-party is built along-side Pulcher.

To build on Linux, you can either set up the environment manually or use the script/configure.py script to setup the build environment for multiple platforms (Linux, Windows 32-bit, Windows 64-bit). You will require Clang, MinGw (for cross-compilation to Windows) and Ninja to use them. You can set up the build environment manually too, just be sure to pass PULCHER_PLATFORM=Linux to CMake.

Simple example to build Linux binary on Linux;

mkdir pulcher ; cd pulcher
git clone https://github.com/aodq/pulcher repo
cd repo
git submodule update --init --recursive
cd ../
mkdir build install
cd build
cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release -DPULCHER_PLATFORM=Linux ../repo

Pulcher is officially built against Clang, but should also build against GCC without warnings.

To build on Mac, use clang and CMake, similar to the above example for building on Linux, except specify the PULCHER_PLATFORM as macOS

cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release -DPULCHER_PLATFORM=macOS ../repo

MacOS support is limited, and there maybe be dependency issues, in particular be sure to install/update GLFW on your system with homebrew.

I haven't tried building Pulcher on Windows, though besides possible MSVC errors, it shouldn't be difficult to set it up. But you probably won't be able to produce Linux binaries with MSVC, your best option is most likely to be to use the Windows Subsystem for Linux to build Linux binaries.

Creating Plugins

The best way to mod Pulcher is to use plugins. This is still in the design phase. Most likely how this will work is that for a plugin PluginTest, it must provide a C-ABI compatible functions;

  • void DebugUiDispatch(pul::core::SceneBundle &); - updates ImGui for developer purposes
  • `void Initialize(pul::core::SceneBundle &); - called when plugin is initialized
  • `void Shutdown(pul::core::SceneBundle &); - unloads the plugin
  • `void LoadMap(pul::core::SceneBundle &); - called when map is initialized, will probably also contain map information to load custom entities
  • void LogicUpdate(pul::core::SceneBundle &); - updates the game @ pul::util::MsPerFrame (16 ms/frame), used to update game-related logic
  • UpdateRenderBundleInstance(pul::core::SceneBundle &, pul::core::RenderBundleInstance &); puts logical information into a render bundle for rendering purposes
  • void Interpolate(float const msDeltaInterp, pul::core::RenderBundleInstance const & previousBundle, pul::core::RenderBundleInstance const & currentBundle, pul::core::RenderBundleInstance::outputBundle); outputs an interpolated bundle based on current/previous bundle and current msDeltaInterp; ei; mix(previous.playerPosition, current.playerPosition, msDeltaInterp);
  • void RenderInterpolated(pul::core::SceneBundle &); - used to provide custom rendering of the scene, can be called at any varying rate, thus the plugin itself must handle its own interpolation, but items within SceneBundle will already be interpolated

thus a plugin writer should generally expect this behavior;


void main() {
  // create scene
  ...

  plugin_Initialize(scene);

  // setup and create map
  ...

  plugin_LoadMap(scene);

  while ( ... ) {
    // update timing ...

    if (readyToComputeLogicalFrame) {
      plugin_Update(scene);

      plugin_UpdateRenderBundleInstance(scene, current);
    }

    // prepare interpolated bundle & rendering
    ...

    plugin_Interpolate(msDeltaInterpolate, previous, current, output);

    // setup rendering
    ...

    plugin_RenderInterpolated(scene, output);

    ...

    plugin_DebugUiDispatch(scene);
  }

  plugin_Shutdown(scene);

  // destroy scene
  ...
}

Plugins should generally otherwise communicate to Pulcher by using entt

pulcher's People

Contributors

aodq avatar jadematrix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

pulcher's Issues

Load / Render Maps

Will be able to load Tiled maps and then batch them in an appropiate manner so they can all be rendered out in a single draw call per texture/spritesheet. Layers would be rendered indiscriminately and use Z-buffer + depth discard in order to fix sorting issues.
2020-09-10-02:52:40.png

player sliding

adds player sliding, the animation doesn't have to be completely correct (like flipping and so forth), it's mostly just implementing the physics

  • crouch slide from standard input (run then crouch)
  • crouch slide from jump
  • test smilecythe

improve cJSON for our usecase

cJSON is fine but if had a function explicitly for loading cJSON from files, renaming functions, possibly adding RAII, etc then it would be much nicer. We could possibly wrap with pul::json too.

Engine / frame documentation

Documents how the engine / frames work, since I basically plan on doing everything double-buffered to add one frame of latency but at the same time will allow multi-threading.

additional physics nuances

  • velocity transfer scale for 90 degree turns:
    -- for example only 50% of hor speed transfers to vertical dashes
    -- for example only 25% of hor speed transfers to vertical wall jumps
  • curve from ground accel to air accel when falling off ledges (maybe after vertical jump also, but NOT hor jump)
  • minimum slide speed (similar to dash)
  • slide friction curve, from frictionless to normal friction
  • threshold and post-threshold equivalent for gravity acceleration (stop the player falling down like a bullet)
  • duration of zero gravity after dashes (ie. 200ms)
  • reverse velocity transfer scale (ie. falling speed to vertical dash or hor speed to horizontal dash)
  • distinction between every dash direction (dash cooldown only applies to one direction)
  • separate friction value for crouch (and/or air friction for crouch when moving to opposite direction)
  • slide cooldown after slide is over (so you can't spam slides consecutively)
  • allow slide animation to end without holding crouch, can cancel the slide by jumping or moving the opposite direction
  • make jumping on the ground reset the dodge air restriction (doesn't ignore cooldown time though)
  • test smilecythe

add air idle steering animation

adds air idle steering, thus when in air the legs steer / transition properly.

  • can steer legs in air idle
  • transition from "default" to "current" air idle state (for example if you fall off at a large speed)
  • transition to air idle using dash vertical

player slope climbing

allow players to 'climb' up/down slopes, instead of just treating it as a wall

  • test smilecythe

fix landing animation

if player lands while going fast, play the land animation then switch to idle.
if player runs while landing, switch to run animation when you've slowed to run speed.
(same logic if you land while walking or crouching)

  • aodq test
  • smilecythe test

Load spritesheets

Spritesheets should be loadable using the hot reloadable asseting loading system. There might need to be a structure inherit to this to get specific information from the spritesheets.

rename extern C plugin function names from Fn to SubsystemFn

Renames extern "C" plugin function names (that are global when dynamic linking without dlopen) to SubsystemFn, for example right now it would be:

ctx.LoadFunction(plugin.animation, "ConstructInstance");
plugin.animation.ConstructInstance(..);

and this is fine bc the ConstructInstance is not polluting global namespaces with plugins. However for windows, these plugins will just be linked in during the linker stage as a dynamic library, thus they pollute global namespaces so it should be as;

ctx.LoadFunction(plugin.animation, "AnimationConstructInstance");
plugin.animation.ConstructInstance(..);

fmod audio backend

adds fmod audio backend which simply has play music and play sound effect at different positions using imgui controls

give components of an animation tags

each component should be able to be tagged (with strings). This will give special behavior within the code, for example if something needs to be stalled while in mid-air

Networking Plugin Handling

This will allow plugins to be cross-compiled and reloaded to everyone connected to the master server, which will allow fast prototyping of features to anyone who is testing at the time.

In the future it will also be able to reload the application (for ABI-incompatible changes) and reload assets from the pulcher-assets repository.

  • Client / Server connection
  • Cross-Compile pulcher with same cmake build
  • Client sends message to Server whether it is windows or linux
  • server can force update of launcher / pulcher client / libs / plugins

Basic collision-detection testable weapon

These will be basic weapons only used to test collision detection with. There will be one test weapon with two firing modes

  1. hitscan test; on one single frame it performs a raycast to test for collision
  2. projectile test; projectile will be arced downwards from gravity, the delta-positions between each frame will have a raycast performed.

many settings should be configured by imgui (travelling speed, gravity, randomness, firing-rate, etc) in order to make sure the physics system is flexible and performant enough for our usecase

  • add weapon code structure / backend
  • add hitscan weapon firing mode
  • add projectile weapon firing mode
  • add imgui configurable options

flip UV coords

many systems have to flip uv coords upside down; if they were to just load in flipped then it would simplify these systems

Basic 'spectator' Player Movement

Player visible as an entity, with default 'spectator' controls. This would be something toggled as a debug option. The player will be able to fly to any location they want using WASD. It does not have to handle collision detection.

Fix MinGW/Windows build

Windows build currently fails, I believe this is an issue due to plugins. Possibly I will just disable "hot-reloading" for windows releases and link them dynamically thru CMake if I can configure the build to do that. I don't really need the feature to be supported on windows.

Hot-Reloadable Asset Loading

Assets (images, sound, etc) will be hot-reloadable as well, thus changes to the file the asset was stored in will automatically update it in the game.

pulcher launcher has meaningful options

pulcher launcher currently just tries to launch the client if possible and has no real control over what happens.

Instead there will be several input commands; nothing will be done by default

  • command check update
  • command download update
  • command launch pulcher
  • command help
  • command quit

Player Collision Detection

The player will handle collision detect on the walls while in flyout mode. We will have to figure out which points on the player model will act as collision points to raymarch from. This is perfect for testing collision detection as you can build up arbitrary speeds and fly yourself into the wall. This is only as a prototype so long as it can be proven that SDF + raymarching is sufficient to our needs.

particle system

Particles need to use same physics system and allow hundreds of particles with minimal performance impact. This doesn't necessarily imply adding any pulcher-specific particles.

Plugin Backend

Backend for plugins, which will allow hot reloading. A basic UI plugin will be used to display debug and diagnostic information of Pulcher.

  • add basic plugin loading backend
  • add/test plugin reloading
  • add basic user interface diagnostics (probably just framerate for now)

collision mask generator from textures for collision detection

SDFs can be easily generated from textures to have a very good approximation of the bounds, which will be useful later to apply raymarches to to allow accurate and fast collision detection. We will basically always be working with raycasts to handle our physics (particles, weapon firing, player vertices, etc). Because the game always works with tiles, it is essentially an acceleration structure in of itself and so the raymarching should be extremely cheap.

  • add physics query structure
  • add point-collision test
  • add raymarch-accelerated raycast test

Input controls

Input controls will be defineable in a JSON config file. In the future this could be set by keypresses in some configurable menu but that is not a big deal if this infrastructure already exists.

manual VSync

The game should be ran in fixed-step time calculations, with interpolation to allow higher framerate. The game will basically process multiple cycles if it is lagging behind.

Entity system

I don't think we necessarily need a full-blown entity component system, but regardless, entities should be a vital component of the game and how we add players, items, scripted map events, and more to the game. It allows updating and rendering of dynamic entities.

It does not compose of specialized rendering features;

  • particles (which need to be accelerated to not become a performance issue)
  • map (which composes of all static entities)
    maybe more

Launcher application

Cross-platform launcher that handles updating the application, thus only the launcher needs to be distributed and all testers will get the updates as necessary.

add Tracy profiler, imgui log and imgui docking

add imgui tracy profiler which will help profiling the entire application and identify bottlenecks.
also add imgui log and imgui docking support to allow full imgui dev / debug support.

  • tracy profiler
  • imgui docking
  • imgui logging

Rendering Backend

Research / select a rendering backend. Either I can do a custom renderer (OpenGL3.3 & OpenGL4.6 code paths) or use a cross-platform rendering backend with support for DX12, Vk, and OpenGL. As long as there is a working code path that renders ImGui on OpenGL3.3 hardware we should be fine, but an additional VK backend or OpenGL4.6 backend would be useful for future performance improvements.

Basically the options boil down to custom (which is simple enough TBH the only difficulty is managing two different API versions), BGFX or DiligentEngine. If I do OpenGL3.3/4.6 then on HW that supports 4.6 I would in the future be able to optimize many draw calls away.

fix player leg turning animation

right now the leg turn is not implemented with the correct logic. It isn't for when velocity changes (there are run backwards/walk backwards animations) -- it's for when moving facing direction left/right w/ mouse

  • add run backwards animation
  • add walk backwards animation
  • fix walk turning logic
  • fix run turning logic

player movement

adds the base for player movement (walking, running, jumping, crouching, etc)

server sends updates to one client only

server sends update information to one client only. It will be able to send metadata as well to clients to check for necessary file updates and so forth.

tilesheet optimizer

The optimizer will remove all unnecessary portions of a spritesheet (empty spaces etc) as well as potentially combining multiple spritesheets into a mega-spritesheet that will allow rendering more entities with less draw calls

player walljumping

  • two distinctive walljump types, horizontal (when holding opposite movement key only) and vertical (when holding only jump or jump+left/right)
  • respective theta and acceleration variables for each walljump type (or theta only and just use normal jump values)

player animations

Many parts of the player need to be animated properly in different conditions. Many of these should be configured from a json file to allow it to be flexible for other animations. Not every component will be animated, as there are many special conditions and variables to consider. This will support the basics; standing, walking, running, jumping, crouching, and aiming.

  • add necessary player animations to json file format
  • load all player animations in json file format in a generic enough manner to be used for other animations
  • render out player animations
  • standing/walking animation cycle
  • rotate hands to aim
  • save JSON file thru animation editor
  • flip body on left/right movement

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.