HELIOS

C++ Game Engine [2D] (2019)
With Mario Clone

What Is Helios?


Helios is my 2D game engine created with the SDL 2 framework. The intent with the engine is to create the cleanest developer environment in code as I could make to allow me to create whatever game I want in future using the engine.

Tell Me More!


The engine represents my aspiration to create the most streamlined experience for the developer as I can make and builds further upon the techniques I developed in the engine I made for my game Firefly. For instance, Helios directly improves on the Firefly engine by having global access to the object pool allowing the developer to find other objects whenever they want. This is important for games as it allows objects to find and access variables that don’t belong to them. Another upgrade is the component system that the HActors have which allows developers to add any component they want and the engine will automatically deal with it without oversight. For instance, in Firefly engine you must explicitly state how the sprites would be drawn and when. This is abstracted away in Helios to allow the developer to focus on the game rather than the renderer.

What Could Be Improved?


The biggest problem I have with Helios is that everything is hard coded into the engine which doesn’t make it very new developer friendly. I think the engine would be much better if I added an external way to add maps and data through JSON or XML. I plan to do this for my next game engine in the future.

Conclusion


Personally, I am very proud of Helios and think there are a lot of techniques I developed for it that I will use in future.

Code Sample


Context: The coin particle is both a collectable coin that exists in the world and a temporary particle spawned by the questionmark block when hit. Which of those two it is, is set by the owner.

Spawn Code

				
CoinParticle *coinTmp = Helios::Objects::SpawnObject<CoinParticle>();
coinTmp->SetActorPosition(GetActorPosition());
coinTmp->bIsPickup = true;
				
				

CoinParticle.h

					
#pragma once

#include "Actor.h"
#include "SpriteComponent.h"
#include "HMarioCharacter.h"
#include "SoundObject.h"

class CoinParticle : public Actor
{
	SpriteComponent *sprite = nullptr;
	float deathTimer = 0;
	Vector2D vel = { 0,-1500 };
	float animTimer = 0;
	unsigned char divToDisplay = 0;
	HMarioCharacter *player = nullptr;
	SoundObject *coinAudio = nullptr;

	Vector2D middleOfSprite = {0,0};
	Vector2D playerMiddleOfSprite = { 0,0 };
public:
	CoinParticle();
	virtual ~CoinParticle();

	virtual void Begin() override;
	virtual void Update(float deltaTime) override;

	bool bIsPickup = false;
};
				
				

CoinParticle.cpp

					
#include "CoinParticle.h"

CoinParticle::CoinParticle()
{
	bShouldTick = true;	//Enables update function to be called every frame
	sprite = AddComponent<SpriteComponent>();
	sprite->SetTexture("Images/Coin.png");
	sprite->Divs.x = 3;

	vel = Vector2D(rand() % 500 - 250, -(rand() % 500 + 500));	//Set random velocity
	divToDisplay = rand() % 3;
	sprite->DivToDisplay.x = divToDisplay; //Set initial frame of sprite sheet to be displayed

	coinAudio = Helios::Objects::SpawnObject<SoundObject>();
	coinAudio->audio->channel = 3;
	coinAudio->LoadAudio("Audio/CoinSoundEffect.wav");
}

CoinParticle::~CoinParticle()
{
	coinAudio->Destroy(coinAudio);
}

//Called just before first update function call
void CoinParticle::Begin()
{
	if (bIsPickup)
	{
		//Get the player pointer for use later
		player = Helios::Objects::GetAllObjectsOfClass<HMarioCharacter>()[0];

		middleOfSprite = Vector2D((sprite->texture->GetWidth() / sprite->Divs.x) / 2,
									sprite->texture->GetHeight() / 2);
		playerMiddleOfSprite = Vector2D(player->spriteDims.x / 2, player->spriteDims.y / 2);
	}
}

//Called every frame if enabled
void CoinParticle::Update(float deltaTime)
{
	if (!bIsPickup)
	{
		if (deathTimer >= 2)
			Destroy(this);

		deathTimer += deltaTime;
		SetActorPosition((vel * deltaTime) + GetActorPosition());
		vel.y += deltaTime * 2000;
	}
	else
	{
		//If the player is colliding with coin
		if (Helios::Collision::Circle(player->GetActorPosition() + playerMiddleOfSprite,
										GetActorPosition() + middleOfSprite, 8, 8))
		{
			player->score += 1 + (rand() % 5);
			coinAudio->Play();
			Destroy(this);
		}
	}

	//Update animation
	animTimer += deltaTime;
	if (animTimer >= .1)
	{
		animTimer = 0;
		if (divToDisplay < 2)
			divToDisplay++;
		else
			divToDisplay = 0;

		sprite->DivToDisplay.x = divToDisplay;
	}
}
					
				  

Back
GitHub LinkedIn
© 2023 Arrien Bidmead