Advice

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Advice

Post by MrGodin » February 24th, 2017, 8:53 am

I was listening to a cppCon speech and they were talking about Data tables and from what i could imagine it seemed something like this ... maybe?. Am I on the right track with this. I kinda like it.

Code: Select all

#include "includes.h"

enum class EnemyType
{
	blob,
	cactus,
	bird,
	numEnemy
};
struct Enemy : public sf::Drawable, public sf::Transformable
{
	int m_hitpoints;
	int ID;
	EnemyType m_type;
	sf::Vertex m_quad[4];
	sf::Texture m_texture;
	Enemy()
	{

	}
private:
	virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
	{
		states.transform *= getTransform();
		states.texture = &m_texture;
		target.draw(m_quad, 4, sf::Quads, states);
	};
	
};
class EnemyTable 
{
	Vec2f m_size = { 64.0f,64.0f };
	sf::Texture m_texture;
	std::vector<int> m_indices;
	
public:

	EnemyTable(std::string textureFileName,float tileSize)
	{
		
		m_texture.loadFromFile(textureFileName);
		m_indices.resize((m_texture.getSize().x / tileSize)*(m_texture.getSize().y / tileSize));
		m_entity.resize((int)EnemyType::numEnemy);
		for (int c = 0; c < m_indices.size(); c++)
			m_indices[c] = c;
		m_entity[(int)EnemyType::blob].m_hitpoints = 10;
		m_entity[(int)EnemyType::blob].m_type = EnemyType::blob;
		m_entity[(int)EnemyType::blob].m_texture = m_texture;
		m_entity[(int)EnemyType::blob].m_quad[0].texCoords = Vec2f(m_indices[0]*tileSize, m_indices[0] * tileSize);
		m_entity[(int)EnemyType::blob].m_quad[1].texCoords  = Vec2f(m_indices[0]+1 * tileSize, m_indices[0] * tileSize);
		m_entity[(int)EnemyType::blob].m_quad[2].texCoords = Vec2f(m_indices[0]+1 * tileSize, m_indices[0]+1 * tileSize);
		m_entity[(int)EnemyType::blob].m_quad[3].texCoords = Vec2f(m_indices[0] * tileSize, m_indices[0]+1 * tileSize);

		m_entity[(int)EnemyType::cactus].m_hitpoints = 10;
		m_entity[(int)EnemyType::cactus].m_type = EnemyType::cactus;
		m_entity[(int)EnemyType::cactus].m_texture = m_texture;
		m_entity[(int)EnemyType::cactus].m_quad[0].texCoords = Vec2f(m_indices[1] * tileSize, m_indices[1] * tileSize);
		m_entity[(int)EnemyType::cactus].m_quad[1].texCoords = Vec2f(m_indices[1] + 1 * tileSize, m_indices[1] * tileSize);
		m_entity[(int)EnemyType::cactus].m_quad[2].texCoords = Vec2f(m_indices[1] + 1 * tileSize, m_indices[1] + 1 * tileSize);
		m_entity[(int)EnemyType::cactus].m_quad[3].texCoords = Vec2f(m_indices[1] * tileSize, m_indices[1] + 1 * tileSize);

		m_entity[(int)EnemyType::bird].m_hitpoints = 15;
		m_entity[(int)EnemyType::bird].m_texture = m_texture;
		m_entity[(int)EnemyType::bird].m_type = EnemyType::bird;
		m_entity[(int)EnemyType::bird].m_quad[0].texCoords = Vec2f(m_indices[2] * tileSize, m_indices[2] * tileSize);
		m_entity[(int)EnemyType::bird].m_quad[1].texCoords = Vec2f(m_indices[2] + 1 * tileSize, m_indices[2] * tileSize);
		m_entity[(int)EnemyType::bird].m_quad[2].texCoords = Vec2f(m_indices[2] + 1 * tileSize, m_indices[2] + 1 * tileSize);
		m_entity[(int)EnemyType::bird].m_quad[3].texCoords = Vec2f(m_indices[2] * tileSize, m_indices[2] + 1 * tileSize);


	}

public:
	
	Enemy operator ()(EnemyType m_type,Vec2f position)
	{
		Enemy e = m_entity[(int)m_type];
		e.m_quad[0].position = Vec2f(position.x, position.y);
		e.m_quad[1].position = Vec2f(position.x + m_size.x, position.y);
		e.m_quad[2].position = Vec2f(position.x + m_size.x, position.y + m_size.y);
		e.m_quad[3].position = Vec2f(position.x, position.y + m_size.y);
		return e;
	};
private:
	std::vector<Enemy> m_entity;
	
};
Used like this
EnemyTable table("image.png",64.0f);
Enemy e = table(EnemyType::blob,Vec2f(100.0f,100.0f));
Curiosity killed the cat, satisfaction brought him back

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Advice

Post by albinopapa » February 24th, 2017, 4:24 pm

My only advice would be to either switch the 'enum class' to regular 'enum', just for sanity's sake. Having to cast to int each time would kill me. I'd at least make a convert function, maybe one that is constexpr.

Code: Select all

constexpr int ToInt( EnemyType Type )
{
     return static_cast<int>( Type );
}
Or, you could also do something like:

Code: Select all

namespace EnemyType
{
     constexpr int blob =  0;
     constexpr int cactus = 1;
     constexpr int bird = 2;
     constexpr int numEnemy = 2;
}
This has the same basic idea as the enum class, but already has defined integral operators. The constants become scoped to the EnemyType namespace, and to me, since you are using them as ints, it would make sense to use ints.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: Advice

Post by MrGodin » February 24th, 2017, 5:02 pm

My only advice would be to either switch the 'enum class' to regular 'enum', just for sanity's sake. Having to cast to int each time would kill me. I'd at least make a convert function, maybe one that is constexpr.
Yeah, i thought of it half way through , but thought, meh i will only write it once. But, having said that, i think i'll refactor to your namespace idea. Thanks :)
Curiosity killed the cat, satisfaction brought him back

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Advice

Post by chili » February 25th, 2017, 1:18 pm

For stuff like that I'd probably prefer a solution with an (unordered)map of string keys to do what I want. If you got it set up with factories, can map string to std::function and init with lambdas. For a small scale project just even inheritance is fine for me though. Larger scale I'd go the route of having stuff in external data files and loaded in I guess.

Still, that solution isn't terrible imo, it'll do.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Advice

Post by albinopapa » February 25th, 2017, 7:09 pm

Ooo, what about using std::map and having the key be the enum class, and it's value would be the int it represents.

No casting, maybe except for initialization. No string based searches.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: Advice

Post by MrGodin » February 26th, 2017, 12:45 am

Well, i've been playing around and come up with stuff

Code: Select all

// to me, no different than just going m_Enemies(1,{10.0f,10.0f}); 
std::function<Enemy(int, Vec2f)> GetEnemy = m_Enemies;


// seemingly nonsensical 
std::unordered_map<int, std::function<Enemy(int,Vec2f)>> map2;
map2[0] = m_Enemies;
auto& GetEnemy2 = [&map2](int a,Vec2f pos)
	{
		return map2[a](0, pos);
	};

// makes more sense
std::unordered_map<int, Enemy> map;
map[0] = m_Enemies(0,Vec2f(10.0f,10.0f));
Curiosity killed the cat, satisfaction brought him back

Post Reply