Gå til innhold

Mitt partikkelsystem, hva syns folket her?


Anbefalte innlegg

Hei, denne helga har jeg satt meg ned og prøvd å lage et partikkelsystem i Delphi. Lett skulle det visst ikke være, men jeg har fått til noe som har gitt greie resultater. Så det hadde vært fint å få litt tilbakemelding på hvordan det er ;)

 

Koden til Partikkelsystemet (ikke ferdig kode):

 

unit uParticleSystem;

interface
uses
 Graphics, Dialogs, SysUtils, Math, Types;

type
 TExPoint = record
   X,
   Y: Extended;
 end;

 TDeflectorType = (dfDeflector, dfForce);
 TDeflectorAction = (daNone, daExplode, daReflect, daXAxis, daYAxis);

 Degrees = Extended;

 TParticle = class
 protected
   { Protected declarations }
 private
   { Private declarations }
   SpeedX,
   SpeedY: Extended;
 public
   { Public declarations }
   Position: TPoint;
   Angle: Degrees;
   Life: integer;
   Speed: extended;
   DeflectorReady: Boolean;

   constructor Create(aX, aY: integer; aSpeed:extended; aAngle: Degrees; aLife: Integer);
   destructor Destroy;

   procedure SetSpeed(aSpeed: extended);
   function GetSpeed: TExPoint;
   procedure Move;
   function IsLiving: Boolean;
 end;

 TDeflector = class
 private
   { Private declarations }
   DeflectorType: TDeflectorType;
   DeflectorAction: TDeflectorAction;
   Start, Stopp: TPoint;
 public
   { Public declaratins }
   Intensity: Extended;
   Active: boolean;
   constructor Create(aStart, aStopp: TPoint; aType: TDeflectorType; aAction: TDeflectorAction);
 end;

 TParticleSystem = class
 protected
   { Protected declarations }
 private
   { Private declarations }
   Position: TPoint;
   Particles: array of TParticle;
   Deflectors: array of TDeflector;
   //ParticleSystems: array of TParticleSystem;

   Speed, SpeedVar,
   Angle, AngleVar,    
   Life, LifeVar: Integer;
 public
   { Public declarations }
   ParticleImage: TBitmap;
   constructor Create(X, Y: integer);
   destructor Destroy;

   procedure Initialize;

   procedure SetPosition(X, Y: integer);
   procedure SetParticleSpeed(ParticleSpeed, SpeedVariation: integer);
   procedure SetParticleAngle(ParticleAngle, AngleVariation: integer);
   procedure SetParticleLife(ParticleLife, LifeVariation: integer);

   function AddParticle:TParticle;
   procedure MoveParticles;
   procedure AddDeflector(Deflector: TDeflector);
   //function AddParticleSystem(X, Y: integer):TParticleSystem;
   procedure Draw(Canvas: TCanvas);
 end;

implementation

procedure FreeAndNil(var Obj);
var
 Temp: TObject;
begin
 Temp := TObject(Obj);
 Pointer(Obj) := nil;
 Temp.Free;
end;

function RandomRange(const AFrom, ATo: Integer): Integer;
begin
 if AFrom > ATo then
   Result := Random(AFrom - ATo) + ATo
 else
   Result := Random(ATo - AFrom) + AFrom;
end;

constructor TParticle.Create(aX, aY: integer; aSpeed:extended; aAngle: Degrees; aLife: Integer);
begin
 inherited Create;

 Position.X := aX;
 Position.Y := aY;

 Angle := aAngle;

 SetSpeed(aSpeed);

 Life := aLife;
 DeflectorReady := true;
end;

destructor TParticle.Destroy;
begin
 inherited Destroy;
end;

procedure TParticle.SetSpeed(aSpeed: extended);
begin
 SpeedY := Sin(-Angle*(Pi/180))*aSpeed;
 SpeedX := Cos(Angle*(Pi/180))*aSpeed;

 Speed := aSpeed;
end;

function TParticle.GetSpeed: TExPoint;
begin
 Result.X := SpeedX;
 Result.Y := SpeedY;
end;

procedure TParticle.Move;
begin
 Position.X := Round(Position.X + SpeedX);
 Position.Y := Round(Position.Y + SpeedY);

 //if IsLiving then
   Dec(Life);
end;

function TParticle.IsLiving: boolean;
begin
 Result := Life <> 0;
end;

constructor TDeflector.Create(aStart, aStopp: TPoint; aType: TDeflectorType; aAction: TDeflectorAction);
begin
 inherited Create;
 DeflectorType := aType;
 DeflectorAction := aAction;

 Start := aStart;
 Stopp := aStopp;

 Intensity := -9.81;
 Active := True;
