Unit ExplosionClass

The explosion object - particles radiating at different speeds

Declaration of routine with many parameters

Procedure bufferSprite:
procedure bufferSprite(sprite : PSprite; x, y, z, scale, r, g, b, a : real);

The unit

unit ExplosionClass;
{
   Copyright (c) 2011 Max Foster

   http://creativecommons.org/licenses/by/3.0/
}
{$mode objfpc}{$H+}

interface

uses GameActorClass;

const
  //The directions of each particle in the explosion
  VECTORS : array[0 .. 13] of array[0 .. 2] of integer =
    ((-1, 1, 1), (-1, 1, -1), (-1, -1, -1), (-1, -1, 1), (1, 1, 1), (1, 1, -1),
    (1, -1, -1), (1, -1, 1), (-1, 0, 0), (1, 0, 0), (0, -1, 0), (0, 1, 0), (0, 0, -1),
    (0, 0, 1));
  //Avoiding unnecessary calculation
  VECTOR_LENGTH_TAKE_ONE = 13;
  VECTOR_LENGTH_TIMES_THREE_TAKE_ONE = 41;

type
  particle = record
    x, y, z, xSpeed, ySpeed, zSpeed, size : real;
  end;

  PExplosion = ^TExplosion;
  TExplosion = object(TGameActor)
  private
    time : real;
    particles : array[0 .. VECTOR_LENGTH_TIMES_THREE_TAKE_ONE] of particle;
  public
    constructor create(destX, destY, destZ : real; newSize : real = 1.0);
    destructor destroy; virtual;
    procedure update; virtual;
    procedure pausedDraw; virtual;
  end;

procedure initExplosions;
procedure freeExplosions;

implementation

uses Display, GraphicalAssetClasses, ShaderClass, SoundClass, GlobalGameVariables;

procedure initExplosions;
begin
  explosionSound := new(PSound, create('explosion', 'assets/sounds/bomb-02.ogg'));
end;

procedure freeExplosions;
begin
  dispose(explosionSound, destroy);
end;

constructor TExplosion.create(destX, destY, destZ : real; newSize : real = 1.0);
var
  i, j, count : integer;
  volume, xDist, zDist, dist : real;
begin
  dieFlag := false;
  attributes := [];
  TGameObject.create('explosion', destX, destY, destZ, PModel(nil));
  count := 0;
  for i := 0 to VECTOR_LENGTH_TAKE_ONE do
    begin
      for j := 1 to 3 do
        begin
          with particles[count] do
            begin
              x := x_;
              y := y_;
              z := z_;
              //Set the speed in each axis for each particle from the direction vectors.
              //For large explosions, each particle needs to travel quicker. The smaller the
              //particle in an explosion, the quicker it moves
              xSpeed := VECTORS[i][0] * j * newSize;
              ySpeed := VECTORS[i][1] * j * newSize;
              zSpeed := VECTORS[i][2] * j * newSize;
              size := (4 / j) * newSize;
            end;
          count += 1;
        end;
    end;

  //Play a sound if we can hear it
  if (cat <> nil) then
    begin
      xDist := x_ - cat^.x;
      zDist := z_ - cat^.z;
      dist := (xDist * xDist) + (zDist * zDist);
      if (dist > MAX_HEARING_DISTANCE_SQAURED) then
        exit;
      dist := sqrt(dist);

      volume := round(20 * (100 / dist));
      if (volume > 30) then
        volume := 30;
      explosionSound^.play(round(volume * soundEffectsVolume));
    end;
end;

destructor TExplosion.destroy;
begin
  TGameObject.destroy;
end;

procedure TExplosion.update;
var
  i : integer;
begin
  time += compensation;
  if (time > 40) then
    dieFlag := true;

  //Move the particles and draw them
  for i := 0 to VECTOR_LENGTH_TIMES_THREE_TAKE_ONE do
    begin
      particles[i].x += compensation * particles[i].xSpeed;
      particles[i].y += compensation * particles[i].ySpeed;
      particles[i].z += compensation * particles[i].zSpeed;
      particles[i].xSpeed -= compensation * 0.02 * particles[i].xSpeed;
      particles[i].ySpeed -= compensation * 0.02 * particles[i].ySpeed;
      particles[i].zSpeed -= compensation * 0.02 * particles[i].zSpeed;
      particles[i].size -= compensation * 0.07 * particles[i].size;
      if (visible_) then
        bufferSprite(smoke, particles[i].x, particles[i].y, particles[i].z,
                     particles[i].size / 5, 1.0, 1.0, 1.0, 1.0);
    end;
end;

procedure TExplosion.pausedDraw;
var
  i : integer;
begin
  //Just draw the particles without updating them
  for i := 0 to VECTOR_LENGTH_TIMES_THREE_TAKE_ONE do
    bufferSprite(smoke, particles[i].x,
                 particles[i].y, particles[i].z, particles[i].size / 5, 1.0, 1.0, 1.0, 1.0);
end;

end.
Programming - a skill for life!

by Max Foster: L6 Age ~17