Adding split-screen multiplayer to c++ game - c++

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

Related

Need to fix switch statement and increasing an integer

I'm making a very simple proof of concept for my parents and tried to create a simple management game, however, in my switch statement, the second case doesn't increase a material - stone. Any idea why? Any other advice would also be appreciated.
#include <iostream>
using namespace std;
int main()
{
bool alive = true;
int stone = 50;
int money = 20;
bool wall = false;
while(alive)
{
int MainChoice;
cout<<endl<<"stone: "<<stone<< " money: "<<money;
cout <<endl<<"You find yourself as the ruler of a castle what do you do?" << endl<<"1. Build a wall: cost 50 stone"<< endl<<"2. Send out miners:gets 50 stone"<< endl<<"3. Oppress the people"<<endl;
cin>>MainChoice;
//Main Menu Choices
switch(MainChoice)
{
//Build the wall
case 1:
if(stone>=50)
{
cout<<"You build the wall";
wall = true;
stone - 50;
}
else
{
cout<<"Insuffcient Stone";
}
break;
//Send out miners
case 2:
stone + 50;
cout<< "Gathered stone";
break;
// Oppress the people
case 3:
if(wall == false)
{
alive = false;
cout<<"You get killed in the riot";
}
else
{
cout<< "The wall saves you from death";
}
break;
default:
cout<<"im sorry that doesnt seem to be correct";
}
}
return 0;
}
Thank you, and sorry for the messy code.
For increasing your variable's value, you can use one of the concepts below:
stone += 50;
or
stone = stone + 50;
The problem is that these lines:
stone - 50;
...
stone + 50;
just calculate the result of the expression and then throws it away. There is no assignment. You could change them to:
stone -= 50;
...
stone += 50;

how to replace a value of a variable inside code from user input?

