用于在 Windows 控制台中运行的游戏的 C++ 控件

标签 c++ c user-controls keyboard c++-cli

我正在尝试制作一个在命令提示符下运行的小型 2 人游戏。在我开始研究玩家控制之前,一切都很好。因此,为了捕获键盘按键,我认为最好的解决方案是使用 getch() 函数。那是因为 getch() 在运行中获取键,而不是在屏幕上显示它,等待输入或其他键被按下。

据我所知,实现它的代码相当简单:

c=getch();
switch(c)
{
case 'a': make player 1 go left
          break;
case 'd': make player 1 go right
          break;
case 's': make player 1 go down
          break;
case 'w': make player 1 go up
          break;
case 'h': make player 2 go left
          break;
case 'k': make player 2 go right
          break;
case 'j': make player 2 go down
          break;
case 'u': make player 2 go up
          break; 
}

当然,一切都在 while 循环中。

问题是我需要两个玩家都能够在同时按下控件时移动。例如,当玩家 1 在玩家 2 按下分配给左移动的键后玩家 1 向右移动时,使用 getch() 时,玩家 1 会阻止玩家 2,因为他们都按住移动键。当然,如果玩家 2 松开按键并按下指定的另一个键,他将控制移动,同时阻挡玩家 1,依此类推。

为了让自己更容易理解,代码如下所示:

c=getch();
switch(c)
{
case 'a': cout <<"a";
          break;
case 'd': cout <<"b";
          break;
}

当某人按住“a”键时,输出将是“aaaaaaaaaaaaaaaa”,而在其他人按下“b”后,即使第一个人按住“a”键,输出也将变为“aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbb”。如果第一个人释放'a'并再次按下它,则输出将是“aaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa”,因为另一个人按住'b'。为了让我的游戏正常运行,当他们同时按住“a”和“b”时,我相信输出应该类似于“ababababababababab”。

老实说,到目前为止,我已经尝试了所有我能想到的方法,但我是 C/C++ 编程的新手,所以我可能只是没有足够的经验来使用这些编程语言。不必使我的 getch()+switch() 策略起作用,任何其他建议也将受到欢迎。但他们必须恢复到 Windows 控制台。

提前感谢您的宝贵时间

最佳答案

你的想法是正确的。在一天结束时,它可能看起来像这样:

void Keypressed()
{
    if (kbhit())
    {
      keypress =getch();
        switch (keypress )
        {

            case key_F1:
                displayHelp();
            break;

            case key_LEFT:


            case key_RIGHT:

            break;

            case key_UP:
                   PlayersPad.y-=3;if (PlayersPad.y<0) PlayersPad.y=0;
            break;

            case key_DOWN:
                   PlayersPad.y+=3;if (PlayersPad.y>18) PlayersPad.y=18;
            break;

            case key_ENTER:
            break;

            case key_SPACE:
            break;

            case key_TAB:
                autoPlay=-autoPlay;
                if (autoPlay>0)
                {
                    setcolor(79);gotoxy(62,23);printf("cheat on  " );setcolor(15);
                }
                else
                {
                    setcolor(79);gotoxy(62,23);printf("cheat off  " );setcolor(15);
                }

            break;


        }
    }

}

enter image description here

作为额外的奖励,这是我编写的 Pong 游戏的代码,它是玩家对玩家或玩家对计算机。

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <iostream.h>
#include <math.h>
#include <fstream.h>

#define Black 0
#define Blue 1
#define Green 2
#define Cyan 3
#define Red 4
#define Magenta 5
#define Yellow 6
#define White 7
#define Gray 8
#define LightBlue 9
#define LightGreen 10
#define LightCyan 11
#define LightRed 12
#define LightMagenta 13
#define LightYellow 14
#define BrightWhite 15

