Garbage Collection

BlitzMax Forums/BlitzMax Programming/Garbage Collection

Cruis.In(Posted 2013) [#1]
Hey guys, I been wondering, what happens if you just rely on Bmax to do garbage collection, can you live without an object pool?

Let's take 2d space combat, where multiple objects, torpedoes and lasers are being created, and killed based on impact or time, could this cause a problem?


tonyg(Posted 2013) [#2]
Bmax is OK at Garbage Collection for many games.

There was a great discussion on Object Pooling if you create/destroy LOTS of objects


Richard Betson(Posted 2013) [#3]
Let's take 2d space combat

I am doing just that writing a 2D space combat game. The technique I used was to use arrays for bullets. I have a base class for ships and a base weapons class that has an array field for the bullets/ordinance. So all I have to do is access the weapon object for a ship and search through or modify the array for bullets/ordinance. It's proved to be a fast method for me and I'm looking at support 500-1000 clients per server in my MMO game.


Cruis.In(Posted 2013) [#4]
Hi Richard, I've been following phoenix a while. :)

I programmed VOD from scratch while learning to program, so needless to say there are probably many things which I've done terribly. I use different lists to hold the enemy bullets from the players, should I just use one?

So if there are 10 enemies, all of their bullets are going to one central enemy list. Is that ok?

Hi Tony! Thanks for the link.

Also would using an array speed it up?

-J


Richard Betson(Posted 2013) [#5]
I use different lists to hold the enemy bullets from the players, should I just use one?


Not necessarily. If it's not causing a problem then I would leave well enough alone.;) There is nothing wrong with having a bunch of lists, just continually adding and removing objects from the list 'can' slow things down.

Really the problem arises when creating and destroying objects in the thousands. I need to support thousands of bullet objects in a given map at any given time aside from hundreds of player objects. I've found that creating a bullet class and then including an array to hold the bullet data is much faster as I can search the array quickly retrieve a bullets position or mark bullets/ordinance as live or dead. This way I can have a bullet object with all of it's properties available and also use those properties with an array of bullets that holds position, velocity, TTL and other data. It works very well this way and is fast.

In VOD you do not have the huge overhead I have, so you are probably good to go. :)

- Rich -


Cruis.In(Posted 2013) [#6]
Hi Richard, yeah pretty much. Although I've detected a potential issue with it.

For Local L:tLaser = EachIn Tlaser.ELList 'Enemy Lasers
	For Local E:Tenemyship= EachIn ShipMasterList  'All Enemyships

		If E.ShipCLass = "Frigate" Or E.RaceID = "Civilian" 'Shipclass check
			If E.RaceID <> L.RaceID 'Not the same race 
	                        'if within this small 'zone' to the target
				If L.X - E.X < 100 And L.X - E.X > -100 And L.Y - E.Y < 100 And L.Y - E.Y > -100
	
					If E.Shield_Strength > 1
						If ImagesCollide2(L.Image,  L.offsetX, L.OffsetY, L.FRAME , L.Angle, viewfactor,viewfactor, E.Image, ship.x + ( (E.x - ship.x) * viewfactor), ship.y + ( (E.y - ship.y) * viewfactor), 0, E.Angle, viewfactor,viewfactor)
							L.Die()
							TimeShieldHit = current_time
							
							'Shield Impact Sound
							If current_time - TimeShieldHit > ShieldHitSoundDelay
								PlaySound(shieldHit)
								TimeShieldHit = current_time
							End If
							
							E.Shield_Strength :- L.WEAPONDAMAGE
							DoShieldHit(L.x, L.y) ' shield effect
							TshieldHit.Create(L.X, L.Y)						 				
						End If 
					End If


Ok so initially when using imagescollide if a lot of objects were on screen and I didn't have some other kind of distance/or zone check, then the bullet object would be checking against all objects on the screen.

So this line:
  'if within this small 'zone' to the target
				If L.X - E.X < 100 And L.X - E.X > -100 And L.Y - E.Y < 100 And L.Y - E.Y > -100


Means the images collide will only start being checked if the bullet comes that close to the target.

Now the issue I see with this, is that for that period of time between 0-100 pixels distance from the target (which can be a lifetime for a computer doing billions of calculations a second), for that period once the bullet enters within 100 pixels, the imagescollide will be checking against ALL the ships in the master list. However, short that period might be in real time, once you have a lot of ships in a melee, and like 100 bullets within the 100 pixel proximity, 100 bullets will be being checked for a collision with all ships.

That is the issue I see with that, and why I am getting slow downs in like 60 ship battles.

Anyway I can optimize this? My collision checking definitely is a bottle neck, as I can have 5000 ships on screen doing nothing, and its smooth.


tonyg(Posted 2013) [#7]
Shifted Grid?
Other than that I think you're on the right track to check a bounding box. Sure there was some code in the archives which reduced the image collision times.


jsp(Posted 2013) [#8]
Hi Tony, long time no see.
Are you back for a new project?


tonyg(Posted 2013) [#9]
Hi Jens, Happy Xmas
Got myself a new PC so looking to get Bmax back up and running. Just taking ages to get all those mods installed and working again. It's nearly there but also keeping an eye on Monkey. Aim is still just to have some fun and write simple games for my kids.
Will get chatty in General Discussion a bit later.


Derron(Posted 2013) [#10]
While Shifted Grid is a good idea, you may also shape off some 0.0x percents using a more "optimized" order of your IF-clauses (if they are not sorted yet).

For better readbility I like to negate the if-clauses and use the "continue"-approach (this shortens lines)

For Local L:tLaser = EachIn Tlaser.ELList 'Enemy Lasers
	For Local E:Tenemyship= EachIn ShipMasterList  'All Enemyships
		'SORT THIS from biggest chance to lowest one
		'so most likely all other ships are from other races
		'that is why we check for race first...  then non-civilian-frigates and ...
		'that is all dependend on complexity of checks etc.

		'Race check - skip friendly fire
		If E.RaceID = L.RaceID then continue
		'class and civilian check
		If E.ShipCLass <> "Frigate" AND E.RaceID <> "Civilian" then continue
		'skip out of reach
		If L.X - E.X > 100 or L.X - E.X < -100 or L.Y - E.Y > 100 or L.Y - E.Y < -100 then continue
		'skip weak shields	
		If E.Shield_Strength > 1 then continue

		'check for collision
		If ImagesCollide2(L.Image,  L.offsetX, L.OffsetY, L.FRAME , L.Angle, viewfactor,viewfactor, E.Image, ship.x + ( (E.x - ship.x) * viewfactor), ship.y + ( (E.y - ship.y) * viewfactor), 0, E.Angle, viewfactor,viewfactor)
			L.Die()
			TimeShieldHit = current_time
							
			'Shield Impact Sound
			If current_time - TimeShieldHit > ShieldHitSoundDelay
				PlaySound(shieldHit)
				TimeShieldHit = current_time
			End If
							
			E.Shield_Strength :- L.WEAPONDAMAGE
			DoShieldHit(L.x, L.y) ' shield effect
			TshieldHit.Create(L.X, L.Y)						 				
		End If 

		...


bye
Ron


Cruis.In(Posted 2013) [#11]
Oh yeah, much easier to read, and less issues with closing the main blocks.

Thanks Ron,

only thing I'll point out is that I think you confused the friendly fire check and the ship class check.

If the E.RaceId = L.RaceID you would not want to go ahead checking for collision, only if it is not equal.

Same for shipclass, I want this function specific for frigate and civilian.

The above would execute only for ships other than civilian and frigates.


Derron(Posted 2013) [#12]
Yeah, I thought I will 100% mess up some clauses during conversion.

Sometimes I also thought that some checks seem illogical to me - but you got the idea :p.

bye
Ron


Cruis.In(Posted 2013) [#13]
How about using rect collide instead of images collide? I never used it. Would that simply entail drawing the rects on all my objects ;ships; and ;bullets; and going from there?


Derron(Posted 2013) [#14]
Imagecollide:
Images are checked for opaque pixels - if opaque pixels are hit - the image collided.

This check is processor heavy (pixel by pixel check).


Rectcollide: Imagine you have 4*x,y-coordinates. They represent an rectangle. As soon as they have a 90° inner angle (2 share the same x while each of them shares the y with another one) you can check for collision with another rect easily:

Is one of my coords within the 4 coords of the other one - the rects collided.


In Short: rectcollide is way easier to accomplish (and lighter for the processor) but it ignores non-opaque areas of your images.


for finer graded checks you could split your images into smaller portions so you end up eg with 20 small rects (with nearly all opaque rects "within") to check against. Other options are collision hulls (polygons).

Feel free to ask Dr. Google for more assistance regarding this (with host: blitzmax.com).


bye
Ron


Cruis.In(Posted 2013) [#15]
Thanks D. Since it is space ships, we can assume space ships have 'bubble' shields, which are a little ways off the main hull, so rect collision might be just fine for my purpose :)