SyntaxBomb - Indie Coders

Languages & Coding => BlitzMax / BlitzMax NG => Topic started by: Cruis.In on October 04, 2019, 16:42:37

Title: Return to blitzmax
Post by: Cruis.In on October 04, 2019, 16:42:37
Hi guys, I have started coding in blitzmax again. I was never a master coder, but looking back on 60,000 lines of code in a 10 year old 2d space game I did is fun! It is well commented and documented too, even if some of my coding was amateur. Or all.

I never did grasp delta time properly, despite the tutorials, maybe I had coded too far along to put it in properly. I think you were supposed to multiply all drawing/render only with the delta. So I locked at 60 fps and that seemed to be ok.

But I realise my collision code is wayy toooo demanding. Hundreds of projectiles and ships checking for pixel perfect collision with imagescollide function too much so I was asking for some advice on re-doing this.

Currently looks like this...

For Local ET:Ettorpedo = EachIn Ettorpedo.ETList ' ALL PROJECTILES

   For Local E:Tenemyship= EachIn ShipMasterList 'ALL SHIPS

then I do the collision code. I don;t know how else I would check for collision between all the projectiles and all the AI ships, otherwise than running for each in loops and keeping it constantly checking.

Any ideas to send me along the right track to get rid of this kind of bottlenecking?
   
   
Title: Re: Return to blitzmax
Post by: Cruis.In on October 04, 2019, 18:34:28
Also question,

do I need to use different lists for holding different projectiles?

I have lasers, torpedoes, many different types of lasers, all using linked list. Can I basically store them all in one linked list and just use one kill method to erase itself when its time?
So for example. I have a TPlayerBullet and an TEnemyBullet. Enemy bullets are stored in enemy bullets list, and same for players bullets.

Can I really store all in one list and not having trouble when checking for collision between objects in the one bullet list, and the player's object and the enemy ship object?
Title: Re: Return to blitzmax
Post by: Derron on October 04, 2019, 22:19:39
a TList can contain various types.

The
for local bla:TMyType = EachIn listOfall
next

would only iterate over "TMyType"-compatible elements.



Regardless of this: a n:m comparison can be costly ("each torpedo versus each ship").

Basic optimization thought:
- store ships in different regions
- store current region of torpedos
- only check for ships in the region of the torpedo


but - if we talk about 20 ships and 20 torpedos the amount of time required to check stuff is not concerning yet.


bye
Ron
Title: Re: Return to blitzmax
Post by: Cruis.In on October 04, 2019, 22:21:35
Hi thanks ron, what if I do a distance check before moving onto the collision function, if the projectile is within a certain distance, then start checking the collision?
Title: Re: Return to blitzmax
Post by: Cruis.In on October 05, 2019, 00:40:48
also how can I change all my includes to a module? I have like 30 files and 30 includes, and compiling takes long even if I only change one line in one of the .bmx includes.
Title: Re: Return to blitzmax
Post by: TomToad on October 05, 2019, 02:38:06
Quote from: Cruis.In on October 05, 2019, 00:40:48
also how can I change all my includes to a module? I have like 30 files and 30 includes, and compiling takes long even if I only change one line in one of the .bmx includes.
You do not need to make the files into a module unless you want to use the files in other projects as well.  You can just use Import "filename.bmx" instead of Include "filename.bmx".  Then the file will only be compiled when changes are made.

Quote from: Cruis.In on October 04, 2019, 22:21:35
Hi thanks ron, what if I do a distance check before moving onto the collision function, if the projectile is within a certain distance, then start checking the collision?

This would help as pixel perfect collision is much slower than distance checking.  Something like
Local ShipTorpedoWidth = (ShipRadius+TorpedoRadius)^2
For Torpedo = Eachin TorpedoList
    For Ship = Eachin ShipList
        If (Torpedo.x-Ship.x)^2+(Torpedo.y-Ship.y)^2 <= ShipTorpedoWidth
            If ImagesCollide(Torpedo.image,Torpedo.x,Torpedo.y,0,Ship.image,Ship.x,Ship.y,0) Then DestroyShip()
        Endif
    Endif
NExt


There are also collision layers that can be used.  Just draw all the ships to one of the collision layers, then while looping through the torpedos, check it against the ship layer and it will tell you if it collided with any ships and which ones,
Look at CollideImage(),CollideRect(), and ResetCollisions()

@Delta timing.
1. Calculate how many seconds have passed since last frame.  Usually, the time will be a fraction of a second.

Int NewTime = Millisecs()
Float Delta = Float(NewTime - OldTime)/1000.0
OldTime = NewTime

2. Decide how far an object should move in a second and multiply that number by Delta
'Our player will move 100 pixels per second along the x axis and 80 pixels per second on the y axis
player.x :+ 100 * Delta
player.y :+ 80 * Delta

