Classical Snake game!

Multiple Players (Full code)

  • (2 Pages)
  • +
  • 1
  • 2

22 Replies - 3701 Views - Last Post: 24 March 2009 - 08:31 PM Rate Topic: -----

#1 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Classical Snake game!

Post icon  Posted 27 February 2009 - 10:22 AM

I wrote Snake back in December 6th of '08. I stopped "working" on it in December 10th. I messed with it again in January (2009) around the 11th for a day and decided I had no ideas. I picked it up yet again! Feb. 22nd and decided to turn it into something more object-oriented...

Here's the outcome:
#include <iostream>
#include <conio.h>
#include <TextControl.h>
using namespace std;

class CREATE_SNAKE {

    public:
        bool GameOver;
        bool Computer;
        bool IsImmortal;
        int X, Y;
        int Player;
        int PlaceX, PlaceY;
        int Width, Height;

    private:
        int Food[3];
        int SnakeColor;
        int CONTROL[4];
        int LastMove;
        int Horizontal[100], Vertical[100];
        int SnakeSize;
        int Score;
        int Lives;

    public:
        CREATE_SNAKE::CREATE_SNAKE(int ID, int X, int Y, int UP, int DOWN, int LEFT, int RIGHT, int COLOR);
        CREATE_SNAKE::CREATE_SNAKE(int ID);
        int GetSnakeSize() { return SnakeSize; }
        int GetXPos(int x) { return Horizontal[x]; }
        int GetYPos(int x) { return Vertical[x]; }
        
        /* Snake collected food? */
        void CollectFood();
        
        /* Snake died, reset! */
        void ResetSnake();
        
        /* Set directional keys for the Snake */
        void SetUpArrow(int UpArrow) { CONTROL[0] = UpArrow; }
        void SetDownArrow(int DownArrow) { CONTROL[1] = DownArrow; }
        void SetLeftArrow(int LeftArrow) { CONTROL[2] = LeftArrow; }
        void SetRightArrow(int RightArrow) { CONTROL[3] = RightArrow; }
        
        /* Snake hit a wall or himself? */
        void Crashed();
        
        /* The user changed direction? */
        void GetUserInput();
        
        /* Update the Snake's position on the "board" */
        void DrawSnake();
        
        /* Set the Snake's walls (invisible) */
        void SetBoundaries(int xWidth, int xHeight, int xPlaceX, int xPlaceY);
        
        /* Draw the Snake's walls (visible) */
        void DrawPlayingField(int color) { DrawBox(color, Width, Height, PlaceX, PlaceY); SetColor(BLACK, BLACK); }
        
        /* Initial food placement for the Snake */
        void DrawFood();

        void DisplayScore(int X, int Y) { PlaceCursor(X, Y); SetColor(WHITE, BLACK); printf("%i", Score); SetColor(BLACK, BLACK); }
        void DisplayLives(int X, int Y) { PlaceCursor(X, Y); SetColor(WHITE, BLACK); printf("%i", Lives); SetColor(BLACK, BLACK); }
        void Grow(int pieces) { SnakeSize += pieces; }
        void AI();

        void UserSelectedDimensions();
};

CREATE_SNAKE::CREATE_SNAKE(int ID) {

    SnakeColor = CYAN;
    for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
    GameOver = false;
    Computer = false;
    IsImmortal = false;
    Width = 80;
    Height = 25;
    PlaceX = 0;
    PlaceY = 0;
    Food[0] = 0;
    Food[1] = 0;
    SnakeSize = 5;
    Lives = 4;
    Score = 0;
    Player = ID;
}

CREATE_SNAKE::CREATE_SNAKE(int ID, int X, int Y, int UP, int DOWN, int LEFT, int RIGHT, int COLOR) {

    SnakeColor = COLOR;
    CONTROL[0] = UP;
    CONTROL[1] = DOWN;
    CONTROL[2] = LEFT;
    CONTROL[3] = RIGHT;
    LastMove = RIGHT;

    for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
    GameOver = false;
    Computer = false;
    IsImmortal = false;
    Horizontal[0] = X;
    Vertical[0] = Y;
    Width = 80;
    Height = 25;
    PlaceX = 0;
    PlaceY = 0;
    Food[0] = 0;
    Food[1] = 0;
    SnakeSize = 5;
    Lives = 4;
    Score = 0;
    Player = ID;
}

