Jump to content
  • Advertisement
Sign in to follow this  
hackdude

Beginning a game. (C , text-based).

This topic is 4954 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, this is my first post :). I have programmed in C for about 2 month now. I did not learn sockets or structures yet. But I learn as I work. And I ask people for help. Right now I am trying to make a text-based game. Like Snake for example. First, I don't know how to make the screen. I want it in the center with 80X and 25Y. I know a little bit on how to control. The first thing I want to make is just the screen with a letter on it. Thats it. When I am done with that, I'll make the controls for it. (Key_up, key_down).I am doing to make that the letter is able to move up, down, left and right. After that, I'll start adding the things that the snake game has. I am kind of new to this kind of game development. I once started on a text-based adventure games. But this is different, the screen should not refresh every move, it should stay the same. If anybody wants to join me and help, please email or PM. Thanks in advance.

Share this post


Link to post
Share on other sites
Advertisement
Repeat myself from a post long ago..

Okaj, i wrote this some two years ago in Turbo C++ inspired by my old Nokia 3210 snake game :). I will be nice and give my code away.

It's text based and may give a hint on how to handle the snake.

It's poorly commented, but the code should be quite straightforward though it tends to rotten with time it should be buildable in VC++ or other alike but some code needs to replaced or commented out.

Oh and about gotoxy() ..I think you can use this in win32 instead of the dos gotoxy() command.

void gotoxy(int x, int y)
{
COORD pos;
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);

pos.X = x;
pos.Y = y;

SetConsoleCursorPosition(screen, pos);
}



//------------------
// INCLUDE FILES
//------------------

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
#include <stdio.h>


//------------------
// GLOBAL CONSTANTS
//------------------

#define TEXT_MODE 0x0003
#define MAX_ANTAL 150
#define STILL_PLAYING 1
#define QUIT 0

const int MOVE_LEFT = 75;
const int MOVE_RIGHT = 77;
const int MOVE_UP = 72;
const int MOVE_DOWN = 80;

const int UP_WALL = 6;
const int DOWN_WALL = 20;
const int LEFT_WALL = 5;
const int RIGHT_WALL = 75;


//------------------
// ENUMERATED TYPES
//------------------

enum BOOL
{
FALSE,
TRUE
};

enum DIRECTION
{
DOWN,
UP,
LEFT,
RIGHT
};

//------------------
// STRUCTURES
//------------------

struct tGame
{
int highScore;
int score;
int level;
};

struct tCoordinate
{
int x;
int y;
};

struct tSnake
{
int size;
tCoordinate body[MAX_ANTAL];
};

struct tFood
{
char food;
tCoordinate pos;
};


//-----------------------
// FUNCTION DECLARATIONS
//-----------------------

void setTextMode();
void init(tGame&, tSnake&, tFood&);
int gameLoop(tGame&, tSnake&, tFood&);
void updateSnake(tSnake&);
void addSegment(tSnake&);
void removeSegment(tSnake&);
void displaySnake(tSnake&);
void processInput();
BOOL wallCollision(tSnake&);
BOOL foodCollision(tSnake&, tFood&);
BOOL snakeCollision(tSnake);
void updateScore(tGame&);
void printScore(tGame);
void increaseSnake(tSnake&);
void updateFood(tFood&, tSnake);
void displayFood(tFood);
BOOL playAgain();
void saveHighscore(tGame&);
void setDirection();
void pause();
char menu();
void gameMain();
char menuInput();
void showInstr();
void displayTitle();


//------------------
// GLOBAL VARIABLES
//------------------

DIRECTION MOVE_DIRECTION;
DIRECTION NEW_DIRECTION;
BOOL NEW_HIGHSCORE;
BOOL GAME_STATUS;


//----------------
// MAIN
//----------------

void main()
{
setTextMode();
do
{
GAME_STATUS = TRUE;
switch (menu())
{
case '1' : gameMain(); break;
case '2' : showInstr(); break;
case '3' : GAME_STATUS = FALSE; break;
}
} while (GAME_STATUS);
}

void setTextMode()
{
_AX = TEXT_MODE;
geninterrupt(0x10);
}

void gameMain()
{
tGame game;
tSnake snake;
tFood food;

do
{
clrscr();
init(game, snake, food);

while (gameLoop(game, snake, food));

if (NEW_HIGHSCORE) // temp
saveHighscore(game);
gotoxy(35,24);
cprintf("GAME OVER");
} while (playAgain());
}

void displayTitle()
{
char ch;
ifstream fin("title.txt", ios::in);
if (!fin)
cerr <<"File error";
gotoxy(1,2);
cout << fin.rdbuf();
fin.close();
}

char menu()
{
clrscr();
textcolor(2);

for (int i = 1; i < 80; i++)
{
gotoxy(i,1);
cprintf("=");
}
displayTitle();

cprintf(" ver.004");
for (i = 1; i < 80; i++)
{
gotoxy(i,10);
cprintf("=");
}

cout <<"\n\n\n";
textcolor(15);
cprintf("Pick a choice");
cout <<"\n\n";
printf("1. Play Game\n");
printf("2. Game Info\n");
printf("3. Exit");
cout << endl << endl;
return menuInput();
}

