C++ and Objects

Discussion in 'Game Development (Technical)' started by Sindarin, Apr 15, 2010.

  1. Sindarin

    Sindarin New Member

    Joined:
    Sep 22, 2008
    Messages:
    57
    Likes Received:
    0
    I have started learning more about c++ objects.
    I am trying to compile a command line "game" just to test things out but it doesn't work. Bigger problem is that I can't find a simple tutorial that explains how to use objects in c++.

    Based on my experience in php and after some trial and error I created this,

    I don't know if player1 = new player(); creates a new player object, I mean that's how you do it in php and actionscript, but can't find how to do it in c++.
     
  2. anpd

    Indie Author

    Joined:
    Nov 8, 2009
    Messages:
    105
    Likes Received:
    0
    player1 shouldn´t be an int it should be a player pointer if you want to new it.
    player* player1 = new player();

    also your variables int x, y, visible, health, lives; should either be under the public or private in the class.
    You can instanceiate a class in two different ways on the stack or on the heap. If you are using new it will be created on the heap but you are using it like it was created on the stack.
    player1.setHealth(20);
    should be player1->setHealth(20);
    otherwise it needs to be created like player player1; just like int x;

    I think you should start with just variables and then functions and then classes. You have uninitalized variables in the code that you are trying to use.
     
    #2 anpd, Apr 15, 2010
    Last edited: Apr 15, 2010
  3. Sindarin

    Sindarin New Member

    Joined:
    Sep 22, 2008
    Messages:
    57
    Likes Received:
    0
    Thank you for your answers, I suspected I had to use pointer somewhere.
    I think I have covered the basics in c++, I just made the above example a bit too quick. So I rewrote it now:

    I now get a weird error with no indication on what line it occurs
    obj\Release\main.o:main.cpp:(.text+0x6b)||undefined reference to `player::player()'|
    ||=== Build finished: 1 errors, 0 warnings ===|

    == EDIT ==

    Ah, finally made it work,
    it seems the constructor was a function like in php, so I added some variable initializations and it worked!

    Thanks again! Also I suppose it's possible to keep all the objects in external files and include them from the main program right?
     
    #3 Sindarin, Apr 15, 2010
    Last edited: Apr 15, 2010
  4. anpd

    Indie Author

    Joined:
    Nov 8, 2009
    Messages:
    105
    Likes Received:
    0
    Nice to see you got it working :) Yes you usually use a header file .h for the class declaration and a .cpp for the defenition. For instance

    in player.h

     
  5. Sindarin

    Sindarin New Member

    Joined:
    Sep 22, 2008
    Messages:
    57
    Likes Received:
    0
    oh great, I think a setup like this would work,

    player.h contains all the player definitions
    enemies.h contains all the enemy definitions
    levels.h contains all the level definitions
    items.h contains the power up definitions
    game.h contains global settings and initializations
    main.cpp the main file

    Oh, and how do I destruct an object?
     
  6. anpd

    Indie Author

    Joined:
    Nov 8, 2009
    Messages:
    105
    Likes Received:
    0
    make sure to ake .cpp versions of all files. Makes compiling faster to "create" the functions there. If you have used new to create an object you destroy it like this: delete player1; just make sure that you don´t try to use player1 again afterwards.
     
  7. Sindarin

    Sindarin New Member

    Joined:
    Sep 22, 2008
    Messages:
    57
    Likes Received:
    0
    Is delete an alias of free() ?

    Ah, it frees it from memory right? So I'd have to reconstruct it with new to use it again in let's say a later level, right?
     
  8. Bmc

    Bmc New Member

    Joined:
    Dec 12, 2004
    Messages:
    1,088
    Likes Received:
    2
    Sort of, but not really. You always want use delete, when you use new. Use free if you used malloc
     
  9. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    Somewhat off topic, but important anyway : setHealth() is the worst possible name for that function you havem which should be called addHealth(). If you need to, have a separate setHealth() and addHealth(). Having a function called set that actually adds guarantees nightmares down the road.
     
  10. Adrian Lopez

    Original Member

    Joined:
    Sep 7, 2004
    Messages:
    489
    Likes Received:
    0
    They are not interchangeable. The delete keyword is used to release memory allocated by new. Calling free() on a memory address obtained via new is a mistake. For one thing, calling free() instead of using delete means your class destructor will not get called, which means you're skipping any necessary cleanup instructions. Furthermore, there's no guarantee that memory obtained via new and memory obtained via malloc() are accounted for through compatible means; memory obtained via new is obtained from the "Free Store", while memory obtained via malloc() is obtained from the "Heap".

    Thus:

    When using malloc:
    Code:
    myobject *a = malloc(sizeof(myobject));
    free(a);
    When using new to allocate a single object:
    Code:
    myobject *a = new myobject();
    delete a;
    When using new to allocate an array of objects:
    Code:
    myobject *a = new myobject[100];
    delete [] a;
     
    #10 Adrian Lopez, Apr 15, 2010
    Last edited: Apr 15, 2010
  11. mduffor

    mduffor New Member

    Joined:
    May 11, 2009
    Messages:
    20
    Likes Received:
    0
    Well, player.hpp and player.cpp would contain the player code, enemies.hpp and enemies.cpp would contain the enemy code, etc. By convention, .c and .h files are C, .cpp and .hpp files are C++ (or .cc/.hh, .cxx/.hxx, .h++/.c++).

    While you are learning to code in C++, you can define your game variables in-code though this is not very flexible. Once you master the language a bit better, you'll want to load your data values from an external file and initialize the class with that. Using an external file allows you to tweak the game without having to recompile the game engine.

    Also, you may want to derive your items, enemies, and player all from the same base class. The base class would handle loading/tracking the graphics, displaying the object to the screen, storing the position in the game world, storing common attributes like health, damage it does, etc.

    Because if you think about it, an enemy, a trap, and a health power up aren't all that different. Instead of addHealth()/subHealth(), just have adjustHealth() and allow it to take either negative or positive values (and bounds check both the minimum and maximum the health can be). An enemy is an object that moves and causes negative health when you hit it. A trap is an object that does not move, and causes negative health when you hit it. A health power up is an object that does not move, and causes positive health when you hit it. Or the power ups might move (bouncing stars or sliding mushrooms in Mario games, etc.), in which case they would use the same movement code as enemies. Don't think of breaking objects into classes based on what they are, but rather by what they do.


    Cheers,
    Michael
     
  12. Sindarin

    Sindarin New Member

    Joined:
    Sep 22, 2008
    Messages:
    57
    Likes Received:
    0
    Yea, I noticed that and had it fixed.


    I think there was some extends keyword for classes, they could
    be used to extend a base class with some object specific values and functions maybe.

    What format is best? txt, ini, xml?
     
  13. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    May I suggest the excellent book Thinking in C++ by Bruce Eckel? Go download it, it's free - http://www.ibiblio.org/pub/docs/books/eckel/. It has everything from the very basic to the extremely advanced, explained very clearly and with lot of examples.
     
  14. mduffor

    mduffor New Member

    Joined:
    May 11, 2009
    Messages:
    20
    Likes Received:
    0
    Well, in C++ you usually extend a base class by inheriting from it

    Code:
    class Base
    {
    protected:
    int A;
    int B;
    public:
    Base ();
    virtual ~Base ();
    }
    
    class Child : public Base
    {
    protected:
    int C;
    public:
    Child ();
    virtual ~Child ();
    }
    etc.

    I would avoid .ini since it isn't cross-platform. I use XML, but that's more work than needed when you are just starting out. So where possible, I would just read from a text file that has key=value pairs and maybe some keywords.

    Code:
    obj player
    health = 100
    speed = 7
    sprite_idle = pic/chars/playerA/Idle.tga
    sprite_runL = pic/chars/playerA/RunL.tga
    sprite_runR = pic/chars/playerA/RunL.tga
    sprite_jumpL = pic/chars/playerA/JumpL.tga
    sprite_jumpR = pic/chars/playerA/JumpR.tga
    size = 32x64
    ai = player
    
    obj powerUpHealthA
    health = 0
    speed = 0
    healthAdjust = 10
    sprite_idle = pic/items/BoxD.tga
    size = 16x16
    
    obj badGuyA
    health = 15
    speed = 3
    sprite_idle = pic/chars/monsterD/Idle.tga
    sprite_runL = pic/chars/monsterD/RunL.tga
    sprite_runR = pic/chars/monsterD/RunL.tga
    sprite_die = pic/chars/monsterD/Die.tga
    size = 32x64
    ai = walkInto
    
    
    Or something along those lines. Class variables that are not initialized use the default class value.

    If you store stuff in a text file, you can edit it with a text editor. This means you don't have to build a data editor, which can be as much work as the game engine itself sometimes! Depending on the game genre and level of graphics, you might even be able to do levels in a text editor as well (though as graphics complexity increases, it becomes necessary to write a gui for level editing).

    Cheers,
    Michael
     
  15. ChrisP

    Indie Author

    Joined:
    Feb 5, 2007
    Messages:
    971
    Likes Received:
    0
    Nonsense. While it certainly had its origins in Windows, it's just a file format, and one that's very similar to (but better than) your suggested format, to boot. As long as you use a parser which works cross-platform, it'll work just fine. I used .ini files for almost everything in Mayhem Intergalactic, and I have (unreleased) versions of the game running on Mac and Linux.

    Of course, it's not a particularly good file format in many ways. Its advantages are simplicity and ease of editing; its disadvantages are lack of flexibility and extendability. It worked for me for that particular project.

    XML isn't all that hard to deal with if you use a decent parsing library. TinyXML is good. Avoid heavyweight XML libraries like the plague.

    All approaches involve tradeoffs. Pick your poison. :)
     
  16. vjvj

    Indie Author

    Joined:
    Sep 25, 2004
    Messages:
    1,732
    Likes Received:
    0
    We use TinyXML, too, and it's great!
     
  17. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    INI is as crossplatform as plain text files are :p.

    Personally i use a custom library i wrote (libbadcfg) which parses files such as
    Code:
    foo = "bar"
    moo
    {
        voo = "doo"
    }
    spam = "no"
    {
        yes = "but"
    }
    
    and creates a tree structure which you can either traverse like
    Code:
    /* load the file */
    BadCFGNode* root = loadBadCFGFile("foo.cfg");
    BadCFGNode* child;
    /* use root node's children */
    for (child=root->child; child; child=child->next) { /* use child */ }
    /* destroy the root node, which destroys all of its children nodes */ 
    destroyBadCFGNode(root);
    
    or simply ask for a value
    Code:
    /* get the value of the blah node */
    const char* blah = getBadCFGValue(root, "blah", "default blah");
    
    or use dot notation for children
    Code:
    /* get the value of the voo child of the moo node */
    const char* blah = getBadCFGValue(root, "moo.voo", "what if");
    
     
  18. JarkkoL

    JarkkoL New Member

    Joined:
    Feb 4, 2009
    Messages:
    363
    Likes Received:
    0
    I just store pretty much all the data in binary and edit the data in a WYSIWYG editor. Works great, though it takes fair amount of work to get proper infrastructure in place which can deal with automatic data conversions and transparently saving data structures. boost::serialization library is kind of halfway there if you are okay bloating your code with boost :)
     
  19. Sindarin

    Sindarin New Member

    Joined:
    Sep 22, 2008
    Messages:
    57
    Likes Received:
    0
    :eek: This is great resource, thanks!

    Oh I see, makes sense.

    Maybe I'll use XML, I have worked with it in PHP, dunno how hard would be in C++ but it's worth trying.

    Ooh, I will look into that too :)

    btw, what does "virtual" and "protected" do?
     
    #19 Sindarin, Apr 19, 2010
    Last edited: Apr 19, 2010
  20. mduffor

    mduffor New Member

    Joined:
    May 11, 2009
    Messages:
    20
    Likes Received:
    0
    Ah, I wasn't aware that there were many .ini parsers outside of the built-in Windows functions, or that .ini was very rigidly defined outside of "just follow how Windows does it." In that case I append my opinion on .ini files to be, you can use them, as long as you have a cross-platform library to read/write them or you process them with your own code.


    You can define variables and methods as either public, private, or protected in C++. Private means only the class itself can see the variables/methods. Public means any other code can access/call those variables/methods. Protected means that only the original base class or its derived children can access/call those variables/methods.

    In practice, I use private and public 99% of the time. But then again I don't have deep hierarchies in my code, and I don't sub-class classes from other libraries very often.

    The virtual keyword denotes a method that can be overridden by a derived class. It allows the derived class's function to be called even if it is accessed by a pointer whose type is that of the base class. It is important to declare the destructor as virtual so that when the object is destroyed, both the derived class's and the base class's destructors will be called. Otherwise you could introduce memory leaks.

    Cheers,
    Michael
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer