Text-Galaga: Continuous Text-Game Looping and Controlling Character - c++

just for fun and possibly for a project for my computer science class, I was making a text based "Galaga" game. Your character is ">" and the enemies are "<" and the lasers are "~" or "-", point is, its pretty simple. 600-700 lines of code. Problem is, you have to enter something for the code to loop. I used system("stty raw") so that I don't have to press enter, but the game stops when you stop holding or pressing buttons. I want to make it a real continuous game that is just made out of text. Any way to accomplish this while also being able to control the movement of your character properly using WASD movements? I am also using Xcode on a macbook if that helps. And this is part of the main function just for some context:
int main()
{
cout<<" ██████╗ █████╗ ██╗ █████╗ ██████╗ █████╗ "<<endl;
cout<<"██╔════╝ ██╔══██╗██║ ██╔══██╗██╔════╝ ██╔══██╗"<<endl;
cout<<"██║ ███╗███████║██║ ███████║██║ ███╗███████║"<<endl;
cout<<"██║ ██║██╔══██║██║ ██╔══██║██║ ██║██╔══██║"<<endl;
cout<<"╚██████╔╝██║ ██║███████╗██║ ██║╚██████╔╝██║ ██║"<<endl;
cout<<" ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ "<<endl;
cout<<endl<<endl;
cout<<"Welcome to text-galaga!"<<endl;
cout<<"_________________________"<<endl;
cout<<"Use W to move forward,"<<endl;
cout<<"A to move left, S to move back,"<<endl;
cout<<"D to move right, and J to shoot"<<endl;
cout<<"_________________________"<<endl;
cout<<"Good luck!"<<endl<<endl;
cout<< "Enter any key to begin..."<<endl;
cin>>x;
// Set terminal to raw mode
system("stty raw");
char input ='c';
int height=10,wide=5;
int turns=0;
int num_destroyed=0;
// ACTUAL MAIN GAME OPERATIONS START HERE...
while((input!='Q'&& input!='q') && (num_destroyed<5) && dead==false)
{
// Wait for single character
input = getchar();
int i=0;
int j=0;
get_inputs(i, j, bad);
render(i, j, height, wide, input, destroyed, dead, bad, turns, shot,
constant_height, constant_wide, shot_distance, next, num_destroyed);
draw(height, wide, j, i, destroyed, dead, bad, shot_distance, shot,
constant_height, constant_wide);
if ((num_destroyed<5) && dead==false)
cout<<endl<<endl;
++turns;
}
// Reset terminal to normal "cooked" mode
system("stty cooked");
// Game End Information
if (num_destroyed==5)
{
cout<<"Congradulations! You win!"<<endl<<endl;
}
if (dead==true)
{
cout<<"You died. Game Over."<<endl<<endl;
}
cout<<"Frames used: "<<turns<<endl;
return 0;
// AND END HERE...
}
Anyways, I know that I should probably put "while (true)" and take out the "getchar()" once I have the rest figured out, but that alone doesn't seem to make it into a sufficient game like a text-galaga. Anyways, sorry about the long post. Thanks guys.

Related

ARROWS DETECTION IN C++ [duplicate]

Today i was testing how key pressing might work in C++ and made simple loop for it,and found that getch() duplicate itself for some reason or idk what is going on honestly,just look at that:
#include <iostream>
#include <windows.h>
#include <conio.h>
#define VK_H 0x48
using namespace std;
int main()
{
int n=1;
int total=0;
bool theEnd=true;
while(theEnd)
{
cout<<total<<endl;
getch();
if(GetAsyncKeyState(VK_LEFT))
{
total -=n;
}else if(GetAsyncKeyState(VK_RIGHT))
{
total +=n;
}else if(GetAsyncKeyState(VK_LSHIFT) && GetAsyncKeyState(VK_F1))
{
total = 0;
} else if(GetAsyncKeyState(VK_ESCAPE))
{
break;
}
}
cout<<total<<endl;
}
Its pretty simple.Program starts with a loop,where endlessly outputs value of variable "total",and after pressing left/right buttons "total" decrements/increments by 1.
Its was worked fine and perfect when i was using system("pause"); Sleep(milliseconds); cin.get();(but this one assume pressing enter each time,so it is not proper one) ,all that output right value on the screen after each pressing on the buttons.But in case with getch(); it somehow appear to working like only one time per/two cycles of the loop.
So the result i've get is like this: i'm pressing button right - current loop working fine,but next one working like without getch(),incrementing and outputting one more time without my command...
I've siting and thinking couple hours,trying find any answers in google and here but nothing...
P.S.without using getch() or other things for purpose stoping loop till next pressing - it will add not +1 to total by single pressing(as i need),but hundreds(average pressing key will do 150-300 loops lol).
From MS documentation
Remarks
The _getch and_getwch functions read a single character from the
console without echoing the character. None of these functions can be
used to read CTRL+C. When reading a function key or an arrow key, each
function must be called twice; the first call returns 0 or 0xE0, and
the second call returns the actual key code.
When you press arrow keys, the input is 2 chars

