Advertisement

Question about health bars

Started by April 09, 2016 03:12 PM
13 comments, last by Alberth 8 years, 9 months ago

Having doubts is good, it shows you aren't afraid to question your own beliefs :)

Maybe you can expand your explanation a bit. Some questions to help you on your way. You may not be able to answer all the questions (I added a few that can be difficult to answer). The main idea is to help you in getting insights of what you did. If you don't want to give the answer here, or only the executives summary, that's fine.

- What was the original reason to introduce your overall GameObject? (What problem was it supposed to solve?)

- What are you using actually using the std::map for in your game now? (Time has funny ways to change goals, it never hurts to check actual usage)

(a short code example of it is probably useful if you post about it)

- Does it do its job well?

- What are its problems?

- What do you need to fix that problem?

- Should it do other jobs too?


It's fine that you're a fan, but to a beginner this is just highly confusing. Please try to keep things as simple as possible in this forum.

You're right, of course. I just know that the OP was having issues with domain modeling in a previous post, so I figured I'd share a relevant trick WRT to domain modeling here.

You(null;) seem to have already solved your problem but I still have some doubts about this issue ( being a beginner myself ).

When I experienced this problem of object references, I created a GameObject class which was the parent of all game objects. The game object class had no default constructor but one constructor which takes a string argument. The GameObject class also consisted of a std::map from string to GameObject. So, in the constructor the object created was added to the map with the string argument as its id. The GameObject class also consisted of a static method 'get' which returned a object given its id.

I don't know whether my approach is correct, so I'm not recommending it to anyone but instead asking for expert review since after this discussion I'm doubtful about my approach. Please review!

The problem in this method seems to be about downcasting to the real type of object( Since I'm using C++ not Java ). Since I never felt the need of downcasting ( I put all the usual methods in GameObject class itself ) I didn't ponder more over this issue. But now I'm looking for correcting my approach.

There's nothing wrong with having a lookup table (std::map) of all game objects. In fact, in some designs, it may be necessary. In time you'll probably learn of a better way to do this, or ways to avoid it. But if it's working fine right now, and it's making your life easier to have it, there's not really any good reason to try and eliminate it. One way you could make this better is to have integer IDs instead of strings, it will make lookup much faster because it requires only one comparison per entry.

It should be rare for downcasting to be necessary if virtual functions are provided for most cases in the base class. It's unlikely you'll run into a situation where downcasting can be avoided by eliminating the lookup table, either.

Advertisement

Thank you all for the help! But as you may have doubts, I feel quite content with my method :D I'd be completely open to other suggestions if my method wasn't efficient or serving its purpose :P

But I really appreciate all the help!

Having doubts is good, it shows you aren't afraid to question your own beliefs :)

Maybe you can expand your explanation a bit. Some questions to help you on your way. You may not be able to answer all the questions (I added a few that can be difficult to answer). The main idea is to help you in getting insights of what you did. If you don't want to give the answer here, or only the executives summary, that's fine.

- What was the original reason to introduce your overall GameObject? (What problem was it supposed to solve?)
- What are you using actually using the std::map for in your game now? (Time has funny ways to change goals, it never hurts to check actual usage)
(a short code example of it is probably useful if you post about it)
- Does it do its job well?
- What are its problems?
- What do you need to fix that problem?
- Should it do other jobs too?


First of all, thanks for trying to clear my doubts, I'll to answer all the questions in a descriptive manner this time.
I'm rewriting all the question one by one followed by their answers.

Q1) What was the original reason to introduce your overall GameObject? (What problem was it supposed to solve?)
Originally I had created the GameObject class as an interface for all game objects. So that I can implement Polymorphism for various general tasks related to game objects.

Q2) What are you using actually using the std::map for in your game now? (Time has funny ways to change goals, it never hurts to check actual usage)
(a short code example of it is probably useful if you post about it)
Here are all the snippets consisting the std::map. (I'm using namespace std)


map<string, GameObject*> GameObject::objectMap;

void GameObject::addObject(string id, GameObject* obj)
{
	objectMap[id] = obj;
}

GameObject* GameObject::get(string id)
{
	return objectMap[id];
}

Q3) Does it do its job well?
Assuming you are talking about std::map and assuming you are talking about its efficiency.
Then I think integers would have worked better. And hence I should have created a enum of object names, right?
Or is this not what you are asking?

Q4) What are its problems?
One: The one which I mentioned above about efficiency.
Two: It becomes more complicated if I'm not sure how objects I'm generating of each type. Since I cannot at that time use enums.
Three: Downcasting!!!