end;

constructor TParticleSystem.Create(X, Y: integer);
begin
 inherited Create;

 SetPosition(X, Y);

 Initialize;
end;

destructor TParticleSystem.Destroy;
var
 i: integer;
begin
 FreeAndNil(ParticleImage);

 for i := Low(Particles) to High(Particles) do
   FreeAndNil(Particles[i]);

 for i := Low(Deflectors) to High(Deflectors) do
   FreeAndNil(Deflectors[i]);

 {for i := Low(ParticleSystems) to High(ParticleSystems) do
   FreeAndNil(ParticleSystems[i]);}

 SetLength(Particles, 0);
 SetLength(Deflectors, 0);
 //SetLength(ParticleSystems, 0);

 inherited Destroy;
end;

procedure TParticleSystem.SetPosition(X, Y: integer);
begin
 Position.X := X;
 Position.Y := Y;
end;

procedure TParticleSystem.SetParticleSpeed(ParticleSpeed, SpeedVariation: integer);
begin
 Speed := ParticleSpeed;
 SpeedVar := SpeedVariation;
end;

procedure TParticleSystem.SetParticleAngle(ParticleAngle, AngleVariation: integer);
begin
 Angle := ParticleAngle;
 AngleVar := AngleVariation;
end;

procedure TParticleSystem.SetParticleLife(ParticleLife, LifeVariation: integer);
begin
 Life := ParticleLife;
 LifeVar := LifeVariation;
end;

procedure TParticleSystem.Initialize;
var
 i: integer;
begin
 SetParticleSpeed(10, 7);

 SetParticleAngle(80, 30);

 SetParticleLife(200, 100);

 for i := Low(Particles) to High(Particles) do
   FreeAndNil(Particles[i]);

 for i := Low(Deflectors) to High(Deflectors) do
   FreeAndNil(Deflectors[i]);

 {for i := Low(ParticleSystems) to High(ParticleSystems) do
   FreeAndNil(ParticleSystems[i]);}

 SetLength(Particles, 0);
 SetLength(Deflectors, 0);
 //SetLength(ParticleSystems, 0);
end;

function TParticleSystem.AddParticle:TParticle;
var
 aAngle, aLife, aSpeed: integer;
begin
 SetLength(Particles, Length(Particles) +1);

 aAngle := RandomRange(Angle - AngleVar, Angle + AngleVar);

 aSpeed := RandomRange(Speed - SpeedVar, Speed + SpeedVar);

 aLife := RandomRange(Life - LifeVar, Life + LifeVar);

 Randomize;

 Particles[High(Particles)] := TParticle.Create(Position.X, Position.Y, aSpeed, aAngle, aLife);
 result := Particles[High(Particles)];
end;

procedure TParticleSystem.MoveParticles;
var
 i, j, k, PHigh, Plow: integer;
 DefAngle: integer;
 P: TParticle;
 Rct: TRect;
begin
 PHigh := High(Particles);
 PLow := Low(Particles);

 for i := PLow to PHigh do
   begin
     for j := Low(Deflectors) to High(Deflectors) do
       case Deflectors[j].DeflectorType of
         dfForce:      case Deflectors[j].DeflectorAction of
                         daYAxis: Particles[i].SpeedY := Particles[i].SpeedY - Deflectors[j].Intensity;
                         daXAxis: Particles[i].SpeedX := Particles[i].SpeedX - Deflectors[j].Intensity;
                       end;

         dfDeflector:  case Deflectors[j].DeflectorAction of
                         daExplode:  begin
                                       Rct.Top := Deflectors[j].Start.Y;
                                       Rct.Left := Deflectors[j].Start.X;
                                       Rct.Right := Deflectors[j].Stopp.X;
                                       Rct.Bottom := Deflectors[j].Stopp.Y;

                                       if PtInRect(Rct, Particles[i].Position) and Deflectors[j].Active and
                                       Particles[i].DeflectorReady then
                                         begin
                                           //Deflectors[j].Active := False;
                                           Particles[i].DeflectorReady := false;
                                           for k := 0 to 30 do
                                             begin
                                               P := AddParticle;
                                               P.Position := Particles[i].Position;
                                               P.Angle := RandomRange(90 - 30, 90 + 30);
                                               P.Speed := RandomRange(5- 2, 5 + 2);
                                               P.Life := RandomRange(40 - 20, 40 + 20);
                                               P.SetSpeed(P.Speed);
                                               P.DeflectorReady := False;
                                             end;

                                           Particles[i].Life := 0;
                                         end;
                                     end;

                         daReflect:  begin
                                     end;
                       end;
       end;

     if Particles[i].IsLiving then
       Particles[i].Move;
   end;
