为什么按键控制飞机移动无效,只有在程序点击运行的时候,我按下按键,可以运动一下
动这一下之后,后面按键就无效了我测试了,第一下那个dx,dy是传进去了的,应该是后面的按键就没传进去
#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>
//#include<MyPlane.h> 如果这里这么用,会发现 当前.h文件和MyPlane.h文件的彼此头文件相互包含,会报错
class MyPlane;//告诉编译器,需要这个类,其他功能结构都没变
using namespace std;
class GameMain
{
public:
//构造函数用于初始化参数,游戏界面设置
GameMain();
//注意,你需要在GameMain类的析构函数中删除MyPlane
//类的实例*以避免内存泄漏。在GameMain类中添加一个析构函数,并在其中删除MP :GameMain.h文件
~GameMain();// 添加析构函数
//游戏界面初始化
void init();
void paly(); // 开始游戏
int* getBgSize();
int rows;
int cols;
private:
void keyEvent();//按键控制
void updateWindow();//渲染界面
private:
bool update;
// 添加这一行,这样其他地方调用这个类的时候,就不用每次都申明,不同地方申明,还是不同的对象,无法
//实现同时操作一辆飞机
MyPlane *MP;
//背景图像参数
IMAGE imgBg;//背景图片
//创建一个动态数组bullets,里面的元素都是一个个Bullet对象
//std::vector<Bullet> bullets;// 添加子弹容器
};
#include "GameMain.h"
#include "MyPlane.h"
#include "Bullet.h"
#include<stdlib.h>
#include <time.h>
#include<graphics.h>
#include <conio.h>
#include"iostream"
#include"string"
#include "fstream"
//音效
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"WINMM.LIB")
using namespace std;
GameMain::GameMain()
{
rows = 438;
cols = 675;
MP = new MyPlane(this);// 在创建 MyPlane 实例时传递 GameMain 类的指针
// 为 MyPlane 类对象的指针 MP 分配内存空间
//MP = new MyPlane();
//将游戏界面的宽度指定成背景图片的显示宽度
}
//析构函数主要作用就是释放资源, 避免内存泄漏
GameMain::~GameMain()
{
delete MP;// 删除 MyPlane 实例
}
void GameMain::init()
{
//播放背景音乐
mciSendString("play E:/res/bg.mp3 repeat", 0, 0, 0);
//创建游戏窗口
*initgraph(rows, cols);
//加载背景图片
loadimage(&imgBg, "E:/Leecode_April/plane/image/background.png");
update = true;
}
void GameMain::paly()
{
init();
update = true;
while (1)
{
BeginBatchDraw();
//接收用户的输入
keyEvent();
if (update == true) {
//更新游戏画面
updateWindow();
}
system("pause");
EndBatchDraw();
}
}
int* GameMain::getBgSize()
{
int num[] = { rows ,cols };
int* ptr = new int;
for (int i = 0; i < 2; i++) {
ptr = num;
}
return ptr;
}
void GameMain::keyEvent()
{
unsigned char ch;
int dx = 0;
int dy = 0;
//判断当前有没有按键输入,如果他没有按键输入,程序正常执行
if (_kbhit()) {
ch = _getch();
//按下字母,返回的就是字母,按下的是方向键
//上,先后返回: 224 72下:224 80 左:75 224,75右:224 77
if (ch == 224) {
ch = _getch();
switch (ch) {
case 72:
dy = -MP->pace;
break;
case 80:
dy = MP->pace;
break;
case 75:
dx = -MP->pace;
break;
case 77:
dx = MP->pace;
break;
default:
break;
}
}
}
if (dx != 0 || dy != 0)//左右移动
{
// MyPlane MP;
MP->Move(dx,dy);
// MP->Move(-20,- 20);
update = true;
}
}
void GameMain::updateWindow()
{
putimage(0, 0, &imgBg);
BeginBatchDraw();
//绘制我方飞机
//MyPlane MP;
IMAGE TEMP_my;
TEMP_my = MP->getImage_Myplane();
putimage(MP->My_current_posiX, MP->My_current_posiY, &TEMP_my);
//绘制子弹
//Bullet BT;
//IMAGE TEMP_BT;
//TEMP_BT = BT.getImage_Bullet();
//putimage(MP->My_current_posiX, MP->My_current_posiY, &TEMP_BT);
//for (Bullet& bullet : bullets) {
// bullet.update();// 更新子弹位置
// IMAGE TEMP_BT;
// TEMP_BT = bullet.getImage_Bullet();
// putimage(bullet.getPosX(), bullet.getPosY(), &TEMP_BT);
//}
EndBatchDraw();
}
#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>
//#include "GameMain.h"
using namespace std;
class GameMain;
class MyPlane
{
public:
MyPlane(GameMain* gm);//MyPlane类的构造函数中使用了 GameMain 类的指针GM 。但是,你没有初始化这个指针
//static IMAGE getImages(); //私有成员可以在public里面,通过函数来间接访问和修改
void Move(int dx, int dy);
static IMAGE getImage_Myplane();
int My_current_posiX;
int My_current_posiY;
int width;
int height;
int pace; //每次按键飞机移动的距离
private:
static IMAGE imgMyplane;
GameMain *GM;
};
#pragma once
#include<graphics.h>
#include<cstring>
#include<vector>
#include "MyPlane.h"
#include "GameMain.h"
using namespace std;
//静态成员,需要在类外进行声明
IMAGE MyPlane::imgMyplane;// 这一行为 imgMyplane 分配内存空间
//`MyPlane` 类在头文件 `MyPlane.h` 中声明,而 `imgMyplane` 的定义位于与类实现相关联的源文件
//`MyPlane.cpp` 中。这样,您就解决了 `LNK2001` 错误。
//如果您将所有代码放在同一个文件中,那么只需在类定义之后添加 `IMAGE MyPlane::imgMyplane; ` 这一行即可。
//IMAGE MyPlane::imgMyplane;// 这一行为 imgMyplane 分配内存空间
MyPlane::MyPlane(GameMain* gm):GM(gm)
{
width = 100;
height = 125;
pace = 20;
loadimage(&imgMyplane, "E:/Leecode_April/plane/image/me1.png");
//初始化飞机的位置在图像的正下方的中心
My_current_posiX = GM->rows / 2 - width / 2;
My_current_posiY = GM->cols - height;
}
IMAGE MyPlane::getImage_Myplane()
{
return imgMyplane;
}
void MyPlane::Move(int dx, int dy)
{
My_current_posiX += dx;
My_current_posiY += dy;
//判断是否超出了边界,还要考虑飞机本身的宽度
if (My_current_posiX > (GM->rows - width / 2) || My_current_posiX < width / 2)
{
My_current_posiX -= dx;
}
if (My_current_posiX > (GM->cols - height / 2) || My_current_posiX < height / 2)
{
My_current_posiY -= dy;
}
}
本帖最后由 isdkz 于 2023-5-3 21:41 编辑
首先,从你的代码中,我发现了一个问题。在GameMain::paly()函数中,你在游戏主循环的每一次迭代后都有一个system("pause");调用。这会导致游戏在每一帧之后都暂停并等待用户按下回车键。这可能是你遇到的按键无效问题的原因之一。要解决此问题,请删除system("pause");这一行。
另外,在GameMain::keyEvent()函数中,你需要在_kbhit()调用之前先调用_flushall() ,以确保在_kbhit()调用之前清除任何缓冲的输入。这是一个解决方案:
void GameMain::keyEvent()
{
_flushall();// 添加此行以清除缓冲的输入
unsigned char ch;
int dx = 0;
int dy = 0;
//判断当前有没有按键输入,如果他没有按键输入,程序正常执行
if (_kbhit()) {
ch = _getch();
//按下字母,返回的就是字母,按下的是方向键
//上,先后返回: 224 72下:224 80 左:75 224,75右:224 77
if (ch == 224) {
ch = _getch();
switch (ch) {
case 72:
dy = -MP->pace;
break;
case 80:
dy = MP->pace;
break;
case 75:
dx = -MP->pace;
break;
case 77:
dx = MP->pace;
break;
default:
break;
}
}
}
if (dx != 0 || dy != 0)//左右移动
{
MP->Move(dx,dy);
update = true;
}
}
在做了这些更改之后,按键控制应该可以正常工作。希望这可以解决你的问题! isdkz 发表于 2023-5-3 21:39
首先,从你的代码中,我发现了一个问题。在GameMain::paly()函数中,你在游戏主循环的每一次迭代后都有 ...
还是动不了诶 isdkz 发表于 2023-5-3 21:39
首先,从你的代码中,我发现了一个问题。在GameMain::paly()函数中,你在游戏主循环的每一次迭代后都有 ...
https://blog.csdn.net/weixin_43528481/article/details/130252992?spm=1001.2014.3001.5502
我是仿照这个俄罗斯方块写的,虽然不是一个游戏,但是思路差不多 猪猪虾 发表于 2023-5-3 21:42
还是动不了诶
system("pause"); 删了吗? isdkz 发表于 2023-5-3 22:05
system("pause"); 删了吗?
删了,还是不行 猪猪虾 发表于 2023-5-3 22:13
删了,还是不行
在 GameMain::paly() 函数的 while (1) 循环中,删除 BeginBatchDraw(); 和 EndBatchDraw(); 函数调用。这些函数实际上是用于双缓冲技术,用于防止屏幕闪烁,但在这种情况下,它们可能会干扰按键事件的处理。将 GameMain::paly() 函数修改为:
void GameMain::paly()
{
init();
update = true;
while (1)
{
//接收用户的输入
keyEvent();
if (update == true) {
//更新游戏画面
updateWindow();
}
}
}
isdkz 发表于 2023-5-3 22:45
在 GameMain::paly() 函数的 while (1) 循环中,删除 BeginBatchDraw(); 和 EndBatchDraw(); 函数调用。 ...
删掉确实可以了,但是频闪{:5_104:}
页:
[1]