hjahre Skrevet 4. november 2007 Del Skrevet 4. november 2007 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
Anbefalte innlegg
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 kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå