Took me five years to figure this out

Posted by Astryl on April 17, 2012, 9:15 a.m.

Apologies

My last blog was too short an irrelevant to anything. This ought to make up for it.

Something for C++ programmers

I've now spent time with both C# and Java, and no longer have too many complaints about them; in fact, I'm using C# for one of my games, and Java for some minor tools, so I must be liking them.

But here's something that bothered me about both languages:

// Java
public MyObject()
{
   super(9001);
}

// C#
public MyObject()
{
   base(9002);
}

Base/Parent constructors.

Don't get me wrong, I love them; what bothers me is… C++ doesn't have them.

Or so I thought. But after wading through many an obscure book and falling into a dark pit on some ancient-and-still-functioning BBS (Yeah, there are still functioning BBS servers), I finally found the knowledge I was seeking (And no thanks to those obscure books/weird message boards).

Completely by accident. You see, I was creating a constructor:

MSprite(int& ic):ID(ic) // This was the intended behavior
{
}

Of course, being Mega as I am and typing away at who-knows-how-many statements per minute, I typed this in and didn't notice the typo until I tried to compile:

MSprite(int& ic):(ic)
{
}

Of course, you'd be expecting a syntax error, but instead I got the "No matching call for Object(int&). Candidates are Object()…" message.

MSprite is inherited from Object, which meant only one thing… I had discovered the way to call a base-class constructor.

I can't believe that in the five years I've been programming in C++, I couldn't find that out, or do it before now. ;_;

Anyway, this is all a part of that game I mentioned I was going to make yesterday.

The little game I started yesterday

Here have another

Made in C++. :D

Also, yay another space shmup that I probably won't get anywhere near to a state of completion, but is great practice.

*Aims the Mega Rifle at Lunacy Star* <- Playful trolling, new members.

Sorry Taizen >:3

I started the actual code yesterday, and in 6 hours I was done with a framework that gives me all the functionality that Hydra had, but works better (Because I now know how to handle my pointers correctly, and make use of Early-Out algorithms for drawing).

It uses SFML, as usual, but was made from scratch. :3

Ludum Dare should be a piece of cake (6 hours working on the 'engine' will leave me with about 42 hours for the rest of the things I need to do).

My last blog was *that* close to being a "I'm feeling depressed" blog. Whay was I feeling depressed? I don't have a clue.

I'm feeling great now though.

My LD plan

Very simple. MAKE GAEM AND WIN!

Or, in simpler terms [/irony]:

> Create a stable and easy to extend OOP framework in the first 6-8 hours of the comp. [Proven that I can]

> Work on design and art assets in the next ?? hours. [Done it before]

> Cobble the final game together. [Done this before as well]

I already have plans for any level-creation I need to do; I'll use a layered map from TileStudio; I just have to write an importer; fortunately I find all binary IO pathetically simple to pull off in a short amount of time. :P

For music, I'm probably going to use GMGME, with standard SFML music objects as a fallback.

In addition to this, I'm going to create an Asset manager (You have no idea how much this speeds up the development process), an Instance manager and who-knows-what-else.

The Instance manager is just a simple system built into my base Game Object's that assigns a unique ID to each instance of the class (Using a global counter), and essentially allows me to remove objects by instance instead of by class.

Well, back to my papered desk (I've got a 'scratchpad' for the RPG design, and another one ready for LD on the weekend).

I've got a checklist for both LD and RPG4D, blank paper stuck on the walls, pencils everywhere, and a blank/cleaned desktop. I think.. Wait, what?!… I'm getting organized?!?! The world is going to end!

*Runs away and spreads the word with bouts of lunatic yelling*

Comments

Rob 12 years, 7 months ago

Quote:
In most cases, I always supply a default constructor in my classes. The default constructors for all parents up the inheritance tree are called in order from the root.

Usually, I take advantage of this in the normal way (Default initialization).

But what if it has parameters that you simply can't default easily? (like coordinates for game entities)

Unless I'm misunderstanding you. Since it's 4:30AM right now there's a pretty high probability of that.

Astryl 12 years, 7 months ago

Quote:
But what if it has parameters that you simply can't default easily? (like coordinates for game entities)

I usually use a copy-constructor and set up my object something like this:

Object* object = new Object();
object->SetPos(x,y).SetSprite(sprite).SetSolid(false).SetAlpha(0.8);
room->Add(new (*object));
delete object;

Kinda…. inelegant. Or I go and define a constructor for each inherited class that looks something like this (Messy as heck):

class Ship: public Object
{
   public:
      Ship();
      Ship(const Ship& C);
      Ship(int x, int y); // etc
      virtual ~Ship();
};

Of course, now I can just define one base constructor that takes a vector (mathematical vector) as an argument. Space saving, looks prettier, and is robust.

Rob 12 years, 7 months ago

:(

blackhole 12 years, 7 months ago

For future reference, C++11 supports calling constructors from the same class so you don't have to go redeclaring everything, if your compiler supports it.

Astryl 12 years, 7 months ago

Good design: Always default your members to something logical. In my case, the coordinates get set to 0,0. Some objects define their own starting locations (HUD elements, usually), others receive a starting location from the room-manager's Create function:

void RoomManager::Create(int x, int y, GameObject* obj)
{
    // I could have supplied new GameObject() in the third argument, 
    // which is perfectly valid.
    obj->SetPos(x,y);
    this->Add(obj); // The room-manager now handles the pointer, and cleans it up afterwards.
}

Astryl 12 years, 7 months ago

Quote:
For future reference, C++11 supports calling constructors from the same class so you don't have to go redeclaring everything, if your compiler supports it.
I'll check up on that. GCC can be…. difficult in that area sometimes.

auto_ptr<> is suspiciously missing; I had to create it using the example in Effective C++.

Rob 12 years, 7 months ago

Just curious, why is it this->Add(obj) instead of just Add(obj)? Is there a reason other than aesthetics? Shouldn't they be functionally the same…?

Same disclaimer as my previous comment, except it's now 4:45AM.

Astryl 12 years, 7 months ago

Quote:
Just curious, why is it this->Add(obj) instead of just Add(obj)? Is there a reason other than aesthetics? Shouldn't they be functionally the same…?
Habit that was hammered into me by some ancient book on the old C++ standard (Can't remember which one?).

I could also use (*this).add(), but that looks messier.

Rob 12 years, 7 months ago

I understand if you have like…

class Rapist
{
public:
         inline Rapist(int x, int y, int gallonsOfSemen)
         {
                  this->x = x;
                  this->y = y;
                  this->gallonsOfSemen = gallonsOfSemen;
                  rapeAbility = rand() % 10;
                  radius = 8 + rand() % 2;
         }
         inline virtual ~Rapist()
         {
         }
         inline bool RapeTheMaids(Maid* victim)
         {
                  if (rapeAbility > victim->resistance && CollisionCircle(x, y, victim->x, victim->y, radius + victim->GetRadius))
                  {
                           victim->CumInside(gallonsOfSemen);
                           return true;
                  }
                  else
                           return false;
         }
         inline int GetRadius()
         {
                  return radius;
         }
private:
         int x, y, gallonsOfSemen, rapeAbility, radius;
};

with the variables being the same as the parameters, but not really with the function calling.

Astryl 12 years, 7 months ago

Like I said: Bad habit. I type too quickly for my own good, and tend to slam too many this->'s everywhere.