CollLib 2.0 released

Archives Forums/BlitzPlus Programming/CollLib 2.0 released

Mahan(Posted 2009) [#1]
CollLib 2.0 runs on both BlitzPlus and Blitz3D and provides Lists, StringLists and StringHashList (a full HashMap).

This really expands the Blitz languages to a new level when it comes to management of massive amounts of Type-instances etc.

(Freeware for any use)

Release thread
http://blitzmax.com/Community/posts.php?topic=86730


Sauer(Posted 2009) [#2]
Is this lists like in Python?

Can you give an example of what this would do?


Mahan(Posted 2009) [#3]
What do you want an example of? This lib mainly provides 3 things: Lists, StringLists, and StringHashLists.

A copy&paste from the README.txt:
format_code('

__What's a List__?

Basically its a list of numbers.
Since all entities and objects in Blitz3D and BlitzPlus are numeric handles
this comes very handy though.

List is very fast both for indexed access aswell as modifications.

Check out the ListDemo.bb for an example.



__What's a StringList__?

This is a ordered list of strings.
Normally strings are in the order you added them, but there are functions
that that lets you insert/delete/swap positions inside the list.
Each string in the stringlist can also optionally have a corresponding
integer value, that can be used for Blitz3D or BlitzPlus handles.

You can also load/save text-files to/from a StringList with a single
command.

StringList is very fast both for indexed access aswell as modifications.

Check out the StringListDemo.bb for an example.



__What's a StringHashList__?

This is a lookup hashtable list/map. (if you got confused read on!)

Easily explained the StringHashList works like an ultra-fast dictionary
or phonebook. You give it a word or a name, and in (almost) no time
at all the StringHashMap returns to you the correct number.

From the example:
The name you look for is called the key. This is a string.
The number the dictionary returns is called the value. This is an integer.

The StringHashMap trades insertion-speed for very high lookup speed.

Check out the StringHashListDemo.bb for an example.

')

If you want to know more or have a specific question about functionality, just ask and I'll try to show a demo or something :-)


Mahan(Posted 2009) [#4]
I wrote an additional B+ demo here to demonstrate the use of separate lists:

(No nice cleanup, can add that upon request)

format_codebox('

; This is a demonstration (not a interactive game)


Type TGameSprite
Field img
Field x#
Field y#
Field xSpeed#
Field ySpeed#
End Type




Const GUY_SIZE = 32
Global goodGuys%
Global badGuys%
Global sWidth%
Global sHeight%


Function spriteFromHandle.TGameSprite(h%)
Return Object.TGameSprite(h)
End Function



; create a game guy
; Good are blue and bad are red
Function createGameDude%(good%=True)


Local oldBuffer=GraphicsBuffer() ; save to restore later
Local newImg = CreateImage(GUY_SIZE, GUY_SIZE) ; dudes image


SetBuffer(ImageBuffer(newImg))

If good Then
Color 0, 0, 255
Else
Color 255, 0, 0
EndIf

Oval(15, 15, GUY_SIZE/2, GUY_SIZE/2)

SetBuffer(oldBuffer)


Local newDude.TGameSprite = New TGameSprite
newDude\img = newImg
newDude\x = Rand(100, GraphicsWidth()-100)
newDude\y = Rand(100, GraphicsHeight()-100)
newDude\xSpeed = Rnd(-2.0, 2.0)
newDude\ySpeed = Rnd(-2.0, 2.0)

Return Handle(newDude)
End Function


Function init()

goodGuys=CreateList() ; ! Start the good guy list
; create some good guys and load the into their list
Local i
For i = 1 To 5
ListAdd(goodGuys, createGameDude())
Next

badGuys=CreateList() ; start the bad guys list
For i = 1 To 200
ListAdd(badGuys, createGameDude(False))
Next

sWidth = GraphicsWidth()
sHeight = GraphicsHeight()

End Function




Function updateGoodGuysKillBadGuys()


; if a good guy catch a badguy, he gets killed

Local survivors% = CreateList()

Local i, j
For i = 0 To ListCount(badGuys) -1
Local badGuySurvived%=True
Local currentBadGuy.TGameSprite = spriteFromHandle(ListGet(badGuys, i))

j = 0
While (badGuySurvived) And (j <= (ListCount(goodGuys) -1))
Local currentGoodGuy.TGameSprite = spriteFromHandle(ListGet(goodGuys, j))
If RectsOverlap(currentGoodGuy\x, currentGoodGuy\y, GUY_SIZE, GUY_SIZE, currentBadGuy\x, currentBadGuy\y, GUY_SIZE, GUY_SIZE)
;good guy hit a bad guy. Bad guy dies
Delete currentBadGuy
badGuySurvived = False
EndIf
j = j + 1
Wend

If badGuySurvived Then
ListAdd(survivors, Handle(currentBadGuy))
EndIf
Next

; replace badguys with the list of survivors.
FreeList(badGuys)
badGuys = survivors

End Function

Function drawSprites(spriteList%)

Local currSprite.TGameSprite
Local i
For i = 0 To ListCount(spriteList)-1
currSprite = spriteFromHandle(ListGet(spriteList, i))
DrawImage(currSprite\img, currSprite\x, currSprite\y)
Next

End Function

Function updateSprites(spriteList%)

Local currSprite.TGameSprite
Local i
For i = 0 To ListCount(spriteList)-1
currSprite = spriteFromHandle(ListGet(spriteList, i))

; if someone hit a wall revese the movement
If (currSprite\x < 0) Or ((currSprite\x + GUY_SIZE) > sWidth) Then currSprite\xSpeed = -currSprite\xSpeed
If (currSprite\y < 0) Or ((currSprite\y + GUY_SIZE) > sHeight) Then currSprite\ySpeed = -currSprite\ySpeed

currSprite\x = currSprite\x + currSprite\xSpeed
currSprite\y = currSprite\y + currSprite\ySpeed
Next
End Function

Function main()
SeedRnd (MilliSecs())

Graphics 800, 600, 0, 2

init()

While Not KeyDown(1)
Cls

updateSprites(goodGuys)
updateSprites(badGuys)

updateGoodGuysKillBadGuys()

drawSprites(goodGuys)
drawSprites(badGuys)

Flip 1
Wend

EndGraphics

End Function

main()


')


Sauer(Posted 2009) [#5]
Ah ok I understand better. So you can pop, push, insert, and remove entries?

Downloading now...

You are quickly becoming the MVP of BlitzPlus.


Mahan(Posted 2009) [#6]

Ah ok I understand better. So you can pop, push, insert, and remove entries?



To create a list use: mylist% = CreateList()
To remove a list use: FreeList(mylist)

With a list you typically just use ListAdd(list%, value%) to add values and then you use ListCount%(list) to check how many values you got and ListGet(list%, index%) to get any value at any time. (Note that index% is zero indexed)


If you want to push and pop like a stack you can do this:

format_code('
LIFO (last in first out) :
1) PUSH:
ListAdd(listHandle%, <value>)
2) POP:
<value>=ListGet(listHandle%, ListCount(listHandle%)-1)
ListDelete(listHandle%, ListCount(listHandle%)-1)

FIFO (First in first out):
1) PUSH:
ListAdd(listHandle%, <value>)
2) POP:
<value>=ListGet(listHandle%, 0)
ListDelete(listHandle%, 0)

')

edit: added some info


Mahan(Posted 2009) [#7]
@Sauer: If you downloaded this lib, be sure to download the new update, and use the new CollLib.decls and CollLib.dll.

I found and fixed a bug today in the StringHashList.


em22(Posted 2009) [#8]
Very nice, this will be very useful for when I'm going to try and do a fuzzy search!


Sauer(Posted 2009) [#9]
I'm currently using the map functionality of this lib in my current project. I was using a single image for the items in my game, but decided to switch to having different items for different images. Rather than edit my item structure to hold this information (which would have required me to edit every aspect of item management) I plan to use a map with the item name as a key and the image handle as the value.

Just thought you'd like to know what your lib is being used for :)


Mahan(Posted 2009) [#10]
Sounds like a good usage example. I'm happy if it simplifies programming in any way. :-)

I was doing something similar in a game I'm writing: This game features a tilemap and the tilemap has Tiles that are mapped to "BaseTiles". Basetiles are the ones holding the unique tile-images. i.e. several Tiles on the tilemap can map the same Basetile if their appearance is identical. I use the name of the images of the Basetiles in a map, to map the tiles to their correct basetiles, in the config files for the game.

(The reason for the Basetile-abstraction (instead of just an image-handle) is that basetiles can be configured with additional properties such as "walkable", "water" etc. so they need to carry with them more than just the tile-image)