char menuInput()
{
char input;
do
{
cprintf("Input : ");
cin >> input;
} while (input != '1' && input != '2' && input != '3');
return input;
}

void showInstr()
{
clrscr();
cprintf("GAME PLAY INFO");
cout <<"\n\n\n";
printf("'P' \t\t: Pause the game\n");
printf("UP ARROW \t: Move snake up\n");
printf("DOWN ARROW \t: Move snake down\n");
printf("LEFT ARROW \t: Move snake left\n");
printf("RIGHT ARROW \t: Move snake right\n");
cout <<"\n\n";
printf("PRESS ANY KEY TO RETURN");
getch();
}

BOOL playAgain()
{
char input;
gotoxy(50,24);
cprintf("PLAY AGAIN ? (y/n) : ");
cin >> input;
if (input == 'y' || input == 'Y')
return TRUE;
else
return FALSE;
}

void pause()
{
gotoxy(35,24);
cprintf("PAUSE");
getch();
gotoxy(35,24);
cprintf(" ");
}

void init(tGame & game, tSnake & snake, tFood & food)
{
textbackground(0);
clrscr();
textcolor(15);
gotoxy(35,2);
cprintf("SNAKE");
cout <<"\t\t\t";
cprintf("ver.004");
textcolor(2);
for (int i = 1; i < 80; i++)
{
gotoxy(i,1);
cprintf("=");
}
for (i = 0; i < 80; i++)
{
gotoxy(i,3);
cprintf("=");
}
for (i = 0; i < 80; i++)
{
gotoxy(i,23);
cprintf("=");
}

textcolor(1);
for (i = 5; i < 22; i++)
{
gotoxy(4,i);
cprintf("#");
}
for (i = 5; i < 22; i++)
{
gotoxy(76,i);
cprintf("#");
}
for (i = 4; i < 77; i++)
{
gotoxy(i,5);
cprintf("#");
}
for (i = 4; i < 77; i++)
{
gotoxy(i,21);
cprintf("#");
}
textcolor(15);

ifstream fin("data.dat", ios::in);
fin >> game.highScore;
fin.close();

game.score = 0;
game.level = 9;

snake.size = 15;
snake.body[0].x = 10;
snake.body[0].y = 10;

for (i = 0; i < snake.size; i++)
{
snake.body.x = snake.body[0].x + i;
snake.body.y = snake.body[0].y;
}

MOVE_DIRECTION = NEW_DIRECTION = RIGHT;
NEW_HIGHSCORE = FALSE;

updateFood(food, snake);
printScore(game);
displaySnake(snake);
gotoxy(35,24);
cprintf("PRESS A KEY TO BEGIN");
getch();
processInput(); // temp
setDirection(); // temp
gotoxy(35,24);
cprintf(" ");
}

int gameLoop(tGame & game, tSnake & snake, tFood & food)
{
char input;

if (kbhit())
{
input = getch();
switch (input)
{
case 0 : processInput(); break;

case 'p' : pause(); processInput(); break;

case char(27) : return QUIT; break;
}
setDirection();
}

updateSnake(snake);

if (wallCollision(snake))
return QUIT;

if (snakeCollision(snake))
return QUIT;

if (foodCollision(snake, food))
{
updateScore(game);
increaseSnake(snake);
addSegment(snake);
increaseSnake(snake);
addSegment(snake);
updateFood(food, snake);
}

return STILL_PLAYING;
}

void updateSnake(tSnake & snake)
{
addSegment(snake);
removeSegment(snake);
if (MOVE_DIRECTION == UP || MOVE_DIRECTION == DOWN)
{
delay(120);
displaySnake(snake);
}
else
{
delay(50);
displaySnake(snake);
}
}

void processInput()
{
char input;
input = getch();

if (int(input) == MOVE_RIGHT)
NEW_DIRECTION = RIGHT;

if (int(input) == MOVE_LEFT)
NEW_DIRECTION = LEFT;

if (int(input) == MOVE_UP)
NEW_DIRECTION = UP;

if (int(input) == MOVE_DOWN)
NEW_DIRECTION = DOWN;
}

void increaseSnake(tSnake & snake)
{
snake.size++;
}

void updateScore(tGame & game)
{
game.score += game.level;
if (game.score >= game.highScore)
{
game.highScore = game.score;
NEW_HIGHSCORE = TRUE;
}
printScore(game);
}

void printScore(tGame game)
{
gotoxy(1,2);
cprintf(" ");
gotoxy(1,2);
cprintf("Highscore: %d", game.highScore);

gotoxy(2,24);
cprintf(" ");
gotoxy(2,24);
cprintf("Score: %d", game.score);
}

void updateFood(tFood & food, tSnake snake)
{
BOOL badPlace = FALSE;

do
{
food.pos.x = (7 + (rand() % 66));
food.pos.y = (7 + (rand() % 13));

for (int i = 0; i < snake.size; i++)
{
if ((food.pos.x == snake.body.x) && (food.pos.y == snake.body.y))
{
badPlace = TRUE;
break;
}
else
badPlace = FALSE;
}

} while (badPlace);

displayFood(food);
}