void CREATE_SNAKE::UserSelectedDimensions() {

    int x = 5;
    int y = 4;
    int px = 35;
    int py = 20;

    char Type[] = "Player";

    DrawBox(RED, x, y, px, py);

    while (true) {
        Sleep(50);

        PlaceCursor(20, 0);
        SetColor(WHITE, BLACK);
        printf("Press C to spawn as a ");
        SetColor(CYAN, BLACK);
        printf("computer");

        PlaceCursor(20, 1);
        SetColor(WHITE, BLACK);
        printf("Press P to spawn as a ");
        SetColor(CYAN, BLACK);
        printf("player");

        PlaceCursor(0, 5);
        SetColor(WHITE, BLACK);
        printf("SPAWN TYPE: ");
        SetColor(CYAN, BLACK);
        printf("%s", Type);

        SetColor(WHITE, BLACK);
        PlaceCursor(0, 0);
        printf("X: %i  ", px);
        PlaceCursor(0, 1);
        printf("Y: %i  ", py);
        PlaceCursor(0, 3);
        printf("Height: %i  ", y);
        PlaceCursor(0, 4);
        printf("Width: %i  ", x);

        /* Placement of the X, Y coordinates */
        if (GetAsyncKeyState(VK_UP) && !GetAsyncKeyState(VK_SHIFT) && py > 1) { DrawBox(BLACK, x, y, px, py); py--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_DOWN) && !GetAsyncKeyState(VK_SHIFT) && (py + y) < 49) { DrawBox(BLACK, x, y, px, py); py++; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_LEFT) && !GetAsyncKeyState(VK_SHIFT) && px > 0) { DrawBox(BLACK, x, y, px, py); px--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_RIGHT) && !GetAsyncKeyState(VK_SHIFT) && (px + x) < 80) { DrawBox(BLACK, x, y, px, py); px++; DrawBox(RED, x, y, px, py); }

        /* Resizing of the box */
        if (GetAsyncKeyState(VK_UP) && GetAsyncKeyState(VK_SHIFT) && y > 4) { DrawBox(BLACK, x, y, px, py); y--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_DOWN) && GetAsyncKeyState(VK_SHIFT) && (py + y) < 49) { DrawBox(BLACK, x, y, px, py); y++; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_LEFT) && GetAsyncKeyState(VK_SHIFT) && x > 5) { DrawBox(BLACK, x, y, px, py); x--; DrawBox(RED, x, y, px, py); }
        if (GetAsyncKeyState(VK_RIGHT) && GetAsyncKeyState(VK_SHIFT) && (px + x) < 80) { DrawBox(BLACK, x, y, px, py); x++; DrawBox(RED, x, y, px, py); }

        if (GetAsyncKeyState('C') && !Computer) { strcpy(Type, "Computer"); Computer = true; }
        if (GetAsyncKeyState('P') && Computer) { strcpy(Type, "Player  "); Computer = false; }

        /* Place the box - "fade out" for cool effects! ;)/> */
        if (GetAsyncKeyState(VK_SPACE)) {
            Sleep(150);
            SetColor(GREY, BLACK);
            DrawBox(x, y, px, py);
            Sleep(150);
            SetColor(DARK_WHITE, BLACK);
            DrawBox(x, y, px, py);
            Sleep(150);
            SetColor(BLACK, BLACK);
            DrawBox(x, y, px, py);
            break;
        }
    }

    /* Save the X, Y, coordinates of the box */
    X = x; Y = y; PlaceX = px; PlaceY = py;

    SetBoundaries(x, y, px, py);
    ClearConsole();
    SetColor(BLACK, BLACK);

    return;
}

void CREATE_SNAKE::DrawFood() {

    srand(time(NULL));

    PLACEFOOD:
    Food[0] = rand() % Width + PlaceX;
    Food[1] = rand() % Height + PlaceY;

    if (Food[1] == PlaceY || Food[1] == Height + PlaceY - 1 || Food[0] == PlaceX || Food[0] == Width + PlaceX - 1) {
        goto PLACEFOOD;
    }

    for (int x = 0; x < SnakeSize; x++) { if (Food[0] == Horizontal[x] && Food[1] == Vertical[x]) { goto PLACEFOOD; } }

    PlaceCursor(Food[0], Food[1]);
    SetColor(YELLOW, BLACK);
    printf("x");
    SetColor(BLACK, BLACK);
}

void CREATE_SNAKE::SetBoundaries(int xWidth, int xHeight, int xPlaceX, int xPlaceY) {

    Width = xWidth;
    Height = xHeight;
    PlaceX = xPlaceX;
    PlaceY = xPlaceY;
    DrawBox(Width, Height, PlaceX, PlaceY);

    return;
}