#define key_F1 59
#define key_UP 72
#define key_DOWN 80
#define key_LEFT 75
#define key_RIGHT 77
#define key_SPACE 32
#define key_ENTER 13
#define key_ESCAPE 27
#define key_TAB 9
#define key_INSERT 82
#define PONG_WIDTH 78
#define PONG_HEIGHT 22
#define PONG_SCREEN_RIGHT PONG_WIDTH-3
#define PONG_SCREEN_LEFT 5
#define PONG_SCREEN_TOP 2
#define PONG_SCREEN_BOTTOM 22

struct t_ball{ int x,y,headingX,headingY;};
struct t_pad{ int x,y,LEFT,RIGHT;};
int temp,kbChar;
int _key=0;
unsigned long   OldTicksPerSecond=GetTickCount(),NewTicksPerSecond=GetTickCount();
unsigned long   PreferredFramesPerSecond;
unsigned long   DeltaTicksPerSecond;
unsigned int frames=0;
float fps=60.0f;
float Refesh;
float InverseFramesPerSecond;
float OneFramePerSecond;
int keypress=0;

t_ball ball;
t_pad  PlayersPad,computersPad;
int  autoPlay,playersScore,computersScore;


void moveBall();
void runGame();
void initGame();
void Keypressed();
void gameLogic();
void removeBall();
void displayHelp();
void displayYouMissed();
void displayCheatEnabled();
void Render_Game_At_60_Frames_Per_Second();

void getKey();
void gotoxy(int x, int y);
void setcolor(WORD color);
void textColor(unsigned char fColor,unsigned char bColor);
void clrscr();
void delay(int milliseconds);

void txtPlot( unsigned char x, unsigned char y, unsigned char Color);
void txtLine( int xx1, int yy1, int xx2, int yy2 ,int color);
void clrbox(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char bkcol);
void box(unsigned x,unsigned y,unsigned sx,unsigned sy,unsigned char col,unsigned char col2,char text_[]);
void putbox(unsigned x,unsigned y,unsigned sx,unsigned sy,
                 unsigned char col, unsigned char col2,unsigned char bkcol,char text_[]);

int main()
{

    runGame();

  return 0;
}







/*********************************
 * runGame()
 ********************************/

void  runGame()
{
    initGame();
    while (keypress !=key_ESCAPE)
    {
        Keypressed();
        gameLogic();
        moveBall();
        Sleep( 50  );

        removeBall();
        setcolor(31);gotoxy(7,22);printf("ball  X=%d,Y=%d ",ball.x,ball.y );setcolor(15);
        setcolor(31);gotoxy(7,23);printf("pad   X=%d,Y=%d ",PlayersPad.x,PlayersPad.y );setcolor(15);
        setcolor(31);gotoxy(32,22);printf("Your Score:       %d ", playersScore );setcolor(15);
        setcolor(79);gotoxy(32,23);printf("Computers Score:  %d ", computersScore );setcolor(15);
    }

}
/*********************************
 * moveBall()
 ********************************/

void moveBall()
{

    txtPlot( ball.x,ball.y,15);
    txtLine(PlayersPad.x,PlayersPad.y,PlayersPad.x,PlayersPad.y+3,15);
    txtLine(computersPad.x,computersPad.y,computersPad.x,computersPad.y+3,15);


}
 /*********************************
 * removeBall()
 ********************************/

void removeBall()
{
    //Sleep( 9  );
    txtPlot( ball.x,ball.y,0);
    txtLine(PlayersPad.x,PlayersPad.y,PlayersPad.x,PlayersPad.y+3,0);
    txtLine(computersPad.x,computersPad.y,computersPad.x,computersPad.y+3,0);

}
 /*********************************
 * gameLogic()
 ********************************/

