Pong

Retro

Project Overview

  • Project Type: Retro Console Game Clone
  • Role: Gameplay Programmer
  • Software: Visual Studio 2017
  • Languages: C++
  • Download link: Play Game
  • Programming Reel: Watch

Project Brief

Using James Mansfield's 2D engine. This retro game clone was a very interesting project to work on because I did two iterations on it. The first one using an object oriented approach with high emphasis on how classes were related to each other. The second one was using a component-based system to build independent and interchangeable modules.


Responsibilities/Achievements

  • - Implement a Component Base System to drive all game logic by analyzing every object and abstracting its properties and behaviours
  • - Calculate the collision between a circle and a box to determine the ball's bounce direction
  • - Use pure virtual functions to create en event-driven system to connect game entities, i.e. physics component with bounce component

Code Smaples


/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/

class GameObject
{
private:
	std::vector<Component*> mComponents;

public:
	GameObject() {}
	~GameObject() 
	{
		for (Component* pComponent : mComponents)
		{
			pComponent->Destroy();
			delete pComponent;
		}
	}

	void Initialize()
	{
		for (Component* pComponent : mComponents)
		{
			pComponent->Initialize();
		}
	}

	void AddComponent(Component* pComponent)
	{
		mComponents.push_back(pComponent);
	}

	template<class T>
	T* FindComponent(ComponentType eType)
	{
		for (Component* pComponent : mComponents)
		{
			if (pComponent->GetType() == eType)
			{
				return (T*)pComponent;
			}
		}

		return nullptr;
	}
};
										

/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/		

class Component
{
public:
	Component(GameObject* pGO): mGO(pGO) {}
	~Component() {}

	virtual ComponentType GetType() const = 0;
	virtual void Initialize() {}
	virtual void Destroy() {}

	GameObject* GetGameObject() const { return mGO; }

protected:
	GameObject* mGO;

	template<class T>
	void AddToComponentVector(std::vector& componentVector)
	{
		componentVector.push_back((T*)this);
	}

	template<class T>
	void RemoveFromComponentVector(std::vector& componentVector)
	{
		componentVector.erase(std::remove(componentVector.begin(), componentVector.end(), this), componentVector.end());
	}
};
										

/*
* Carlos Adan Cortes De la Fuente
* All rights reserved. Copyright (c)
* Email: dev@carlosadan.com
*/		
										
class COGBounce : public Component, public IPhysicsCollisionEvent
{
public:

	static std::vector<COGBounce*> mBounceComponents;

	COGBounce(GameObject* pGO) : Component(pGO) {}
	~COGBounce() {}

	virtual ComponentType GetType() const { return ComponentType::Bounce; }

	virtual void Initialize() override
	{
		AddToComponentVector(mBounceComponents);
		// Registers itself to the collision events
		mGO->FindComponent<COGPhysics>(ComponentType::Physics)->AddListener(this);
	}

	virtual void Destroy() override 
	{
		RemoveFromComponentVector(mBounceComponents);
	}

	virtual void OnCollision(COGPhysics* pMe, COGPhysics* pOther, exCollision collision) override 
	{	
		// Changes the velocity of the ball so it bounces off the surfaces
		exVector2& velocity = pMe->GetVelocity();

		float transformation = 2 * (velocity.x * collision.normalX + velocity.y * collision.normalY);
		collision.normalX *= transformation;
		collision.normalY *= transformation;
		
		velocity.x -= collision.normalX;
		velocity.y -= collision.normalY;
	}
};
// Init static vector
std::vector<COGBounce*> COGBounce::mBounceComponents;