void CREATE_SNAKE::ResetSnake() {

    DrawPlayingField(WHITE);
    for (int x = 0; x < SnakeSize; x++) { PlaceCursor(Horizontal[x], Vertical[x]); printf(" "); }
    for (int x = 0; x < 100; x++) { Horizontal[x] = 0; Vertical[x] = 0; }
    Horizontal[0] = PlaceX + 2;
    Vertical[0] = PlaceY + 1;
    LastMove = CONTROL[3]; /* To the right */
    SnakeSize = 5;

    if (!IsImmortal) {
        Lives--;

        SetColor(WHITE, BLACK);
        PlaceCursor(PlaceX, PlaceY + Height); printf("Lives: ");
        DisplayLives(PlaceX + 7, PlaceY + Height);
        SetColor(BLACK, BLACK);

        if (Lives <= 0) {
            GameOver = true;

            int CenterX = ((Width / 2) + PlaceX) - (9 / 2);
            int CenterY = ((Height / 2) + PlaceY) - 1;

            PlaceCursor(Food[0], Food[1]);
            SetColor(BLACK, BLACK);
            printf(" ");

            PlaceCursor(CenterX, CenterY);
            SetColor(WHITE, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(RED, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(WHITE, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(RED, BLACK);
            printf("GAME OVER");
            Sleep(150);

            PlaceCursor(CenterX, CenterY);
            SetColor(YELLOW, BLACK);
            printf("GAME OVER");
            SetColor(BLACK, BLACK);
        }
    }

    return;
}

void CREATE_SNAKE::Crashed() {

    for (int x = SnakeSize - 1; x > 1; x--) {
        if (Horizontal[0] == Horizontal[x] && Vertical[0] == Vertical[x]) {
            PlaceCursor(Horizontal[0], Vertical[0]);
            SetColor(RED, BLACK);
            printf("X");
            PlaceCursor(30, 0);
            printf("Player %i has hit himself!", Player);
            Sleep(500);
            PlaceCursor(30, 0);
            SetColor(BLACK, BLACK);
            printf("                            ");
            ResetSnake();
            return;
        }
    }

    if (Vertical[0] == PlaceY || Vertical[0] == Height + PlaceY - 1 ||
        Horizontal[0] == PlaceX || Horizontal[0] == Width + PlaceX - 1) {

        char WallPieceHit = '\0';
        if (Vertical[0] == PlaceY || Vertical[0] == Height + PlaceY - 1) { WallPieceHit = ''; } /* Vertical Wall */
        else { WallPieceHit = ''; } /* Horizontal Wall */

        PlaceCursor(Horizontal[0], Vertical[0]);
        SetColor(RED, BLACK);
        printf("%c", WallPieceHit);
        PlaceCursor(30, 0);
        printf("Player %i hit the wall!", Player);
        Sleep(500);
        PlaceCursor(30, 0);
        SetColor(BLACK, BLACK);
        printf("                         ");
        ResetSnake();
        return;
    }

    return;
}

void CREATE_SNAKE::GetUserInput() {

    HANDLE InHandle = GetStdHandle(STD_INPUT_HANDLE);
    FlushConsoleInputBuffer(InHandle);

    if (GetAsyncKeyState(CONTROL[0]) && LastMove != CONTROL[1]) { LastMove = CONTROL[0]; } else
    if (GetAsyncKeyState(CONTROL[1]) && LastMove != CONTROL[0]) { LastMove = CONTROL[1]; } else
    if (GetAsyncKeyState(CONTROL[2]) && LastMove != CONTROL[3]) { LastMove = CONTROL[2]; } else
    if (GetAsyncKeyState(CONTROL[3]) && LastMove != CONTROL[2]) { LastMove = CONTROL[3]; }

    return;
}

void CREATE_SNAKE::DrawSnake() {

    if (LastMove == CONTROL[0]) { PlaceCursor(Horizontal[0],   Vertical[0]--); } else
    if (LastMove == CONTROL[1]) { PlaceCursor(Horizontal[0],   Vertical[0]++); } else
    if (LastMove == CONTROL[2]) { PlaceCursor(Horizontal[0]--, Vertical[0]);   } else
    if (LastMove == CONTROL[3]) { PlaceCursor(Horizontal[0]++, Vertical[0]);   }

    SetColor(SnakeColor, BLACK);
    for (int x = SnakeSize; x > 0; x--) { Horizontal[x] = Horizontal[x - 1]; Vertical[x] = Vertical[x - 1]; }
    for (int x = SnakeSize; x >= 0; x--) { PlaceCursor(Horizontal[x], Vertical[x]); printf("*"); }

    PlaceCursor(Horizontal[0], Vertical[0]); printf("@");
    if (Horizontal[0] != Horizontal[SnakeSize] || Vertical[0] != Vertical[SnakeSize]) {
        PlaceCursor(Horizontal[SnakeSize], Vertical[SnakeSize]); SetColor(BLACK, BLACK); printf(" ");
    }

    PlaceCursor(Food[0], Food[1]);
    SetColor(YELLOW, BLACK);
    printf("x");
    SetColor(BLACK, BLACK);
    return;
}

void CREATE_SNAKE::CollectFood() {

    /* Begin loop */
    if (Horizontal[0] == Food[0] && Vertical[0] == Food[1]) {
    PLACEFOOD:

        Food[0] = rand() % Width + PlaceX;
        Food[1] = rand() % Height + PlaceY;

        /* Check wall range - if false start over */
    if (Food[1] == PlaceY || Food[1] == Height + PlaceY - 1 || Food[0] == PlaceX || Food[0] == Width + PlaceX - 1) {
            goto PLACEFOOD;
        }

        /* Check if it's on the snake - if false start over */
        for (int x = 0; x < SnakeSize; x++) {
            if (Food[0] == Horizontal[x] && Food[1] == Vertical[x]) {
                goto PLACEFOOD;
            }
        }

        Score++;
        Grow(1);

        PlaceCursor(Food[0], Food[1]);
        SetColor(YELLOW, BLACK);
        printf("x");

        SetColor(WHITE, BLACK);
        PlaceCursor(PlaceX, PlaceY - 1);
        printf("Player %i (score): ", Player);
        DisplayScore(PlaceX + 18, PlaceY - 1);
        SetColor(BLACK, BLACK);

    } /* End loop */

    return;
}

void CREATE_SNAKE::AI() {

    if (Food[1] > Vertical[0]) { if (LastMove != CONTROL[0]) { LastMove = CONTROL[1]; } else { LastMove = CONTROL[2]; } } else
    if (Food[1] < Vertical[0]) { if (LastMove != CONTROL[1]) { LastMove = CONTROL[0]; } else { LastMove = CONTROL[2]; } } else
    if (Food[0] > Horizontal[0]) { if (LastMove != CONTROL[2]) { LastMove = CONTROL[3]; } else { LastMove = CONTROL[0]; } } else
    if (Food[0] < Horizontal[0]) { if (LastMove != CONTROL[3]) { LastMove = CONTROL[2]; } else { LastMove = CONTROL[0]; } }

    return;
}

void CheckPlayersHit(vector<CREATE_SNAKE> &Snake, int SnakeX) {

/* Main idea on how to check collision status (initial Snake vs. opposing):
    - Cycle through all Snakes
    - Compare each Snake (head) cycled against all other Snakes (bodies)

    Step 1) Find initial Snake to compare to all others
    Step 2) Find size of initial Snake so you can compare against all others
    Step 3) Compare initial Snake (loop based on size) against all others
*/

    /* Loop through all Snakes in the vector */
    for (int x = SnakeX - 1; x >= 0; x--) {

        /* Loop through Snake X's size */
        for (int o = SnakeX - 1; o >= 0; o--) {

            /* Loop through all (other) Snakes in the vector to check a collison status against */
                for (int s = Snake.at(o).GetSnakeSize() - 1; s > 0; s--) {
                    if (Snake.at(x).Player != Snake.at(o).Player && !Snake.at(x).GameOver) {
                    if (Snake.at(x).GetXPos(0) == Snake.at(o).GetXPos(s) && Snake.at(x).GetYPos(0) == Snake.at(o).GetYPos(s)) {
                    Snake.at(x).ResetSnake();
                    }
                }
            }
        }
    }

    return;
}

bool GameInProgress(vector<CREATE_SNAKE> &Snake, int SnakeX, int &Winner) {

    int GamesEnded = 0;
    bool Player[SnakeX];

    /* Fill in the values */
    for (int x = SnakeX - 1; x >= 0; x--) {
        Player[x] = Snake.at(x).GameOver;

        if (Player[x] == true) { GamesEnded++; }
        if (Player[x] == false) { Winner = (x + 1); }
    }

    if (GamesEnded == SnakeX) { return false; }
    else { return true; }
}

int main() {

    HANDLE OutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE InHandle = GetStdHandle(STD_INPUT_HANDLE);
    SetConsoleTitle("Snake");
    SMALL_RECT windowSize = {0, 0, 79, 49};
    SetConsoleWindowInfo(OutHandle, TRUE, &windowSize);

    ClearConsole();
    RemoveCursor();
    int GameSpeed = 50;
    int Winner = 0;

    int NumSnakes = 0;
    printf("How many Snakes do you want? ");
    scanf("%d", &NumSnakes);
    ClearConsole();

    vector<CREATE_SNAKE> Snake;
    for (int x = 0; x <= NumSnakes; x++) { Snake.push_back(CREATE_SNAKE(x + 1)); }
    for (int x = 0; x <= NumSnakes; x++) {
        Snake.at(x).SetUpArrow(VK_UP);
        Snake.at(x).SetDownArrow(VK_DOWN);
        Snake.at(x).SetLeftArrow(VK_LEFT);
        Snake.at(x).SetRightArrow(VK_RIGHT);
    }

    Snake.at(1).SetUpArrow('W');
    Snake.at(1).SetDownArrow('S');
    Snake.at(1).SetLeftArrow('A');
    Snake.at(1).SetRightArrow('D');

    for (int x = 0; x < NumSnakes; x++) { Snake.at(x).UserSelectedDimensions(); }

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(RED);
    printf("READY?");
    Sleep(500);

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(YELLOW);
    printf("SET...");
    Sleep(500);

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(GREEN);
    printf("GO!   ");
    Sleep(500);

    PlaceCursor((80 / 2) - 6, (50 / 2) - 1);
    SetColor(BLACK);
    printf("   ");

    for (int x = 0; x < NumSnakes; x++) { Snake.at(x).DrawPlayingField(WHITE); }

    while (GameInProgress(Snake, NumSnakes, Winner)) {

        for (int x = 0; x < NumSnakes; x++) {
            if (!Snake.at(x).GameOver) {
                Snake.at(x).GetUserInput();
                Snake.at(x).DrawSnake();
                Snake.at(x).CollectFood();
                if (Snake.at(x).Computer) { Snake.at(x).AI(); }
                Snake.at(x).Crashed();
            }
        }

        CheckPlayersHit(Snake, NumSnakes);

        PlaceCursor(30, 0);
        SetColor(WHITE, BLACK);
        printf("GameSpeed: %i ", GameSpeed);

        if (GetAsyncKeyState(VK_ADD) && GameSpeed > 0) { GameSpeed--; }
        if (GetAsyncKeyState(VK_SUBTRACT) && GameSpeed < 150) { GameSpeed++; }

        if (GetAsyncKeyState(VK_ESCAPE)) { break; }
        Sleep(GameSpeed);
    }

    int CenterX = ((Snake.at(Winner - 1).Width / 2) + Snake.at(Winner - 1).PlaceX) - (23 / 2);
    int CenterY = ((Snake.at(Winner - 1).Height / 2) + Snake.at(Winner - 1).PlaceY);

    PlaceCursor(CenterX, CenterY);
    SetColor(WHITE, BLACK);
    printf("THE WINNER IS: Player %i", Winner);

    PlaceCursor(0, 0);
    SetColor(BLACK, BLACK);

    FlushConsoleInputBuffer(InHandle);
    _flushall();
    _getch();
    return 0;
}


I am not very good at judging when I need to make a new class, nor am I very good at using classes altogether with C++. If you have any ideas, advice, tips, hints, etc. Please say them in a non "Flaming" manner, because being a jerk simply gets you ignored (WolfCoder).

This isn't the prettiest code in the world; I put the comments in this post only, they don't exist in my *.cpp file, because I honestly don't think they're needed. What I have is pretty much self-explainitory; I attempted to use the STL (vectors) in improve this. Creating the routine where any Snake can hit any other Snake was very difficult, and it could be improved (it's in an ascending order, meaning Player 1 wins any head-on-collisions).

The only reason I have conio in there is for the _getch() at the very end, because in a version one above this, I was attempting to create a menu (and it was giving me issues using cin.get(), which I'll find a way around when I'm ready).

I'm unaware of how class inheritence works entirely; For instance: When spawning "Parent" classes that have "Child" classes, are the "child" classes tied in with the "Parent" class that was spawned? If the child class is tied with the parent class, then I could easily split the food spawning into its own class, allowing me to "Enable" food stealing from Player 1 to Player 2 (assuming their boundaries overlapped), because as of current, each Snake has its own food, and if you go over say Player 2's food, Player 2's food isn't eaten (it's redrawn so it doesn't vanish).

There could be many improvements on this simple! Program that demonstrates the usage of classes & vectors, and I'd love to hear them in a useful manner.

Hope this helps somebody (yay for Google!)... or somebody finds it entertaining. :) Sort of like Diablo II hacks are, or Diablo II mods.

This post has been edited by Hyper: 27 February 2009 - 03:55 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Classical Snake game!

#2 stayscrisp  Icon User is online

  • フカユ
  • member icon

Reputation: 1000
  • View blog
  • Posts: 4,181
  • Joined: 14-February 08

Re: Classical Snake game!

Posted 28 February 2009 - 08:31 AM

Hey there,

This is looking good but you should take a look at naming conventions, they can be quite useful in making sure that you know what kind of value you are looking at. Such as member variables should be named with an m_ such as m_x and m_y.
pointers and boolean should be named p_ and b_ respectively, p_gameScreen or b_alive are good examples.

These can also be combined to make m_bAlive which is a boolean member variable or m_pgameScreen, a pointer and a member variable. Also a class should name an object not a function. You chose to call your snake class CREATE_SNAKE when really it should be called Snake, sounds picky but it doesn't look right to see CREATE_SNAKE::DOAI() when what you really mean is Snake::doAI(), it just looks better and makes a lot more sense.

I mean its obvious you can get by without these "rules" but i find them useful a lot of the time.

Anyway that's just food for thought.

Because snake doesnt really have many objects then going over the top with inheritance and polymorphism is total overkill.
A good start would be to think about what kind of functions and values these objects have in common and then decide if its worth creating a base class for all your other objects to inherit from.

in my game i have GameObject class that contains Draw,Init,Update and other functions that all other objects will need,
the draw function draws the sprite to the screen which is how all other objects will be drawn to the screen. Why write another sprite drawing function for each object when they can all use the GameObject one :) same applies with update and init, obviously these functions can be overridden to suit the needs of your inherited classes.

So once you have created your gameobject base class you can create a vector of pointers to these objects, then all inherited classes can be pushed into this vector, then in your main game logic drawing all your objects will be as simple as looping through this vector and calling the gameobject draw function
for(int i = 0;i < GameObject::pGameObjects.size();i++) { // loop through vector
		if(!GameObject::pGameObjects[i]) continue; 
		
		GameObject::pGameObjects[i]->Draw(game->m_pScreen); // call draw function
}



All of your inherited classes will use the game object draw function so you will not need to specify the type of object even if its function has been overridden, that is my understanding anyway.

This is all very well outlined in many C++ books and although it seems daunting at first once you have a grasp it makes everything a lot simpler.

Hope that helps a little

This book helped me a lot
http://www.amazon.co...t/dp/1584502274

:^:
Was This Post Helpful? 0
  • +
  • -

#3 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 28 February 2009 - 12:17 PM

"Anyway that's just food for thought."
Thank you, but I was already aware of that. I personally think it's harder to read, and another variation of that, is to use less underscores. Such as "bGameOver" or "bImmortal," but yes, thanks. Something you forgot to mention, is classes are prefixed with "c" or "c_," so it should be "cSnake" or "c_Snake" or with what I have, "c_CREATE_SNAKE" or even "cCREATE_SNAKE" but, again, thank you. :P

"Because snake doesnt really have many objects then going over the top with inheritance and polymorphism is total overkill."
Anything and everything I've ever written I wouldn't classify as needing "class inheritence" or "polymorphisism" or even object oriented method, because structural would be way shorter and more readable (to me).

"A good start would be to think about what kind of functions and values these objects have in common and then decide if its worth creating a base class for all your other objects to inherit from."
I have a real difficult time at making decisions, opinions (on specific things or just odd days), and I have a really hard time classifying things, segregation, uh.. categorization? But, here's the best I can think of (off the top of my head) about how to segregate the game:
Commonality between the "base class" Snake would be
- All Snakes grow, shrink, can be reset
- All Snakes have an ID, set amount of Lives, and score
- All Snakes have their own seperate food (which I'd like to have an option for "Food stealing" but with how it's setup right now, that's rather difficult)
Other than those few misc. things, I don't understand how to segregate.

"you can create a vector of pointers to these objects, then all inherited classes can be pushed into this vector"
What would be the benefit of using a vector of pointers over using a vector of objects? Is there any technical performance difference...? Is it simply easier to read? Easier to modify? Easier to "maintain...?" (Not that I, nor any other will likely modify the game alot.) What's the main benefit of using a vector of pointers to (inherited class) objects?

Thank you very much again!

PS: I think there's a huge fire coming through the woods at my house (there was a brush fire Feb. 26th that cleared 3+ acres and that's like.. less than a mile from here)

http://i44.tinypic.com/hvt4w1.jpg
http://i43.tinypic.com/2dh7mv4.jpg

http://www.mediafire...674b4331ca82222
Mandatory evacution, bye y'all~ See you whenever.

This post has been edited by Hyper: 28 February 2009 - 12:51 PM

Was This Post Helpful? 0
  • +
  • -

#4 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 03 March 2009 - 12:09 PM

stayscrisp? No reply?
Was This Post Helpful? 0
  • +
  • -

#5 stayscrisp  Icon User is online

  • フカユ
  • member icon

Reputation: 1000
  • View blog
  • Posts: 4,181
  • Joined: 14-February 08

Re: Classical Snake game!

Posted 04 March 2009 - 10:56 AM

Hey

Sorry thought your house had burned down lol :P

Pointer are quite hard to explain so heres a link

Basically it is a lot faster to use pointers or vectors of pointers as they are only pointers to data in memory rather than copies of data, so its easier and more efficient to use them when dealing with a vector of objects. Why have copies of data when you can just point to the address of the data. :) That link should explain better, but i guess you just have to trust me that its a better idea :P
Was This Post Helpful? 0
  • +
  • -

#6 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 05 March 2009 - 11:11 AM

Thank you for the link and short explaination, but I knew what a pointer was already. Summarization of a pointer is, "A variable that holds the address of another variable." They're great for passing by reference. :)

I don't quite understand what you'd meant by using a vector of pointers on child objects, you were rather vague (from my understanding of it all). But, you'd already stated that using inheritence would be quote, "Overkill" so, I suppose it really doesn't matter either way.
PS: He mis spelled "whole," he put "hole" (on the tutorial) :D

You didn't respond to one question specifically though: How would I create a "base class" for Snake? How would I chop it up? Segregate it?

Thanks again, and no, my house wasn't burned down (Thankfully).
Was This Post Helpful? 0
  • +
  • -

#7 stayscrisp  Icon User is online

  • フカユ
  • member icon

Reputation: 1000
  • View blog
  • Posts: 4,181
  • Joined: 14-February 08

Re: Classical Snake game!

Posted 05 March 2009 - 02:18 PM

Hi

Well if you knew what pointers where then you knew the answer to your own question :P

To answer your question you would not create a base class for snake you would create a base class for all game object.

Here's an example

// gameobject .h
class GameObject
{
   public:

   bool Load();
   void Draw();
   void Update();

   GameObject();
   virtual ~GameObject(); // virtual destructor;)

   protected:
   
   float xpos;
   float ypos;

   std::vector<GameObject*> gameObjects;  // vector of POINTERS! to game objects :P
};

// gameobject.cpp

GameObject::GameObject()
{
}

GameObject::Load()
{
   // load function
}

//  etc etc for other functions



That is a very basic base class of course but you can extend it for your own needs :)

