【问题标题】:Delphi7, make a shape jump when pressing Up keyDelphi7,按向上键时进行形状​​跳跃
【发布时间】:2013-05-08 16:30:18
【问题描述】:

我想在玩家按下UP键时进行形状​​跳跃,所以我能想到的最好的就是这个,但是我使用的方法很糟糕而且有问题:

(形状坐标:shape1.top:=432;)

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
case key of
vk_up: shape1.top:=shape1.top-40   //so that it jumps to 392
end; 
end;

现在这个计时器:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
timer1.interval:=300
if shape1.Top<400 then      //if shape1.top=392 < 400
begin
shape1.Top:=432;            //move back to 432
end;

end;

问题是玩家可以不断地按下 UP 键,这是我不想要的。我知道这种方法很糟糕,所以我希望你有比这更好的方法,如果你能与我分享,我将不胜感激。

【问题讨论】:

  • 您正在编写游戏。 VCL 几乎可以肯定是错误的库。您应该使用游戏库。这将有一个不断运行的循环,并且不会使用事件驱动的编程风格。您可能也使用了错误的语言。
  • @David:也许它不打算成为 GTA VI,所以如果你使用 DirectX 或 OpenGL,Delphi 会很好用。如果您不需要非常精美的图形,老式的 GDI 就可以了。
  • @AndreasRejbrand 与其说是图形,不如说是事件驱动并不是游戏编程的标准。游戏编程使用主游戏循环和异步键盘处理。我认为 Mason 为 Delphi 编写了一个游戏编程库。我可能会用 pygame 写一个游戏。

标签: delphi key shape


【解决方案1】:

这是一个在恒定力场(例如,靠近地球表面的重力场)中弹跳的球。侧壁和地板是弹跳表面。您可以使用箭头键添加额外的力量:

unit Unit5;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TRealVect = record
    X, Y: real;
  end;

const
  ZeroVect: TRealVect = (X: 0; Y: 0);

type
  TForm5 = class(TForm)
    Timer1: TTimer;
    procedure FormPaint(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    { Private declarations }
    function ACC: TRealVect;
  const
    RADIUS = 16;
    DAMPING = 0.8;
    DT = 0.2;
    GRAVITY: TRealVect = (X: 0; Y: 10);
  var
    FForce: TRealVect;
    FPos: TRealVect;
    FVel: TRealVect;
  public
    { Public declarations }
  end;

var
  Form5: TForm5;

implementation

{$R *.dfm}

function RealVect(X, Y: real): TRealVect;
begin
  result.X := X;
  result.Y := Y;
end;

function Add(A, B: TRealVect): TRealVect;
begin
  result.X := A.X + B.X;
  result.Y := A.Y + B.Y;
end;

function Scale(A: TRealVect; C: real): TRealVect;
begin
  result.X := C*A.X;
  result.Y := C*A.Y;
end;

function TForm5.ACC: TRealVect;
begin
  result := Add(GRAVITY, FForce);
end;

procedure TForm5.FormCreate(Sender: TObject);
begin
  FPos := RealVect(Width div 2, 10);
  FVel := RealVect(0, 0);
end;

procedure TForm5.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_UP:
      FForce := RealVect(0, -20);
    VK_DOWN:
      FForce := RealVect(0, 10);
    VK_RIGHT:
      FForce := RealVect(10, 0);
    VK_LEFT:
      FForce := RealVect(-10, 0);
  end;
end;

procedure TForm5.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  FForce := ZeroVect;
end;

procedure TForm5.FormPaint(Sender: TObject);
begin
  Canvas.Brush.Color := clRed;
  Canvas.Ellipse(round(FPos.X - RADIUS), round(FPos.Y - RADIUS),
    round(FPos.X + RADIUS), round(FPos.Y + RADIUS));
end;

procedure TForm5.Timer1Timer(Sender: TObject);
begin
  FVel := Add(FVel, Scale(ACC, DT));
  FPos := Add(FPos, Scale(FVel, DT));
  if FPos.Y + RADIUS >= ClientHeight then
  begin
    FVel.Y := -DAMPING*FVel.Y;
    FPos.Y := ClientHeight - RADIUS - 1;
  end;
  if FPos.X - RADIUS <= 0 then
  begin
    FVel.X := -DAMPING*FVel.X;
    FPos.X := RADIUS + 1;
  end;
  if FPos.X + RADIUS >= ClientWidth then
  begin
    FVel.X := -DAMPING*FVel.X;
    FPos.X := ClientWidth - RADIUS - 1;
  end;
  Invalidate;
end;

end.

将计时器的间隔设置为30,就像“通常”一样。

Compiled sample EXE

【讨论】:

  • 正向欧拉。你真的需要一个带有运算符重载的漂亮向量类。
  • @David:我有这样一个库。但是 IIRC,OP 正在使用 Delphi 7,其中运算符重载是不可能的。无论如何,这个答案只是对初学者来说是一个非常简单的练习,所以我不想把它吹得太大。
  • 如果你想制作游戏,不要在带有计时器的 vcl 表单周围推动形状。您将编写大量代码以产生微弱的效果。使用 pygame 之类的。如果它必须是 Delphi(对于游戏来说可能是一个糟糕的选择),那么至少使用一个游戏库。不要使用 vcl。
  • +1 表示太过分了。并不是说你真的需要 49k :)
  • @user2296565 有很多很棒的游戏库。 Delphi 不是制作游戏的坏选择。此外,GameMaker 是用 Delphi 编写的。我强烈建议您访问pascal game development site 并在那里提出更多问题。至于图书馆:我用过Asphyre,效果很好。
【解决方案2】:

如果玩家可以按住某个键并且 KeyDown 反复触发,则可以将其锁定。

首先,在表单上声明一个名为FKeyLock: set of byte 的字段。 (注意:如果您得到任何高于 255 的 Key 值,此技术将失败,但您可能处理的值不会那么高。)

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if key in FKeyLock then
    Exit;
  case key of
    vk_up:
    begin
      shape1.top:=shape1.top-40;   //so that it jumps to 392
      include(FKeyLock, vk_up);
    end;
  end;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   exclude(FKeyLock, key);
end;

【讨论】:

  • @user2296565:但这里没有花哨的弹跳!
  • @Andreas:是的。您的回答具有更酷的效果,但实际上并没有解决 OP 询问的确切问题。所以我想我会写这个。 :P
  • @Mason:是的,我承认我有点忘乎所以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-24
相关资源
最近更新 更多