Thread: Design question

  1. #1
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96

    Design question

    This is My first attempt at creating a rogue style game. Right now all I have is a blank screen with the player ( a '*' ) and a small wall. I can move the player around the screen and bump into the edges of the screen and the wall. As it is right now I have the function to move the player as a member function of the player class. Later, I intend on making a base class that will include (among other things) that move function and derive the player and creature classes from it. My question is should I leave the move function as a member or not? Here is the code
    Code:
    #define NOGDI
    
    #include <my_consoleopps.h>
    #include <iostream>
    
    class PLAYERS {
        public :
        PLAYERS() { Create(); };
        ~PLAYERS() {};
        WORD Movement();
        
        private :
        COORD               current_position;
        HANDLE              hIn,
                            hOut;
        SMALL_RECT          screen_size;
        DWORD               NumRead,
                            NumWritten;
        INPUT_RECORD        InRec;
        
        bool invalid_move;
        void MovePlayer(COORD&);
        void Message();
        WORD GetCode();
        void Create();
    };
    
    WORD PLAYERS::Movement() {
        char ch;
        COORD new_position = current_position;
        WORD direction = GetCode();
        if (InRec.Event.KeyEvent.bKeyDown) {
            if (invalid_move) {
                invalid_move = false;
                Message();
            }
            switch (direction) {
                case VK_NUMPAD8 : // Move north
                new_position.Y--;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.Y > screen_size.Top && ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
            
                case VK_NUMPAD7 : // Move northwest
                new_position.X--; new_position.Y--;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.Y > screen_size.Top &&
                    current_position.X > screen_size.Left &&
                    ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
            
                case VK_NUMPAD4 : // Move west
                new_position.X--;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.X > screen_size.Left && ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
            
                case VK_NUMPAD1 : // Move southwest
                new_position.X--; new_position.Y++;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.Y < (screen_size.Bottom - 1) &&
                    current_position.X > screen_size.Left &&
                    ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
            
                case VK_NUMPAD2 : // Move south
                new_position.Y++;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.Y < (screen_size.Bottom - 1) && ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
    
                case VK_NUMPAD3 : // Move southeast
                new_position.X++; new_position.Y++;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.Y < (screen_size.Bottom - 1) &&
                    current_position.X < screen_size.Right &&
                    ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
            
                case VK_NUMPAD6 : // Move east
                new_position.X++;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.X < screen_size.Right && ch != '#') {
                    MovePlayer(new_position);
                } else { 
                    invalid_move = true;
                    Message();
                }
                break;
            
                case VK_NUMPAD9 : // Move northeast
                new_position.X++; new_position.Y--;
                ReadConsoleOutputCharacter(hOut,&ch, 1, new_position, &NumRead);
                if (current_position.Y > screen_size.Top &&
                    current_position.X < screen_size.Right &&
                    ch != '#') {
                    MovePlayer(new_position);
                } else {
                    invalid_move = true;
                    Message();
                }
                break;
            
            }
        }
        return direction;
    }
    
    void PLAYERS::MovePlayer(COORD& new_position) {
        SetConsoleCursorPosition(hOut, current_position);
        WriteConsole(hOut, " ", 1, &NumWritten, NULL);
        SetConsoleCursorPosition(hOut, new_position);
        WriteConsole(hOut, "*", 1, &NumWritten, NULL);
        current_position = new_position;
        return;
    }
    
    void PLAYERS::Message() {
        char message[] = "You Cannot Move There!";
        char clear[]   = "                      ";
        COORD pos = {5, (screen_size.Bottom + 1)};
        SetConsoleCursorPosition(hOut, pos);
        if (invalid_move)
            WriteConsole(hOut, &message, sizeof(message), &NumWritten, NULL);
        else
            WriteConsole(hOut, &clear, sizeof(clear), &NumWritten, NULL);
        SetConsoleCursorPosition(hOut, current_position);
        return;
    }
    
    WORD PLAYERS::GetCode() {
        ReadConsoleInput(hIn, &InRec, 1, &NumRead);
        return InRec.Event.KeyEvent.wVirtualKeyCode;
    }
    
    void PLAYERS::Create() {
        hIn  = GetStdHandle(STD_INPUT_HANDLE);
        hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD winsize = GetLargestConsoleWindowSize(hOut);
         screen_size.Right = winsize.X - 3;
         screen_size.Bottom = winsize.Y - 3;
         screen_size.Left = 1;
         screen_size.Top = 2;
        invalid_move = false;
        
        // set start position
        current_position.X = 3; current_position.Y = 3;
        MovePlayer(current_position);
        return;
    }
    
    
    int main() {
        // set console title and make full screen
        InitConsole("Test Game", true);
        
        // Make cursor invisible
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_CURSOR_INFO cursor_info;
        cursor_info.dwSize = 10;
        cursor_info.bVisible = false;
        SetConsoleCursorInfo(hOut, &cursor_info);
        
    
        // Display Game Screen
        COORD pos;
        std::cout<<"Use Num Pad Arrow Keys To Move Cursor.  Hit <ENTER> To Quit.\n";
        std::cout<<(unsigned char)201;
        for (int i = 0; i < (MaxXposition() - 3); ++i)
            std::cout<<(unsigned char)205;
        std::cout<<(unsigned char)187;
        for (int i = 2; i < (MaxYposition() - 3); ++i) {
            SetCursorPosition(0, i);
            std::cout<<(unsigned char)186;
            SetCursorPosition( (MaxXposition() - 2), i);
            std::cout<<(unsigned char)186;
        }
        SetCursorPosition(0, (MaxYposition() - 3) );
        std::cout<<(unsigned char)200;
        for (int i = 0; i < (MaxXposition() - 3); ++i)
            std::cout<<(unsigned char)205;
        std::cout<<(unsigned char)188;
        
        // Set up maze
        
            
        // This is a test wall
        SetCursorPosition(20,20); std::cout<<"#####";
    
        // Set up Player and move him to the start position
        PLAYERS Player;
        
        //  Movement loop
        WORD code;
        do {
            code = Player.Movement();
        } while (code != VK_RETURN);
    
        return 0;
    }
    BTW, my_consoleopps is a wrapper of sorts that I created that addresses console issuses such as size and positioning.
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

  2. #2
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    If you're thinking of having a base class, and deriving a player class and a monster class from it, then yes, I'd say put movement code into the base class. Something like a function that's int Move(direction), and tries to move the player/monster/etc in that direction (and might return failure if it's bumping into a wall.) But since a lot of movement issues will be the same between mosters and players (direction handling, colision detection, etc.), it doesn't make much sense to write it all twice.
    Monsters, however, don't care about keypushes. So, the player might have a HandleInput(), or some such, which (on the appropriate key) would call the above Move().
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  3. #3
    Devil's Advocate SlyMaelstrom's Avatar
    Join Date
    May 2004
    Location
    Out of scope
    Posts
    4,079
    Keep in mind, your creature AI will require a locate function (to locate the player, or whatever it's targeting), to replace the players input function. Otherwise, it won't know where or why it's moving.
    Sent from my iPadŽ

  4. #4
    Master of Puppets rwmarsh's Avatar
    Join Date
    Feb 2006
    Location
    Texas
    Posts
    96
    Quote Originally Posted by SlyMaelstrom
    Keep in mind, your creature AI will require a locate function (to locate the player, or whatever it's targeting), to replace the players input function. Otherwise, it won't know where or why it's moving.
    That brings me to my next question, where can I find some information about how to create that AI for my monsters. I have been able to come up with only one idea and it seems VERY ugly. Any one know a tut or a web site that will explain how to go about setting up the AI.

    Ok, I have found a few sites on the web and have been looking at A* pathfinding. Am I right in thinking that this would be the best meathod to allow my monsters to seek out and chase the player?
    Last edited by rwmarsh; 08-12-2006 at 10:24 AM.
    Using DEV-C++ Under Windows XP
    +------------------------------+

    "No! Do, or Do Not. There is no Try..."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Game design question
    By h3ro in forum Game Programming
    Replies: 6
    Last Post: 02-28-2008, 08:20 AM
  2. Question about engine design.
    By Shamino in forum Game Programming
    Replies: 9
    Last Post: 01-29-2008, 10:53 AM
  3. question about class design and overloading
    By l2u in forum C++ Programming
    Replies: 7
    Last Post: 12-13-2007, 02:02 PM
  4. database app design question
    By MPSoutine in forum Windows Programming
    Replies: 4
    Last Post: 12-02-2003, 10:13 PM
  5. design question: opinion
    By ggs in forum C Programming
    Replies: 2
    Last Post: 01-29-2003, 11:59 AM