Recent

Author Topic: Simple utility function for Allegro users  (Read 6658 times)

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Simple utility function for Allegro users
« on: January 22, 2018, 01:11:27 pm »
Games tend to involve lots of images, sounds and fonts and keeping track of what needs to be destroyed when the program ends is a nuisance, especially during development when resources can be changed around frequently. I just came up with these two simple routines to help with this problem and they seem to work so I thought I'd share them.

Given that this is within scope...
Code: [Select]
bitmapList: array of ALLEGRO_BITMAPptr;

I can call addBitmap() whenever I want to load a bitmap and it gets added to the list to be destroyed by destroyBitmaps() so I don't have to remember to do it manually. Also, the array and routines can easily be changed to use the variant type so fonts, sounds etc could be stored in the same list - all that's needed is to check the actual type with vartype() in the destroy procedure and call the appropriate allegro routine.

Note: there's no error checking for existence of files etc as it stands!

Code: [Select]
    function addBitmap(fileName: string): ALLEGRO_BITMAPptr;
    var
temp: ALLEGRO_BITMAPptr;
len:         integer;
    begin
temp := al_load_bitmap(fileName);
len := length(bitmapList) + 1;
setlength(bitmapList, len);
bitMapList[len - 1] := temp;
addBitmap := temp;
    end;
   
    procedure destroyBitmaps();
    var
i: integer;
    begin
for i:= 0 to length(bitmapList) - 1 do
al_destroy_bitmap(bitMapList[i]);
    end;

Might help someone :D
« Last Edit: January 23, 2018, 02:38:15 pm by mrguzgog »

Paul_

  • Full Member
  • ***
  • Posts: 143
Re: Simple utility function for Allegro users
« Reply #1 on: January 22, 2018, 02:45:31 pm »
What if you want remove single item? :)

E.g. linked list is better than array in this case.

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: Simple utility function for Allegro users
« Reply #2 on: January 22, 2018, 03:20:10 pm »
Yes, the ability to remove a single item would need need a slightly different approach - a record with a 'tag' alongside the pointer to the bitmap might work and be easier than a linked list ;).

