怎样解决双人小游戏移动互相干扰的问题

1

我在实现双人小游戏的时候发现自己写的代码运行时如果玩家1长按控制方向的按键时,玩家2按下自己控制方向的按键,就会中断玩家1的移动。于是我在网上找解决方法,就看到了村长给一个跟我有一样问题的网友的回答,我按照村长的回答写了下面这段代码,虽然这样可以在按下一个键的时候处理另一个按键的消息,但是不能实现长按移动,所以想问一下有没有更好的解决方法。

//编译环境:VS2022,EasyX_20220901
#include <stdio.h>
#include <easyx.h>
struct Ball
{
	int x;
	int y;
	int r;
};
int main()
{
	initgraph(800, 600);
	
	//创建并初始化两个小球
	struct Ball ball1 = { 300, 300, 30 };
	struct Ball ball2 = { 500, 300, 30 };

	BeginBatchDraw();
	while (1)
	{
		cleardevice();
		//绘制小球
		setfillcolor(WHITE);
		solidcircle(ball1.x, ball1.y, ball1.r);
		solidcircle(ball2.x, ball2.y, ball2.r);
		//小球移动
		ExMessage m;
		if (peekmessage(&m, EX_KEY))
		{
			if (m.message == WM_KEYDOWN && m.prevdown == false)
			{
				switch (m.vkcode)
				{
				case 'A':
					ball1.x -= 10;
					break;
				case 'D':
					ball1.x += 10;
					break;
				case 'W':
					ball1.y -= 10;
					break;
				case 'S':
					ball1.y += 10;
					break;
				case VK_LEFT:
					ball2.x -= 10;
					break;
				case VK_RIGHT:
					ball2.x += 10;
					break;
				case VK_UP:
					ball2.y -= 10;
					break;
				case VK_DOWN:
					ball2.y += 10;
					break;
				}
			}
			else if (m.message == WM_KEYUP && m.prevdown == true)
			{
				switch (m.vkcode)
				{
				case 'A':
					ball1.x -= 10;
					break;
				case 'D':
					ball1.x += 10;
					break;
				case 'W':
					ball1.y -= 10;
					break;
				case 'S':
					ball1.y += 10;
					break;
				case VK_LEFT:
					ball2.x -= 10;
					break;
				case VK_RIGHT:
					ball2.x += 10;
					break;
				case VK_UP:
					ball2.y -= 10;
					break;
				case VK_DOWN:
					ball2.y += 10;
					break;
				}
			}
		}
		Sleep(25);
		FlushBatchDraw();
	}
	EndBatchDraw();

	getchar();
	closegraph();
	return 0;
}
ava
三日月

2023-2-17

2

以下是基于你代码的修改。

不算复杂,我就不多做解释了,相信你一看就懂。

实现了同时控制两个小球的移动(包括斜向移动)。

注意:有些键盘支持同时按下的按键数量有限,可能在两个小球同时斜向移动(即同时按下四个按键)时,可能会丢失一个按键。这是硬件限制,无解。这也是一些游戏键盘写的“支持 10 键无冲突”的意思。

// 程序名称:同时控制两个小球的移动
// 编译环境: VC6 ~ VS2022, EasyX_20220901
//
#include <easyx.h>
#include <conio.h>

struct Ball
{
	int x, y;		// 坐标
	int r;			// 半径
	int dx, dy;		// 运动增量
};

int main()
{
	initgraph(800, 600);
	BeginBatchDraw();
	
	// 创建并初始化两个小球
	struct Ball ball1 = { 300, 300, 30, 0, 0 };
	struct Ball ball2 = { 500, 300, 30, 0, 0 };

	ExMessage m;
	while (true)
	{
		// 获取控制信息
		while(peekmessage(&m, EX_KEY))
		{
			if (m.message == WM_KEYDOWN && m.prevdown == false)
			{
				switch (m.vkcode)
				{
					case 'A':		ball1.dx = -3;	break;
					case 'D':		ball1.dx =  3;	break;
					case 'W':		ball1.dy = -3;	break;
					case 'S':		ball1.dy =  3;	break;
					case VK_LEFT:	ball2.dx = -3;	break;
					case VK_RIGHT:	ball2.dx =  3;	break;
					case VK_UP:		ball2.dy = -3;	break;
					case VK_DOWN:	ball2.dy =  3;	break;
				}
			}
			else if (m.message == WM_KEYUP && m.prevdown == true)
			{
				switch (m.vkcode)
				{
					case 'A':
					case 'D':		ball1.dx = 0;	break;
					case 'W':
					case 'S':		ball1.dy = 0;	break;
					case VK_LEFT:
					case VK_RIGHT:	ball2.dx = 0;	break;
					case VK_UP:
					case VK_DOWN:	ball2.dy = 0;	break;
				}
			}
		}

		// 计算小球位置
		ball1.x += ball1.dx;
		ball1.y += ball1.dy;
		ball2.x += ball2.dx;
		ball2.y += ball2.dy;

		// 绘制小球
		cleardevice();
		setfillcolor(WHITE);
		solidcircle(ball1.x, ball1.y, ball1.r);
		solidcircle(ball2.x, ball2.y, ball2.r);
		FlushBatchDraw();

		// 延时
		Sleep(25);
	}

	_getch();
	EndBatchDraw();
	closegraph();

	return 0;
}
ava
慢羊羊

2023-2-17

技术讨论社区