Correcting a Tic Tac Toe-Draw function

I am making a multiplayer tic tac toe game with a semi-graphical interface. I have made the code and most of it works.The only part of it that doesn't work is the draw function.
I do understand that I am using TurboC++,which is a highly out of date compiler,but the Indian education system follows only TurboC++,so I have to make my project in it.(The syllabus was changed to have Python instead of C++ recently but I happened to be in the last batch of students that will not be taught Python)
The problem is in the last part of the result() function. I was unable to find what was wrong with it.I have not used graphics.h because it is not in my syllabus.
result function alone:
struct mat //To store the positions and what is present in the 9 boxes
{
int x,y;char ch;
};
struct xo //To keep track of the match
{
int actp,actx,acty;
mat pos[3][3];
char flag;
void setup() //To create the boxes/bars
{
actp=1,actx=1,acty=1;
flag=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
pos[i][j].ch=0;
}
}
void result() //To find the result
{
char flage;
for(int i=0;i<3;i++) //Column win
{
if(pos[i][0].ch==pos[i][1].ch&&pos[i][1].ch==pos[i][2].ch)
flage=pos[i][0].ch;
}
for(i=0;i<3;i++) //Row win
{
if(pos[0][i].ch==pos[1][i].ch&&pos[1][i].ch==pos[2][i].ch)
flage=pos[0][i].ch;
}
if(pos[0][0].ch==pos[1][1].ch&&pos[1][1].ch==pos[2][2].ch) //Diagonal win
flage=pos[0][0].ch;
if(pos[0][2].ch==pos[1][1].ch&&pos[1][1].ch==pos[2][0].ch) //Other diagonal win
flage=pos[0][2].ch;
if(flage=='X')flag='1';
else if(flage=='O')flag='2';
else flag='0';
int chk=1;
for(i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{if(pos[i][j].ch=='0'){chk=0;gotoxy(3,15);cout<<chk;} }//Added cout statement for debugging
}
if(flag=='0'&&chk==0)flag='D';//I understand that the condition is supposed to be chk==1,but it works only if I have this condition
}
}a;
Here is the whole code,if necessary:
https://drive.google.com/open?id=19WMexp3Hw_p9hO3qiYm0HRj-GGAJeaTr
A screenshot:
https://i.stack.imgur.com/wGh7a.jpg
If I use the correct condition, the program says that the match is drawn just after 1 move.
With this wrong condition, the program works to a certain extent and is able to find winners but never declares a match drawn even if it happens.
Thanks for the help!!
I have corrected the errors, will elaborate soon. Thanks for the help.

Controls not responding properly in snake

I'm writing a basic snake game as console application in c++. It's based on two-dimensional array of "tile" structures. My problem is: when pressing button to change the direction the snake is going it doesn't work immidiately but waits for next "tick" instead. The function that manages game itself looks like this:
void board::play()
{
display();
while(1)
{
getInput();
delay(0.5);
getInput();
resetCursor();
tick();
display();
}
}
display() is pretty self-explanatory, displays whole board in console window.
delay() as well, it's function which gets number of seconds as a float and waits this much time before proceeding
getInput() looks like this:
void board::getInput()
{
int input;
if(kbhit())
{
input=getch();
if(input==KEY_LEFT)
turnLeft();
if(input==KEY_RIGHT)
turnRight();
if(input==KEY_UP)
turnUp();
if(input==KEY_DOWN)
turnDown();
}
}
resetCursor() sets the cursor to 0,0 coordinate so each time the board will write over itself and not one under another
And now for the game itself: class board contains amongst others field int direction. The tiles themselves contain a counter, which counts down by 1 with each move, and when reaches 0 the tile becomes empty. If the counter is equal to the lenght of a snake the tile is considered a head.
The tick()function does just that: decreases all counters by 1, remembers where head was and spawns a new head in the field next to previous one in direction specified. It looks like this:
void board::tick()
{
int posx, posy;
for(int i=0; i<boardSize; i++)
{
for(int j=0; j<boardSize; j++)
{
if(tab[i][j].getCounter()==lenght)
{
posx=i;
posy=j;
}
tab[i][j].tick();
}
}
switch(direction)
{
case UP: tab[posx-1][posy].addSnake(lenght);
break;
case DOWN: tab[posx+1][posy].addSnake(lenght);
break;
case LEFT: tab[posx][posy-1].addSnake(lenght);
break;
case RIGHT: tab[posx][posy+1].addSnake(lenght);
break;
}
}
Problem is, as stated before, that game waits one "tick" before changing direction when it should do so immediately after pressing associated button, e.g. when turning from UP to LEFT it does one more move up and only after that moves left.
It seems to me that you have an extra getInput() call. Could it be the problem?
while(1)
{
getInput(); // <--
delay(0.5);
getInput(); // <--
resetCursor();
tick();
display();
}
Solved.
Turns out there were too many things put into buffer, as the program started going crazy if you mashed controls randomly during waiting time. I solved it by replacing
if(kbhit())
{
input=getch();
//reactions
}
with
while(kbhit())
{
input=getch();
}
//reactions
It now checks every signal in the buffer and reacts only to the last one, so the delay is eliminated.