i am trying to add a developer mode in my program. since duty of car defers every month,i want give my user permission to change every single variables in my program alike duty lccost yen2taka freight
#include <iostream>
using namespace std;
class A
{
public:
int carbid,duty;
void Input()
{
cout<<"please insert the car price you want to bid for(in yen): ";
cin>>carbid;
cout<<"duty of the car: ";
cin>>duty;
}
int Exportcost()
{
int exportcost;
int servicechrg=10;
int freight=20;
exportcost=servicechrg+freight+carbid;
return exportcost;
}
int Yen2taka()
{
int yen2taka;
int taka2dollarrate=10;
int dollar2yen=1;
yen2taka=((Exportcost())/dollar2yen)*taka2dollarrate;
return yen2taka;
}
int Importcost()
{
int importcost;
int lccost=10;
int cnfcost=20;
importcost=lccost+cnfcost;
return importcost;
}
int Totalcosting()
{
int total;
int myprofit=10; //80000
total=myprofit+Importcost()+Yen2taka();
cout<<total;
return total;
}
void summary()
{
cout<<
}
};
int main()
{
x:
A ob;
ob.Input();
ob.Exportcost();
ob.Yen2taka();
ob.Importcost();
ob.Totalcosting();
int ch;
cout<<"press 1 to see the summery of the costing or 2 to restart costing again"<<endl;
cin>>ch;
switch(ch)
{
case 1:
ob.summary();
break;
case 2:
goto x;
}
}
At first, you should collect these parameters in a separate class:
class Configuration // maybe you find a better name...
{
int m_servicechrg = 10; // default
int m_freight = 20;
// ...
public:
int servicechrg() { return m_servicechrg; }
void servicechrg(int value); { /* check some limits? */ m_servicechrg = value; }
int freight() { return m_freight; }
void freight(int value); { /* check some limits? */ m_freight = value; }
// ...
};
// will allow you to do:
// C c; std::cout << c;
ostream& operator<<(ostream& s, Configuration const& c)
{
// which ever formatting is appropriate...
s << c.servicechrg() << ' ' << c.freight();
return s;
}
The setters could alternatively return bool to indicate invalid values.
Now you can use this class within main:
Configuration c;
A a;
int cost = a.exportCost(c); // you'd have to adjust signatures...
int value;
switch(ch)
{
case 4:
if(stc::cin >> freight) // catches invalid user input!
// one ALWAYS should do, otherwise you might end up in
// your program not working any more
{
c.freight(value);
// or, if you have:
if(!c.freight(value))
{
// some appropriate error message
// (it's better not to output in the setter, you are more flexible this
// way – maybe you want different messages at different occasions?)
}
}
else
{
// appropriate error handling
}
break;
default:
// handling invalid user input
// again, you always should; but stream state is not in error state,
// so you just can print appropriate error message
break;
}
See this answer for how to correctly handle stream errors.
If you wonder about the differences in error handling: First case is met if user enters non-numerical input, such as ss, second case, if input is numerical, but out of valid range (77).
Now if you don't want to pass the configuration as parameter all the time, you could make a global variable from (but careful, there are some dangers with global variables, use them as sparely as possible) or implement the singleton pattern.
Side notes: goto can be a fine tool sometimes, but it is a dangerous one (and the label's name x isn't a good one, prefer a name that clearly shows intention, such as REENTRY_POINT, LOOP_START, ...). If you can get along without unreasonable effort, prefer such variants:
bool isRunning = true;
do
{
// ...
case 2:
isRunning = false;
break;
}
while(isRunning);
Sure, an additional variable, an additional check; unfortunately, you cannot use break to exit a (pseudo-) endless loop (for(;;)) (but don't apply this pattern for nested loops, then it gets more and more unreadabla – and ineffcient: bool isExit = false; for(int i = 0; !isExit && i < n; ++i) { for(j = 0; j < n; ++j) { isExit = true; break; } } – see what I mean?). A variant might be:
for(;;)
{
switch(ch)
case 1:
// ...
//break; <- replace
continue;
case 2:
//
break;
} // end of switch
break; // break the surrounding for(;;) loop
}
But that's not really nice either.
A pretty nice variant allowing to exit the loop in the given case, as there isn't anyhting to do afterwards:
for(;;)
{
switch(ch)
{
case 2:
// maybe yet some cleaning up here
return 0;
default:
// ...
break;
}
}
Drawback: The function's exit point possibly is deeply nested inside the code.
There are yet other tricks to allow this pattern, like packing sub-sections of code in a lambda having a return inside and call that one directly. But that now really starts going beyond the scope...
Finally, if you insist on goto, my variant would rather be:
for(;;)
{
switch(ch)
{
case 2:
// ...
goto LOOP_EXIT;
default:
// ...
break;
}
}
LOOP_EXIT:
return 0; // e. g. main
(void)0; // if there isn't anything to do in the function any more
// (labels require an instruction afterwards!)
There won't be a hidden loop now and it is more obvious what you actually are doing. Currently, not really an issue, but if your code grows, the hidden loop gets more and more difficult to spot.
In such cases, I clearly mark the gotos so that another coder can immediately spot the critical code points:
///////////////////////////////////////////////////
// possibly some comment why applying this pattern
goto SOME_LABEL;
///////////////////////////////////////////////////
One could do the same with deeply nested function exit points (return).

C++: Using multiple conditions in switch statements

I am in a beginning C++ programming class and I need help with nesting switch statements and using multiple conditions, because I have to translate a program I already wrote from if/else statements to switch statements, because I didn't know I was supposed to use the switch statement.
For example, how do I change something like:
if (temperature >= -459 && temperature <= -327)
{
cout << "Ethyl Alcohol will freeze.\n";
}
else if (temperature >= -326 && temperature <= -30)
{
cout << "Water will freeze.\n";
}
else if ...
{
}
else
{
}
Into a switch/case statement? I can get the first level, but how do I nest and have multiple conditions like the temperature statements above?
Switch statements work like this:
int variable = 123; // or any other value
switch (variable)
{
case 1:
{
// some code for the value 1
break;
}
case 12:
{
// some code for the value 12
break;
}
case 123:
{
// some code for the value 123
break;
}
case 1234:
{
// some code for the value 1234
break;
}
case 12345:
{
// some code for the value 12345
break;
}
default:
{
// if needed, some code for any other value
break;
}
}
First of all, this question is in C and not in C++. C++ inherited most of the C language, including the switch-case.
You can't do this with a switch, unless you start enumerating all the values one by one, like this:
switch (temperature) {
case -459:
case -458:
....
case -327: <do something>; break;
case -326:
.....
}
This is because in C, switch-case is simply translated to a series of if-goto statements, with the cases just being the labels.
In your case, your stuck with an if-else-if ladder.
You could use a lookup table that has temperatures and the text to print:
struct Temperature_Entry
{
int min_temp;
int max_temp;
const char * text_for_output;
};
static const Temperature_Entry temp_table[] =
{
{-459, -327, "Ethyl Alcohol will freeze.\n"},
{-326, -30, "Water will freeze.\n"},
};
static const unsigned int entry_count =
sizeof(temp_table) / sizeof(temp_table[0]);
//...
int temperature;
for (unsigned int i = 0; i < entry_count; ++i)
{
if ( (temperature >= temp_table[i].min_temp)
&& (temperature < temp_table[i].max_temp))
{
std::cout << temp-table[i].text_for_output;
}
}
As many have pointed out, you cannot use switch case for ranges and dynamic formulas. So if you want to use them anyway, you will have to write a function which takes a temperature and returns a temperature range out of a pre-known set of temperature ranges. Then, finally, you can use a switch/case for the temperature ranges.
enum TemperatureRange { FrigginCold, UtterlyCold, ChillinglyCold, Frosty, ... };
TemperatureRange GetRange( int temperature );
// ...
switch( GetRange( temperature ) )
{
case FrigginCold: cout << "The eskimos vodka freezes."; break;
case UtterlyCold: cout << "The eskimo starts to dress."; break;
// ...
}

