【问题标题】:Object movement with multiple arrow keys pressed in Delphi and openGL在 Delphi 和 openGL 中按下多个箭头键的对象移动
【发布时间】:2018-08-07 02:50:16
【问题描述】:

我在一个 delphi 程序中有一个 3d 对象,我正在尝试用箭头键控制他在 3d 空间中的移动。

第一个问题:对于单箭头键,移动工作正常 - 对象根据按下的键转身或前进,但它似乎不适用于多键按下。在UP键和左或右键按下的情况下,它会旋转但不前进。

第二个问题: UP 键移动被延迟了。按下 UP 键仅 0.5 秒后,对象开始向前移动。这是为什么呢?

代码如下:

function KeyPressed(nKey: Integer): Boolean;
begin
Result := (GetAsyncKeyState(nKey) and $8000) <> 0;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if keypressed(VK_LEFT) then
     if heroMove.angle < 360 then inc(heroMove.angle,5) else heroMove.angle:=0
else if keypressed(VK_RIGHT) then
     if heroMove.angle < 360 then inc(heroMove.angle,-5) else heroMove.angle:=0 else
if keypressed(VK_UP) then
begin
  heroMove.x:=heroMove.x+0.2*Sin(heroMove.angle*3.1415/180);
  heroMove.y:=heroMove.y+0.2*Cos(heroMove.angle*3.1415/180);
  pose:=1;
end;

if keypressed(VK_LEFT) and keypressed(VK_UP) then
begin
if heroMove.angle < 360 then inc(heroMove.angle,5) else heroMove.angle:=0;
  heroMove.x:=heroMove.x+0.2*Sin(heroMove.angle*3.1415/180);
  heroMove.y:=heroMove.y+0.2*Cos(heroMove.angle*3.1415/180);
  pose:=1;
end else
if keypressed(VK_RIGHT) and keypressed(VK_UP) then
begin
  if heroMove.angle < 360 then inc(heroMove.angle,-5) else heroMove.angle:=0;
  heroMove.x:=heroMove.x+0.2*Sin(heroMove.angle*3.1415/180);
  heroMove.y:=heroMove.y+0.2*Cos(heroMove.angle*3.1415/180);
  pose:=1;
end;

end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key=VK_UP then
pose:=0;
end;

附:参数“pose”只是控制对象的动画类型。

【问题讨论】:

    标签: delphi opengl 3d game-physics arrow-keys


    【解决方案1】:

    您需要停止使用事件驱动的编程方法。您需要切换到更传统的游戏编程风格。

    您想要运行一个游戏循环,为您的程序提供稳定的脉冲。此循环的每次迭代都检查键盘状态。为此使用GetAsyncKeyState。检查您感兴趣的每个键的状态。在您的游戏循环中,您还将推动对 OpenGL 画布的任何更新。

    我可以从您的更新中看到您已经在使用GetAsyncKeyState。但是当用于响应OnKeyDown 事件时,这真的没有多大意义。要么使用事件驱动的同步 I/O,要么轮询异步 I/O。我不明白您为什么要尝试混合这两种范式。

    你打电话给GetAsyncKeyState 的方式看起来不对。你应该这样写:

    function KeyPressed(nKey: Integer): Boolean;
    begin
      Result := GetAsyncKeyState(nKey) < 0;
    end;
    

    我还建议在主循环的每次迭代中调用GetAsyncKeyState 一次,并且只为每个键调用一次。将返回值保存到局部变量。这避免了在迭代开始时一个键被认为是关闭的情况,但随后同一键在迭代的某个稍后时间点处于打开状态。这是您需要通过异步 I/O 解决的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多