end;

procedure TParticleSystem.AddDeflector(Deflector: TDeflector);
begin
 SetLength(Deflectors, Length(Deflectors) +1);

 Deflectors[High(Deflectors)] := Deflector;
end;

{function TParticleSystem.AddParticleSystem(X, Y: integer): TParticleSystem;
begin
 SetLength(ParticleSystems, Length(ParticleSystems) +1);

 ParticleSystems[High(ParticleSystems)] := TParticleSystem.Create(X, Y);
 ParticleSystems[High(ParticleSystems)].ParticleImage := ParticleImage;

 Result := ParticleSystems[High(ParticleSystems)];
end;}

procedure TParticleSystem.Draw(Canvas: TCanvas);
var
 i, x, y: integer;
begin
 for i := Low(Particles) to High(Particles) do
   begin
     x := Particles[i].Position.X - (ParticleImage.Width div 2);
     y := Particles[i].Position.Y - (ParticleImage.Height div 2);

     if Particles[i].IsLiving then
       Canvas.Draw(x, y, ParticleImage);
   end;

{ for i := Low(ParticleSystems) to High(ParticleSystems) do
   ParticleSystems[i].Draw(Canvas);}
end;

end.

 

 

Litt eksempelkode:

 

unit uMain;

interface

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

type
 TForm1 = class(TForm)
   Timer1: TTimer;
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormPaint(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
   procedure FormKeyUp(Sender: TObject; var Key: Word;
     Shift: TShiftState);
 private
   { Private declarations }
   ParticleSystem: TParticleSystem;
   ParticleImage: TBitmap;
   procedure InitializeParticleSystem;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.InitializeParticleSystem;
var
 i, ParticleNumber: integer;
 Deflector: TDeflector;
 Pnt1, Pnt2: TPoint;
begin
 ParticleSystem.Initialize;

 ParticleNumber := 50;

 ParticleImage := TBitmap.Create;
 ParticleImage.Width := 10;
 ParticleImage.Height := 10;
 ParticleImage.Canvas.Brush.Color := clYellow;
 ParticleImage.Canvas.Pen.Width := 2;
 ParticleImage.Canvas.Pen.Color := clBlack;
 ParticleImage.Canvas.Ellipse(0, 0, ParticleImage.Width, ParticleImage.Height);

 ParticleImage.TransparentMode := tmAuto;
 ParticleImage.TransparentColor := ParticleImage.Canvas.Pixels[0, 0];
 ParticleImage.Transparent := True;

 ParticleSystem.ParticleImage := ParticleImage;

 for i := 0 to ParticleNumber -1 do
   ParticleSystem.AddParticle;

 Pnt1.X := 0;
 Pnt1.Y := 0;
 Pnt2.X := 2;
 Pnt2.Y := 10;
 Deflector := TDeflector.Create(Pnt1, Pnt2, dfForce, daYAxis);
 Deflector.Intensity := -0.15;
 ParticleSystem.AddDeflector(Deflector);

 Pnt1.X := 0;
 Pnt1.Y := 400;
 Pnt2.X := Form1.ClientWidth;
 Pnt2.Y := 500;

 Deflector := TDeflector.Create(Pnt1, Pnt2, dfDeflector, daExplode);
 Deflector.Intensity := 1.2;
 ParticleSystem.AddDeflector(Deflector);
 //Deflector := nil;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Form1.DoubleBuffered := true;

 ParticleSystem := TParticleSystem.Create(Form1.ClientWidth div 2, Form1.ClientHeight div 2);

 InitializeParticleSystem;
 //Timer1.Enabled := true;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 FreeAndNil(ParticleSystem);
 FreeAndNil(ParticleImage);  
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
 Canvas.Brush.Color := clBlack;
 Canvas.FillRect(Canvas.ClipRect);

 ParticleSystem.Draw(Canvas);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 ParticleSystem.MoveParticles;
 Form1.Paint;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
 Shift: TShiftState);
begin
 case Key of
   VK_RETURN:  Timer1.Enabled := not Timer1.Enabled;
   VK_ESCAPE:  begin
                 Timer1.Enabled := false;
                 InitializeParticleSystem;
               end;
 end;
end;

end.

 

 

På forhånd takk for alle svar :)

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...