Q5) What do you need to fix that problem?
For fixing problem one mentioned above: Using integers for increase in performance
For Problem 2) Stick with strings, so that I can append nos to them. Or maybe I can use some other type of container...
For Problem 3) Think of some way to do the downcast, or maybe the eliminate the need of downcasting completely! (I don't think is always possible, so my doubt :( )

Q6) Should it do other jobs too?
Well, this one is kinda hard to understand.
But I think the map should also hold the type information about the game objects its holding!

(Its a wonder how a little bit of thinking and structured questioning can help us understand out problem better! Awesome help I'll remember it forever. Please tell if I've answered some questions wrongly or incompletely)


It's fine that you're a fan, but to a beginner this is just highly confusing. Please try to keep things as simple as possible in this forum.

You're right, of course. I just know that the OP was having issues with domain modeling in a previous post, so I figured I'd share a relevant trick WRT to domain modeling here.

You(null;) seem to have already solved your problem but I still have some doubts about this issue ( being a beginner myself ).

When I experienced this problem of object references, I created a GameObject class which was the parent of all game objects. The game object class had no default constructor but one constructor which takes a string argument. The GameObject class also consisted of a std::map from string to GameObject. So, in the constructor the object created was added to the map with the string argument as its id. The GameObject class also consisted of a static method 'get' which returned a object given its id.

I don't know whether my approach is correct, so I'm not recommending it to anyone but instead asking for expert review since after this discussion I'm doubtful about my approach. Please review!

The problem in this method seems to be about downcasting to the real type of object( Since I'm using C++ not Java ). Since I never felt the need of downcasting ( I put all the usual methods in GameObject class itself ) I didn't ponder more over this issue. But now I'm looking for correcting my approach.

There's nothing wrong with having a lookup table (std::map) of all game objects. In fact, in some designs, it may be necessary. In time you'll probably learn of a better way to do this, or ways to avoid it. But if it's working fine right now, and it's making your life easier to have it, there's not really any good reason to try and eliminate it. One way you could make this better is to have integer IDs instead of strings, it will make lookup much faster because it requires only one comparison per entry.

It should be rare for downcasting to be necessary if virtual functions are provided for most cases in the base class. It's unlikely you'll run into a situation where downcasting can be avoided by eliminating the lookup table, either.

Thanks for your help! I remembered about the efficiency part because of you.

Originally I had created the GameObject class as an interface for all game objects. So that I can implement Polymorphism for various general tasks related to game objects.

Ok, this means you expected to have a lot of common properties in all objects, right?
Personally, I have some reservations, but I also see firm believers in this approach here, so let's assume here your ideas were correct.

Now that you created the game, how many methods do you have as truly common (ie fully fitting in your goal) methods? How many do not? Are there positive or negative exceptions there? Was your idea worth it, in hindsight?

Assuming you are talking about std::map and assuming you are talking about its efficiency.
Then I think integers would have worked better. And hence I should have created a enum of object names, right?
Or is this not what you are asking?

My question was intended much more generally. You picked GameObject because you expected it to help you in solving your problem (you said "...created the GameObject class as an interface for all game objects. So that I can implement Polymorphism for various general tasks..."). Now, looking back, is it actually doing that? Is it doing that well? (probably not, since you asked about it). So what is it not doing that you expected beforehand? Why? (can you think of reasons to explain why it didn't work out as you intended).

One: The one which I mentioned above about efficiency.

I would say, the first goal should be to have good global game structures. That may also be the second and third goals. If your data structures are well designed, efficiency mostly comes by itself.

In the details you can still gain a lot, but the impact is a lot less than a well designed overall structure.

For fixing problem one mentioned above: Using integers for increase in performance

If you can switch to integers, why do you need a map? I mean, a vector or an array would work too, right? That also holds for using enums, of course.

maybe the eliminate the need of downcasting completely!

I find this an interesting thought.

If you look at what you did from a distance, I think you'd see the following:

You wrapped all objects in a black uniform box. They are nicely stackable, and they fit exactly in the new closet that you bought. It all looks so tidy.

Now after a while, you find out that at times, you want to look inside the box, to see what it contains. Apparently, everything in the same box isn't ideal.

So maybe you shouldn't have coloured all boxes black? Maybe use different colours for different kinds of things? (my reservations about universal objects surfaces here!!).

As a thought experiment, what would happen if you delete the GameObject class? Would having several collections of different object types help?

At the end, I seem quite motivated by my dislike about universal classes, so you may want to take my comments and questions with that in mind.

This topic is closed to new replies.

Advertisement