Showing posts with label BB. Show all posts
Showing posts with label BB. Show all posts

Thursday, March 21, 2013

March update, getting older soon...

HFB game experiment and BB framework updated:

  • BB
    • TSpriteEngine, fixed some minor Z issues
    • New TSpriteEngine.SpritesAt() that returns the list of all sprites inside a rectangle 
    • New ISurface.GetRectangle()
    • New ILayer.GetSurfaceAt()
    • TSpriteEngine.Render() improved (list removed)
    • TAnimationSprite now updates the current sprite before testing collision.
    • TAnimationSprite.AnimationName now accepts an empty string (meaning that no animation is set)
    • gsPause removed from TGame state, now it is a variable
    • Fixed some bugs in the collision system
    • New ISprite.SetOnDie()
    • TSoundFactory now stores as cache IBuffer (not TSound)
    • TQueue<T> improved
    • TPolygons removed (didn't make sense)
    • Remove all TSprite method related to pointers for surface access since all of them can be done via GetSurface
    • TSuperSprite removed (never used/tested)
    • TInterfacedObjectEx = TObjectEx
    • Surface cache is now searched per index rather than hash
    • Buffers are finally sorted properly and selected automatically via hash (property SortBuffers, False by default)
    • Surface cache in sprite engine improved
    • TPolygonEx.GetHash() improved
    • New TPolygonEx.HasAlpha() (used for polygon hash so now we only have 0 or 1, not 0..255)
    • Render buffers now clean better the D3D stages
    • Some primitives were not filling properly the Z render buffer
    • Many memory leaks removed!, TAnimation,,TSpriteEngine ,TSpritePool ,TLayer ,TDummySprite ,TCollision ,TSurface2Poly ,TSurface ,TPolygons ,TLogHandler ,TSingleton ,TRenderBuffer ,TSoundFactory ,TEvents , TObjectPool, TConcurrentDictionary, TEvents

  • HBF
    • All game sprites are inherited from TElement 
    • New platform that can rotate around an axis
    • THero slope code refactored
    • New sprite var SLOPE
    • TGameSprite.IsDieAttribute() that accepts a cell
    • New prizes "Time", "Kill Them All" and "Immunity" (bitmaps, units and classes)
    • TGameSprite CreateItemAt() renamed to ConvertTile2Item()
    • When hero dies on top of a moving ball, the ball stops
    • THero.IsCollisionBottom() code cleaned
    • New element Rainbow (a bit silly just testing)
    • New enemy Titan
    • Hero now frees the samples (memory leak)
    • Some new samples (New metal sound, Titan uses it)
    • Some new music 
    • Removed some unused units 
    • Improved TSoundDispatcher, now all sounds are played via this class
    • Pause now pauses all playing sounds
    • Lava and water are not longer treated as solid so some enemies can move inside, like Titan
    • New SpriteFactory (file and class) (all sprite creation move to TSpriteFactory)
    • Pixel shader used then pausing enemies via pickup 
    • Hero cannot pickup coins when dying
    • Background does not longer move 
    • Background is now freed (memory leak)
    • SpriteEngineLayer2 is now freed (memory leak)
    • TSpriteFactory is now freed (memory leak)
    • Fixed a double free class with rotating platforms
    • New classesTNonGravityElement and TNonGravityEnemy, some enemies and elements inherit from them.
    • New enemy Chandelier 
    • All sprites now behave like hero (they interact with the environment since many functions were moved from THero to TGameSprite)
    • Ray more realistic (...)
    • Blob side collisions improved
    • Bomb side collisions improved
    • Titan side collisions improved
    • All tiles can now be "moving tapes" (before they were sprites)
    • When starting and finishing a level a fading effect is used 







Summer is coming soon!

Thursday, December 6, 2012

BB 1.3d last update of the year

These are the changes:

  • DX editor had some fixes
  • ColorKey detection improved (none, TopLeft, BottomRight, Specified)
  • TLayer.Render cleaned
  • BB compiles under XE3
  • New class TThreadPool (experiment)
  • Sprites can be paused via SetPaused()
Sources updated

Friday, April 20, 2012

New version of the framework BB 1.3b

 There is a new version of the BB framework, it is neede4d if you want to compile ChessKISS, HBF or any demo project.

What's new?

  • Colorkey issues fixed
  • Files handled correctly in maps when they are in different folders than main executable
  • Fixed really nasty collision bug via UpdateCollider()
  • Fixed some memory leaks
  • Swap the way KeyPress() is handled  in Input
  • Some bugs fixed
  • Some little improvements



Saturday, April 30, 2011

Bit functions

 I've been adding new functions to BB.Utils.Bits, some of this functions cannot be that fast with the funcionality from a high level language:


function TBit.PopFirstBitSet(var aValue: integer): integer;
//In = [EDX] Out = EAX
ASM
  PUSH ECX
  MOV ECX, [EDX]
  BSF EAX, ECX
  BTR [EDX], EAX
  POP ECX
END;
function TBit.LastBitSet(aValue: integer): integer;
//EDX
ASM
  BSR EAX, EDX
END;
function TBit.FirstBitSet(aValue: integer): integer;
//EDX
ASM
  BSF EAX, EDX
END;
function TBit.BitSetCount(aValue: integer): integer;
begin
  { TODO : optimize with array[0..65535] }
  result := 0;
  while aValue <> 0 do
  begin
    aValue := aValue and (aValue - 1);
    Inc(result);
  end;
end;
function TBit.PopLastBitSet(var aValue: integer): integer;
begin
  result := LastBitSet(aValue);
  _Clear(aValue, result);
end;

Monday, October 4, 2010

Using big files

In the BB.Utils.BigFile namespace, there is a class called TBigFile that helps you handling compressed files merged into one file, this is an example of use:


  f: TBigFile;
  wave, bmp: TStream;



  f := TBigFile.Create;
  f.Load('test.big');
  bmp := f.GetFile('test.bmp');
  wave := f.GetFile('pow.wav');

  spr := TSprite.Create;
  spr.LoadFile(bmp, TRGB.Blue.ToInt(32));

Almost all classes that have a load filename method have an overloaded method can be be called with a stream. Creating a big file is piece of cake, an example can be found in demos\utils\BigFile.dpr

Synchronizing, part 2

In namespace BB.Task you can find:
  • TTask,  helps you creating all kind of task chaining
  • TParallelForEach<T>, iterates throught a loop in a concurrent way taking into account CPU affinity.

Synchronizing, part 1

In BB.Sync there are a few useful classes:


  • TFuture<T>, calls a method within a thread and/or waits for the result. In TinyChess I use it to get the response from the search (here ProcessComputer is called over an infinite loop)
function TChessEngine.ProcessComputer: TMoveStatus;
var
  move: TMove;

begin
  if FTask = nil then
    FTask := TFuture<TMove>.Create(FSearch.Execute, tpHighest);

  if FTask.Available then
  begin
    move := FTask.Value;
    if move <> 0 then
    begin
      SendDataToProtocol(msMove, TMoveHelper.ToString(move));

      result := Play(move);
    end else
      result := msCheckmate;

    FreeAndNil(FTask);
  end else
    result := msNone;
end;
  • Many locks that implements the ILock interface (semaphores, mutex, SpinLocks, LockFree locks, critical sections, etc)
  • Extended thread (TThreadEx) with Java behaviour (threads can wait or awake other threads)
  • Interlocked functions (including 64 bit operations)

Sunday, October 3, 2010

BB, part 4, loading a 2d map


A very simple example, the important thing is how to create those maps, there is a silly tool called editor.exe in the demos that should help you.

uses
  BB.Input.Keys, BB.Screen.Types, BB.Screen.D3D, BB.Math, BB.Screen.Maps,
  BB.Colors;

procedure TForm1.FormActivate(Sender: TObject);
var
  m: TMap;
  gd: TGraphicDriver;

begin
  gd := TD3DDriver.Create;
  try
    gd.WindowHandle := WindowHandle;
    gd.Width := Width;
    gd.Height := Height;
    gd.BPP := 32;
    gd.ScreenFlags := [sfWait, sfClear];
    gd.Initialize;

    m := TMap.Create;
    m.FileName := 'test';
    m.LoadFile;
    m.Layers[0].SpeedX := 1;
    m.Layers[0].SpeedY := 1;
    m.Layers[0].X := 0;

    repeat
      gd.BeginRender;
      m.Layers[0].X := 1024 + (512 * Cos(gd.TotalFrames * Rad));
      m.Layers[0].Y := 512 + (256 * Sin(gd.TotalFrames * Rad));
      m.Render;

      gd.Rectangle(0, 16, gd.CurrentFPS, 16, TRGB.White);
      gd.EndRender;

      Application.ProcessMessages;
    until Inkey(VK_ESCAPE);

  finally
    gd.Free;
  end;

  Close;
end;




BB, part 3, creating a 3d object


uses
  BB.Screen,
  BB.Screen.D3D, BB.Input.Keys, BB.Screen.Types, BB.Math.Vector, BB.Colors,
  BB.Math.Matrix, BB.E3D.Scene,
  BB.E3D.Ents, BB.E3D.Camera, BB.Screen.Surfaces, BB.Types, BB.E3D.Lights,
  BB.E3D.Objects, BB.Screen.Interfaces,
  BB.Factory;

procedure TfrmMain.FormActivate(Sender: TObject);
var
  s: TScene;
  main: TEnt;
  c: TCamera;
  t: ISurface;
  l: TLight;
  f: TFactory;
  gd: IGraphicsDriver;

begin
  f := TFactory.Create(WindowHandle);
  gd := f.SetProvider(gpD3D);
  gd.Initialize(ClientWidth, ClientHeight, 32, [sfClear, sfWait]);
  gd.GetInfo.SetBackgroundColor(TRGB.Blue.ToInt(32));

  s := f.GetScene;

  // Texture
  t := s.NewSurface;
  t.Load('dirt.bmp');
  t.SetFilter(sfLinear);

  // Light
  l := s.NewLight;
  l.Range := 1024;
  l.Position := TVector.Create(0, -100, 0);
  l.Diffuse := TRGB.Orange;

  // 3D
  main := TEnt.Create;
  main.FileName := 'castalia.asc';
  main.LoadFile;
  main.Position := TVector.Create(0, 0, 0);
  main.Parent := s;
  main.RenderMethod := rmTexture;
  main.SmoothShading := True;
  main.SetTexture(t);
  main.Shade := [sSpecular, sDiffuse];
  s.Ents.Add(main);

  // Camera
  c := s.NewCamera;
  c.Position := TVector.Create(0, 0, -150);

  repeat
    main.Rotate(0.1, 0.3, 0.6);

    gd.BeginRender;

    s.BeginScene;
    s.Render;
    gd.GetPrimitives.Rectangle(0, 0, gd.GetInfo.GetCurrentFPS, 16, TRGB.White);
    s.EndScene;

    gd.EndRender;

  until InKey(VK_ESCAPE);

  Close;
end;


This time I've used a factory rather than the driver directly, is just an option, as the library grows, I always add new stuff to make my life easier

BB, part 2, creating a sprite

uses
  BB.Screen.D3D, BB.Screen.Types, BB.Input.Keys, BB.Colors, BB.Screen,
  BB.Screen.Surfaces, BB.Screen.Sprites, BB.Screen.Engines;


procedure TForm1.FormActivate(Sender: TObject);
var
  DD: TGraphicDriver;
  e: TSpriteEngine;
  demon, hero: TMaskedSprite;
  x, y: integer;

begin
  DD := TD3DDriver.Create;
  try
    DD.WindowHandle := WindowHandle;
    DD.Width := Width;
    DD.Height := Height;
    DD.BPP := 32;
    DD.ScreenFlags := [sfClear];
    DD.MaxFPS := 100;
    DD.Initialize;

    e := TSpriteEngine.Create;
    e.FileNames.Add('demon.bmp');
    e.FileNames.Add('fire.bmp');
    e.FileNames.Add('hero.bmp');
    e.LoadFile;

    demon := TMaskedSprite.Create;
    demon.Engine := e;
    demon.Masked := True;
    demon.AnimationName := 'demon';
    demon.GoCenter;
    demon.CollisionShape := csPrecise;

    hero := TMaskedSprite.Create;
    hero.Engine := e;
    hero.Masked := True;
    hero.AnimationName := 'hero';
    hero.GoCenterY;
    hero.CollisionShape := csPrecise;

    repeat
      DD.BackgroundColor := 0;

      if Inkey(VK_LEFT) then
        hero.x := hero.x - 1
      else if Inkey(VK_RIGHT) then
        hero.x := hero.x + 1;

      if Inkey(VK_UP) then
        hero.y := hero.y - 1
      else if Inkey(VK_DOWN) then
        hero.y := hero.y + 1;

      hero.Masked := True;
      demon.Masked := True;
      if hero.Collision(demon, x, y) then
        DD.BackgroundColor := TRGB.Blue.ToInt(32);

      hero.Masked := False;
      demon.Masked := False;
      if hero.Collision(demon, x, y) then
        DD.BackgroundColor := TRGB.Red.ToInt(32);

      DD.BeginRender;
      e.Render;
      DD.EndRender;

      Application.ProcessMessages;
    until Inkey(VK_ESCAPE);

  finally
    DD.Free;
  end;

  Close;
end;

end.



A TSpriteEngine is a container of sprites that also offers some loading methods, one of them is for every bitmap set create a .ini that configures the behaviour:

[cfg]
Method=Fix
Width=240
Height=144

[demon]
Frames=2,1,0
Type=PingPong
Cadency=10

[demon_mask]
Frames=5,4,3
Type=PingPong
Cadency=10




This way the engine knows what to do once you assign "demon" no the AnimationName property of the TSpriteAnimation class. The possible values for the [cfg] method are: 
  • Manual  (you set the values manually via Index option)
  • Circular (once the last frame is reached, next frame is the first one)
  • PingPong (once the last frame is reached, it goes back to the first one and again...)
  • Lineal (once the last frame is reached, nothing happens...)
  • LinealFree (once the last frame is reached, the sprite is freed)


BB, part 1

A minimal D3D:


uses
 BB.Input.Keys, BB.Screen.D3D, BB.Colors, BB.Screen.Types, BB.Screen;

procedure TForm1.FormActivate(Sender: TObject);
var
 gd: TGraphicDriver;

begin
 gd := TD3DDriver.Create;
 gd.WindowHandle := WindowHandle;
 gd.Width := Width;
 gd.Height := Height;
 gd.BPP := 32;
 gd.ScreenFlags := [sfClear, sfWait];
 gd.BackgroundColor := TRGB.Red.ToInt(32);
 gd.Initialize;

 repeat
  gd.BeginRender;
  try
     gd.Rectangle(0, 0, gd.CurrentFPS, 16, 1, TRGB.Green, TRGB.Yellow, False);
  finally
         gd.EndRender;
      end;
 until InKey(VK_ESCAPE);

 Close;
end;

end.