1

I am making a simple game using C++ It's just a tile game with an ASCII map. The game itself works fine, but the console screen(map) is flickering when I move my player and I don't know how to fix this. Any help appreaciated, thanks!

Code:

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <ctime>
#include <vector>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;

vector<string> map;
int playerX = 10;
int playerY = 10;
int oldPlayerX;
int oldPlayerY;
bool done = false;

void loadMap();
void printMap();
void setPosition(int y, int x);
void eventHandling();

int main()
{
    loadMap();
    map[playerY][playerX] = '@';
    printMap();
    while(!done){
        eventHandling();
        printMap();
    }
    exit(1);
    return 0;
}

void eventHandling(){
    char command;
    command = _getch();
    system("cls");
    oldPlayerX = playerX;
    oldPlayerY = playerY;

    if(command == 'w'){
        playerY--;
    }else if(command == 'a'){
        playerX--;
    }else if(command == 'd'){
        playerX++;
    }else if(command == 's'){
        playerY++;
    }

    if(map[playerY][playerX] == '#'){
        playerX = oldPlayerX;
        playerY = oldPlayerY;
    }

    setPosition(playerY,playerX);

}

void setPosition(int y, int x){
    map[oldPlayerY][oldPlayerX] = '.';
    map[y][x] = '@';
}

void  printMap(){
    for(int i = 0 ; i < map.size() ; i++){
        cout << map[i] << endl;
    }
}

void loadMap(){
    ifstream file;
    file.open("level.txt");

    string line;
    while(getline(file, line)){
        map.push_back(line);
    }
}
OpenGLmaster1992
  • 281
  • 2
  • 5
  • 13
  • 3
    It is all happening because of ``system("cls");`` Use another method, for example print entire page yourself or clear it manually by printing space character everywhere, then print your mapdata. – 72DFBF5B A0DF5BE9 Oct 02 '15 at 19:15
  • 3
    you're better off not calling `system("cls");` at all. I know when you first start out making command-line games it feels "cleaner," but most programs don't do this, and people generally don't like having their screen cleared when they didn't try to do it. Additionally it's not portable while the rest of your code likely is. – Ryan Haining Oct 02 '15 at 19:21
  • `using namespace std;` is a bad practice so don't get in the habit of doing it. just write out `std::map`, `std::ifstream`, `std::cout`, `std::getline`, etc. It will bite you eventually if you don't (you don't know everything that's in `std`, what if you use the same name as something?) – Ryan Haining Oct 02 '15 at 19:22
  • What do you guys think is the proper way to clear the console screen? – OpenGLmaster1992 Oct 02 '15 at 19:22
  • @HugoCornel don't clear it. there isn't a portable way without some third party library (which will also be limited). Your program doesn't know it's writing to the screen, all it knows is that it is writing to `stdout` which could be a file, a pipe, a socket, a printer, who knows? – Ryan Haining Oct 02 '15 at 19:24
  • Possible duplicate of [Update console without flickering - c++](http://stackoverflow.com/questions/34842526/update-console-without-flickering-c) – ScottishTapWater Jan 19 '16 at 19:35

3 Answers3

4

std::cout is not intended to be used that way.

You should refer to the system specific API for the target OS and environment. For example, for Windows you should use Console API functions for your purpose. These functions are defined in Wincon.h include file.

Andrey Nasonov
  • 2,619
  • 12
  • 26
1

It also helps if you use a double buffering system such that only what needs to be overwritten every frame is changed. IO operations are extremely expensive so ought to be minimized.

Cameron Gives a Very Thorough Description of How to Do this Here

But in essence, you'd use two arrays, one containing the current state of the map, one containing the previous state and only write to the specific locations that have changed.

Community
  • 1
  • 1
ScottishTapWater
  • 3,656
  • 4
  • 38
  • 81
  • For a true double buffering please see my [reply](https://stackoverflow.com/a/69098693/4609659) in the same thread. In essence, Instead of having two arrays you better create two native console buffers and switch them as you'd normally do in OpenGL or Direct3D. Please see the reply for the full example source code. – Tali Oat Sep 10 '21 at 09:17
0

One method to clear the screen that works on many systems is to print the form feed character, \f. The Linux console supports this, and so did MS-DOS if you loaded ansi.sys. Unix has ncurses and terminfo to abstract these functions.

Davislor
  • 14,674
  • 2
  • 34
  • 49
  • This answer is not related to the question. – Thomas Dickey Aug 16 '23 at 23:40
  • @ThomasDickey It’s a method I’ve used as a poor-man’s `terminfo` to draw a series of text images on the screen. Terminals that support VT102 codes can double-buffer the screen, and the Linux text-mode console, as well as `xterm` and `gnome-terminal`, do. – Davislor Aug 17 '23 at 01:28