8 个解决方案
#1
在事件循环里,对某个键是否按下进行判断:
伪代码
伪代码
int main()
{
init();
while (isRunning())
{
if (isKeyDown(KEY_LEFT))
player.x -= 10;
if (isKeyDown(KEY_RIGHT))
player.x += 10;
// 渲染...
}
return 0;
}
#2
额,一般的游戏键盘事件是可以的没问题,比如下面实现的移动是没问题的
问题是按键有延迟,每次按键都需要停顿一下然后才能一直移动,就像平时打字一样,按住一个键不放不会立即重复出现对应键位的值,而要等一会儿才行
bool gameOver = false;
while(!gameOver)
{
SDL_Event gEvent;
while(SDL_PollEvent(&gEvent) > 0)
{
if(gEvent.type == SDL_QUIT)
gameOver = true;
if(gEvent.type == SDL_KEYDOWN)
{
switch(gEvent.key.keysym.sym)
{
case SDLK_ESCAPE:
gameOver = true;
break;
case SDLK_UP:
j -= 5;
break;
case SDLK_DOWN:
j += 5;
break;
case SDLK_LEFT:
i -= 5;
break;
case SDLK_RIGHT:
i += 5;
break;
}
//渲染
SDL_RenderClear(gRenderer);
backTex.render(gRenderer,0,0);
frontTex.render(gRenderer,i,j);
SDL_RenderPresent(gRenderer);
}
}
}
问题是按键有延迟,每次按键都需要停顿一下然后才能一直移动,就像平时打字一样,按住一个键不放不会立即重复出现对应键位的值,而要等一会儿才行
#3
用SDL_GetKeyboardState获得按键的状态
const Uint8 *state = SDL_GetKeyboardState(NULL);
if (state[SDL_SCANCODE_RETURN]) {
printf("<RETURN> is pressed.\n");
}
if (state[SDL_SCANCODE_RIGHT] && state[SDL_SCANCODE_UP]) {
printf("Right and Up Keys Pressed.\n");
#4
游戏里面的人物都能按一个键就一直走
和
按键重复延迟
没关系。
和
按键重复延迟
没关系。
#include <conio.h>
#include <windows.h>
void ConPrintAt(int x, int y, char *CharBuffer, int len)
{
DWORD count;
COORD coord = {x, y};
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hStdOut, coord);
WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
}
void HideTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void ShowTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = TRUE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void GetWH(int *w,int *h) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
*w=csbi.srWindow.Right;
*h=csbi.srWindow.Bottom;
} else {
*w=80;
*h=25;
}
}
void ClearConsole()
{
//Get the handle to the current output buffer...
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//This is used to reset the carat/cursor to the top left.
COORD coord = {0, 0};
//A return value... indicating how many chars were written
// not used but we need to capture this since it will be
// written anyway (passing NULL causes an access violation).
DWORD count;
//This is a structure containing all of the console info
// it is used here to find the size of the console.
CONSOLE_SCREEN_BUFFER_INFO csbi;
//Here we will set the current color
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//This fills the buffer with a given character (in this case 32=space).
FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
//This will set our cursor position for the next print statement.
SetConsoleCursorPosition(hStdOut, coord);
}
}
int main() {
unsigned short k;
int x,y,w,h;
char d;
SetConsoleOutputCP(437);
ClearConsole();
GetWH(&w,&h);
x=w/2;y=h/2;
HideTheCursor();
ConPrintAt(x,y,"O",1);
d='o';
while (1) {
Sleep(50);
if (kbhit()) {
k=getch();
if (27==k) break;//按Esc键退出
if (0==k||0xe0==k) k|=getch()<<8;//非字符键
switch (k) {
case 0x48e0:case 0x04800://上
d='u';
if (y>0) {
ConPrintAt(x,y," ",1);
y--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x50e0:case 0x05000://下
d='d';
if (y<h) {
ConPrintAt(x,y," ",1);
y++;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4be0:case 0x04b00://左
d='l';
if (x>0) {
ConPrintAt(x,y," ",1);
x--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4de0:case 0x04d00://右
d='r';
if (x<w-1) {
ConPrintAt(x,y," ",1);
x++;
ConPrintAt(x,y,"O",1);
}
break;
}
// cprintf("%04x pressed.\r\n",k);
} else {
switch (d) {
case 'u':
if (y>0) {
ConPrintAt(x,y," ",1);
y--;
ConPrintAt(x,y,"O",1);
}
break;
case 'd':
if (y<h) {
ConPrintAt(x,y," ",1);
y++;
ConPrintAt(x,y,"O",1);
}
break;
case 'l':
if (x>0) {
ConPrintAt(x,y," ",1);
x--;
ConPrintAt(x,y,"O",1);
}
break;
case 'r':
if (x<w-1) {
ConPrintAt(x,y," ",1);
x++;
ConPrintAt(x,y,"O",1);
}
break;
}
}
}
ClearConsole();
ShowTheCursor();
return 0;
}
#5
#include <conio.h>
#include <windows.h>
void ConPrintAt(int x, int y, char *CharBuffer, int len)
{
DWORD count;
COORD coord = {x, y};
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hStdOut, coord);
WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
}
void HideTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void ShowTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = TRUE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void GetWH(int *w,int *h) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
*w=csbi.srWindow.Right;
*h=csbi.srWindow.Bottom;
} else {
*w=80;
*h=25;
}
}
void ClearConsole()
{
//Get the handle to the current output buffer...
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//This is used to reset the carat/cursor to the top left.
COORD coord = {0, 0};
//A return value... indicating how many chars were written
// not used but we need to capture this since it will be
// written anyway (passing NULL causes an access violation).
DWORD count;
//This is a structure containing all of the console info
// it is used here to find the size of the console.
CONSOLE_SCREEN_BUFFER_INFO csbi;
//Here we will set the current color
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//This fills the buffer with a given character (in this case 32=space).
FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
//This will set our cursor position for the next print statement.
SetConsoleCursorPosition(hStdOut, coord);
}
}
int main() {
unsigned short k;
int x,y,w,h;
SetConsoleOutputCP(437);
ClearConsole();
GetWH(&w,&h);
x=w/2;y=h/2;
HideTheCursor();
ConPrintAt(x,y,"O",1);
while (1) {
Sleep(50);
k=getch();
if (27==k) break;//按Esc键退出
if (0==k||0xe0==k) k|=getch()<<8;//非字符键
switch (k) {
case 0x48e0:case 0x04800://上
if (y>0) {
ConPrintAt(x,y," ",1);
y--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x50e0:case 0x05000://下
if (y<h) {
ConPrintAt(x,y," ",1);
y++;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4be0:case 0x04b00://左
if (x>0) {
ConPrintAt(x,y," ",1);
x--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4de0:case 0x04d00://右
if (x<w-1) {
ConPrintAt(x,y," ",1);
x++;
ConPrintAt(x,y,"O",1);
}
break;
}
// cprintf("%04x pressed.\r\n",k);
}
ClearConsole();
ShowTheCursor();
return 0;
}
#6
额,感谢大神们的帮助,这样好像能解决一些问题,但是感觉还不太完善
原因大概是在长按的停顿事件发生时pollevent没有接收到任何事件,故不会做出反应。所以没有接收到事件的时候就通过检查是否按下按键来直接检测键盘的状态,但是这么做的话就需要对事件进行两次相同的处理。
原因大概是在长按的停顿事件发生时pollevent没有接收到任何事件,故不会做出反应。所以没有接收到事件的时候就通过检查是否按下按键来直接检测键盘的状态,但是这么做的话就需要对事件进行两次相同的处理。
bool gameOver = false;
const Uint8 *state;
while(gameOver == false)
{
SDL_Event gEvent;
if(SDL_PollEvent(&gEvent) > 0)
{
state = SDL_GetKeyboardState(NULL);
if(gEvent.type == SDL_QUIT)
gameOver = true;
if(state[SDL_SCANCODE_XXXX])
{
//do something
}
if (state[SDL_SCANCODE_ESCAPE])
break;
}
else if(gEvent.key.state == SDL_PRESSED)
{
//do something
}
SDL_Delay(100);
}
#7
SDL_GetKeyboardState() 不要放在SDL_PollEvent()里边。
看看这本书里是怎么处理的 《SDL Game Development》作者Shaun Ross Mitchell
看看这本书里是怎么处理的 《SDL Game Development》作者Shaun Ross Mitchell
#8
可以了,这样就感觉达到效果了,谢谢!前段时间在看Focus on SDL,目前在看Lazy foo的教程,正好也看看这本书。
bool gameOver = false;
const Uint8 *state;
while(gameOver == false)
{
SDL_Event gEvent;
while(SDL_PollEvent(&gEvent) > 0)
{
//printf(".");
if(gEvent.type == SDL_QUIT)
gameOver = true;
}
state = SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_RIGHT])
printf("-");
SDL_Delay(50);
}
#1
在事件循环里,对某个键是否按下进行判断:
伪代码
伪代码
int main()
{
init();
while (isRunning())
{
if (isKeyDown(KEY_LEFT))
player.x -= 10;
if (isKeyDown(KEY_RIGHT))
player.x += 10;
// 渲染...
}
return 0;
}
#2
额,一般的游戏键盘事件是可以的没问题,比如下面实现的移动是没问题的
问题是按键有延迟,每次按键都需要停顿一下然后才能一直移动,就像平时打字一样,按住一个键不放不会立即重复出现对应键位的值,而要等一会儿才行
bool gameOver = false;
while(!gameOver)
{
SDL_Event gEvent;
while(SDL_PollEvent(&gEvent) > 0)
{
if(gEvent.type == SDL_QUIT)
gameOver = true;
if(gEvent.type == SDL_KEYDOWN)
{
switch(gEvent.key.keysym.sym)
{
case SDLK_ESCAPE:
gameOver = true;
break;
case SDLK_UP:
j -= 5;
break;
case SDLK_DOWN:
j += 5;
break;
case SDLK_LEFT:
i -= 5;
break;
case SDLK_RIGHT:
i += 5;
break;
}
//渲染
SDL_RenderClear(gRenderer);
backTex.render(gRenderer,0,0);
frontTex.render(gRenderer,i,j);
SDL_RenderPresent(gRenderer);
}
}
}
问题是按键有延迟,每次按键都需要停顿一下然后才能一直移动,就像平时打字一样,按住一个键不放不会立即重复出现对应键位的值,而要等一会儿才行
#3
用SDL_GetKeyboardState获得按键的状态
const Uint8 *state = SDL_GetKeyboardState(NULL);
if (state[SDL_SCANCODE_RETURN]) {
printf("<RETURN> is pressed.\n");
}
if (state[SDL_SCANCODE_RIGHT] && state[SDL_SCANCODE_UP]) {
printf("Right and Up Keys Pressed.\n");
#4
游戏里面的人物都能按一个键就一直走
和
按键重复延迟
没关系。
和
按键重复延迟
没关系。
#include <conio.h>
#include <windows.h>
void ConPrintAt(int x, int y, char *CharBuffer, int len)
{
DWORD count;
COORD coord = {x, y};
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hStdOut, coord);
WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
}
void HideTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void ShowTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = TRUE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void GetWH(int *w,int *h) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
*w=csbi.srWindow.Right;
*h=csbi.srWindow.Bottom;
} else {
*w=80;
*h=25;
}
}
void ClearConsole()
{
//Get the handle to the current output buffer...
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//This is used to reset the carat/cursor to the top left.
COORD coord = {0, 0};
//A return value... indicating how many chars were written
// not used but we need to capture this since it will be
// written anyway (passing NULL causes an access violation).
DWORD count;
//This is a structure containing all of the console info
// it is used here to find the size of the console.
CONSOLE_SCREEN_BUFFER_INFO csbi;
//Here we will set the current color
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//This fills the buffer with a given character (in this case 32=space).
FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
//This will set our cursor position for the next print statement.
SetConsoleCursorPosition(hStdOut, coord);
}
}
int main() {
unsigned short k;
int x,y,w,h;
char d;
SetConsoleOutputCP(437);
ClearConsole();
GetWH(&w,&h);
x=w/2;y=h/2;
HideTheCursor();
ConPrintAt(x,y,"O",1);
d='o';
while (1) {
Sleep(50);
if (kbhit()) {
k=getch();
if (27==k) break;//按Esc键退出
if (0==k||0xe0==k) k|=getch()<<8;//非字符键
switch (k) {
case 0x48e0:case 0x04800://上
d='u';
if (y>0) {
ConPrintAt(x,y," ",1);
y--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x50e0:case 0x05000://下
d='d';
if (y<h) {
ConPrintAt(x,y," ",1);
y++;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4be0:case 0x04b00://左
d='l';
if (x>0) {
ConPrintAt(x,y," ",1);
x--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4de0:case 0x04d00://右
d='r';
if (x<w-1) {
ConPrintAt(x,y," ",1);
x++;
ConPrintAt(x,y,"O",1);
}
break;
}
// cprintf("%04x pressed.\r\n",k);
} else {
switch (d) {
case 'u':
if (y>0) {
ConPrintAt(x,y," ",1);
y--;
ConPrintAt(x,y,"O",1);
}
break;
case 'd':
if (y<h) {
ConPrintAt(x,y," ",1);
y++;
ConPrintAt(x,y,"O",1);
}
break;
case 'l':
if (x>0) {
ConPrintAt(x,y," ",1);
x--;
ConPrintAt(x,y,"O",1);
}
break;
case 'r':
if (x<w-1) {
ConPrintAt(x,y," ",1);
x++;
ConPrintAt(x,y,"O",1);
}
break;
}
}
}
ClearConsole();
ShowTheCursor();
return 0;
}
#5
#include <conio.h>
#include <windows.h>
void ConPrintAt(int x, int y, char *CharBuffer, int len)
{
DWORD count;
COORD coord = {x, y};
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hStdOut, coord);
WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
}
void HideTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void ShowTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = TRUE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void GetWH(int *w,int *h) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
*w=csbi.srWindow.Right;
*h=csbi.srWindow.Bottom;
} else {
*w=80;
*h=25;
}
}
void ClearConsole()
{
//Get the handle to the current output buffer...
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//This is used to reset the carat/cursor to the top left.
COORD coord = {0, 0};
//A return value... indicating how many chars were written
// not used but we need to capture this since it will be
// written anyway (passing NULL causes an access violation).
DWORD count;
//This is a structure containing all of the console info
// it is used here to find the size of the console.
CONSOLE_SCREEN_BUFFER_INFO csbi;
//Here we will set the current color
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//This fills the buffer with a given character (in this case 32=space).
FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
//This will set our cursor position for the next print statement.
SetConsoleCursorPosition(hStdOut, coord);
}
}
int main() {
unsigned short k;
int x,y,w,h;
SetConsoleOutputCP(437);
ClearConsole();
GetWH(&w,&h);
x=w/2;y=h/2;
HideTheCursor();
ConPrintAt(x,y,"O",1);
while (1) {
Sleep(50);
k=getch();
if (27==k) break;//按Esc键退出
if (0==k||0xe0==k) k|=getch()<<8;//非字符键
switch (k) {
case 0x48e0:case 0x04800://上
if (y>0) {
ConPrintAt(x,y," ",1);
y--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x50e0:case 0x05000://下
if (y<h) {
ConPrintAt(x,y," ",1);
y++;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4be0:case 0x04b00://左
if (x>0) {
ConPrintAt(x,y," ",1);
x--;
ConPrintAt(x,y,"O",1);
}
break;
case 0x4de0:case 0x04d00://右
if (x<w-1) {
ConPrintAt(x,y," ",1);
x++;
ConPrintAt(x,y,"O",1);
}
break;
}
// cprintf("%04x pressed.\r\n",k);
}
ClearConsole();
ShowTheCursor();
return 0;
}
#6
额,感谢大神们的帮助,这样好像能解决一些问题,但是感觉还不太完善
原因大概是在长按的停顿事件发生时pollevent没有接收到任何事件,故不会做出反应。所以没有接收到事件的时候就通过检查是否按下按键来直接检测键盘的状态,但是这么做的话就需要对事件进行两次相同的处理。
原因大概是在长按的停顿事件发生时pollevent没有接收到任何事件,故不会做出反应。所以没有接收到事件的时候就通过检查是否按下按键来直接检测键盘的状态,但是这么做的话就需要对事件进行两次相同的处理。
bool gameOver = false;
const Uint8 *state;
while(gameOver == false)
{
SDL_Event gEvent;
if(SDL_PollEvent(&gEvent) > 0)
{
state = SDL_GetKeyboardState(NULL);
if(gEvent.type == SDL_QUIT)
gameOver = true;
if(state[SDL_SCANCODE_XXXX])
{
//do something
}
if (state[SDL_SCANCODE_ESCAPE])
break;
}
else if(gEvent.key.state == SDL_PRESSED)
{
//do something
}
SDL_Delay(100);
}
#7
SDL_GetKeyboardState() 不要放在SDL_PollEvent()里边。
看看这本书里是怎么处理的 《SDL Game Development》作者Shaun Ross Mitchell
看看这本书里是怎么处理的 《SDL Game Development》作者Shaun Ross Mitchell
#8
可以了,这样就感觉达到效果了,谢谢!前段时间在看Focus on SDL,目前在看Lazy foo的教程,正好也看看这本书。
bool gameOver = false;
const Uint8 *state;
while(gameOver == false)
{
SDL_Event gEvent;
while(SDL_PollEvent(&gEvent) > 0)
{
//printf(".");
if(gEvent.type == SDL_QUIT)
gameOver = true;
}
state = SDL_GetKeyboardState(NULL);
if(state[SDL_SCANCODE_RIGHT])
printf("-");
SDL_Delay(50);
}