Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Jabberwocky

Pages: 1 ... 5 6 [7] 8 9 ... 11
91
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 20, 2015, 10:39:33 pm »
True, but as a user of such an ECS you have to be aware that any change to the structure of the components (their addition or removal) invalidates all component pointers and references. That's why you would re-acquire a pointer from the handle.

Totally agreed.  That's all I was saying, too. 

92
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 20, 2015, 10:26:27 pm »
Yep, honestly for a smallish-type game, I think your more simple ECS approach is probably best, Elias.  Like I said earlier, it gives all the flexibility of an ECS, a clean simple solution, but just not the performance benefits (which you likely don't need).


Where do you get the "bitwise copy" notion from?
The default copy ctor does not do a bitwise copy - it does a member by member copy.
And if you are memcpy()'ing (a bitwise copy) an object, then it better be std::is_pod.

What exactly do you mean?

Oh, yeah sorry.  That was confusing on my part.

What I mean is that normally the constructor, copy constructor, assignment operator and destructor is where you would (de)allocate new memory, if needed.  For example, let's say I have an ActiveEffects component, which stores what effects (e.g. spells in an RPG) an entity is currently affected by.

// This is a component which stores effects on an entity
class ActiveEffects
{
private:
   // These are the individual effects which this entity has.
   // e.g. Maybe I cast a spell called "wind runner" on myself that makes me run fast.
   // I need Effect* pointers because there are different kinds of Effect subclasses,
   // e.g.  MoveSpeedEffect, AttributeBoostEffect, etc.
   std::vector<Effect*> m_effects;  
};

Normally, you'd see those pointers and think, I need to write a whole lot of constructor/copy constructor/assignment operator/destructor logic, or I might end up with memory leaks or duplicate pointers. 

For example, your copy constructor might look like this:

ActiveEffects::ActiveEffects(const ActiveEffects& i_rhs)
{
   std::vector<Effect*>::const_iterator it = i_rhs.m_effects.begin();
   std::vector<Effect*>::const_iterator end = i_rhs.m_effects.end();
   for(; it != end; ++it)
   {
      const Effect* pOriginal = *it;
      // This next line doesn't even actually work, because Effect* is pointing at
      // a subclass, but you get the idea...
      Effect* pCopy = new Effect(*pOriginal);
      m_effects.push_back(pCopy);
   }
}
 

So, now every time your vector of ActiveEffect components moves in memory, the copy constructor and destructor is called on every each one.  This is a whole bunch of newing in the copy constructor, and a whole lot of deleting in the destructor.  That's really stupid, because we aren't changing any effects.

Move constructors can solve this.  But now every component in the game, and every data member they contain needs to have:
  • assignment operator
  • move assignment operator
  • copy constructor
  • move constructor

That's fine, and that's what they're designed for.But my approach is to skip all of those.

The default copy constructor does exactly what I want - it copies the pointers without newing or deleting the Effects.  But that means I can't delete any memory in the destructor (if I did, I would delete all my Effects every time the ActiveEffects vector grew).  Instead, I put my destructor logic in a function called Component::Destroy(), which is called by the ComponentSystem whenever we actually want to destroy a component, rather than just moving it.

Haha, wow this thread is going crazy.  2 new posts while I was typing this up!  Interesting game and tech discussion, I guess.  :)

93
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 20, 2015, 09:46:05 pm »
How do I store different components in one vector?

Ahh, right!  I somehow missed that you stored your components in the Entity, rather than in the system.  As dabbertorres pointed out (heh), this only works if you store your components in a system, not in the entity.

So there's a system for each component type, e.g. PhysicsSystem which stores a vector of Physics components, e.g.

class PhysicsSystem
{
public:
   // called per-frame.
   // iterates over and updates every Physics component in the game as required
   void Update();

   // retrieve a Physics component
   // simple implementation, in real life you'd want bounds checking
   Physics* GetPhysics(unsigned int index) { return m_physicsComponents[index]; }

   Physics*  CreatePhysics(...);
   void DestroyPhysics(unsigned int index);

private:
   std::vector<Physics> m_physicsComponents;
}
 

You can use c++ templates to make this work for any component in the game, although again this approach is more complex than you need for many types of games.

An Entity is then just a collection of components like this:

enum ComponentType
{
   Physics,
   Graphics,
   // etc...
};

class Entity
{
private:
   // Maps a ComponentType to the index of the component, which must be looked up
   // via the corresponding ComponentSystem.
   // (This particular implementation does not support multiple components of the same type.)
   std::map<ComponentType, unsigned int> m_components;
};


1.  It invalidates any Component pointers or references which may currently be in use by your gamesystem code, since the vector moves in memory.  This can lead to some nasty dangling pointer/reference bugs if you're not very careful about when you add components to the vector, in relation to when you operate on components within the vector.
As a solution to this problem, typical ECS implementations use a sort of handles (e.g. integers containing information to index) instead of pointers and references.

