I'm creating a game in C++ using SFML but I ran into an issue with moving shapes using the mouse.
I am drawing multiple shapes, each shape has it's own handle input method and when I handle the window event, I loop over a vector array and call the handle input method of each shape.
void Plank::HandleInput(sf::Event event)
{
switch (event.type)
{
case sf::Event::MouseButtonPressed:
{
if (event.mouseButton.button == sf::Mouse::Button::Left)
{
m_MouseHold = true;
std::cout << "Left Press\n";
}
if (m_Shape.getGlobalBounds().contains(sf::Vector2f(sf::Mouse::getPosition(m_Game->m_Window))))
{
std::cout << "In Bounds\n";
m_MoveShape = true;
}
break;
}
case sf::Event::MouseButtonReleased:
{
m_MouseHold = false;
m_MoveShape = false;
break;
}
case sf::Event::MouseMoved:
{
if (m_MoveShape)
{
std::cout << "Move Shape\n";
m_Shape.setPosition(sf::Vector2f(sf::Mouse::getPosition(m_Game->m_Window)));
}
break;
}
default: break;
}
}
The issue is that if two shapes overlap and you click on where the shapes intersect you can move both shapes.
I want to only be able to move the shape which is on top, but I couldn't figure out how after some thinking and research.
So I did something similar to what you said #0x5453
In my window poll event I looped over my array of shapes and stored the array position of the shape which contained my mouse in its global bounds first. Then from there on I simply moved the shape in the array position I had noted.
for (size_t i = m_PlankObjects.size(); i-- > 0;)
{
if (m_PlankObjects[i].m_Shape.getGlobalBounds().contains(sf::Vector2f(sf::Mouse::getPosition(m_Game->m_Window))))
{
selectedObject = i;
break;
}
}
Related
I'm working currently on simple project in Qt. It is based on popular game "Ludo". But I've got annoying problem with making any changes on screen. Board drawing works nice, but it's enough to uncomment line with play() function and disaster guaranteed. Simply I'm not able to setPixmap of field in Player::turn() to show pawns' movement. Scene becomes plain and every drawn field disappears. On the other hand, game runs logically and correctly due to output. Unfortunately, it completely doesn't cooperate with GUI.
I attached images "before-after" and necessary code.
main.cpp
QApplication a(argc, argv);
Board *scene = new Board();
QGraphicsView *view = new QGraphicsView(scene);
view->resize(1200, 1000);
view->show();
scene->draw();
// scene->play();
return a.exec();
Board::play()
dice = new Dice();
unsigned int i=0;
while(true) {
bool playMore = players.at(i)->turn(dice, players, fieldsToPlay);
if(playMore) {
i++;
if(i == 4)
i=0;
}
else break;
}
Player::turn()
int result;
std::cout << "Player " << colour << " ";
if(hasPawnOnField) {
// TODO: check if field has pawn
result = dice->roll();
std::cout << result << '\n';
while(result) {
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/border.png"));
pawns.at(0)->currentField->setPawn(nullptr);
bool finito = pawns.at(0)->move(fieldsToPlay, baseAndFinish);
pawns.at(0)->currentField->setPawn(pawns.at(0));
char col = pawns.at(0)->getColour();
switch (col) {
case 'b':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/bluepawn.png"));
break;
case 'r':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/redpawn.png"));
break;
case 'y':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/yellowpawn.png"));
break;
case 'g':
pawns.at(0)->currentField->set_Pixmap(QPixmap(":/img/greenpawn.png"));
break;
}
if(finito) {
finishedPawns++;
delete pawns.at(0);
pawns.erase(pawns.begin());
hasPawnOnField = false;
break;
}
result--;
}
if(finishedPawns == 4) // condition which ends the game
return 0;
}
else {
int attempts = 3;
while(attempts) {
result = dice->roll();
std::cout << result << '\n';
if(result == 6) {
hasPawnOnField = true;
if(start->getPawn()) {
char col = start->getPawn()->getColour();
switch (col) {
case 'b':
players.at(0)->pawns.at(0)->setField(fieldsToPlay.at(0));
players.at(0)->pawns.at(0)->zero();
fieldsToPlay.at(0)->setPawn(players.at(0)->pawns.at(0));
fieldsToPlay.at(0)->set_Pixmap(QPixmap(":/img/bluepawn.png"));
break;
case 'r':
players.at(1)->pawns.at(0)->setField(fieldsToPlay.at(12));
players.at(1)->pawns.at(0)->zero();
fieldsToPlay.at(12)->setPawn(players.at(1)->pawns.at(0));
fieldsToPlay.at(12)->set_Pixmap(QPixmap(":/img/redpawn.png"));
break;
case 'y':
players.at(2)->pawns.at(0)->setField(fieldsToPlay.at(24));
players.at(2)->pawns.at(0)->zero();
fieldsToPlay.at(24)->setPawn(players.at(2)->pawns.at(0));
fieldsToPlay.at(24)->set_Pixmap(QPixmap(":/img/yellowpawn.png"));
break;
case 'g':
players.at(3)->pawns.at(0)->setField(fieldsToPlay.at(36));
players.at(3)->pawns.at(0)->zero();
fieldsToPlay.at(36)->setPawn(players.at(3)->pawns.at(0));
fieldsToPlay.at(36)->set_Pixmap(QPixmap(":/img/greenpawn.png"));
break;
}
}
pawns.at(0)->setField(start);
start->setPawn(pawns.at(0));
start->set_Pixmap(baseAndFinish.at(finishedPawns)->getPixmap());
baseAndFinish.at(finishedPawns)->set_Pixmap(QPixmap(":/img/border.png"));
break;
}
attempts--;
}
}
Pawn::move()
passedFields++;
if(passedFields >= 48) {
currentField = basFin.at(4+(passedFields-48));
if(passedFields == FINISH) {
FINISH--;
delete basFin.at(basFin.size()-1);
basFin.pop_back();
return true;
}
}
else
currentField = fieldsToPlay.at( (startID+passedFields)%48);
return false;
Board.h
class Board : public QGraphicsScene {
Q_OBJECT
public:
Board();
virtual ~Board();
void draw();
void drawField(std::vector<Field *> &vec, Vector ¤t, Vector dir, QString image);
void play();
static const int rect_size = 70;
Vector directions[4] = {Vector (0, -rect_size), //up
Vector (rect_size, 0), //right
Vector (0, rect_size), //down
Vector (-rect_size, 0) }; //left
private:
std::vector<Field *> fieldsToPlay;
std::vector<Player *> players;
std::vector<Field *> fieldsBlue; //fields 0-3 basement, fields 4-7 finish
std::vector<Field *> fieldsRed;
std::vector<Field *> fieldsYellow;
std::vector<Field *> fieldsGreen;
Dice *dice;
QTimer *timer;
};
Scene before updating Pixmap
Scene after
What am I doing wrong? How to update my scene in runtime without crash?
Rather than use an infinite loop you could make use of a QTimer (I see Board already has a QTimer * member so perhaps that was the intention all along). Rather than use an explicit timer you might want to use QTimer::singleShot to `nudge' the game one step forward at a time.
Firstly, make the player counter/index i a member of Board and initialise it and dice in the constructor...
Board::Board ()
: dice(new Dice)
, i(0)
{
...
}
Now change Board::play so that it makes a single call to Player::turn for the current player and rearms a timer if required...
void Board::play ()
{
/*
* Give the current player their turn.
*/
bool playMore = players.at(i)->turn(dice, players, fieldsToPlay);
if (playMore) {
/*
* The game hasn't yet finished so update the player index
* and rearm the timer with a lambda to make another call
* to play() in 1 second.
*/
i++;
if (i == 4)
i=0;
QTimer::singleShot(1000,
[this]()
{
play();
});
}
}
I haven't tested the above but it at least shows the basic outline of what you should aim for.
Thank you for reading this thread. I am a beginning programmer and am trying to make a simple snake game with C++. It isn't finished yet, but I think I got a nice start to it. However, when I try to run the program it instantly crashes. (The compiler says there are 0 warnings and errors. I am using the Code::Blocks IDE. Does anyone know why my program isn't working? I think it may have something to do with the "vector coordHistory", but I can't tell for sure. At least that is the last thing I added to the program.
This is my code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <windows.h>
#include <conio.h>
#include <vector>
#define MAXX 156 //Number of columns that fits on my screen
#define MAXY 62 //Number of rows that fits on my screen
using namespace std;
// This function clears the console window
void clearConsole()
{
system("cls"); //empties console window
};
// This function returns the x position of the cursor
int getcursorX()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
return csbi.dwCursorPosition.X;
}
};
// This function returns the y position of the cursor
int getcursorY()
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
return csbi.dwCursorPosition.Y;
}
};
// This function sets the x position of the cursor
void setcursorX(int x)
{
COORD coord = {x, getcursorY()};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
// This function sets the y position of the cursor
void setcursorY(int y)
{
COORD coord = {getcursorX(), y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
// The snake class contains the coordinates of the snake and direction in which it is moving
class Snake
{
private:
bool isAlive;
int snakexCoord;
int snakeyCoord;
char snakeDirection;
int snakeLength;
public:
//getters
int getsnakexCoord() { return snakexCoord; };
int getsnakeyCoord() { return snakeyCoord; };
char getsnakeDirection() { return snakeDirection; };
bool getisAlive() { return isAlive; };
int getsnakeLength() { return snakeLength; };
//setters
void setsnakexCoord(int newsnakexCoord) { snakexCoord = newsnakexCoord;};
void setsnakeyCoord(int newsnakeyCoord) { snakeyCoord = newsnakeyCoord;};
void setsnakeDirection(char newsnakeDirection) { snakeDirection = newsnakeDirection;};
void setisAlive(bool newisAlive) { isAlive = newisAlive; };
void setsnakeLength(int newsnakeLength) { snakeLength = newsnakeLength; };
//constructor
Snake()
{
snakexCoord = MAXX / 2;
snakeyCoord = MAXY / 2;
snakeDirection = 'E';
isAlive = true;
snakeLength = 1;
};
//destructor
~Snake(){};
};
int main()
{
int i; //iterator
system("mode 650"); //makes console window full-screen
Snake snake; //initializes Snake object snake
char c; //char that stores user input to change snake direction
vector<int[2]> coordHistory; //vector of arrays that stores previous locations of snake
while (snake.getisAlive())
{
//Adds snake coordinates to coordHistory
coordHistory[coordHistory.size()][0] = snake.getsnakexCoord();
coordHistory[coordHistory.size()-1][1] = snake.getsnakeyCoord();
//Iterates backwards through coordHistory and draws an "O" until the snake is as long as it should be
for(i = coordHistory.size() - 1; i > coordHistory.size() - 1 - snake.getsnakeLength(); i--)
{
setcursorX(coordHistory[i][0]);
setcursorY(coordHistory[i][1]);
cout << "O";
}
//Allows user to change snake direction
c = _getch();
switch (c){
case 'w':
snake.setsnakeDirection('N');
break;
case 'd':
snake.setsnakeDirection('E');
break;
case 's':
snake.setsnakeDirection('S');
break;
case 'a':
snake.setsnakeDirection('W');
break;
}
//Checks in which direction snake is going and changes coordinates accordingly
switch (snake.getsnakeDirection())
{
case 'N':
snake.setsnakeyCoord(snake.getsnakeyCoord()-1);
break;
case 'E':
snake.setsnakexCoord(snake.getsnakexCoord()+1);
break;
case 'S':
snake.setsnakeyCoord(snake.getsnakeyCoord()+1);
break;
case 'W':
snake.setsnakexCoord(snake.getsnakexCoord()-1);
break;
}
//Checks if snake goes out of boundaries
if ((snake.getsnakexCoord() > MAXX) || (snake.getsnakexCoord() < 0) || (snake.getsnakeyCoord() > MAXY) || (snake.getsnakeyCoord() < 0))
{
snake.setisAlive(false);
}
//Sleep(200); Ignore WIP
clearConsole();
}
return 0;
}
Your vector usage is wrong.
coordHistory[coordHistory.size()][0] = snake.getsnakexCoord();
coordHistory[coordHistory.size()-1][1] = snake.getsnakeyCoord();
You appear to assume that vector[n-1] will automatically create as many elements as needed to result in a vector of size n. It doesn't.
You are twice accessing the first element of vector coordHistory, a vector which is actually empty.
To add elements, in general use the member function push_back or emplace_back. You're really going to struggle with a vector of arrays, though, since arrays are neither assignable nor copyable. That's why I can't use push_back here; I have to explicitly resize the vector then access the newly-created elements as you were doing before:
coordHistory.resize(1);
coordHistory[0][0] = snake.getsnakexCoord();
coordHistory[0][1] = snake.getsnakeyCoord();
This is pretty awkward. why don't you instead store a nice delicious class type with x and y members?
std::vector<deliciousClassType> coordHistory;
coordHistory.emplace_back(
snake.getsnakexCoord(),
snake.getsnakeyCoord()
);
I am coding for the NDS in c++ with libnds, but this question is not NDS-Specific. I currently have a text-based game in which the top screen just displays a logo, and you play on the bottom screen.
So I want to add a type of single-DS multiplayer in which one player plays on the top screen, and the other on the bottom. I dont have a problem with setting up the text engine with both screens, I just need to find a method of efficiently coding in multiplayer. Below I wrote a summary or simplified version of it.
Note: consoleClear() clears the screen and the only spot where the game stops is att the pause function.
//Headers
void display(int x,int y,const char* output))
{
printf("\x1b[%d;%dH%s", y, x,output);
}
void pause(KEYPAD_BITS key) //KEYPAD_BITS is an ENUM for a key on the NDS
{
scanKeys();
while (keysHeld() & key)
{
scanKeys();
swiWaitForVBlank();
}
while (!(keysHeld() & key))
{
scanKeys();
swiWaitForVBlank();
}
return;
}
void pause() //Only used to simplify coding
{
pause(KEY_A);
return;
}
int main(void)
{
//Initializations/Setup
while (1)
{
if (rand()%2==1) //Say Hello
{
if (rand()%3!=1) //To Friend (greater chance of friend than enemy)
{
display(6,7,"Hello Friend!");
display(6,8,"Good greetings to you.");
pause();
consoleClear(); //Clears text
display(6,7,"Would you like to come in?");
pause();
//Normally more complex complex code (such as interactions with inventories) would go here
}
else //To enemy
{
display(6,7,"Hello enemy!");
display(6,8,"I hate you!");
pause();
consoleClear();
display(6,7,"Leave my house right now!!!");
pause();
}
}
else //Say goodbye
{
if (rand()%4==1) //To Friend (lesser chance of friend than enemy)
{
display(6,7,"Goodbye Friend!");
display(6,8,"Good wishes to you.");
pause();
consoleClear();
display(6,7,"I'll see you tomorrow.");
pause();
consoleClear();
display(6,7,"Wait, I forgot to give you this present.");
pause();
}
else //To enemy
{
display(6,7,"Goodbye enemy!");
display(6,8,"I hate you!");
pause();
consoleClear();
display(6,7,"Never come back!!");
pause();
consoleClear();
display(6,7,"Good riddance!"); //I think I spelt that wrong...
pause();
}
}
}
}
I know gotos are confusing and can be considered a bad habit, but I cant think of a better way. My version of integrating multiplayer:
//Headers and same functions
int game(int location)
{
switch (location)
{
case 1: goto one; break;
case 2: goto two; break;
case 3: goto three; break;
case 4: goto four; break;
case 5: goto five; break;
case 6: goto six; break;
case 7: goto seven; break;
case 8: goto eight; break;
case 9: goto nine; break;
case 10: goto ten; break;
default: break;
}
if (rand()%2==1) //Say Hello
{
if (rand()%3!=1) //To Friend (greater chance of friend than enemy)
{
display(6,7,"Hello Friend!");
display(6,8,"Good greetings to you.");
return 1;
one:;
consoleClear(); //Clears text
display(6,7,"Would you like to come in?");
return 2;
two:;
//Normally more complex complex code (such as interactions with inventories) would go here
}
else //To enemy
{
display(6,7,"Hello enemy!");
display(6,8,"I hate you!");
return 3;
three:;
consoleClear();
display(6,7,"Leave my house right now!!!");
return 4;
four:;
}
}
else //Say goodbye
{
if (rand()%4==1) //To Friend (lesser chance of friend than enemy)
{
display(6,7,"Goodbye Friend!");
display(6,8,"Good wishes to you.");
return 5;
five:;
consoleClear();
display(6,7,"I'll see you tomorrow.");
return 6;
six:;
consoleClear();
display(6,7,"Wait, I forgot to give you this present.");
return 7;
seven:;
}
else //To enemy
{
display(6,7,"Goodbye enemy!");
display(6,8,"I hate you!");
return 8;
eight:;
consoleClear();
display(6,7,"Never come back!!");
return 9;
nine:;
consoleClear();
display(6,7,"Good riddance!"); //I think I spelt that wrong...
return 10;
ten:;
}
return -1;
}
}
int main(void)
{
//Initializations/Setup
int location1 = -1, location2 = -1;
location1 = game(location1);
location2 = game(location2);
while (1)
{
scanKeys(); //Whenever checking key state this must be called
if (keysDown() & KEY_A) //A key is used to continue for player1
location1 = game(location1);
if (keysDown() & KEY_DOWN) //Down key is used to continue for player2
location2 = game(location2);
}
}
Aside from this method being a bad practice, in the actual source code, I have hundreds of gotos I would need to add which would be too time consuming.
Any help is appreciated. If anyone has the slightest of a question, or answer, please ask/reply.
Edit: Though it is not preferred to do so, I am willing to rewrite the game from scratch if someone has a method to do so.
Using if-else conditional statements for each case is a simple solution that comes first to mind.
For example:
int game(int i){
if(i == 1){
//first case code here.
}
else if(i == 2){
//second case code here.
}
//....
return 0;
}
The code in each case can even be put in other functions that will be invoked depending on each condition.
This will probably be enough for your case.
A more flexible solution (but much more complex) is a dispatch table.
The idea is to have separate functions with each desired functionality, and put pointers of them in an array. Then, you can call them by indexing the table, using those function pointers. This can be extremely helpful if you have a sequence of executions (function invokes) to be done and you want to set it done easily, or you want to have different results depending on your input, without changing your program.
There is an example below.
This code can be used in C too, if you replace std::cout with printf and iostream with stdio library.
#include <iostream>
using namespace std;
// Arrays start from 0.
// This is used for code
// readability reasons.
#define CASE(X) X-1
typedef void (*chooseCase)();
// Functions to execute each case.
// Here, I am just printing
// different strings.
void case1(){
cout<< "case1" << endl;
}
void case2(){
cout<< "case2" << endl;
}
void case3(){
cout<< "case3" << endl;
}
void case4(){
cout<< "case4" << endl;
}
//Put all the cases in an array.
chooseCase cases[] = {
case1, case2, case3, case4
};
int main()
{
//You can call each scenario
//by hand easily this way:
cases[CASE(1)]();
cout << endl;
//Idea: You can even set in another
// array a sequence of function executions desired.
int casesSequence[] = {
CASE(1), CASE(2), CASE(3), CASE(4),CASE(3),CASE(2),CASE(1)
};
//Execute the functions in the sequence set.
for(int i = 0; i < (sizeof(casesSequence)/sizeof(int)); ++i){
cases[casesSequence[i]]();
}
return 0;
}
This will print at the output:
case1
case1
case2
case3
case4
case3
case2
case1
I'm getting a "incompatible vector iterator" error to what i believe is a invalid iterator
void Bomb::CreateExplosion(Game_Manager* EGame_Manager)
{
for(irr::f32 iteration = 0; iteration < BlastRadius; iteration++) //up direction blast
{
***//PROGRAM CRASHES AT THIS LINE-->*** for(EGame_Manager->getEntityManager()->GetEntityIterator() = EGame_Manager->getEntityManager()->GetEntityList().begin(); EGame_Manager->getEntityManager()->GetEntityIterator() != EGame_Manager->getEntityManager()->GetEntityList().end(); ++EGame_Manager->getEntityManager()->GetEntityIterator())
{
if(CheckForCollision(UpExplosion->getTransformedBoundingBox(), (*EGame_Manager->getEntityManager()->GetEntityIterator())->GetEntityNode()->getTransformedBoundingBox()) == true)//check for collision against the unbreakable blocks (entity.type equals 0)
{
if((*EGame_Manager->getEntityManager()->GetEntityIterator())->GetType() == unbreakableblock)
{
break;
}
else if((*EGame_Manager->getEntityManager()->GetEntityIterator())->GetType() == gameplayer)
{
(*EGame_Manager->getEntityManager()->GetEntityIterator())->SetLives(this->GetLives() -1);
break;
}
else if((*EGame_Manager->getEntityManager()->GetEntityIterator())->GetType() == gameitem)
{
break;
}
}
else
{
UpExplosion->setScale(irr::core::vector3df(1,1,iteration)); //standard width of UpExplosion, iterated height of the UpExplosion
}
}
}
CreateExplosion is called by Bomb::UpdateEntity() which is called by EntityManager::UpdateList() which then loops through the vector<*Entity> List calling each Entity's respective Update function.
This function adds the Entities to the vector I'm not sure if it causes the problem
EntityManager::AddEntity(Entity* addtoList)
{
List.push_back(addtolist);
addtolist->GetEntityNode()->setID(List.size());
EntityIterator = List.begin();
}
Also the instance of the Bomb class that calls these functions is declared in the Player class if that helps with anything. And I can post more code if needed.
I am writing a small console adventure game and I faced a few problems.
1. The input is kinda laggy, I'm using while loop ( while(getch() == 'w') ). After a key is pressed the first time, nothing happens (you have to press it 2 times) and if you switch directions (press key A/D/S) it also doesn't react the 1st time. If you hold a key, it works fine. How can this be fixed?
2. Here's the function I use to refresh game (render the game scene when a key is pressed):
void refresh(char map[Y][X])
{
system("cls");
for (int i = 0; i<UP; i++)
{
cout<<endl;
}
for (int i = 0; i<Y; i++)
{
for (int k = 0; k<LEFT; k++)
{
cout<<" ";
}
for (int j = 0; j<X; j++)
{
cout<<map[i][j];
}
cout<<endl;
}
}
When I use this function once, it's ok, but when they key is pressed or held multiple times - the game field starts to flash. I figured that I need to redraw only a part of the field (where changes are made/movements are done), not the whole field. Can you offer any ideas how to do that?
The sample code for input:
while(getch() == 'w')
{
if (map[y-1][x]!= WALL)
{
map[y-1][x] = CHARACTER;
map [y][x] = ' ';
y--;
refresh(map);
Sleep(SPEED); // this is unnecessary, SPEED is 0, I just kept it for tests
}
}
Basically, the main function looks like this:
int main()
{
(...) Variables (...)
generateMap(FROM FILE);
refresh(); // First initialization of the field
while (getch() != 'q') // While not quitting
{
while(getch() == 'w')
{
if (THE FIELD ABOVE IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 's')
{
if (THE FIELD BELOW IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 'a')
{
if (THE FIELD ON THE LEFT IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 'd')
{
if (THE FIELD ON THE RIGHT IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
return 0;
}
Don't use system("cls"), it is really slow, instead set the cursor on the beginning of the screen with the following code:
COORD cur = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);
You should call getch() only one time in the loop, like this:
char key;
do
{
key = getch();
if(key == 'w')
{
//do something
}
//the other if statements
}while(key != 'q');
The code should have only one getch() in the whole code (if possible) and inside a switch you do the action for each input. So, it is switch inside the loop, and not loops inside the switch. Something like this:
while ((ch = getch()) != 'q')
{
switch (ch)
{
case 'a':
GoLeft();
break;
...
}
}
There is a library called ncurses that you can use to move the cursor around the screen, and write anything anywhere.
It looks like your problem is calling getch() multiple times. Have only one loop, and call getch() once per loop, and store the result. Test that result for each value (q, w, s, ...) for each iteration of the loop.
I would recommend you to use function input() as it stands:
void input()
{ if (GetKeyState('W') & 0x8000) // That means when button "W" is pressed
... your code ...
// (changes global variables, or you can pass variables by reference)
}
without any getch() command that stops your game every single time.
You can use it with the draw() and calculate()/refresh() functions in the main(), like:
int main()
{
... other part of code ...
while (!gameover)
{
input();
calculate();
draw();
}
}
so that you will always have some sort of input value before the calculations, and then you would draw (+ it's much easier to debug ;) )