That is basically it.  Now the player will move at the same speed on all machines.
Title: Re: Return to blitzmax
Post by: Cruis.In on October 05, 2019, 02:53:19
Clear and concise thanks. Import...gotcha! Except, it just stops processing about 76% and says it can't find something........I get the feeling its not as simple as importing simply like
import "types.bmx"  using the correct path and file name of course. I went and looked at the sample provided for tempest in the samples folder of blitzmax, i realise he imported two files transformfunctions.bmx and vectorfont.bmx using Import "transformfunctions.bmx"  his tempest sample works fine. So then I opened transformfunctions.bmx and vectorfront.bmx and ran those too, and they compile just fine on their own, they don't do anything, but they compile and make an .exe 

My files that I want to go from include to import, none of them can compile on their own. It is basically just my code split into files, so there are variables and globals referenced by some files which are in other files. I have a globals.bmx which just has globals. I can't compile that can I?

Re the collision layers. So I add the players ship to the collision mask, as well as any enemy ships. Then looping through all bullets/torpedoes to check collision....but it gets more complicated since i have added shield quadrants around the sprites, so that they can have individual shield arcs for, fore,left,right,rear. So it seems like it is so many different kinds of collision, and not just testing for a collision I need, which makes collide image not possible?

Deltatime example is clear. I do have it in, but I am wondering exactly where it goes, on only render updates which are :+ ? or all physics updates?

This is from my update method in the Playership Class.

Quotevx :+ Cos(angle)*thrust     * delta'move ship in angle facing
             vy :+ Sin(angle)*thrust     * delta'same
         
             'add calculation above to the ship x and y positions
            x  :+  vx       * delta         
            y  :+  vy      * delta         
            
            vx :* 0.98      * delta
            vy :* 0.98      * delta      

I wrote it 14 years ago...lol :)

Title: Re: Return to blitzmax
Post by: therevills on October 05, 2019, 03:45:55
When I saw the title of this thread I just thought of: Return of the Max.... Return of the Max...  :P

Title: Re: Return to blitzmax
Post by: Derron on October 05, 2019, 11:13:48
@ includes and imports
You already found out by yourself that stuff which references each other cannot simply be imported instead of included.

Include: puts the whole file content at the position of the "include" command. End result is a big big big file. This is why compilation takes so long.
Imports can be precompiled and so there is way less to compile each time. But to enable it, each to "import" file needs to be self-contained. Every dependency it has must be solveable.

So assume you have
car.bmx
wheels.bmx
street.bmx
game.bmx

car.bmx contains TCar which contains "field wheels:TWheel"
wheels.bmx contains "TWheel" and nothing more
street.bmx contains TStreet with "field carsOnIt:TCar[]" 
game.bmx contains TGame with "field streets:TStreet[]"

game.bmx includes all three other files. Compilation works.
If you now try to change 'include "car.bmx"' with 'import "car.bmx"' this won't work as car.bmx is not aware of the type "TWheel".
Now you need to import "wheels.bmx" within "car.bmx". TCar can now access TWheel. During compilation you will run into "duplicate identifiers" as "car.bmx" imported "wheels.bmx" (wheels.bmx gets precompiled and then car.bmx can use it and precompile too). But as your "game.bmx" still 'include "wheels.bmx"' it would have another TWheel which makes it fail. So remove the 'include "wheels.bmx"' in your game.bmx too.

Now it would compile - even with the street.bmx still being just included. You could safely transform that into an import now - ohh it misses "TCar", so just `import "car.bmx"' in the street.bmx file. No worries about duplicates. The car.bmx would only be imported once - even if there are multiple files importing it.

Means in a file you can safely import all used "components" even if one of the "components" is already importing one of the other "components" already.


The tricky part are circular dependencies:
TCar knows TStreet
TStreet knows TCar

you either pack them simply in one file (include or a simple single file) or you resolve the circular dependency:
TCarBase file
TCar file
TStreetBase file
TStreet file

TCar knows about TStreetBase
TStreet knows about TCarBase

TCarBase knows nothing about streets
TStreetBase knows nothing about cars



bye
Ron
Title: Re: Return to blitzmax
Post by: Cruis.In on October 05, 2019, 19:17:48
thanks, yeah to do that now to this large code and files would be a night mare but i could still try a bit :)

tried every which way I can the whole, day I got one single file to compile. Other ways I just ran into circulars, something always needs something from another file, referencing calling. i mean its like 100k lines written so many years ago and hacked together. it works as is, but to try to change the structure would require a complete re-write. As it is it takes about 25 seconds to compile, I am not sure how much would be gained by putting most in imports.