在 Windows 控制台中运行的游戏的 C++ 控件
我正在尝试制作一个在命令提示符下运行的小型 2 人游戏.在我开始研究玩家控制之前,一切都很好.因此,对于捕获键盘键,我认为最好的解决方案是使用 getch() 函数.那是因为 getch() 即时获取键,而不是在屏幕上显示它,等待输入或其他键被按下.
I'm trying to make a small 2 players game that runs in the command prompt. All things were good until I've started working on players controls. So, for capturing the keyboard keys I thought the best solution would be the use of getch() function. That's because getch() takes keys on the fly, without displaying it on screen, waiting for enter or other keys to be pressed.
据我所知,实现这一点的代码相当简单:
The code to accomplish that, as far as I could think, is fairly simple:
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循环中.
everything being inside a while loop of course.
问题是我需要两个玩家能够在同时按下控件时移动.例如,当玩家 1 在玩家 2 按下分配给左移动的键后向右移动时,使用 getch() 时,玩家 1 会阻止玩家 2,因为他们都按住移动键.当然,如果玩家 2 松开按键并按下另一个分配的按键,他会在阻止玩家 1 的同时控制移动,依此类推.
The thing is I need both players to be able to move while the controls are pressed at the same time. With getch() when player 1 moves right after player 2 presses the key assigned for left movement for example, player 1 blocks player 2 as they both keep pressed the movement keys. Of course if player 2 releases the key and presses another key assigned, he takes control on movement while blocking player 1, and so one.
为了让自己更容易理解,代码如下:
To make myself a bit more understood, with a code looking like this:
c=getch();
switch(c)
{
case 'a': cout <<"a";
break;
case 'd': cout <<"b";
break;
}
当有人按住'a'键时,输出将是aaaaaaaaaaaaaaaa",而在其他人按下'b'后,即使第一个人按住'a',输出也会变成aaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb".如果第一个人释放'a'并再次按下它,输出将是aaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa",因为另一个人持有'b'.为了让我的游戏正常运行,当他们同时按下a"和b"时,我相信输出应该类似于ababababababababab".
when someone keeps 'a' key pressed the output will be "aaaaaaaaaaaaaaa", and after someone else presses 'b', even if the first person keeps his hold on 'a', the output will become "aaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbb". If the first person releases 'a' and presses it again the output would be "aaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaa" as the other one holds 'b'. For my game to work, when they both keep pressed 'a' and 'b', I believe the output should be something like "ababababababababab".
老实说,到目前为止,我已经尝试了所有我能想到的方法,但是我是 C/C++ 编程的新手,所以我可能只是没有足够的这些编程语言的经验来使它工作.不必让我的 getch()+switch() 策略起作用,任何其他建议也将受到欢迎.但他们必须恢复到 Windows 控制台.
Honestly I've tried everything I could think so far, but I'm new to C/C++ programming so maybe I just don't have enough experience with these programming languages to make it work. It's not necessarilly to make my getch()+switch() strategy work, any other suggestions would be welcomed just as well. But they'll have to resume to windows console.
提前感谢您的宝贵时间
推荐答案
你的想法是对的.归根结底,它可能看起来像这样:
Your thinking is correct. At the end of the day, it would probably look like this:
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;
}
}
}
作为额外的奖励,这是我编写的 Pong 游戏的代码,它是玩家与玩家或玩家与计算机的游戏.
And as an added bonus, here is code to a Pong game i have written, its a player vs player or player vs computer.
#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("o"); //Left Vertical line
gotoxy(sx,i);cprintf("o"); //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();
}
相关文章