How do I add a "play again" feature to my C++ guessing game? Loop trouble

So for this assignment I have to include a play again function. Meaning once the person has guessed correctly the program should give the user the choice to play again or not. Also, I am trying to include a function where if the user guesses correctly in 5 guesses or less, then the program should print "Good Job!" and if it takes them more than 5 guesses, it should display "You can do better than that!". Help me please! I am a beginner in programming and I keep getting stuck in trying to fix this problem.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main( void )
{
int i, n = 0, r;
int answer;
srand( time( NULL ) );
r = rand() %100 +1;
char userName[15];
printf("Welcome to GUESS MY NUMBER!\n\nPlease type your name here: ");
scanf("%s", &userName);
printf("\n\nI am thinking of a number between 1 and 100.\n\nCan you guess what it is? ");
while(scanf("%d", &i))
{
if (n >= 9 && i != r)
{
printf("\n\nSorry, the number was %d.\n", r);
printf("You should have gotten it by now.\n");
printf("Better luck next time.\n\n");
system ("PAUSE");
break;
}
if (i > r)
{
n++;
printf("Your guess is high. You only get 10 guesses. Try again: ");
}
else if (i < r)
{
n++;
printf("Your guess is low. You only get 10 guesses. Try again: ");
}
else if (i == r)
{
printf("\n\nCongratulations %s!\nYou guessed the number within %d guesses!\nWould you like to play again? y/n?\n",userName, n+1,answer);
scanf("%d", &answer);
system ("PAUSE");
break;
}
}
return 0;
}
An easy thing to do is create a bool variable (originally set to true) which can be checked in the while statement and updated after the user has been given the option to continue or not. Then just change your breaks into continues and you should be in good shape.
Wrap the whole thing in another loop, and at the end of this outer loop, ask the user if he wants to play again. Either a while() or do-while() loop. If the user says yes, continue looping, otherwise exit the loop.
-Initialize the game
-Load any resources needed (in this case, none)
Begin looping continually
- Handle input
- Think
- Show results
End looping if exited
-Free any resources (in this case, none)
-Exit

Am I using the getch() function from the ncurses library incorrectly?

I am writing a Pacman game in c++ using the ncurses library, but I am not able to move the Pacman properly. I have used getch() to move it it up, down, left and right, but it only moves right and does not move anywhere else when I press any other key.
This is a code snippet for moving up. I have written similar code with some conditions altered accordingly for moving left, right and down.
int ch = getch();
if (ch == KEY_RIGHT)
{
int i,row,column;
//getting position of cursor by getyx function
for (i=column; i<=last_column; i+=2)
{
//time interval of 1 sec
mvprintw(row,b,"<"); //print < in given (b,row) coordinates
//time interval of 1 sec
mvprintw(row,(b+1),"O"); //print "O" next to "<"
int h = getch(); //to give the option for pressing another key
if (h != KEY_RIGHT) //break current loop if another key is pressed
{
break;
}
}
}
if (condition)
{
//code to move left
}
Am I using getch() wrong, or is there something else I have to do?
Many of the "special" keys on a keyboard -- Up, Down, Left, Right, Home, End, Function keys, etc. actually return two scan codes from the keyboard controller back to the CPU. The "standard" keys all return one. So if you want to check for special keys, you'll need to call getch() twice.
For example up arrow is first 224, then 72.
261 is consistent with KEY_RIGHT (octal 0405 in curses.h). That tells us at least that keypad was used to allow getch to read special keys.
The fragment shown doesn't give clues to how it was incorporated into the rest of the program. However, the use of getch in a loop is likely a source of confusion, since on exiting the loop the value is discarded. If you expect to do something different (from KEY_RIGHT), you could use ungetch to save the (otherwise discarded) value within the loop, e.g.,
if (h != KEY_RIGHT) //break current loop if another key is pressed
{
ungetch(h); //added
break;
}
Doing that will allow the next call to getch to return the key which exits the loop.