I'm trying to work out a simple, functioning game engine, and I'm starting out as basic as I think I can get.
I have a virtual base class, Entity; the only child class I have for it currently is the Block class. I have a SceneManager class that contains a vector of Entity pointers, and with the Init() function, I attempt to populate it with Block objects, using an overloaded constructor. At first I thought it was because I did not have a corresponding overloaded constructor in the base class, but even when I added it, I got the same error:
-
LNK2019: unresolved external symbol "public: __thiscall Entity::Entity(void)" referenced in function "public: __thiscall Block::Block(short,short)"
-
This is my code:
Entity.hpp
[spoiler]
#pragma once
/* Entity.hpp
- base class for all entities
- also contains flag enumerations specifically for general entity and enemy-like types
*/
#include "Collision.hpp"
#include "Vector.hpp"
#include <Windows.h>
enum EnemyFlags
{
enInit = 0x01,
enAlive = 0x02,
enScared = 0x04,
enHiding = 0x08,
enBeaming = 0x10
};
enum EntityIDs
{
eIDBlock = 0x01,
eIDRed = 0x02,
eIDBlu = 0x04,
eIDGrn = 0x08
};
class Entity
{
static unsigned short Count;
public:
Entity();
virtual void Init() = 0;
virtual void Act() = 0;
virtual bool Alive() = 0;
virtual void Draw(const HANDLE) = 0;
virtual Collision Collide(Entity*) = 0;
const COORD GetPos() { return Position; };
const __int32 ID;
protected:
virtual void Move() = 0;
virtual void Die() = 0;
COORD* Beacon;
COORD Position;
Vector Velocity;
Vector Dimensions;
char Flags;
char Frames[4];
short CurFrame, EndFrame;
short FrameDelay, FrameTimer;
unsigned short Timer;
};
[/spoiler]
Block.hpp
[spoiler]
#pragma once
/* Block.hpp
- stores information about block objects
- contains a position and dimensions
*/
#include "Entity.hpp"
class Block : public Entity
{
public:
Block();
Block(short, short);
void Init();
void Act();
bool Alive();
void Draw(const HANDLE);
Collision Collide(Entity*);
const __int32 ID;
protected:
void Move();
void Die();
COORD Position;
Vector Dimensions;
Vector Velocity;
};
[/spoiler]
Block.cpp
[spoiler]
// Block.cpp
#include "Block.hpp"
#include <iostream>
Block::Block() :
ID (eIDBlock)
{
// empty for now
}
Block::Block(short x, short y) :
ID (eIDBlock)
{
Position.X = x;
Position.Y = y;
Dimensions.X = 16;
Dimensions.Y = 16;
Velocity.X = 0;
Velocity.Y = 0;
}
void Block::Draw(const HANDLE backbuffer)
{
SetConsoleCursorPosition(backbuffer, Position);
std::cout << char(219);
}
Collision Block::Collide(Entity* other)
{
// blank for now
Collision info;
info.Contact = false;
info.Intersection.X = 0;
info.Intersection.Y = 0;
info.Intersection.Z = 0;
info.OtherID = 0;
info.Velocity.X = 0;
info.Velocity.Y = 0;
info.Velocity.Z = 0;
return info;
}
void Block::Move()
{
// empty for now
}
void Block::Init()
{
// empty for now
}
void Block::Act()
{
// empty for now
}
bool Block::Alive()
{
return true;
}
void Block::Die()
{
// empty for now
}
[/spoiler]
SceneManager.cpp
[spoiler]
// SceneManager.cpp
#include <fstream>
#include "SceneManager.hpp"
#include "Block.hpp"
SceneManager::SceneManager():
hOut(GetStdHandle(STD_OUTPUT_HANDLE))
{
// empty for now
}
void SceneManager::Init(__int32 stateID, short info)
{
// depending on which state ID is given, it loads from an information file depending on info
for (short col = 0; col < 80; col++)
for (short row = 0; row < 25; row++)
Entities.push_back(new Block(col, row));
}
void SceneManager::Quit()
{
// empty for now
}
void SceneManager::Tick()
{
for (unsigned short i = 0; i < Entities.size(); i++)
Entities[i]->Draw(hOut);
}
void SceneManager::Save()
{
// empty for now
}
void SceneManager::Load()
{
// empty for now
}
[/spoiler]