How can I fix, "Invalid use of void expression"? C++

I've written a game to move "players" around a board using a semaphore to lock the board before allowing another player access.
I'll skip most of the code for the sake of brevity, but here are the things I'm getting messed up with.
The first is a function that runs the thread for one of the "players"
void* xTurn(){
int move; //generate random number to place items on board
move = rand()%4+1;
//generates a number between 1 and 4
while(tokens!=0){ //while there are still "tokens" on the board, continue
sem_wait(&sB);
for(int i = 0; i < ROW; i++){
for(int j = 0; j < COL; j++){
if(board[i][j] == 'X'){
switch(move){
case '1':
if(i++>8){
xTurn();
}
else{
if(board[i++][j]=='a'){
xScore++;
tokens--;
}
if(board[i++][j]=='A'){
xScore+2;
tokens--;
}
board[i][j]='-';
board[i++][j]='X';
break;
}
case '2':
if(i--<0){
xTurn();
}
else{
if(board[i--][j]=='a'){
xScore++;
tokens--;
}
if(board[i--][j]=='A'){
xScore+2;
tokens--;
}
board[i][j]='-';
board[i--][j]='X';
break;
}
case '3':
if(j++>8){
xTurn();
}
else{
if(board[i][j++]=='a'){
xScore++;
tokens--;
}
if(board[i][j++]=='A'){
xScore+2;
tokens--;
}
board[i][j]='-';
board[i][j++]='X';
break;
}
case '4':
if(j--<0){
xTurn();
}
else{
if(board[i][j--]=='a'){
xScore++;
tokens--;
}
if(board[i][j--]=='A'){
xScore+2;
tokens--;
}
board[i][j]='-';
board[i][j--]='X';
break;
}
}
}
}
}
}
sem_post(&sB);
}
And I'm calling it here. Just assume that I have methods yTurn and zTurn; print is headed in a similar manner.
void playgame(){
createBoard();
srand (time(NULL));
sem_init(&sB,0,0);
pthread_create(&tX,NULL,&xTurn,NULL);
pthread_create(&tY,NULL,&yTurn,NULL);
pthread_create(&tZ,NULL,&zTurn,NULL);
pthread_create(&tP,NULL,&print,NULL);
pthread_join(tX,NULL);
pthread_join(tY,NULL);
pthread_join(tZ,NULL);
pthread_join(tP,NULL);
if(xScore>yScore&&zScore){
cout<<"Player X Wins with a score of "<<xScore;
}
if(yScore>xScore&&zScore){
cout<<"Player Y Wins with a score of "<<yScore;
}
if(zScore>yScore&&xScore){
cout<<"Player Z Wins with a score of "<<zScore;
}
sleep(20);
menu();
}
When I run it I get two different errors:
One that tells me sleep is not declared, but that will be solved when running it Linux.
Two is --invalid conversion from 'void* ()()' to 'void(*)(void*_' [-fpermissive]
This problem occures at the third argument in the pthread_create.
I haven't a clue as to what that means. I've tried a number of different things, but haven't the slightest idea as to how to solve the problem
The signature of pthread_create is:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
So the function you pass to it has to take a void* parameter, even if you aren't using it, i.e your declaration should be
void* xTurn(void*) ...
A thread function called as by pthread_create should have a void * argument and return a void * value.
So, change:
void* xTurn()
to
void* xTurn(void *)

C++ console game input && refresh function

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 ;) )