12.09.2012, 09:17
|
Прохожий
|
|
Регистрация: 12.09.2012
Сообщения: 13
Репутация: 10
|
|
Арканоид home made
Помогите, пожалуйста, с проблемой, возникшей в процессе написания простого арканоида. Дело в том, что не правильно работает обработка столкновений шарика с блоками. Иногда шарик отскакивает правильно, а иногда пролетает сквозь блоки, подвешивая программу. Проверка столкновения происходит по 6 точкам (по двум слева - сверху и снизу спрайта, 2 сверху - слева и справа, 2 справа - сверху и снизу).
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, DXDraws, DXInput, DXClass, DXSprite, math;
type
TForm1 = class(TDXForm)
DXDraw1: TDXDraw;
DXSpriteEngine1: TDXSpriteEngine;
DXTimer1: TDXTimer;
DXImageList1: TDXImageList;
DXInput1: TDXInput;
procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
vector: integer;
map: array[0..9,0..9] of byte;
i,j,speed:byte;
implementation
{$R *.dfm}
type
TMapSprite = class(TImageSprite);
TBaseSprite = class(TImageSprite)
protected
procedure DoMove(MoveCount: Integer); override;
end;
TBallSprite = class(TImageSprite)
protected
procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
procedure DoMove(MoveCount: Integer); override;
end;
Procedure TBallSprite.DoMove(MoveCount: Integer);
Begin
inherited DoMove(MoveCount);
if y>form1.DXDraw1.SurfaceHeight-image.Height then //если шарик бьется о низ экрана, то прогирали
halt;
if x>form1.DXDraw1.SurfaceWidth-image.Width then //отражение от правой стенки экрана
if vector<=180 then
begin
vector:=180-vector;
x:=form1.DXDraw1.SurfaceWidth-image.Width+cos(degtorad(vector))*speed;
end else
begin
vector:=540-vector;
x:=form1.DXDraw1.SurfaceWidth-image.Width+cos(degtorad(vector))*speed;
end;
if y<0 then
begin //отражение от верха экрана
vector:=360-vector;
y:=-sin(degtorad(vector))*speed;
end;
if x<0 then //отражение от левой стенки экрана
if vector<=180 then
begin
vector:=180-vector;
x:=cos(degtorad(vector))*speed;
end else
begin
vector:=540-vector;
x:=cos(degtorad(vector))*speed;
end;
collision;
x:=x+cos(degtorad(vector))*speed; //перемещение
y:=y-sin(degtorad(vector))*speed; //шарика
end;
procedure TBallSprite.DoCollision(Sprite: TSprite; var Done: Boolean);
begin
if Sprite is TBaseSprite then //столкновение с базой
if isLeft in Form1.DXInput1.States then
begin
vector:=380-vector; {при движении базы к углу полета шарика добавляется 20 градусов в сторону движения базы}
y:=y-sin(degtorad(vector))*speed;
end else
if isRight in Form1.DXInput1.States then
begin
vector:=340-vector;
y:=y-sin(degtorad(vector))*speed;
end else
begin
vector:=360-vector;
y:=y-sin(degtorad(vector))*speed;
end;
if Sprite is TMapSprite then // проверка на столкновение шарика с блоком, если ДА, то идет проверка - с какой стороны
if (form1.DXdraw1.Surface.canvas.Pixels[round(x-1),round(y)]<>57536)or(form1.DXdraw1.Surface.canvas.Pixels[round(x-1),round(y+10)]<>57536) then
begin //если столкновение с левой стороны (57536 - цвет фона)
if vector<=180 then
begin
vector:=180-vector;
x:=x+cos(degtorad(vector))*speed;
end else
begin
vector:=540-vector;
x:=x+cos(degtorad(vector))*speed;
end;
end else
if (form1.DXdraw1.Surface.canvas.Pixels[round(x),round(y)-5]<>57536)or(form1.DXdraw1.Surface.canvas.Pixels[round(x)+10,round(y)-5]<>57536) then
begin // если столкновение сверху
vector:=360-vector;
y:=y-sin(degtorad(vector))*speed;
end else
if (form1.DXdraw1.Surface.canvas.Pixels[round(x)+15,round(y)]<>57536)or(form1.DXdraw1.Surface.canvas.Pixels[round(x)+15,round(y)+10]<>57536) then
begin //если столкновение справа
if vector<=180 then
begin
vector:=180-vector;
x:=x+cos(degtorad(vector))*speed;
end else
begin
vector:=540-vector;
x:=x+cos(degtorad(vector))*speed;
end;
end else
begin // если столкновение снизу
if vector<=180 then
begin
vector:=180-vector;
y:=y-sin(degtorad(vector))*speed;
end else
begin
vector:=360-vector;
y:=y-sin(degtorad(vector))*speed;
end;
end;
end;
Procedure TBaseSprite.DoMove(MoveCount: Integer);
Begin
inherited DoMove(MoveCount); //движение базы
if isLeft in Form1.DXInput1.States then x:=x-5; //влево
if isRight in Form1.DXInput1.States then x:=x+5; //вправо
if x>=form1.DXDraw1.SurfaceWidth-image.Width then //ограничение движения экраном
x:=form1.DXDraw1.SurfaceWidth-image.Width;
if x<=0 then
x:=0;
end;
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
if not DXDraw1.CanDraw then exit;
DXInput1.Update;
DXSpriteEngine1.Move(LagCount);
DXSpriteEngine1.Dead;
DXDraw1.Surface.Fill(0);
DXSpriteEngine1.Draw;
DXDraw1.Flip;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
speed:=1; //скорость шарика
randomize;
vector:=random(120)+30; //начальный угол полета шарика в градусах
for i:=0 to 9 do //задание массива где будут стоять блоки
for j:=0 to 9 do
map[i,j]:=1;
for i:=0 to 9 do //расстановка блоков согласно массива map
for j:=0 to 9 do
if map[i,j]=1 then
with TMapSprite.Create(Dxspriteengine1.Engine) do
begin
PixelCheck:=True;
Image:=form1.dxImageList1.Items.Find('Block');
x:=20+60*i;
y:=20+20*j;
Width:=Image.Width;
Height:=Image.Height;
end;
with TBaseSprite.Create(Dxspriteengine1.Engine) do //создание базы
begin
PixelCheck:=True;
Image:=form1.dxImageList1.Items.Find('Base');
x:=280;
y:=460;
Width:=Image.Width;
Height:=Image.Height;
end;
with TBallSprite.Create(Dxspriteengine1.Engine) do //создание шарика
begin
PixelCheck:=True;
Image:=form1.dxImageList1.Items.Find('Ball');
x:=320;
y:=400;
Width:=Image.Width+5;
Height:=Image.Height+5;
end;
with TBackgroundSprite.Create(DXSpriteEngine1.Engine) do // создание фона
begin
SetMapSize(1,1);
Image:=dxImageList1.Items.Find('bkg');
Z:=-2;
Tile:=True;
end;
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key=VK_ESCAPE then application.Terminate; //ESC - выход
end;
end.
Последний раз редактировалось Shpingalet, 14.09.2012 в 09:15.
|