void gameLogic()
{
    /* update ball's x location */
    ball.x+=ball.headingX;
    /* update ball's y location */
    ball.y+=ball.headingY;

    /* if ball at most right of screen then reverse ball's x heading */
    if( (ball.x>PONG_SCREEN_RIGHT) )
    {
        ball.headingX=-ball.headingX;
        computersScore+=10;
    }
    /* check if ball's location at top or bottom of screen,if true reverse ball's y heading */
    if( (ball.y<PONG_SCREEN_TOP) || (ball.y>PONG_SCREEN_BOTTOM-2) ) ball.headingY=-ball.headingY;

    PlayersPad.LEFT=PlayersPad.y-3;
    PlayersPad.RIGHT=PlayersPad.y+5;

    /* check if ball lands on pad, if true bounce back */
    if ( (ball.y>= PlayersPad.LEFT) && (ball.y<= PlayersPad.RIGHT) && (ball.x==PlayersPad.x))
    {
        ball.headingX=-ball.headingX;
        playersScore+=10;
    }
    /* let computer track ball's movement */
    if (ball.x>PONG_SCREEN_RIGHT-18) computersPad.y=ball.y;

    /* if cheat enabled,let player track ball's movement */
    if (autoPlay>0)
    {

        if (ball.x<PONG_SCREEN_RIGHT-50) PlayersPad.y=ball.y;
        if (ball.x>PONG_SCREEN_LEFT+16)
        {
            if (PlayersPad.y<10) while (PlayersPad.y<10) PlayersPad.y++;
            if (PlayersPad.y>12) while (PlayersPad.y>10) PlayersPad.y--;
        }

    }
    /* check if ball misses pad, if true display you missed */
    if (ball.x<PONG_SCREEN_LEFT)
    {
        displayYouMissed();
        ball.x=75;
        ball.y=15;
        computersScore+=10;

    }
}

/*********************************
 * initGame()
 ********************************/

void  initGame()
{

    playersScore=0;
    computersScore=0;
    ball.x=15;
    ball.y=5;
    ball.headingX=1;
    ball.headingY=1;

    PlayersPad.x=5;
    PlayersPad.y=12;
    computersPad.x=75;
    computersPad.y=12;


    displayCheatEnabled();

    setcolor(15);
    clrscr();
    txtLine(6,0,74,0,1);
    txtLine(6,22,74,22,1);
    txtLine(6,23,74,23,1);

        autoPlay=1;
    if (autoPlay>0)
    {
        setcolor(79);gotoxy(62,23);printf("cheat on  " );setcolor(15);
    }
    else
    {
        setcolor(79);gotoxy(62,23);printf("cheat off  " );setcolor(15);
    }

    setcolor(31);gotoxy(62,22);printf("<F1> Help" );setcolor(15);
}

void displayHelp()
{
    clrbox(10,8,70,16,79);
    box(10,8,70,16,31,79,"Pong Game, Player vs Computer");

    gotoxy(18,10);cprintf("Controls  ");
    gotoxy(18,11);cprintf("<LEFT>   move pad left");
    gotoxy(18,12);cprintf("<RIGHT> move pad right");
    gotoxy(18,13);cprintf("<TAB>  cheat mode ON/OFF");
    gotoxy(18,15);cprintf("press any key to continue");
    keypress =getch();
    clrbox(10,8,75,21,0);



}

void displayYouMissed()
{
        clrbox(10,8,70,16,79);
        box(10,8,70,16,31,79,"You missed");

        gotoxy(18,10);cprintf("  ");
        gotoxy(18,11);cprintf("The ball has missed the paddle");
        gotoxy(18,12);cprintf("press press space to continue");
        gotoxy(18,13);cprintf("");
        gotoxy(18,14);cprintf("");
        keypress =getch();
        clrbox(10,8,75,21,0);


}

void displayCheatEnabled()
{
        clrbox(10,8,70,16,79);
        box(10,8,70,16,31,79,"Player vs. Computer");
        gotoxy(15,10);cprintf("The Cheat' pad will track  ball movement' is enabled");
        gotoxy(15,11);cprintf("press <TAB> to enable or disable the cheat.");
        gotoxy(15,13);cprintf("press press space to continue");
        gotoxy(18,14);cprintf("");
        gotoxy(18,14);cprintf("");
        keypress =getch();
        clrbox(10,8,75,21,0);


}

/*********************************
 * Keypressed()
 ********************************/

