You've already forked lazarus-ccr
iphonelazext: improve iArkanoid example, fixing ball bouncing bugs
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1141 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -15,7 +15,7 @@ unit gameengine;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Types, Classes, SysUtils;
|
Classes, SysUtils;
|
||||||
|
|
||||||
const
|
const
|
||||||
ballVelocity = 18;
|
ballVelocity = 18;
|
||||||
@ -43,7 +43,6 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure BoundsBack(const HitRect: TRect; var dx, dy: single);
|
procedure BoundsBack(const HitRect: TRect; var dx, dy: single);
|
||||||
procedure BallMove(var move: TGameItem; atime: single);
|
procedure BallMove(var move: TGameItem; atime: single);
|
||||||
procedure SetPaddleX(AValue: Integer);
|
|
||||||
procedure ResetPaddle;
|
procedure ResetPaddle;
|
||||||
public
|
public
|
||||||
bricks : array [0..99] of TBrick;
|
bricks : array [0..99] of TBrick;
|
||||||
@ -64,6 +63,21 @@ type
|
|||||||
property PaddleX: single read fPaddleX write SetPaddleX;
|
property PaddleX: single read fPaddleX write SetPaddleX;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
type
|
||||||
|
TMoveRecord = packed record
|
||||||
|
sx, sy : single;
|
||||||
|
dx, dy : single;
|
||||||
|
k : single; // y = kx + b
|
||||||
|
divk : single;
|
||||||
|
b : single;
|
||||||
|
end;
|
||||||
|
|
||||||
|
THitSide = (hs_LeftRight, hs_TopBottom);
|
||||||
|
THitSides = set of THitSide;
|
||||||
|
|
||||||
|
procedure InitMoveRecord(sx, sy, dx, dy: single; var r: TMoveRecord);
|
||||||
|
function HitRect(const r: TRect; const mr: TMoveRecord; var hitpoint: TPoint; var HitSides: THitSides): Boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ TArkanoid }
|
{ TArkanoid }
|
||||||
@ -81,7 +95,6 @@ begin
|
|||||||
fPaddleX := AValue;
|
fPaddleX := AValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// hacky test
|
|
||||||
procedure TArkanoid.BoundsBack(const HitRect: TRect; var dx, dy: single);
|
procedure TArkanoid.BoundsBack(const HitRect: TRect; var dx, dy: single);
|
||||||
var
|
var
|
||||||
my : Integer;
|
my : Integer;
|
||||||
@ -91,6 +104,92 @@ begin
|
|||||||
else dx := -dx;
|
else dx := -dx;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure InitMoveRecord(sx, sy, dx, dy: single; var r: TMoveRecord);
|
||||||
|
var
|
||||||
|
diff : single;
|
||||||
|
begin
|
||||||
|
r.sx:=sx;
|
||||||
|
r.sy:=sy;
|
||||||
|
r.dx:=dx;
|
||||||
|
r.dy:=dy;
|
||||||
|
diff:=dx-sx;
|
||||||
|
|
||||||
|
//todo:
|
||||||
|
if diff<>0 then begin
|
||||||
|
r.k:=(dy-sy) / diff;
|
||||||
|
if r.k<>0 then r.divk:=1/r.k
|
||||||
|
else r.divk:=0;
|
||||||
|
end else begin
|
||||||
|
r.k:=0;
|
||||||
|
r.divk:=0;
|
||||||
|
end;
|
||||||
|
r.b:=sy-sx*r.k;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InRange(p, r1,r2: Integer): Boolean; overload; inline;
|
||||||
|
begin
|
||||||
|
if r1<r2 then Result:=(p>=r1) and (p<r2)
|
||||||
|
else Result:=(p>=r2) and (p<r1)
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InRange(p: Integer; r1,r2: single): Boolean; overload; inline;
|
||||||
|
begin
|
||||||
|
if r1<r2 then Result:=(p>=r1) and (p<r2)
|
||||||
|
else Result:=(p>=r2) and (p<r1)
|
||||||
|
end;
|
||||||
|
|
||||||
|
function HitRect(const r: TRect; const mr: TMoveRecord; var hitpoint: TPoint; var HitSides: THitSides): Boolean;
|
||||||
|
var
|
||||||
|
c, ch : Integer;
|
||||||
|
hitside : Boolean;
|
||||||
|
hittop : Boolean;
|
||||||
|
begin
|
||||||
|
HitSides:=[];
|
||||||
|
|
||||||
|
with r, mr do begin
|
||||||
|
if sx<=dx then begin
|
||||||
|
c:=Left;
|
||||||
|
end else begin
|
||||||
|
c:=Right;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ch:=Round(k*c+b);
|
||||||
|
hitside:=inRange(c, sx, dx) and (ch >= Top) and (ch < Bottom);
|
||||||
|
if hitside then begin
|
||||||
|
hitpoint:=Point(c, ch);
|
||||||
|
Include(HitSides, hs_LeftRight)
|
||||||
|
end;
|
||||||
|
|
||||||
|
if sy<=dy then begin
|
||||||
|
c:=Top
|
||||||
|
end else begin
|
||||||
|
c:=Bottom;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if k <> 0 then
|
||||||
|
ch:=Round((c-b)/k)
|
||||||
|
else
|
||||||
|
ch:=Round(sx);
|
||||||
|
|
||||||
|
hittop:=inRange(c, sy, dy) and (ch>=Left) and (ch<Right);
|
||||||
|
if hittop then begin
|
||||||
|
hitpoint:=Point(ch, c);
|
||||||
|
Include(HitSides, hs_TopBottom)
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result:=hittop or hitside;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SqrLen(const p1, p2: TPoint): single;
|
||||||
|
var
|
||||||
|
x,y:single;
|
||||||
|
begin
|
||||||
|
x:=p1.x-p2.x;
|
||||||
|
y:=p1.y-p2.y;
|
||||||
|
Result:=x*x+y*y;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TArkanoid.BallMove(var move: TGameItem; atime: single);
|
procedure TArkanoid.BallMove(var move: TGameItem; atime: single);
|
||||||
var
|
var
|
||||||
cx, cy : single;
|
cx, cy : single;
|
||||||
@ -98,6 +197,14 @@ var
|
|||||||
i : Integer;
|
i : Integer;
|
||||||
|
|
||||||
t : single;
|
t : single;
|
||||||
|
hitidx : Integer;
|
||||||
|
hsides : THitSides;
|
||||||
|
hitsides : THitSides;
|
||||||
|
hlen : single ;
|
||||||
|
hitlen : single;
|
||||||
|
hpnt : TPoint;
|
||||||
|
hitpnt : TPoint;
|
||||||
|
mr : TMoveRecord;
|
||||||
begin
|
begin
|
||||||
with move do begin
|
with move do begin
|
||||||
if sticked then Exit;
|
if sticked then Exit;
|
||||||
@ -108,6 +215,8 @@ begin
|
|||||||
cy := 0;
|
cy := 0;
|
||||||
dy := -dy;
|
dy := -dy;
|
||||||
end;
|
end;
|
||||||
|
InitMoveRecord(x, y, cx, cy, mr);
|
||||||
|
|
||||||
|
|
||||||
if cx < 0 then begin
|
if cx < 0 then begin
|
||||||
cx := 0;
|
cx := 0;
|
||||||
@ -117,17 +226,32 @@ begin
|
|||||||
dx := -dx;
|
dx := -dx;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
p.x := Round(cx);
|
p.x := Round(x);
|
||||||
p.y := Round(cy);
|
p.y := Round(y);
|
||||||
|
|
||||||
for i := 0 to brickCount - 1 do begin
|
hitidx:=-1;
|
||||||
if (bricks[i].health > 0) and PtInRect(bricks[i].hitRect, p) then begin
|
hitlen:=0;
|
||||||
BoundsBack(bricks[i].bounds, dx, dy);
|
for i := 0 to brickCount - 1 do begin
|
||||||
bricks[i].flash:=2;
|
if (bricks[i].health > 0) and HitRect(bricks[i].bounds, mr, hpnt, hsides) then begin
|
||||||
dec(bricks[i].health);
|
hlen:=SqrLen(hpnt, p);
|
||||||
|
if (hitidx<0) or (hlen<hitlen) then begin
|
||||||
|
hitidx:=i;
|
||||||
|
hitlen:=hlen;
|
||||||
|
hitsides:=hsides;
|
||||||
|
hitpnt:=hpnt;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if hitidx>=0 then begin
|
||||||
|
if hs_TopBottom in hitsides then move.dy:=-move.dy;
|
||||||
|
if hs_LeftRight in hitsides then move.dx:=-move.dx;
|
||||||
|
bricks[hitidx].flash:=2;
|
||||||
|
cx:=hitpnt.x;
|
||||||
|
cy:=hitpnt.y;
|
||||||
|
dec(bricks[hitidx].health);
|
||||||
|
end;
|
||||||
|
|
||||||
if (cy >= PaddleY-5) and (cx >= PaddleX) and (cx <= PaddleX + PaddleW) and (dy>0) then begin
|
if (cy >= PaddleY-5) and (cx >= PaddleX) and (cx <= PaddleX + PaddleW) and (dy>0) then begin
|
||||||
t := (cx - PaddleX - PaddleW/2) / (PaddleW/2);
|
t := (cx - PaddleX - PaddleW/2) / (PaddleW/2);
|
||||||
|
|
||||||
@ -152,10 +276,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TArkanoid.SetPaddleX(AValue: Integer);
|
|
||||||
begin
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TArkanoid.ResetPaddle;
|
procedure TArkanoid.ResetPaddle;
|
||||||
var
|
var
|
||||||
@ -168,12 +288,12 @@ begin
|
|||||||
ballcount := 1;
|
ballcount := 1;
|
||||||
for i := 0 to ballcount - 1 do
|
for i := 0 to ballcount - 1 do
|
||||||
with Balls[i] do begin
|
with Balls[i] do begin
|
||||||
{x := random(height-40)+20;
|
|
||||||
y := random(width-40)+20;}
|
|
||||||
x := PaddleX+PaddleW/2;
|
x := PaddleX+PaddleW/2;
|
||||||
y := PaddleY-5;
|
y := PaddleY-5;
|
||||||
a := random*pi/4 + (pi/2 - pi/8);
|
//a := random*pi/4 + (pi/2 - pi/8);
|
||||||
if cos(a)*5 < 0.1 then a := a + pi/5;
|
//if cos(a)*5 < 0.1 then a := a + pi/5;
|
||||||
|
//a:=5*pi/4;
|
||||||
|
a:=3*pi/2;
|
||||||
dx := ballVelocity*cos(a);
|
dx := ballVelocity*cos(a);
|
||||||
dy := ballVelocity*sin(a);
|
dy := ballVelocity*sin(a);
|
||||||
sticked:=true;
|
sticked:=true;
|
||||||
|
Reference in New Issue
Block a user