Thread: Total newbie question

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    27

    Total newbie question

    Well, as the title suggests...

    I'm just starting with Dev-C++, really basic stuff. My eventual goal is to make a roguelike, so I'm starting out by generating a blank map.

    Windows programming is a little beyond me for the time being (I'd like to get used to using C++ expressions and the C++ mindset before I even *think* about that), so I'm using the DOS interface provided by Windows and making a bas DOS program. Unfortunately, I cannot for the life of me figure out how to lock the DOS window into a certain width and height - something which is just a little bit crucial to what I'm trying to do. At the moment I'm having real problems setting how many characters wide the map display is.

    I'm kind of not sure if this is something I can reconfigure via coding, since being a DOS app, it would normally be run fullscreen... Any advice on the matter would be greatly appreciated.

    EDIT: Hm. I found out how to change the width, still not sure how to lock it in. But I suppose that's not really an issue.... My bad.
    Unfortunately, I'm now having trouble with the character width. The printing section reads

    Code:
    void mapprint() //function to display the map as a whole
    { 
        int x(150); // initialise the map displayers's x location to allow for the screen display to be half of the map
        int y(190); // initialise the map displayer's y location, likewise
        
        
        while (y < 210) {                  //This may seem odd, but not all of the map is being displayed.
              while (x < 251) {            //This way, items/monsters/whatevers can be offscreen
                     cout<<field[x][y];     //yet still present in the game.
                     x++;
                     }
              x = 0;
              y++;
              }
    }
    Each field[x][y] is currently a ".", but for some reason, the x-value runs overboard, and I end up with far too many "."s, more than half again as many as I should have. I've tested the display, and it is 100 characters...
    Last edited by 20,000leeks; 09-16-2006 at 07:37 AM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    Ugh, this is slow going. Still, my C++ skills are improving at a great rate of knots. I've managed to solve my last problem, but now I'm stuck on something entirely new - how to draw input from the keyboard using the getch() function from the cornio header.

    My current movement code (very simple) goes something like this:

    Code:
    int movechar() //Function called from main after map is generated.
    {   
         char movedir;
         field[charx][chary]='.';          //The display is changed back to an empty tile prior to  movement
         while ((movedir = getch()) != EOF // Most of this I got out of the FAQ, as far as I can tell it holds while waiting for the user to press q to quit
              && movedir != '\r'
              && movedir != 'q')
         if (movedir == 8) chary--;             //
         else if (movedir == 4) charx--;     //  As far as I can tell, these don't do anything at all.
         else if (movedir == 6) charx ++;  //  Charx and chary are the character's x and y positions.
         else if (movedir == 2) chary ++;  //
         else return 0;
    }

  3. #3
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    The first time through the loop, x begins with the value 150.

    Every time after that, it begins with the value 0 because that's what you set it to at the end of the loop.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
         if (movedir == 8) chary--;             //
         else if (movedir == 4) charx--;     //  As far as I can tell, these don't do anything at all.
         else if (movedir == 6) charx ++;  //  Charx and chary are the character's x and y positions.
         else if (movedir == 2) chary ++;  //
         else return 0;
    }
    What are you returning if movedir is one of the specified values? Nothing. A random value. [edit] Sorry, I thought the if statement was outside the loop. You need to indent the loop's contents a little. [/edit]

    If those statements don't appear to be doing anything, perhaps movedir isn't one of those numbers. Or perhaps you passed charx and chary by value so the calling function never sees the change. (Are they global variables?) Wait! I know . . . you need single quotes around those numbers.
    Code:
    if (movedir == 8) chary--;
    ->
    Code:
    if (movedir == '8') chary--;
    '0' and 0 are two very different things.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    Ahhh, that seems to have fixed it! Thanks for your help!

    Revised code:

    Code:
         char movedir;
         field[charx][chary]='1';
         while ((movedir = getch()) != EOF 
              && movedir != 'q') {                        //'q' for quit
              if (movedir == '8'){ chary--;
              return 0;}                                       //These return 0s make the character instantly move
              else if (movedir == '4'){ charx--;
              return 0;}
              else if (movedir == '6'){ charx ++;
              return 0;}
              else if (movedir == '2'){ chary ++;
              return 0;}
              else return 0;}                              //Hopefully more commands later!

    The only problem is that it redraws the entire map every time the character moves.... which is not going to be helpful in the long run. Currently, my mapdrawing code is as follows

    Code:
        int x(0); 
        int y(0);
        int x1(0); // initialise the map displayers's x location to allow for the screen display to be half of the map
        int y1(0); // initialise the map displayer's y location
        x1 = mapx/2 - 50; // sets the map display to halfway width
        y1 = mapy/2 - 15; //sets the map display to halfway height
        
        objects();          //Check for object spaces - currently limited to the '@' character
        while (y < 30) {                  //This may seem odd, but not all of the map is being displayed.
              while (x < 100) {         //This way, items/monsters/whatevers can be offscreen
                     if (field[x1][y1] == 1){    //checks for terrain type - empty space terrain
                     textcolor (7);       
                     cout<<".";}
                     else if (field[x1][y1] == 99){   //character
                     textcolor (15);
                     cout<<"@";}
                     else
                     cout<<" ";      //no terrain displayed at all in this space.
                     x++;
                     x1++;
                     }
              x = 0;
              x1 = mapx/2 - 50;  //resets the map width display
              y++;
              y1++;
              }
              return 0;
    Ultimately, I'd like to have a way of the map remaining static or semi-static while objects move around on top of this... But I'm not sure how to achieve this, since I'm using the array to display x and y positions, which is really inefficient - if one thing changes, the entire map has to be redrawn. Is there any way of positioning the print cursor so I can reprint only the objects that are moving rather than the entire screen?

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    The way I do it is to have a copy of the array that represents the screen at the start of the frame. Then you make any changes to the array that you want. Then, when you go to paint everything, only paint the characters that have changed from the previous frame to the current frame *. Finally, you set the previous-frame array to the current one again (copying arrays is much faster than painting them) and start all over again.

    * If you have a function that sets the cursor position you're all set; seek to the position that needs to be changed. If you do it properly you can avoid seeking twice if there are two modified characters in a row.

    If only one or two characters change between frames, it would be more efficient to locate the position of the character that changed and modify only that one.

    I wrote a maze game called tmaze a while ago that runs on an XT processor (I'm not sure exactly how fast it is but it's around 4 MHz) at a reasonable pace. It was designed in such a way that most of the map had to be repainted every frame, but not all of it. I used the method outlined above and it became at least 10x faster. (I've also used it to design a simple graphics library for mode 13h. Don't ask what that is.)

    [edit] All this relys on you having a cursor positioning function. To get one, see this FAQ: http://faq.cprogramming.com/cgi-bin/...&id=1043284392 [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    Wow, thanks for your help! I can't say I understand half of your tmaze program, but it's nice to know that it *can* be done.

    As to my own efforts, I've tried setting up an overlaying 'object field' - rather than containing the terrain information, it overlays a grid of the same size that contains all the objects.... My code goes something like this:

    Code:
    #include <iostream> //include I/O functions such as cout
    #include <conio.h>
    #include "conio2.h"
    
    
    using namespace std; //tells compiler to use standard functions, such as cout
    
    
    int field[600][600]; //sets up main field space
    
    int charx;
    int chary;
    
    
    struct objectmap{
           int obj;   //two types of things can occupy a square - objects (items, etc.)
           int monst; //and characters (PC, NPC, monsters...)
    }
    
    objectmap objectfield [600][600]; //sets up an overlaying objects field
    Unfortunately, it's not recognising my structure. Rather than trying to make the 'objectfield' a global variable, should I just define it in the main() function and use pointers to access it? I think it might pop up quite frequently now and then, so I thought it'd just be easier to make it global.

    Likewise, is there an easier way of defining multiple characteristics to one space than arrays? At the moment, I'm considering going back to the single field array and adding two extra dimensions -

    Code:
    int field[600][600][1][1]
    where the last two dimensions are for objects and monsters respectively. By increasing the length of each dimension, I should be able to specify how many objects or monsters can occupy a single space... but I'm not sure if that would work. Plus it would be a pain to code in checking for movement, not to mention map generation (if I ever get that far).

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    If you only have one item per square, you could use a structure like this:
    Code:
    struct square_t {
        void *data;
        enum {
            TERRAIN,
            BEAST,
            // ...
        } type;
    };
    If not, you might be able to have something like this:
    Code:
    struct {
        void *data;
        enum {
            TERRAIN,
            BEAST,
            // ...
            TYPES
        };
    } field[600][600][TYPES];
    or since this is the C++ forum, a base class instead of a void pointer. Having an array like what you have up there, with 3 or 4 or more dimensions, can quickly become very slow.

    If your object are few and far between, it would be more efficent to store them like this:
    Code:
    struct object_t {
        int x, y;
    } beast[BEASTS];
    You could have a compromise; store the terrain in a 600x600 array, and the beasts or whatever in an array of their own.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    I like the idea of having types, that sounds much more efficient (and easier for me to figure out exactly what I was thinking when I need to debug). To be honest, I've never seen the enum declaration before (like I said, *very* new to C++).

    Something like

    Code:
    enum {TERRAIN,
                MONST,
                ITEM,
                BUILDING,
                TYPES}
    int field[600][600][TYPES];
    and then when I need to define terrain, say
    Code:
    field[x][y][TERRAIN]=1;
    The only thing is I can't quite see how to have multiple objects of the same type in one location. For example, say there were two torches lying on the ground, and the integer 65 stands for torches.

    Code:
    field[x][y][ITEM]=65;
    defines just one torch being on the ground. As for your suggestion about classes... do you mean have a class LOCATION that contains the functions for setting terrain, objects, creatures, etc...? Something like

    Code:
    class location{
    public:
          location;
          ~location;
          void setlocation(int x, int y);
          void setterrain()
          void setitems()
          void setmonsters()
          void setbuildings()
          void readterrain()
          void readitems()
          void readmonsters()
          void readbuildings()
    protected:
          int terrain;
          int item1;
          int item2;                 //Up to 'n' items in one spot
          int item4;
          ....
          int itemn;
          int monster;
          int building;
    };
    ....and from there make the functions that respectively set and read each of the attributes? Sorry if that's totally the wrong idea, I'm not great at using classes.

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    You could do that. If you want to use inheritance, then you could have a location class that looks more like this:
    Code:
    class location {
    public:
        void add_object(object &o) { items.push_back(o); }
        int items() { return items.size(); }
        object get_object(int x) { return items[x]; }
    protected:
        vector<object> items;
    };
    and then you could have an object class from which other classes derive (such as terrain, building, monster). Your inheritance diagram could look like this:
    Code:
    object
        +- terrain
        |   +- grassland
        |   +- hills
        |   \- mountains
        +- item
        |    +- armour
        |    |    \- boots
        |    \- food
        |        \- banana
        +- monster
        |    +- goblin
        |    +- human
        |    \- scorpion
        \- building
             +- grocery_store
             +- hardware_store
             \- armoury
    etc. (Like the ASCII art? )

    The terrain might have functions like has_water() which returns true based on the percent chance that a particular square has water. Monsters might have get_hitpoints(), get_health_left(), get_representing_character() (returns '@' for humans, etc). Buildings might have get_wares() which would return a vector of objects, hammers and bannanas and nails and boots. Each of those would have methods too, like get_health_restore for food, get_armour_rating() for boots, get_number_left() for nails, get_energy_required() for hammers . . . etc etc etc.

    For multiple objects, use vectors.

    This is probably too compilcated for a simple game like you're trying to make, but it gives my fingers and brain excersice.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    Hmm, this is starting to get a bit heavy-going - like I said, I'm not too confident with classes. I understand the basic ideas behind inheritance though, and it sounds like a perfect way to add types of items (maybe reading from an 'item.obj' file to allow for easier editing? That would have to be some point in the future, though). The ASCII art is great, too - easy to see what you mean there.

    I'm not quite sure what you mean by a few things, though- namely

    Code:
        void add_object(object &o) { items.push_back(o); }  //This adds the item to the top of the pile?
        int items() { return items.size(); }         //I'm guessing this calls a function that reads the number of items at the spot?
        object get_object(int x) { return items[x]; }   //...even less sure what this means, return the item types one by one?
    and vectors. :S

    What I have in mind is something like

    Code:
    class location{
    public:
    location();
    ~location();
    int get_terrain(int x, int y)   //returns the terrain type at location x,y
    int get_itemno(int x, int y)   //returns the number of items at location
    int get_item(int x, int y, int stack)       //returns the list of items at that location (not sure quite how to return more than one integer here... maybe do a repeat call from getitemno() if necessary?
    int get_monst(int x, int y)  //returns any monsters at location
    int get_build(int x, int y)    //returns any structures at that location - door, window, wall, etc
    protected:
    int terrain;
    int itemno;
    int item;
    int monst;
    int build;
    };
    
    class item{
    public:
    item();
    ~item();
    int can_carry(int itemdesc);    //checks if the item described by integer itemdesc is carryable
    int get_weight(int itemdesc); //checks the item's weight (possibly making the previous obsolete
    protected:
    int item_weight
    int can_carry
    };
    
    class shoe : public item{
    public:
    int armour();                        //returns the armour value of the type of shoe
    int encumbrance();               //returns encumbrance value
    int footarm;
    int footenc;
    };
    and so forth.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    It works! There's a little character that moves around the screen! (only in cardinal directions at the moment, but that's easy to change).

    ...all that at only 1.24 mb -.-

    Efficient, it is not.

    Is it possible to turn the blinking cursor on or off? It kind of detracts from the map view.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Hmm, this is starting to get a bit heavy-going - like I said, I'm not too confident with classes. I understand the basic ideas behind inheritance though, and it sounds like a perfect way to add types of items (maybe reading from an 'item.obj' file to allow for easier editing? That would have to be some point in the future, though). The ASCII art is great, too - easy to see what you mean there.
    Yes, I thought it might be too complicated but my fingers got carried away.

    I'm not quite sure what you mean by a few things, though- namely
    Code:
        void add_object(object &o) { items.push_back(o); }  //This adds the item to the top of the pile?
        int items() { return items.size(); }         //I'm guessing this calls a function that reads the number of items at the spot?
        object get_object(int x) { return items[x]; }   //...even less sure what this means, return the item types one by one?
    and vectors. :S
    get_object() returns the xth object. .size() returns the number of items in the vector, and .push_back adds a new item to the end ("back") of the vector. http://cppreference.com/cppvector/index.html

    A vector is kind of like an array (using the same syntax; array_or_vector[x]) which you can grow, shrink, and perform other operations on. They're very useful.

    Code:
    class location{
    public:
    location();
    ~location();
    int get_terrain(int x, int y)   //returns the terrain type at location x,y
    int get_itemno(int x, int y)   //returns the number of items at location
    int get_item(int x, int y, int stack)       //returns the list of items at that location (not sure quite how \
    to return more than one integer here... maybe do a repeat call from getitemno() if necessary?
    int get_monst(int x, int y)  //returns any monsters at location
    int get_build(int x, int y)    //returns any structures at that location - door, window, wall, etc
    protected:
    int terrain;
    int itemno;
    int item;
    int monst;
    int build;
    };
    
    class item{
    public:
    item();
    ~item();
    int can_carry(int itemdesc);    //checks if the item described by integer itemdesc is carryable
    int get_weight(int itemdesc); //checks the item's weight (possibly making the previous obsolete
    protected:
    int item_weight
    int can_carry
    };
    
    class shoe : public item{
    public:
    int armour();                        //returns the armour value of the type of shoe
    int encumbrance();               //returns encumbrance value
    int footarm;
    int footenc;
    };
    Again, to return more than one integer, you could use a vector or another STL object.

    You could do something like that. But you need to decide if you're going to use tile-based or object-based arrays or classes or whatever. Or a combination. In a tile-based class, you store everything that exists on one square; in an object-based class, you store all the bananas in one place.

    ...all that at only 1.24 mb -.-

    Efficient, it is not.
    The source or the executable? Either way, quite large . . . larger than I've ever had.

    Is it possible to turn the blinking cursor on or off? It kind of detracts from the map view.
    Yes, you can with Win32 functions. I don't know if you want to use them, because they're not really portable; but then neither is the cursor positioning function. I don't know what they are offhand. Try searching. I can look up what they are later if you can't find them.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    27
    Hmm, in that case, a vector may be what I'm looking for. At the moment, I'm limiting the number of items in a position to five, but the check for items depends on the first slot being empty.

    I'm using a tile-based class at the moment that stores information about terrain, items, creatures, etc. in seperate arrays for every location. That just seemed the natural way to do things, since I can link that to my movement routines. I'm not sure how successful it will be when it comes to AI, though.

    And the executable is 1.25mb. The source is a little smaller. I think it's because I'm repeating a lot of code (sort of like inlining, but I don't realise how often I'm going to use it until I use it). Also, everything is at the moment in the one source file. I should probably start to split it up into headers and various source files, just to make editing easier.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with day of the week program
    By Punkakitty in forum C++ Programming
    Replies: 10
    Last Post: 01-14-2009, 06:55 PM
  2. Replies: 8
    Last Post: 11-03-2008, 09:48 PM
  3. Stupid Newbie question
    By TimL in forum C++ Programming
    Replies: 4
    Last Post: 07-22-2008, 04:43 AM
  4. Newbie with Very Newbie Question
    By Jedi_Mediator in forum C++ Programming
    Replies: 18
    Last Post: 07-01-2008, 08:00 AM
  5. total newbie question
    By Unregistered in forum C++ Programming
    Replies: 15
    Last Post: 08-16-2002, 09:38 PM