Giter Club home page Giter Club logo

aether-game-utils's Introduction

aether game utils

Windows MacOS Emscripten Ubuntu clang Ubuntu g++

aether.h is a single-header collection of cross platform C++ utilities for quickly creating small games. Platforms currently supported are Mac, Windows, Linux, and Web. Core tenants of this library are to statisfy the (often times at odds!) goals of:

  • Providing useful and performant utilities tailored for game development
  • Providing utilities that naturally conform to game development best practices
  • Not overstepping or emposing a particular game engine architecture

Modules and utilities include:

Example

The following are instructions to get started with aether-game-utils. This example is a single source file which only includes aether.h (which handles linking the required system libraries). It has first person arrow key controls, textured geometry and basic kinematic physics.

Click To Play

main.cpp (or main.mm on Mac)

#define AE_MAIN
#define AE_USE_MODULES
#include "aether.h"
const ae::Tag TAG_RESOURCE = "resource";
extern const char* kVertexShader;
extern const char* kFragmentShader;

int main()
{
	ae::Window window;
	ae::GraphicsDevice graphicsDevice;
	ae::Input input;
	ae::TimeStep timeStep;
	ae::FileSystem fileSystem;
	window.Initialize( 640, 320, false, true );
	window.SetTitle( "Game" );
	graphicsDevice.Initialize( &window );
	input.Initialize( &window );
	timeStep.SetTimeStep( 1.0f / 60.0f );
	fileSystem.Initialize( "", "ae", "Game" );

	ae::VertexBuffer vertexData;
	ae::CollisionMesh<> collisionMesh = TAG_RESOURCE;
	ae::Texture2D tex;
	ae::Shader shader;
	shader.Initialize( kVertexShader, kFragmentShader, nullptr, 0 );
	shader.SetCulling( ae::Culling::CounterclockwiseFront );
	shader.SetDepthWrite( true );
	shader.SetDepthTest( true );
	const ae::File* geoFile = fileSystem.Read( ae::FileSystem::Root::Data, "level.obj", 2.5f );
	const ae::File* textureFile = fileSystem.Read( ae::FileSystem::Root::Data, "level.tga", 2.5f );

	ae::PushOutInfo player;
	player.sphere.radius = 0.7f;
	player.sphere.center = ae::Vec3( 0.0f, player.sphere.radius, 0.0f );
	float angle = 0.0f;
	float angularVel = 0.0f;

	auto Update = [&]()
	{
		const float dt = ae::Min( timeStep.GetDt(), 0.03f );
		input.Pump();
		if( input.GetPress( ae::Key::F ) )
		{
			window.SetFullScreen( !window.GetFullScreen() );
		}

		// Async load for web
		if ( geoFile && geoFile->GetStatus() == ae::File::Status::Success )
		{
			ae::OBJFile obj = TAG_RESOURCE;
			obj.Load( geoFile->GetData(), geoFile->GetLength() );
			obj.InitializeVertexData( { &vertexData } );
			obj.InitializeCollisionMesh( &collisionMesh, ae::Matrix4::Identity() );
			geoFile = nullptr;
		}
		if ( textureFile && textureFile->GetStatus() == ae::File::Status::Success )
		{
			ae::TargaFile tga = TAG_RESOURCE;
			tga.Load( textureFile->GetData(), textureFile->GetLength() );
			tex.Initialize( tga.textureParams );
			textureFile = nullptr;
		}

		graphicsDevice.Activate();
		graphicsDevice.Clear( ae::Color::White() );
		if ( fileSystem.GetFileStatusCount( ae::File::Status::Success ) == fileSystem.GetFileCount() )
		{
			// Input
			const ae::Vec3 forward( -cosf( angle ), 0.0f, sinf( angle ) );
			const ae::Vec2 mouse = ( ae::Vec2( input.mouse.position ) / window.GetWidth() ) - ae::Vec2( 0.5f, 0.15f );
			if ( input.Get( ae::Key::Up ) || ( input.mouse.leftButton && mouse.y > 0.1f ) ) { player.velocity += forward * dt * 20.0f; }
			if ( input.Get( ae::Key::Down ) || ( input.mouse.leftButton && mouse.y < -0.1f ) ) { player.velocity -= forward * dt * 20.0f; }
			if ( input.Get( ae::Key::Left ) || ( input.mouse.leftButton && mouse.x < -0.2f ) ) { angularVel += dt * 10.0f; }
			if ( input.Get( ae::Key::Right ) || ( input.mouse.leftButton && mouse.x > 0.2f ) ) { angularVel -= dt * 10.0f; }
			if ( input.Get( ae::Key::Meta ) && input.GetPress( ae::Key::F ) ) { window.SetFullScreen( !window.GetFullScreen() ); }

			// Physics
			player.velocity.SetXZ( ae::DtSlerp( player.velocity.GetXZ(), 2.5f, dt, ae::Vec2( 0.0f ) ) );
			angularVel = ae::DtLerp( angularVel, 3.5f, dt, 0.0f );
			player.velocity.y -= dt * 20.0f;
			player.sphere.center += player.velocity * dt;
			angle += angularVel * dt;
			player = collisionMesh.PushOut( ae::PushOutParams(), player );
			ae::RaycastParams raycastParams;
			raycastParams.source = player.sphere.center;
			raycastParams.ray = ae::Vec3( 0, player.sphere.radius * -1.1f, 0 );
			ae::RaycastResult r = collisionMesh.Raycast( raycastParams );
			if ( r.hits.Length() )
			{
				player.sphere.center = r.hits[ 0 ].position +  ae::Vec3( 0, player.sphere.radius * 1.1f, 0 );
				player.velocity.y = ae::Max( 0.0f, player.velocity.y );
			}

			// Rendering
			ae::UniformList uniforms;
			ae::Matrix4 worldToView = ae::Matrix4::WorldToView( player.sphere.center, forward, ae::Vec3( 0, 1, 0 ) );
			ae::Matrix4 viewToProj = ae::Matrix4::ViewToProjection( 0.9f, graphicsDevice.GetAspectRatio(), 0.5f, 10.0f );
			uniforms.Set( "u_worldToProj", viewToProj * worldToView );
			uniforms.Set( "u_tex", &tex );
			vertexData.Bind( &shader, uniforms );
			vertexData.Draw();
		}
		graphicsDevice.Present();
		timeStep.Tick();

		return !input.quit;
	};

#if _AE_EMSCRIPTEN_
	emscripten_set_main_loop_arg( []( void* fn ) { (*(decltype(Update)*)fn)(); }, &Update, 0, 1 );
#else
	while ( Update() ) {}
#endif

	// Terminate
	fileSystem.DestroyAll();
	input.Terminate();
	graphicsDevice.Terminate();
	window.Terminate();
	return 0;
}

const char* kVertexShader = R"(
	AE_UNIFORM_HIGHP mat4 u_worldToProj;
	AE_IN_HIGHP vec3 a_position;
	AE_IN_HIGHP vec2 a_uv;
	AE_OUT_HIGHP float v_depth;
	AE_OUT_HIGHP vec2 v_uv;
	void main()
	{
		v_uv = a_uv;
		gl_Position = u_worldToProj * vec4( a_position, 1.0 );
		v_depth = gl_Position.z / 10.0;
	}
)";

const char* kFragmentShader = R"(
	AE_UNIFORM sampler2D u_tex;
	AE_IN_HIGHP float v_depth;
	AE_IN_HIGHP vec2 v_uv;
	void main()
	{
		AE_COLOR = mix( AE_TEXTURE2D( u_tex, v_uv ), vec4( 1.0, 1.0, 1.0, 1.0 ), v_depth );
	}
)";

Building on Mac

Create a file called main.mm with the above contents and download aether.h, level.obj and level.tga to the same folder. Open the Terminal application. Type cd (with a space after it) and then drag the folder containing main.mm into the terminal window and press enter. With Xcode installed run the following:

clang++ -std=c++17 -fmodules -fcxx-modules main.mm && ./a.out

Building on Windows

Create a file called main.cpp with the above contents and download aether.h, level.obj and level.tga to the same folder. With Visual Studio installed, right click inside the containing directory and choose Open in Terminal. Run "C:\Program Files\Microsoft Visual Studio\20XX\EDITION\VC\Auxiliary\Build\vcvars64.bat", replacing 20XX with the year, and EDITION with Community etc. Finally build it with:

cl /std:c++17 -D_UNICODE -DUNICODE main.cpp

Building with Emscripten

Create a file called main.cpp with the above contents and download aether.h, level.obj, level.tga and index.html to the same folder. Change to the directory with the downloaded files. With emsdk activated run:

emcc -s MIN_WEBGL_VERSION=3 -s MAX_WEBGL_VERSION=3 -s ALLOW_MEMORY_GROWTH main.cpp -o index.js

You can run and play the result of the above command by running this in the same folder:

emrun index.html

Building on Linux

All utilities are currently supported on Linux except for windowing and graphics. Full windowing and graphics support is planned.

Games using aether game utils

Bella Lunaux: The Case of the Diamond Panther Tiara

Play in Browser

See on Itch.io

Dependencies

aether-game-utils's People

Contributors

johnhues avatar vkidd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

aether-game-utils's Issues

Support glsl layout qualifier

Update example/07_cube

const char* kFragShader = "\
	AE_IN_HIGHP vec4 v_color;\
	AE_IN_HIGHP vec4 v_pos;\
	layout(location = 0) out vec4 diffuseColor;\
	layout(location = 1) out vec4 depth;\
	void main()\
	{\
		diffuseColor = v_color;\
		depth = vec4( vec3( v_pos.z / v_pos.w ), 1.0 );\
	}";```

Fix freeing aeAudioData

It's not safe to free aeAudioData before aeAudio, and sounds much be stopped manually.

Should allocate/destroy aeAudioData from aeAudio. Destroy can handle proper cleanup.

audio example should also be updated!

Allow scaling of backbuffer

This feature was removed to fix awkwardness of when backbuffer size was set. It should probably always automatically fit the window, and a scaling factor and an aspect ratio should be set. An aeRenderTarget can be used when this behavior is not suitable.

These examples should be updated:
Sprites
TextInput

Windows linker warnings

LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library

Improve aeRender resizing interface

Currently aeRender uses the window size as the default backbuffer size. This can lead to getting unexpected values during initialization (before StartFrame is called).

aeFixedTimeStep vsync issue

When aeFixedTimeStep is set to 60 fps and a vsync of 30 is forced, it will cause simulation to run at half speed

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.