So from this base class you can derive each of your other objects such as your snake,food and whatever :)
for example

// snake.h
#include "gameobject.h"

class Snake : public GameObject
{
	public:
	
	Snake();
	bool Load();
	void Draw();
	void Update();
};

// snake.cpp

Snake::Snake()
{
}

bool Load(/*pass in stuff*/)
{
   GameObject::Load(/* pass in stuff*/);
   // plus snake specific stuff
}

// etc etc



now here comes the best part so in your game class you have pretty similar functions to your gameobjects really, you have draw,update, load and some values. but now because of this excellent design updating drawing and loading objects is very quick and easy


Snake snake1;
Snake snake2;
GameObject snakefood1;
GameObject snakefood2;

Game::Load()
{
	snake1.Load(/*stuff*/);
	snake1.Load(/*stuff*/);
	snakefood1.Load(/*stuff*/);
	snakefood2.Load(/*stuff*/);

	GameObject::gameObjects.push_back(&snake1);
	GameObject::gameObjects.push_back(&snake2);
	GameObject::gameObjects.push_back(&snakefood1);
	GameObject::gameObjects.push_back(&snakefood2);
}

Game::Update()
{
		  // loop through vector of pointers and call update for each
		  for(int i = 0;i < GameObject::GameObjects.size();i++) {
		if(!GameObject::GameObjects[i]) continue;
		
		GameObject::GameObjects[i]->Update();
	}
}

Game::Draw()
{
	 // loop through vector of game objects and call draw on each
	 for(int i = 0;i < GameObject::GameObjects.size();i++) {
		if(!GameObject::GameObjects[i]) continue;
		
		GameObject::GameObjects[i]->Draw();
	}
}



I personally find this an excellent way to write games and is a really nice way of keeping things nicely sorted instead of a huge list of functions and lines and lines of code, things are nicely encapsulated.

notice you didnt need to specify the type of object you where calling it simpy called the update function for each individual object even if you had object specific code :)

Wow that was a long post , but hopefully it cleared things up. sorry if you already knew a lot of this as you keep saying you do, but i thought id try and be thorough :^:

this is how i was taught at college :)
Was This Post Helpful? 0
  • +
  • -

#8 NeoTifa  Icon User is offline

  • Whorediot
  • member icon





Reputation: 2699
  • View blog
  • Posts: 15,738
  • Joined: 24-September 08

Re: Classical Snake game!

Posted 05 March 2009 - 08:27 PM

Quote

being a jerk simply gets you ignored (WolfCoder).


You're my hero :rolleyes:

Some of those decisions are all on personal preference. Me, I like to make every single freaking little thing a class because I like to make things more complicated so I can complain about how complicated my program is XD. I don't know if I am actually answering your question or not...
Was This Post Helpful? 0
  • +
  • -

#9 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 06 March 2009 - 04:14 PM

NeoTifa, No, that was not answering my question. I'm glad to be your hero.

stayscrisp: Thank you for being more clear and showing an example of what you mean, it helps to explain it alot further (because I was confused as to something you were being foggy about).

I'm curious however, what I have and what you have are quite alike.
Snake snake1;
Snake snake2;
GameObject snakefood1;
GameObject snakefood2;


That would be a down-fall to how I have this setup. I don't want a static set of Snakes, I want it to change during run-time (which it does as is), that way, a player can add/remove Snakes as he chooses without having to recompile or modify anything (other than the UI with the "Snakes in game" option).

I was slightly confused about the pointers with the objects and child class but, now it makes alot more sense (I glanced at it earlier, I read it the second time around).

Thank you again, very much, very helpful!

Also I may have been programming for quite a while, but I haven't gone anywhere in a long time. I've never attended a school or had any "formal training" with programming. I lost interest in it for a few years, but I messed around learning tid-bits. Then I realized what MSDN was!

Somebody had shown me a link and it sparked my interests x10-fold and I've been happily coding ever since. Making gobs of pointless (yet entertaining!) programs. I reguarly attempt to get other people interested, but I don't think people find it too fun... Hope this wasn't too long and personal of a read for you. Just wanted to let you know that I'm not "All that" in a bag of potatoe chips. I know what I know, and that's that (like with pointers!).