void displayFood(tFood food)
{
gotoxy(food.pos.x, food.pos.y);
cprintf("*");
}

void addSegment(tSnake & snake)
{
switch (MOVE_DIRECTION)
{
case LEFT :
snake.body[snake.size].y = snake.body[snake.size-1].y;
snake.body[snake.size].x = snake.body[snake.size-1].x-1; break;
case RIGHT :
snake.body[snake.size].y = snake.body[snake.size-1].y;
snake.body[snake.size].x = snake.body[snake.size-1].x+1; break;
case UP :
snake.body[snake.size].y = snake.body[snake.size-1].y-1;
snake.body[snake.size].x = snake.body[snake.size-1].x; break;
case DOWN :
snake.body[snake.size].y = snake.body[snake.size-1].y+1;
snake.body[snake.size].x = snake.body[snake.size-1].x; break;
}
}

void removeSegment(tSnake & snake)
{
gotoxy(snake.body[0].x, snake.body[0].y);
cprintf(" ");
gotoxy(1,1);

for (int i = 1; i <= snake.size; i++)
snake.body[i-1] = snake.body;
}

void displaySnake(tSnake & snake)
{
textcolor(2);
for (int i = 0; i < snake.size; i++)
{
gotoxy(snake.body.x, snake.body.y);
if (i == (snake.size-1))
textcolor(14);
cprintf("O");
}
textcolor(15);
}

BOOL wallCollision(tSnake & snake)
{
if (snake.body[snake.size].x == LEFT_WALL
|| snake.body[snake.size].x == RIGHT_WALL)
return TRUE;

if (snake.body[snake.size].y == UP_WALL
|| snake.body[snake.size].y == DOWN_WALL)
return TRUE;

return FALSE;
}

BOOL foodCollision(tSnake & snake, tFood & food)
{
if ((snake.body[snake.size].x == food.pos.x) &&
(snake.body[snake.size].y == food.pos.y))
return TRUE;

return FALSE;
}

BOOL snakeCollision(tSnake snake)
{
for (int i = 0; i < (snake.size - 1); i++)
{
if ((snake.body[snake.size].x == snake.body.x) &&
(snake.body[snake.size].y == snake.body.y))
return TRUE;
}

return FALSE;
}

void saveHighscore(tGame & game)
{
ofstream fout("data.dat", ios::out);
fout << game.highScore;
fout.close();
}

void setDirection()
{
switch (MOVE_DIRECTION)
{
case RIGHT : if (NEW_DIRECTION == RIGHT || NEW_DIRECTION == LEFT) break;
else MOVE_DIRECTION = NEW_DIRECTION; break;
case LEFT : if (NEW_DIRECTION == LEFT || NEW_DIRECTION == RIGHT) break;
else MOVE_DIRECTION = NEW_DIRECTION; break;
case UP : if (NEW_DIRECTION == UP || NEW_DIRECTION == DOWN) break;
else MOVE_DIRECTION = NEW_DIRECTION; break;
case DOWN : if (NEW_DIRECTION == DOWN || NEW_DIRECTION == UP) break;
else MOVE_DIRECTION = NEW_DIRECTION; break;
}
}




Maybe you will be able to descipher some good out of this. [smile]

Share this post


Link to post
Share on other sites
One little thing - #include <stdlib.h> is deprecated in the C++ standard. Use <cstdlib> instead. Same goes for stdio.h and other C headers.

And <iostream.h> is not standard C++, use <iostream> instead.

the old headers should work with most c++ compilers, but that might change in the future

also you'll need to add the following near the top of the file:
using namespace std;

otherwise everytime you call something like cout it needs to be std::cout



Edit: iostream.h is not actually deprecated, it was never part of the standard

[Edited by - Will F on April 25, 2005 6:09:18 PM]

Share this post


Link to post
Share on other sites
Quote:
void gotoxy(int x, int y)
{
COORD pos;
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);

pos.X = x;
pos.Y = y;

SetConsoleCursorPosition(screen, pos);
}
This bit of code that DayZero posted will let place the text cursor at whatever position you want. You also need to include windows.h

As for moving a character around the screen, you said that you already know how to get the moves, so nuff said there. You use gotoxy, cout the character, get the input, go back to the old spot (using gotoxy), cout a blank space, gotoxy (the new one) cout the character.

Put it in a loop. You should do fine.

Edit: Oh, and as for making the screen, just check if the x and y variables == 0, or == 80 (or 25 for y), if x == 0, then ignore any KEY_LEFT input, if x == 80, ignore any KEY_RIGHT input, etc. Actually You need to make it less, because if x is 80, ie the last character on the line, the cursor is automatically placed at the next line. When you get to bottom (80, 25) this will cause the screen to scroll unexpectedly.

[Edited by - skulldrudgery on April 25, 2005 12:37:35 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!