For sure, handles are the way to go.  But even then you can run into trouble.  At some point, you need to turn a handle into a pointer or a reference to call functions on it. 

Here's an example of where you might get into trouble.

void SummonPet(Entity* pEntity)
{
   // ...

   // check my Mana component (or Vitals component, or whatever) to see if I have
   // enough Mana to summon the pet.
   int nManaToSummon = 10;

   Mana* pMana = ManaSystem::GetMana(pEntity);
   if (pMana->GetCurrent() < nManaToSummon)
   {
      return false;
   }

   // ... code to create pet entity here ...

   // decrement mana
   pMana->DecrementCurrent(nManaToSummon);
   // *** CRASH ***
   // The ManaSystem's vector of Mana component may have shifted,
   // because we created a new Entity (the pet) which may itself have required a Mana
   // component, and called ManaSystem::CreateMana.  This invalidates our pMana
   // pointer (dangling pointer bugs, ew!).

   return true;
};
 

____________

re:  move constructors and move assignment operators:

Yep, this is totally one way to solve the problem.

Another way is to just rely on the default destructors and constructors (bitwise copy), for your components, and control your component's lifetimes with a Component::Init() and Component::Destroy() function, which is where you would handle any dynamic mem allocation, for instance.

94
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 20, 2015, 05:19:29 pm »
I hope you don't mind a bit more discussion on ECS. 

Overall, our implementations of ECS seem pretty similar.

One minor, although significant difference is that you store a vector/array of pointers to components.  That will be totally fine for a game which doesn't have a huge number of entities/components operating at once, as looks to be the case with your game, given that it works screen by screen.

For a game that does process a huge number of entities at once, say a large, dynamic, open world game with entities that continue to operate while off-screen, you would lose some performance because of the pointers.  It's a cache miss problem, because while the pointers are arranged sequentially in memory, the actual component data is not.  So when a system iterates over an array of components, it's jumping all over memory.

It's more optimal to store a straight up array of components, not component pointers.  i.e.

class ComponentSystem
{
private:
   // not this:
   // std::vector<Component*> m_components;
   // but this:
   std::vector<Component> m_components;
};

Then, when you iterate over m_components, it's all sequential memory, which is really fast.  The biggest problem with this approach is that when m_components grows, as can happen when you add new elements, two tricky things happen:

1.  It invalidates any Component pointers or references which may currently be in use by your gamesystem code, since the vector moves in memory.  This can lead to some nasty dangling pointer/reference bugs if you're not very careful about when you add components to the vector, in relation to when you operate on components within the vector.

2.  It calls constructors and destructors on every component in the vector, which can lead to unintended consequences if you treat your constructors and destructors as meaning the entity/component is being created and destroyed in a gameplay sense.

Bottom line, arrays of pointers are easier (avoiding the problems above), provide all the flexibility of an ECS, and work great for most games.  They do lose some of the performance benefits of an ECS, but that's only important for a few kinds of massive, open world games.  So this is not a critique of your approach at all (it seems really good!), just some of the thoughts I've had. 

95
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 20, 2015, 12:46:50 am »
Looks great, Elias.  Thanks for sharing.

I enjoyed your write-up on the ECS model you're using.  I'm also using ECS.  It can be a bit of work t get set up properly.  But once you do, there's massive flexibility in designing different kinds of game objects.  I doubt I'd ever go back to using anything different.

96
General discussions / Re: SFML 2.3 released!
« on: May 20, 2015, 12:21:55 am »
Gratz guys, thanks for all the hard work!

97
System / Re: Single or separate axis for Xbox controller
« on: May 07, 2015, 07:02:33 pm »
Thanks Laurent.

I found some more info on this. 
http://en.wikipedia.org/wiki/DirectInput#Xbox_360_Controller_support

Quote
An Xbox 360 Controller, with the default Microsoft driver, has the following limitations with DirectInput, compared to XInput:

- the left and right triggers will act as a single axis representing the signed difference between the triggers, not as independent analog axes
- vibration effects will not operate
- querying for headset devices will not operate

None of these limitations exist if using the Xbox 360 Controller with XInput.

Given what I know of SFML's philosophy, I doubt there's any interest to provide an XInput back-end to support XBox controllers, which is understandable.  It's a Microsoft design blunder (there is some discussion of this on the wiki linked above).  But the single axis is an annoying limitation. 

98
System / Re: Single or separate axis for Xbox controller
« on: May 07, 2015, 05:41:07 pm »
Cool, thanks eXpl0it3r.
I'll give that a shot when I pick up an x-box controller (busted my old one).