Thanks again~ Appreciated :)
Was This Post Helpful? 0
  • +
  • -

#10 stayscrisp  Icon User is online

  • フカユ
  • member icon

Reputation: 1000
  • View blog
  • Posts: 4,181
  • Joined: 14-February 08

Re: Classical Snake game!

Posted 06 March 2009 - 04:26 PM

Quote

I want it to change during run-time (which it does as is), that way, a player can add/remove Snakes as he chooses without having to recompile or modify anything (other than the UI with the "Snakes in game" option).


Ah well that is a whole different ball game :)

I also have a lot of information about using text files to dynamically input your enemies,players,snakes and food. it would be using data driven design which means that your entire game could be read in from a text file which means people could edit values and other things from a text file without touching your code.

if your prepared for a read, its not overly complicated?
Was This Post Helpful? 0
  • +
  • -

#11 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 07 March 2009 - 09:43 PM

I wasn't asking you to rewrite my game. Reading from a datafile (you do realize it can be in binary?) isn't difficult by any means, but that'd make spawning food arbitrarly would be impossible (static data = bad!).

"Enemies?" This is Snake for Christ sake! Players...? The players are the Snakes. Snakes (self explainitory).... Sheesh! If you want to post it by all means, feel free. It'd be interesting to see how you'd go about doing it. :)