For my simple game and the comparatively huge amount of memory available these days I'm not interested in deleting individual resources (although those in the title/menu/options will get loaded and free'd via their own lists).

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: Simple utility function for Allegro users
« Reply #3 on: January 23, 2018, 01:51:36 pm »
Instead of use a global variable, I recommend you to use a more Object Oriented approach (even without use of CLASSes, as you'll see).  That way you'll be able to manage your bitmaps more easy and grouped (i.e. PlayerImages, Alien1Images, Alien2Images...).  Even loading images would be more easy.

Also, you can reproduce the same to manage sound samples.

For example:
Code: Pascal  [Select][+][-]
  1. TYPE
  2. (* Contains a list of bitmaps. *)
  3.   TBitmapList = RECORD
  4.     Bmp: ARRAY OF ALLEGRO_BITMAPptr;
  5.     Count: INTEGER;
  6.   END;
  7.  
  8.  
  9.  
  10. (* Finds an empty place. *)
  11.   FUNCTION FindEmptyBmp (VAR aList: TBitmapList): INTEGER;
  12.   VAR
  13.     Ndx: INTEGER;
  14.   BEGIN
  15.     IF Length (aList.Bmp) < 1 THEN
  16.     BEGIN
  17.       aList.Count := 0;
  18.       EXIT (-1)
  19.     END;
  20.     FOR Ndx := 0 TO (aList.Count - 1) DO
  21.       IF aList.Bmp[Ndx] = NIL THEN EXIT (Ndx);
  22.     FindEmptyBmp := -1
  23.   END;
  24.  
  25.  
  26.  
  27. (* Adds a new bitmap.  Returns index. *)
  28.   FUNCTION AddBmp (VAR aList: TBitmapList; aBmp: ALLEGRO_BITMAPptr): INTEGER;
  29.   VAR
  30.     MyNdx: INTEGER;
  31.   BEGIN
  32.   { Find an empty place. }
  33.     MyNdx := FindEmptyBmp (aList);
  34.     IF MyNdx < 0 THEN
  35.     BEGIN
  36.     { If there's no space reserve more space. }
  37.       IF aList.Count < 1 THEN
  38.       BEGIN
  39.         SetLength (aList.Bmp, 8);
  40.         FOR MyNdx := 0 TO 7 DO aList.Bmp[MyNdx] := NIL
  41.       END
  42.       ELSE IF Length (aList.Bmp) <= aList.Count THEN
  43.       BEGIN
  44.         SetLength (aList.Bmp, aList.Count * 2);  
  45.         FOR MyNdx := aList.Count TO HIGH (aList.Bmp) DO
  46.           aList.Bmp[MyNdx] := NIL
  47.       END;
  48.     { Where to put the new bitmap. }
  49.       MyNdx := aList.Count;
  50.  
  51.       INC (aList.Count)
  52.     END;
  53.     aList.Bmp[MyNdx] := aBmp;
  54.     AddBmp := MyNdx
  55.   END;
  56.  
  57.  
  58.  
  59. (* Removes (and destroys) a bitmap. *)
  60.   PROCEDURE DestroyBitmap (VAR aList: TBitmapList; CONST Ndx: INTEGER);
  61.   BEGIN
  62.   { Avoid go outside the list. }
  63.      IF (0 > Ndx) OR (Ndx >= aList.Count) THEN Exit;
  64.      IF aList.Bmp[Ndx] = NIL THEN Exit;
  65.   { Destroy. }
  66.      al_destroy_bitmap (aList.Bmp[Ndx]);
  67.      aList.Bmp[Ndx] := NIL
  68.   END;
  69.  
  70.  
  71.  
  72. (* Destroy all bitmaps. *)
  73.   PROCEDURE ClearBitmapList (VAR aList: TBitmapList);
  74.   VAR
  75.     Ndx: INTEGER;
  76.   BEGIN
  77.     FOR Ndx := 0 TO (aList.Count - 1) DO
  78.       IF aList.Bmp[Ndx] <> NIL THEN al_destroy_bitmap (aList.Bmp[Ndx]);
  79.     SetLength (aList.Bmp, 0);
  80.     aList.Count := 0
  81.   END;
  82.  

Finding and fixing flaws and bugs are left as exercise (I didn't test the code so I'm not sure if it is correct).

If you want to use CLASSes, you can still using the ARRAY approach, but you would use TList or TFPList or any of the generics version instead.

[edit] I've fixed some very obvious flaws.
« Last Edit: January 23, 2018, 02:00:07 pm by Ñuño_Martínez »
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

mrguzgog

  • Jr. Member
  • **
  • Posts: 71
Re: Simple utility function for Allegro users
« Reply #4 on: January 23, 2018, 03:10:56 pm »
I'm sure that would work but I was shooting for simplicity :D Your code would also require a bunch of integer variables or arrays or something to hold the indexes but as you say if you need finer control that's the way to go.

I'm not using a global 'bitMapList' BTW, it's declared in the implementation of the particular unit along with the variables holding the bitmap pointers, which seems the most logical place. Where would you define 'aList' in your example?

Thanks for the suggestions :D

Handoko

  • Hero Member
  • *****
  • Posts: 5122
  • My goal: build my own game engine using Lazarus
Re: Simple utility function for Allegro users
« Reply #5 on: January 23, 2018, 03:30:07 pm »
We need to find a balance between simplicity and maintainability. Code written using OOP paradigm is usually easier to maintain and improved but OOP has it's disadvantage too.

A quote from Wikipedia:
Quote
The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.

Don't get me wrong, I like and often use OOP. But for simple cases and prototyping I prefer the way mrguzgog did. Only after the that function grows more complex and needs to be separated to be maintain separately, I will rewrite it to OOP style.

My 2 cents.

Paul_

  • Full Member
  • ***
  • Posts: 143
Re: Simple utility function for Allegro users
« Reply #6 on: January 23, 2018, 06:19:43 pm »
I'm not sure if generics like TList are best way how make games. This is often big failure of engines like Unity or Unreal which leads into poor performance.
For example author of Rimworld have whole game loop + objects outside Unity framework, it was too slow.

Handoko

  • Hero Member
  • *****
  • Posts: 5122
  • My goal: build my own game engine using Lazarus
Re: Simple utility function for Allegro users
« Reply #7 on: January 23, 2018, 07:24:11 pm »
So that is why programming is an art. We need to consider between simplicity vs extensibility, readability vs performance, and many more.

Ñuño_Martínez

  • Hero Member
  • *****
  • Posts: 1186
    • Burdjia
Re: Simple utility function for Allegro users
« Reply #8 on: January 26, 2018, 01:40:27 pm »
I'm not using a global 'bitMapList' BTW, it's declared in the implementation of the particular unit along with the variables holding the bitmap pointers, which seems the most logical place. Where would you define 'aList' in your example?
It is a parameter.  Define the actual object it wherever you need it, and so much objects you need.
Are you interested in game programming? Join the Pascal Game Development community!
Also visit the Game Development Portal

 

TinyPortal © 2005-2018