void Keypressed()
{
    if (kbhit())
    {
      keypress =getch();
        switch (keypress )
        {

            case key_F1:
                displayHelp();
            break;

            case key_LEFT:


            case key_RIGHT:

            break;

            case key_UP:
                   PlayersPad.y-=3;if (PlayersPad.y<0) PlayersPad.y=0;
            break;

            case key_DOWN:
                   PlayersPad.y+=3;if (PlayersPad.y>18) PlayersPad.y=18;
            break;

            case key_ENTER:
            break;

            case key_SPACE:
            break;

            case key_TAB:
                autoPlay=-autoPlay;
                if (autoPlay>0)
                {
                    setcolor(79);gotoxy(62,23);printf("cheat on  " );setcolor(15);
                }
                else
                {
                    setcolor(79);gotoxy(62,23);printf("cheat off  " );setcolor(15);
                }

            break;


        }
    }

}

/*********************************
 * Render_Game_At_60_Frames_Per_Second()
 ********************************/

void Render_Game_At_60_Frames_Per_Second()
{
    NewTicksPerSecond=GetTickCount();
    DeltaTicksPerSecond=NewTicksPerSecond-OldTicksPerSecond;
    frames++;

    if(DeltaTicksPerSecond>=PreferredFramesPerSecond)
    {


        OldTicksPerSecond=NewTicksPerSecond;
        InverseFramesPerSecond=1/((float)PreferredFramesPerSecond/1000.0f);
        OneFramePerSecond=(float)frames*InverseFramesPerSecond;
        fps+=OneFramePerSecond;
        fps/=2;
        setcolor(31);gotoxy(70,22);printf(" %d FPS ",DeltaTicksPerSecond );setcolor(15);
        frames=0;
        Refesh=60/fps;
    }
    Sleep(3);
}





        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************

        void gotoxy(int x, int y)
        {
            COORD coord;
            coord.X = x; coord.Y = y;
            SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
            return;
        }
        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************

        void setcolor(WORD color)
        {
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
            return;
        }


        //
        //     colors:
        //     0 = Black
        //     1 = Blue
        //     2 = Green
        //     3 = Cyan
        //     4 = Red
        //     5 = Magenta
        //     6 = Yellow
        //     7 = LightGray
        //     8 = DarkGray
        //     9 = LightBlue
        //     10 = LightGreen
        //     11 = LightCyan
        //     12 = LightRed
        //     13 = LightMagenta
        //     14 = LightYellow
        //     15 = White


        //

        void setForeGroundAndBackGroundColor(int ForeGroundColor,int BackGroundColor)
        {
           int color=16*BackGroundColor+ForeGroundColor;
           setcolor(color);
}



        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************

        void clrscr()
        {
            COORD coordScreen = { 0, 0 };
            DWORD cCharsWritten;
            CONSOLE_SCREEN_BUFFER_INFO csbi;
            DWORD dwConSize;
            HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

            GetConsoleScreenBufferInfo(hConsole, &csbi);
            dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
            FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
            GetConsoleScreenBufferInfo(hConsole, &csbi);
            FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
            SetConsoleCursorPosition(hConsole, coordScreen);
            return;
        }
        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************

        void box(unsigned x,unsigned y,unsigned sx,unsigned sy,unsigned char col,unsigned char col2,char text_[])
        {  unsigned i,j,m;
            {

               m=(sx-x);                       //differential
               j=m/8;                          //adjust
               j=j-1;                          //more adjustment
               gotoxy(x,y);cprintf("É");       //Top left corner of box
               gotoxy(sx,y);cprintf("»");      //Top right corner of box
               gotoxy(x,sy);cprintf("È");      //Bottom left corner of box
               gotoxy(sx,sy);cprintf("¼");     //Bottom right corner of box

               for (i=x+1;i<sx;i++)
               {
                  gotoxy(i,y);cprintf("Í");     // Top horizontol line
                  gotoxy(i,sy);cprintf("Í");    // Bottom Horizontal line
               }

               for (i=y+1;i<sy;i++)
               {
                  gotoxy(x,i);cprintf("º");     //Left Vertical line
                  gotoxy(sx,i);cprintf("º");    //Right Vertical Line
               }

                  gotoxy(x+j,y);cprintf(text_); //put Title
                  gotoxy(1,24);
            }
        }
        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************

        void clrbox(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char bkcol)
        {
            int x,y;
            setcolor(bkcol);                       //Set to color bkcol

            for (y=y1;y<y2;y++)                    //Fill Y Region Loop
            {
                for (x=x1;x<x2;x++)               //Fill X region Loop
                {
                  gotoxy(x,y);cprintf(" ");       //Draw Solid space
                }
            }
        }
        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************

        void putbox(unsigned x,unsigned y,unsigned sx,unsigned sy,
                 unsigned char col, unsigned char col2,unsigned char bkcol,char text_[])
        {
            clrbox(x,y,sx,sy,bkcol);
            box(x,y,sx,sy,col,col2,text_);
        }

        //*****************************************************************************
        //*                                                                           *
        //*****************************************************************************


        void txtPlot( unsigned char x, unsigned char y, unsigned char Color)
        {
                setcolor(Color);
                gotoxy(x,y);cprintf("Û");
        }


    //**********************************************
    //**                                          **
    //**********************************************




         void  txtSwap(int first, int second )
        {
          int  temp ;


            temp   = first;
            first  = second;
            second = temp;
          }




     void txtCircle(int X, int Y, int rad, int col)
     {
       float deg = 0;
       do {
         X = (int) (rad * cos(deg));
         Y = (int) (rad * sin(deg));
         txtPlot (40+X, 12+Y,  col);
         deg +=  0.005;
       }
       while (deg <= 6.4);
     }


    //**********************************************
    //**                                          **
    //**********************************************



    void txtLine(int x0, int y0, int x1, int y1, int color)
    {
        int pix = color;
        int dy = y1 - y0;
        int dx = x1 - x0;
        int stepx, stepy;

        if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
        if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
        dy <<= 1;                                                  // dy is now 2*dy
        dx <<= 1;                                                  // dx is now 2*dx

      txtPlot( x0, y0,pix);
        if (dx > dy) {
            int fraction = dy - (dx >> 1);                         // same as 2*dy - dx
            while (x0 != x1) {
                if (fraction >= 0) {
                    y0 += stepy;
                    fraction -= dx;                                // same as fraction -= 2*dx
                }
                x0 += stepx;
                fraction += dy;                                    // same as fraction -= 2*dy
                txtPlot( x0, y0,pix);
            }
        } else {
            int fraction = dx - (dy >> 1);
            while (y0 != y1) {
                if (fraction >= 0) {
                    x0 += stepx;
                    fraction -= dy;
                }
                y0 += stepy;
                fraction += dx;
                txtPlot( x0, y0,pix);
            }
        }
    }


    //**********************************************
    //**                                          **
    //**********************************************




        void delay(unsigned int milliseconds)
        {
            clock_t ticks1, ticks2;
            unsigned int tic1=0,tic2=0,tick=0;

            ticks1=clock();
            while(tick<milliseconds)
            {
                ticks2=clock();
                tic1=ticks2/CLOCKS_PER_SEC-ticks1;
                tic2=ticks1/CLOCKS_PER_SEC;
                tick=ticks2-ticks1;
            }
            ticks2=clock();
        }

关于用于在 Windows 控制台中运行的游戏的 C++ 控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20019945/

相关文章:

C++ 代码在 VS2010 中工作但在 2013 中不工作

c++ - 写入后linux c刷新串行缓冲区

c - 函数内绑定(bind)和函数外绑定(bind)的区别

c - 为什么下面的代码不会在多次运行时生成随机字符串?

WPF-MVVM 将 ViewModel-Property 绑定(bind)到嵌套的 UserControl

c++ - 这段 C++ 代码的奇怪行为(std::wcout 和 std::exception)

c++ - VC++ 2010 "array is not a member of std"错误

c - 简单的 if 语句和 scanf 不适合我

javascript - 简单且通用的客户端持久性解决方案?

asp.net - 用户控件的描述(和许多属性)不显示信息