How to take multiple key input in wxwidgets? - c++

As I am making a game in Wxwidgets. The place where i am stuck is to jump Mario and take the input when the Mario is jumping in the air. Let me make you clear - When an player press space to jump vertical
the loop to jump Mario will run but when the player presses the "d" key to move forward while jumping it should jump forward.... i also need your help to take two input at the same time like in game when we press shift and "w" the player will walk faster but when we press only "w" key the player will walk slow..
void MyFrame :: OnChar(wxKeyEvent& event){
wxChar uc = event.GetUnicodeKey();
switch ( uc )
{
case 97:
tempx = x;
x = x - 5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Refresh();
break;
case 100:
tempx =x;
x = x + 5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Refresh();
break;
case 32:
tempy = y;
for(int i=0;i<=10;i++){
check = true;
tempx = x;
Sleep(1);
y=y-7;
x=x+5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Update();
Refresh();
}
for(int j=0;j<=10;j++){
check = true;
tempx = x;
Sleep(1);
y=y+7;
x=x+5;
Check(x);
FindGround(x);
CheckForNextMove(x,y,CurrentGroundX,CurrentGroundY,PreviousGroundX,PreviousGroundY,NextGroundX,NextGroundY);
Update();
Refresh();
if(stop){ stop = false; break; }
}
check = false;
Update();
Refresh();
break;
}
event.Skip();
}
here is the code where pressing space bar will make mario to jump in parabolic path but i wanted to make it more professional. I want mario to jump in parabolic when we press two key at the same time i.e. (when I press vertical jump key and right motion key then it will have to jump in right direction in parabolic path.

You need to change your program control flow to only remember that a key was pressed or released in wxEVT_KEY_{DOWN,UP} handlers instead of trying to do everything in wxEVT_CHAR handler.
Also, you definitely shouldn't ever have any calls to Sleep() or long-running loops in the event handlers, so whenever you think about putting them there, you can be sure that you're doing something wrong.

Related

opengl automatically move object for x times

My main loop is working fine, but the problem I'm encountering is when I click the "esc" button on my keyboard, the shape that I have should move to the right every 1 second for five times then terminate. I did a loop on it, but it doesn't work. I call this function with
case 27:
glutTimerFunc(25, move, 1);
Here's the portion of that code I did:
void move(int value)
{
int i = value;
while (i <= 5)
{
pX += 0.5; //pX is the position of the object in x-axis
i++;
}
glutPostRedisplay();
exit(0);
}
Can you help me point out my mistakes? I'm still confused on how glutTimerFunc works so any tips/explanation would be nice. Thanks.

OpenGL:How to make "Feet" go up and down?

I'm writing code that draws a polygon and gives it two feet, walks from the right until it gets to the middle, does a flip, and then lands and walks to the left. I'm having a lot of trouble figuring out how to animate his feet. All I want to do is make one go up, then come down, then the other go up, and then come down. I know all I have to do is change the Y values of his feet, but I can't figure out how.
My professor talks about key frames a lot, but wouldn't every step that my "Polyman" would take be a key frame leading to infinite amount of cases? Here is my timer function...
void TimerFunction(int value) //float plx = 7.0, ply=-3.0, linet=0.00;
{
switch(frame)
{
case 1:
dx-=0.15;
plx-=0.15; //dx=polygon, plx = one foot, pl2x = other foot
pl2x-=0.15;
if(dx<=0.0)
{
plx=0.0; //this case makes polyman walk to the middle
dx=0.0;
pl2x=0.0;
frame=2;
}
break;
case 2:
dxt+=0.05;
if (dxt<=-0.00) //this is a triangle I translate over polyman appearing as if he's opening his mouth
{
dxt=0.00;
frame=3;
}
break;
case 3:
dy+=0.2;
theta+=10.0;
thetat+=10.0;
dyt+=0.2; //this is the flip with polyman's mouth open
ply+=0.2;
pl2y+=0.2;
linet2+=10.0;
linet+=10.0;
if(dy>5.0 || theta>360.00)
{
dy=5.0;
dyt=5.0;
ply=5.0;
pl2y=5.0;
linet2=0.0;
theta=0.0;
thetat=0.0;
linet=0.0;
frame=4;
}
break;
case 4:
dy-=0.2;
dyt-=0.2;
ply-=0.2;
pl2y-=0.2;
if(dy<=-3.0) //this is polyman coming back down to earth
{
dy=-3.0;
dyt=-3.0;
ply=-3.0;
pl2y=-3.0;
frame=5;
}
break;
case 5:
dxt-=0.2;
if (dxt<-3)
{ //this is the triangle slowly translating left appearing as if he's closing his mouth
dxt-=3.0;
}
if (dxt<=-8)
{
dxt = -8;
frame = 6;
}
break;
case 6:
dx-= 0.15;
plx-= 0.15;
pl2x-=0.15; //this is polyman walking off the stage to the left
if(dx<=-8.0)
{
dx=-8.0;
plx=-8.0;
pl2x=-8.0;
}
break;
}
glutPostRedisplay();
glutTimerFunc(30, TimerFunction, 1);
}
All variables that are used in my timerfunction are global. Thanks for your time! If you need any more of my code just ask and i'll append.

C++/SDL, Tic Tac Toe turn taking

Alright so I have this tic tac toe game I'm making with SDL and C++. I'm trying to implement AI into the game. I don't have a problem setting up the AI, but I have a problem making it where you can take turns. My problem is that when I make my move, I can just move as many times as I want before the AI moves. I want it so I can make my move, and I can't make my move again until the AI makes a move. No matter what I do it seems the turn taking doesn't work properly.
This is the class header
class Buttons
{
private:
SDL_Rect squares[8];
public:
Buttons();
void handle_input();
void load_Squares(SDL_Rect sqRects, SDL_Texture* squarTexs);
void show_Squares();
void AI_move();
int grid[9];
bool moveMade = true;
};
Here I check for mouse input, and depending on the location during the left button press, it sets the according grid value to equal 1, meaning it becomes displayed as a circle on the screen. I also make sure that the AI has made a move before it allows me to click.
void Buttons::handle_input()
{
double mouseX = 0, mouseY = 0;
if((event.type == SDL_MOUSEBUTTONDOWN))
{
//If left mouse button was clicked and AI has made a move
if(event.button.button == SDL_BUTTON_LEFT && moveMade == true)
{
//Get mouse location
mouseX = event.button.x;
mouseY = event.button.y;
//If mouse location is in particular square, set according grid value to 1
if((mouseX >= 0) && (mouseX < SCREEN_WIDTH / 3) && (mouseY >= 0) && (mouseY < SCREEN_HEIGHT / 3) && (grid[0] == 0))
{
grid[0] = 1;
moveMade = false;
}
//Basically does this for all other 9 grids
Here is my AI function, where I check to make sure the moveMade variable = false. Every time I make a move in the input function above, it sets moveMade to false, which means it should access this function, and only until it finishes this AI_move function should I be able to make a move again, because moveMade is set back equal to true.
void Buttons::AI_move()
{
if(moveMade == false)
{
AI_block(&moveMade);
AI_complete(&moveMade);
AI_rand(&moveMade);
moveMade = true;
}
}
Last is my show function, where I show a Circle(player) if the grid array value = 1, and I show the X(AI) if the grid value = 2.
void Buttons::show_Squares()
{
switch(grid[0])
{
case 1:
load_Squares(squares[0], circleTexture); break;
case 2:
load_Squares(squares[0], xTexture); break;
}
switch(grid[1])
{
//Does this all the way to grid[8]
}
Alright so my problem doesn't have to do with the AI dealing accordingly, as I haven't even set up my defense and offense functions. My problem is that I can make another move before the AI moves. Sorry if this is way too long, but if I could get any feedback on this that would be great.
Have you tried putting breakpoints at various points such as if(event.button.button == SDL_BUTTON_LEFT && moveMade == true) and then following the program through the see if moveMade ever actually gets changed to false?
You should also look at changing show_Squares() into a loop as there is a lot of repeated code using incremented indexes. Something like this:
void Buttons::show_Squares()
{
size_t array_size = sizeof(squares) / sizeof(int); //gets the number of elements in the array
for(size_t i = 0; i < array_size; i++)
{
switch(grid[i])
{
case 1:
load_Squares(squares[i], circleTexture); break;
case 2:
load_Squares(squares[i], xTexture); break;
}
}
}

movement not working ncurses game

I am making an ncurses game which has a spaceship fire bullets at other enemies.
I've got the ship firing bullets how ever when I fire more than one bullet, only the latest bullet will move and the rest will stay still.
int i=0 , j=-1;
switch(key){
case KEY_UP: playership.row=changeRow(playership.row,-1,playership.col); /* move up */
break;
case KEY_DOWN: playership.row=changeRow(playership.row,+1,playership.col); /* move down */
break;
case KEY_LEFT:playership.col=changeColumn(playership.col,-1,playership.row); /* move left */
break;
case KEY_RIGHT:playership.col=changeColumn(playership.col,+1,playership.row); /* move right */
break;
case ' ': {j++; bullets[0].col=playership.col+5; bullets[j].row=playership.row-2 ;break;}
default: break; /* do nothing if other keys */
}
if (j!=-1){
attrset(COLOR_PAIR(2));
mvprintw(bullets[j].row,bullets[0].col,"%c",bullet);
mvprintw(bullets[j].row+1,bullets[0].col," ");
bullets[j].row=bullets[j].row-1;
refresh();
}
I tried to implement the suggestion from the comments in this answer to my earlier question, but I don't think I've done it right:
If you can have 5 bullets at once, you need to store their positions.
If you have int bullet_pos[5] that would be fine. You could use -1 in
each position to say that no bullets are active. Then when you want to
fire one you search the array to find the first position that is -1
and change it to 0. When you draw the bullets, you go through the
array and draw a bullet for any position that is not -1, and update
its position.
If you don't already, try adding a flag to your bullet structure. Something like alive.
When you want to fire, you check through your array and find an unused bullet position (if any):
for( int i = 0; i < MAX_BULLETS; i++ ) {
if( !bullets[i].alive ) {
bullets[i].alive = true;
bullets[i].row = playership.row;
bullets[i].col = playership.col+5;
break;
}
}
Then when you update or draw:
for( int i = 0; i < MAX_BULLETS; i++ ) {
if( bullets[i].alive ) {
attrset(COLOR_PAIR(2));
mvprintw(bullets[i].row, bullets[i].col, "%c", bullet);
mvprintw(bullets[i].row+1, bullets[i].col, " " );
bullets[i].col++;
// TODO check for bullet death. If bullet is done, set `alive` to false.
}
}
refresh();

SDL poll event inverting w with z and viceversa

I'm doing a simple camera movement with the WASD keys:
switch (k) {
case SDLK_w:
this->up = true;
break;
case SDLK_s:
this->down = true;
break;
case SDLK_a:
this->left = true;
break;
case SDLK_d:
this->right = true;
break;
default:
break;
}
It's pretty self explanatory. But when I press w it simply doesn't detect that button pressing. If I press a or d or s it works. The cool thing about it is that if I just change SDLK_w to any other button (let's say SDLK_q) keeping the same exact code, it just works. It's not an issue of how I handle this->up because even if I print something on the screen inside the case SDLK_w: and I press w it doesn't print anything.
PS: obviously my w key is not broken otherwise I would have had trouble writing this post doWn.
What's wrong with w?
It could depend on the type of keyboard you are using, actually your W and Z key could be inversed depending on your keyboard layout. I recommand you try ALT+SHIFT.
Do not use SDLK_w for this as it gives you whatever key actually gives you a W letter, whereas what you want is the key that you'd expect at the W position regardless of the layout, you do this by using scancodes, in this case SDL_SCANCODE_W.