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

Author Topic: cannon and bullet  (Read 8785 times)

0 Members and 1 Guest are viewing this topic.

lorence30

  • Full Member
  • ***
  • Posts: 124
    • View Profile
    • Email
cannon and bullet
« on: May 22, 2015, 08:10:18 pm »
what would be the best idea to write cannon and bullets?


class Cannon{};
class Bullet : pubic Cannon{};

or write them separately?
class Cannon{};
class Bullet{};

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: cannon and bullet
« Reply #1 on: May 22, 2015, 08:20:57 pm »
When you inherit from a class you should usually think of it as having a "is a" relationship. When you instead use composition you should think of a "has a" relationship.

So, when you say "class Bullet : public Cannon" you are, in a way, saying "a bullet IS A cannon" - which is clearly false.

If instead you make them different standalone classes (which makes sense since they are clearly two different things) and then make the Cannon contain containers of Bullet(s), then you are saying " a cannon HAS A bullet" - which makes sense.

PS: how is this SFML related???
« Last Edit: May 22, 2015, 08:26:23 pm by Jesper Juhl »

lorence30

  • Full Member
  • ***
  • Posts: 124
    • View Profile
    • Email
Re: cannon and bullet
« Reply #2 on: May 22, 2015, 08:29:53 pm »
i also thought for inheritance like, "cannon needs bullet to fire , okay it needs to inherit cannon".
and since cannon needs singleton


@Jesper Juhl thanks i get your point, that was fast reply.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: cannon and bullet
« Reply #3 on: May 22, 2015, 08:30:45 pm »
PS: how is this SFML related???
or graphics related!
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: cannon and bullet
« Reply #4 on: May 22, 2015, 08:47:45 pm »
and since cannon needs singleton
Right there I died a little inside :(
Please, please don't use the Singleton pattern. It is an anti-pattern. It has all the problems of global variables and more and no real advantages. It will bite and hurt you. Just say no!

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: cannon and bullet
« Reply #5 on: May 22, 2015, 08:50:34 pm »
Is it just as bad when you declare a class normally and fill it with variables that need to be passed to a group of functions, then just define a single instance of that class, rather than specifically restricting it to one, and it is created in main? Is there a problem with that?

lorence30

  • Full Member
  • ***
  • Posts: 124
    • View Profile
    • Email
Re: cannon and bullet
« Reply #6 on: May 22, 2015, 09:32:49 pm »
okay thanks guys, now i know.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: cannon and bullet
« Reply #7 on: May 22, 2015, 09:34:55 pm »
What you lose with global variables (and singletons which you can generally consider to just be glorified globals) is control over when they get created (and destroyed) compared to other objects (remember; creation order of globals is only defined within a single compilation unit). So, if multiple globals (or singletons) depend on each other you have trouble on your hands.
Also, when do globals (and singletons in general) get destroyed? When you leave main and global dtors are run, that's when. At that point in time you again face a problem since destruction order is (again) only well defined for objects within a single compilation unit and additionally, if your destructor wants to do anything non-trivial it now has to do this in a world where we've left main and a lot of assumptions about the world are generally not valid. That is, if your destructor even gets run at all (singletons are commonly heap allocated and leaked at exit).
Then you also have the problem that globals/singletons increase coupling between your classes and it becomes difficult to reason about the overall state of the system since anyone could be changing the global at any time.
If you are using threads it gets even worse since you now have to ensure that creation/destruction of the global/singleton is atomic with respect to other threads and ensure that changes to the global state is properly synchronized.
Globals/Singletons just land you in a world of hurt and you are better off just avoiding them like the plague (unless you have really, really good reasons and really know what you are doing and why - which is very rarely the case).

Edit: there are more potential problems, but the best way to learn is to do. So I invite you to try and use a lot of globals and singletons in a real (100K+ lines of code) application and then come back and tell me how many weird crashes and other issues you had and how much debugger time you had to spend. I'll bet you a beer that most of those issues/time were caused by the globals/singletons.  Go ahead, try it. I have and I have the scars to prove it. That way lies madness.
« Last Edit: May 22, 2015, 10:55:03 pm by Jesper Juhl »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: cannon and bullet
« Reply #8 on: May 22, 2015, 10:12:19 pm »
What Jesper Juhl said cannot be emphasized enough. There are many games using those dubious manager classes for anything, whose responsibility and scope is so vague that they cannot even be named meaningfully. Even worse, they're mostly implemented as singletons.

People think they've found a simple and great design "because you don't have to pass the parameters to every function" (which you don't have to otherwise either, btw). At one point the project exceeds a certain complexity, and the initially saved time strikes back, with a force hundred times bigger than you'd expect (Jesper's scars prove it). A while ago I also listed some reasons why singletons should be avoided as a general-purpose pattern in game development. Four years later, they still apply literally.

Just recently I had to maintain an older codebase with those cool singleton managers. The master of those managers initializes the others, who are later accessed indirectly via the master. Now, an object initialized during master initialized dared to access a manager. This lead to a line static Singleton instance; before that instance finished construction. This worked perfectly well on one compiler. When porting the project, things would freeze in a deadlock because this compiler handles initializations of static variables differently. Well, you can imagine how funny it was to track down the cause. Of course, things were hidden deep down in a class where the global circular access was everything but obvious. And here, we're talking about deterministic, reproducible bugs... I don't even want to start with multithreading in combination with global/static variables.


Is it just as bad when you declare a class normally and fill it with variables that need to be passed to a group of functions, then just define a single instance of that class, rather than specifically restricting it to one, and it is created in main? Is there a problem with that?
That's the way you usually do it -- why should it be bad?
Except that in bigger projects, you probably won't use main() for that...
« Last Edit: May 22, 2015, 10:24:03 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: cannon and bullet
« Reply #9 on: May 22, 2015, 10:44:44 pm »
Thank you for that validating post Nexus.
Spoken like a true - battle hardened - veteran :)

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: cannon and bullet
« Reply #10 on: May 22, 2015, 10:56:32 pm »
Is it just as bad when you declare a class normally and fill it with variables that need to be passed to a group of functions, then just define a single instance of that class, rather than specifically restricting it to one, and it is created in main? Is there a problem with that?
That's the way you usually do it -- why should it be bad?
Except that in bigger projects, you probably won't use main() for that...
Thank you, it's just that when I was first using OOP, the first way it occurred to me to do things is as above and then I heard about singletons being a bad idea and this sounded to me like any class which is designed so that it only makes sense to have one instance is a bad thing, for example I almost always have a brain class that holds all of the fundamental variables and handles background functions and I've always had a nagging doubt that the don't use singletons advice could apply to that sort of thing, even though it's just a normal class (or struct) first instanciated at the start of main().

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: cannon and bullet
« Reply #11 on: May 22, 2015, 11:07:35 pm »
The fact that you instantiate it inside main (not in global scope) makes a world of difference. You now have control of its lifetime and order of creation compared to other objects and it gets destroyed inside a scope (main) where the world is still (supposed to be) sane.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: cannon and bullet
« Reply #12 on: May 22, 2015, 11:07:58 pm »
Jesper: tough battle eh? 8)

[...] and this sounded to me like any class which is designed so that it only makes sense to have one instance is a bad thing
There are many classes of which there exists only one instance at a time, simply because of the nature of the concept they represent: application, game, world, camera...

for example I almost always have a brain class that holds all of the fundamental variables and handles background functions and I've always had a nagging doubt that the don't use singletons advice could apply to that sort of thing, even though it's just a normal class (or struct) first instanciated at the start of main().
Depending on what your brain class does, it may be built upon a different anti-pattern: god class (too many responsibilities). Your failure to describe it concretely ("fundamental variables and background functions") is a strong indicator for that :P

What is it for? Maybe it can be split into different classes and functions. In any case, it does not suffer from the same problems as singleton ;)
« Last Edit: May 22, 2015, 11:09:38 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: cannon and bullet
« Reply #13 on: May 22, 2015, 11:11:22 pm »
Jesper: tough battle eh? 8)
Yeah. I doubt we'll ever win the war. But we may win a few battles and that still has some value I guess...
« Last Edit: May 22, 2015, 11:12:57 pm by Jesper Juhl »

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: cannon and bullet
« Reply #14 on: May 22, 2015, 11:16:34 pm »
Oh I didn't describe it very well because it does different things depending on the program, the two biggest ones I've done so far were as follows:
A made a graphical program (using SFML, thanks for giving me a good chance in my GCSE. Full marks in programming! :D ) that contained various separate functions that the exam board asked for and the brain class handled things like starting the program and doing titlescreen and menuscreen.

In my other one, in order to learn programming, I set myself the challenge of making a gameboy style game and it handled menus, saving, etc and in both, the brain class was used to store any variables that would need to be passed to lots of functions. I started doing it when I was getting functions with 20 -30 variable references passed to each function. This was when I thought encapsulation was stupid because it removes control and access and so everything was public and I used them in order to classify which variables were used for what so that I didn't have to do name mangling of my variables.