弹跳球赛

时间:2015-07-13 23:37:17

标签: delphi collision-detection

在学校项目上工作并需要一些帮助...我已经建立了一个游戏,旨在避免你的主球撞到每30秒产生的随机球。我的问题是随机球没有停留在框架内,我不确定我做错了什么。任何帮助将非常感激。谢谢

procedure TFrmGamePage.EnemyBall(shpEnemy: TShape);
  VAR
    bOutside, bAbove, bBelow, bFarLeft, bFarRight : Boolean;
    ixMove, iyMove, iyDirec{Negative = increase, Positive = decrease}, ixDirec{positive = increase, negative = decrease} : integer;
  begin

    bAbove := pnlArena.Height-shpEnemy.Top > pnlArena.Height;
    bBelow := pnlArena.Height < shpEnemy.Top;

    bFarLeft := pnlArena.Width-shpEnemy.Left > pnlArena.Width;
    bFarRight := pnlArena.Width < shpEnemy.Left;

    ixMove:=random(3)+1;
    iyMove:=random(3)+1;

    ixDirec:=1;
    iyDirec:=1;

      //Check if the shape is outside.
        if bAbove=true or bBelow=true or bFarLeft=true or bFarRight=true then
          Begin
            bOutside:=true;
          End
        Else
          begin
            bOutside:=False;
          end;
      // if shape is outside swop relavent direction
        if bOutside=true then
          Begin

              Begin
                if bAbove=true then
                  begin
                    iyDirec:=1;
                  end;
                if bBelow=true then
                  begin
                    iyDirec:=-1;
                  end;

                if bFarRight then
                  begin
                    ixDirec:=-1;
                  end;
                if bFarLeft then
                  begin
                    ixDirec:=1;
                  end;

              End;
          End;

      shpEnemy.Top := shpEnemy.Top + iyMove * iyDirec;
      shpEnemy.Left := shpEnemy.Left + ixMove * ixDirec;    // Change pos of enemy shapes

  end;

1 个答案:

答案 0 :(得分:0)

你犯了两个主要错误:

  1. 您没有正确计算负责改变球方向的条件(bAbovebBelow等)。
  2. 这里要知道的重要一点是球的位置是相对于它的父(在这种情况下是pnlArena)。用不同的词来解释:球对外界一无所知,pnlArena是球的整个世界。因此,如果您的窗口坐标系原点位于左上方,则pnlArena的最左侧等于0(pnlArena.Left = 0),最远的顶部也是0(pnlArena.Top = 0)。

    知道这一点,你现在可能猜到球会在shpEnemy.Left < 0时穿过它的世界的左边界。我不会详细介绍其他方向,尝试理解我提供的代码。

    1. 第二个错误更微妙。目前,您的shpEnemy不会在竞技场的墙壁上正确反弹。问题是shpEnemy不记得它的最后方向。你只需要在必要时改变方向,而不是每次都改变方向。
    2. 这是一个完整的例子:

      unit Unit144;
      
      interface
      
      uses
        Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
        Dialogs, StdCtrls, ExtCtrls;
      
      // Our shape needs to remeber its direction, otherwise it won't move correctly.
      type
        TBallShape = class(TShape)
        public
          xDirec, yDirec: Integer;
          constructor Create(AOwner: TComponent; AParent: TWinControl); reintroduce;
        end;
      
      
      type
        TForm144 = class(TForm)
          pnlArena: TPanel;
          Button1: TButton;
          procedure Button1Click(Sender: TObject);
          procedure FormCreate(Sender: TObject);
        private
          BallShape: TBallShape;
        public
          procedure EnemyBall(shpEnemy: TBallShape);
        end;
      
      var
        Form144: TForm144;
      
      implementation
      
      {$R *.dfm}
      
      { TForm144 }
      
      procedure TForm144.Button1Click(Sender: TObject);
      begin
        EnemyBall(BallShape);
      end;
      
      procedure TForm144.EnemyBall(shpEnemy: TBallShape);
       VAR
          bOutside, bAbove, bBelow, bFarLeft, bFarRight : Boolean;
          ixMove, iyMove : integer;
        begin
      
          ixMove:=random(3)+1;
          iyMove:=random(3)+1;
      
          bAbove := shpEnemy.Top < 0;
          bBelow := shpEnemy.Top + shpEnemy.Height >  pnlArena.Height;
      
          bFarLeft := shpEnemy.Left < 0;
          bFarRight := shpEnemy.Left + shpEnemy.Width >  pnlArena.Width;
      
            //Check if the shape is outside.
              if bAbove or bBelow or bFarLeft or bFarRight then
                Begin
                  bOutside:=true;
                End
              Else
                begin
                  bOutside:=False;
                end;
            // if shape is outside swop relavent direction
              if bOutside=true then
                Begin
                    Begin
                      if bAbove=true then
                        begin
                          shpEnemy.yDirec:=1;
                        end;
                      if bBelow=true then
                        begin
                          shpEnemy.yDirec:=-1;
                        end;
                      if bFarRight then
                        begin
                          shpEnemy.xDirec:=-1;
                        end;
                      if bFarLeft then
                        begin
                          shpEnemy.xDirec:=1;
                        end;
      
                    End;
                End;
      
            shpEnemy.Top := shpEnemy.Top + iyMove * shpEnemy.yDirec;
            shpEnemy.Left := shpEnemy.Left + ixMove * shpEnemy.xDirec;    // Change pos of enemy shapes
      end;
      
      procedure TForm144.FormCreate(Sender: TObject);
      begin
        Randomize;
        BallShape := TBallShape.Create(Self, pnlArena);
        BallShape.Shape := stCircle;
      end;
      
      { TBallShape }
      
      constructor TBallShape.Create(AOwner: TComponent; AParent: TWinControl);
      var
        LDirection: Integer;
      begin
        inherited Create(AOwner);
      
        Width := 20;
        Height := 20;
      
        // We chose random direction of our ball.
        Self.Parent := AParent;
        LDirection := Random(1);
        if LDirection = 0 then
          xDirec := - 1
        else
          xDirec := 1;
        LDirection := Random(1);
        if LDirection = 0 then
          yDirec := - 1
        else
          yDirec := 1;
        // We must place our ball somewhere on the parent.
        Left := Random(AParent.Width) - Self.Width;
        if Left < 0 then
          Left := 0;
        Top := Random(AParent.Height) - Self.Height;
        if Top < 0 then
          Top := 0;
      end;
      
      end.
      

      希望这有帮助。