99
System / Re: Single or separate axis for Xbox controller
« on: May 07, 2015, 05:05:29 pm »
Single axis (Z) in 2.2 and older.  :( :( :(

That does suck.

That means you can't use the triggers as buttons, as many games like to.  For example, a game in which left trigger is "aim" and right trigger is "fire".  The problem is because if both triggers are pressed at once, they cancel each other out, and report a 0 (neutral) axis value, the same as if neither are pressed.

I was worried that might be the case.  I once read that you need to use XInput to properly detect each trigger separately, although I can't verify that for certain.

100
System / Re: Single or separate axis for Xbox controller
« on: May 07, 2015, 04:21:19 pm »
Your definition of "hijack" and "unrelated" must be slightly different than mine.  ;)


101
System / Re: Single or separate axis for Xbox controller
« on: May 07, 2015, 03:31:47 pm »
I've split this topic. Next time please don't necro a 5 year old thread to ask a completely unrelated question!

Weird, I thought I posted it in this recent and related thread:  http://en.sfml-dev.org/forums/index.php?topic=17898.0
Apologies, I'm not sure what went wrong, or what thread I necro'd.

102
System / Single or separate axis for Xbox controller
« on: May 07, 2015, 06:57:53 am »
Does anyone know if SFML treats the xbox controller triggers as a single axis, or two separate axes?

103
Graphics / Re: Text drawing problem, characters missing
« on: April 15, 2015, 07:40:59 pm »
Very cool old-school rogue-like you've got going on there.  They came in many flavors, but back in the day I played some versions called Moria and Angband.

The problem is simple.  It's your font.  You need a fixed width font, also sometimes called a monospace font.  Google either of those terms and you will find some to your liking.

Then replace "arial.ttf" "somefixedwidthfont.ttf" and you're good to go.

104
Graphics / Re: GL_MAX_TEXTURE_IMAGE_UNITS?
« on: April 15, 2015, 08:27:42 am »
\glGetString() with GL_VENDOR and GL_RENDERER will return strings like "Microsoft Corporation" and "GDI Generic" respectively. If you see any of those, chances are the user didn't bother to install proper drivers themselves or their OEM lied to them and/or simply don't care when they provided their driver package for download. The latter case is easier to answer: Never buy hardware from them again. :P The former case is a bit trickier. The first half of the problem is informing the user that there might be something wrong, the second half is getting them to acknowledge there is something wrong and take corrective measures. If they do choose to perform corrective action, I can imagine opting to open a browser pointing to either the AMD or Nvidia driver download pages to save them the hassle of searching themselves.

Much appreciated.

I'm not too worried about the stubborn/ignorant people.  I'll just make sure to very clearly indicate up to date graphics drivers are necessary in the system requirements.  Beyond that, I won't feel guilty if someone refuses to follow a few simple steps that should be part of any gamer's regular routine.

About Steam and driver updates -
Now that you mention it, I definitely recall Steam telling me a new driver was available.  I just can't remember whether it was on Linux or Windows.  I just booted up steam (windows), and see that there's a menu option:  Steam > Check for Video Driver Updates

Provided that works as advertised, that makes support quite a bit easier.

105
Graphics / Re: GL_MAX_TEXTURE_IMAGE_UNITS?
« on: April 14, 2015, 08:56:22 pm »
Packaging a default DirectX driver and a barely usable OpenGL driver is just as bad as packaging Internet Explorer without any alternatives with a default installation of Windows.

Yeah, I have read that the default OpenGL drivers on windows boxes are crap.

From opengl.org

Quote
Without drivers, you will default to a software version of OpenGL 1.1 (on Win98, ME, and 2000), a Direct3D wrapper that supports OpenGL 1.1 (WinXP), or a Direct3D wrapper that supports OpenGL 1.1 (Windows Vista and Windows 7). None of these options are particularly fast, so installing drivers is always a good idea.

In your experience, what has been the general approach of OpenGL-based software on windows?  Simply some kind of instructions to update your drivers, perhaps on the website?  And probably a crap-ton of support cases of people who ignored those instructions and are experiencing terrible performance?  Or is there some better way of handling it?

I really wonder how Vulkan support on Windows will turn out to look like. It is a direct competitor to DirectX 12, so there is already an obvious motivation to hinder its proliferation from the get-go.

Yep, there's a battle brewing for sure. I doubt we'll see MS change their tactics on this.

That's the thing, since SFML is licensed under zlib, there is no obligation to even mention it in your final software. People around here have been working hard to track down projects that do indeed make use of SFML, and all I can say is that there doesn't seem to be a lack of them.

Is this the list?

For sure, I don't mean to dismiss those lightly.  There's a couple in there I'm pretty excited about.  I've got a feeling moonman is going to do quite well.  I chipped in to it's kickstarter.

And about "build it, and they will come": SFML is not a for-profit organization. I don't see any need to lure new developers into using it, for whatever reason one could think of.

Yeah, totally.  I get it. 

Non-profit open source is interesting in its relationship between the creators and users.  I imagine there is usually some desire to see FOSS used in cool projects.  But there is certainly no obligations to serve users in any way.

Also, about the console support: I think indie developers who come to SFML asking if it supports consoles underestimate the amount of effort/money it takes to support them, both on SFML's side and the developer's side.

Totally agreed.


Pages: 1 ... 5 6 [7] 8 9 ... 11