Yes, it is a whole different ball game, one that I've won prior to posting this! But thank you for the suggestions (I prefer dynamic and arbitrary over static and repetition).
Was This Post Helpful? 0
  • +
  • -

#12 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 11 March 2009 - 07:27 PM

I assume you aren't going to show how you'd do it (I was being sincere).

I've come across yet another puzzling question (not really, just want an opinion):
Should I store highscores in binary format, or ASCII format so they can edit it (cheat)?
If so! How should I go about it? Should there be a limit on how many users can be in the Scoreboard datafile? How should it be formatted (for viewing on the game)? I'm not the worlds best at creating ideas or designing games. :(

</help sign>
Was This Post Helpful? 0
  • +
  • -

#13 no2pencil  Icon User is online

  • Admiral Fancy Pants
  • member icon

Reputation: 5351
  • View blog
  • Posts: 27,306
  • Joined: 10-May 07

Re: Classical Snake game!

Posted 11 March 2009 - 07:34 PM

Store the high score in a hidden file in a hidden directory.

Then make a registry entry for the high score set date. For even more security, control all of this through a dll.

Check the date of the file against the date of the registry entry. If they don't match, display "CHEATER", rather than the high score.
Was This Post Helpful? 0
  • +
  • -

#14 Hyper  Icon User is offline

  • Banned

Reputation: 108
  • View blog
  • Posts: 2,129
  • Joined: 15-October 08

Re: Classical Snake game!

Posted 11 March 2009 - 07:34 PM

Are you being serious or yanking my chain?
EDIT: I have a superstitious feeling it's the latter.

This post has been edited by Hyper: 11 March 2009 - 07:35 PM

Was This Post Helpful? 0
  • +
  • -

#15 no2pencil  Icon User is online

  • Admiral Fancy Pants
  • member icon

Reputation: 5351
  • View blog
  • Posts: 27,306
  • Joined: 10-May 07

Re: Classical Snake game!

Posted 11 March 2009 - 07:36 PM

Take it for what it's worth.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2