### Author Topic: Things that slow Danmakufu down  (Read 7532 times)

#### Blargel ##### Things that slow Danmakufu down
« on: January 25, 2010, 03:44:40 PM »
This thread is for keeping a list of not-obvious things that will slow down Danmakufu.
Things that are obvious, like massive amounts of bullets/graphics/enemies/effects/loops do not belong here. Feel free to suggest things to the list, but try to test it and give reasonable proof that what you suggest is causing slowdown. Also feel free to suggest solutions and alternatives to the problematic situations listed here.

Trigonometric functions
If you are doing a lot of positioning every frame with sin, cos, and atan2, you will be slowing Danmakufu more than if you are using precalculated numbers.

Example:

ascent(i in 0..8){
SetGraphicAngle(i*45, 0, 0);
DrawGraphic3D(sin(i*45), 0, cos(i*45));
}

Solution:
The framerate can be improved by writing out each SetGraphicAngle and DrawGraphic3D while writing in the exact values of sin and cos instead of calling the functions. Of course writing the same thing with different values is quite tedious, especially if you need to do it for several hundred functions. This solution should only be used if you are desperate to regain a stable framerate.

Looking up values in large arrays
Contrary to what you might expect (especially if you are a programmer that is used to more... conventional... languages), the larger the array, the longer it takes for Danmakufu to find a value in it. Incidentally, this makes look-up tables for sin, cos, and tan too slow to be a solution to the previous problem.

Example:

let Array = [0, 1, 2, 3, 4, etc..., 390892];
let Value = Array; //This line will take longer, the longer Array is in length.

Solution:
Simply avoid large arrays as much as possible and split 2D arrays into multiple arrays instead.

Calling functions on non-existent/deleted objects
Even if the object is deleted already it will still cost a bit of processing power to call the functions on it. This seems like common sense, but consider the example below.

Example:

let obj = Obj_Create(OBJ_SHOT);
// other stuff, let's assume I wrote it already.
let counter = 0;
loop {
// do some other stuff
if(counter==180){
Obj_Delete(obj);
}
counter++;
yield ;
}
}

Solution:
The obvious solution is to replace loop {} with while(!Obj_BeDeleted(obj)){}, but sometimes, even with a while block instead of loop, some functions may still run before the while block finishes executing and the condition is checked again before it exits the loop. To prevent this, you can call return; right after the Obj_Delete(obj); and it will exit out of the task immediately.

Anyone else discover anything interesting?
« Last Edit: January 25, 2010, 03:58:56 PM by Blargel »
<WorkingKeine> when i get home i just go to the ps3 and beat people up in blazblue with a loli
<Azure> Keine: Danmakufu helper by day, violent loli by night.

#### Danielu Yoshikoto ##### Re: Things that slow Danmakufu down
« Reply #1 on: January 25, 2010, 04:48:04 PM »
letting multiple bullets appear at the same place and in the same frame.
« Last Edit: January 25, 2010, 05:12:16 PM by Danielu Yoshikoto »

#### Helepolis ##### Re: Things that slow Danmakufu down
« Reply #2 on: January 25, 2010, 06:29:50 PM »
letting multiple bullets appear at the same place and in the same frame.
Depends on how intense the bullet spawning is. You need be more precise with your post.

#### Infy♫ ##### Re: Things that slow Danmakufu down
« Reply #3 on: January 25, 2010, 06:40:41 PM »
drawtext, when used a lot, causes severe lag.

#### Danielu Yoshikoto ##### Re: Things that slow Danmakufu down
« Reply #4 on: January 25, 2010, 07:20:39 PM »
Depends on how intense the bullet spawning is. You need be more precise with your post.

30 bullets times 4 times 2.
That would be: 240.

#### Helepolis ##### Re: Things that slow Danmakufu down
« Reply #5 on: January 25, 2010, 08:58:22 PM »
Extreme bullet spawning is common, you cannot expect Danmakufu to draw you 1000 bullets on your screen without causing lag. The purpose of this thread is to bring forward certain things that are done in danmakufu ( like given examples above ) that cause lag when normally you would think it would not. ( failure explanation )

For example, nobody actually knows that sin/cos maths (+ loops) in 3D drawing is a bad thing because it is not common occurring, however if it occurs, people can use this thread as possibly reference material.

#### Blargel ##### Re: Things that slow Danmakufu down
« Reply #6 on: January 25, 2010, 09:41:49 PM »
drawtext, when used a lot, causes severe lag.

That's STATED in the DrawText function's description in the wiki.

30 bullets times 4 times 2.
That would be: 240.
This thread is for keeping a list of not-obvious things that will slow down Danmakufu.
Things that are obvious, like massive amounts of bullets/graphics/enemies/effects/loops do not belong here.
<WorkingKeine> when i get home i just go to the ps3 and beat people up in blazblue with a loli
<Azure> Keine: Danmakufu helper by day, violent loli by night.

#### Suikama ##### Re: Things that slow Danmakufu down
« Reply #7 on: January 26, 2010, 12:38:24 AM »
Lotsa Brofists

#### Blargel ##### Re: Things that slow Danmakufu down
« Reply #8 on: January 26, 2010, 01:05:43 AM »
Lotsa Brofists
Example:

#include_function "lib\BROFIST_REPLACE\BROFIST_REPLACE.txt"
@Intialize{
initmebro;
}
@MainLoop{
ascent(i in 0..36){
CreateShot01(GetX, GetY, 8, GetAngleToPlayer+i*10, RED01, 10);
}
}

Solution:
Don't use brofists.
<WorkingKeine> when i get home i just go to the ps3 and beat people up in blazblue with a loli
<Azure> Keine: Danmakufu helper by day, violent loli by night.

#### Naut ##### Re: Things that slow Danmakufu down
« Reply #9 on: January 26, 2010, 01:20:37 AM »
Trigonometric functions
If you are doing a lot of positioning every frame with sin, cos, and atan2, you will be slowing Danmakufu more than if you are using precalculated numbers.

wat

Code: [Select]
`task bullat1(anglee, osc, vv, ell){ let oscx = GetPlayerX + 200*cos(anglee); let oscy = GetPlayerY + 200*sin(anglee); let enemy = 1000; let i = 0; let ex = vv + 100*cos(osc); let ey = 0; let counter = 0; let fdis = 0; let rdpo = 0; let rdoe = 0; let rdlk = 0; let obj = Obj_Create(OBJ_SHOT); Obj_SetPosition(obj, GetPlayerX, GetPlayerY); Obj_SetAngle(obj, 0); ObjShot_SetGraphic(obj, 1); ObjShot_SetDamage(obj, 1); ObjShot_SetPenetration(obj, 1); let elec = Obj_Create(OBJ_EFFECT); ObjEffect_SetTexture(elec, GetCurrentScriptDirectory~"elec.png"); ObjEffect_CreateVertex(elec, 6); ObjEffect_SetRenderState(elec, ADD); ObjEffect_SetPrimitiveType(elec, PRIMITIVE_TRIANGLEFAN); if(ell==0){ ObjEffect_SetVertexUV(elec, 0, 0, 0); ObjEffect_SetVertexUV(elec, 1, 15, 0); ObjEffect_SetVertexUV(elec, 2, 15, 14); ObjEffect_SetVertexUV(elec, 3, 15, 27); ObjEffect_SetVertexUV(elec, 4, 0, 27); ObjEffect_SetVertexUV(elec, 5, 0, 13); } if(ell==1){ ObjEffect_SetVertexUV(elec, 0, 0 + 16, 0); ObjEffect_SetVertexUV(elec, 1, 15 + 16, 0); ObjEffect_SetVertexUV(elec, 2, 15 + 16, 14); ObjEffect_SetVertexUV(elec, 3, 15 + 16, 27); ObjEffect_SetVertexUV(elec, 4, 0 + 16, 27); ObjEffect_SetVertexUV(elec, 5, 0 + 16, 13); } if(ell==2){ ObjEffect_SetVertexUV(elec, 0, 0 + 32, 0); ObjEffect_SetVertexUV(elec, 1, 15 + 32, 0); ObjEffect_SetVertexUV(elec, 2, 15 + 32, 14); ObjEffect_SetVertexUV(elec, 3, 15 + 32, 27); ObjEffect_SetVertexUV(elec, 4, 0 + 32, 27); ObjEffect_SetVertexUV(elec, 5, 0 + 32, 13); } if(ell==3){ ObjEffect_SetVertexUV(elec, 0, 0 + 48, 0); ObjEffect_SetVertexUV(elec, 1, 15 + 48, 0); ObjEffect_SetVertexUV(elec, 2, 15 + 48, 14); ObjEffect_SetVertexUV(elec, 3, 15 + 48, 27); ObjEffect_SetVertexUV(elec, 4, 0 + 48, 27); ObjEffect_SetVertexUV(elec, 5, 0 + 48, 13); } while(!Obj_BeDeleted(obj)){ oscx = GetPlayerX + 200*cos(anglee - 30); oscy = GetPlayerY + 200*sin(anglee - 30); osc+=3; if(GetEnemyNum>0){ if(!IsBossExisting){ ascent(i in EnumEnemyBegin..EnumEnemyEnd) { enemy=EnumEnemyGetID(i); i=EnumEnemyEnd; } }else{ i = EnumEnemyBegin; enemy=EnumEnemyGetID(i); } ex = GetEnemyInfo(enemy, ENEMY_X); ey = GetEnemyInfo(enemy, ENEMY_Y); }else{ ex = vv + 100*cos(osc); ey = 0; } if(counter<=10){ let apo = atan2(oscy - GetPlayerY, oscx - GetPlayerX); let aoe = atan2(ey - oscy, ex - oscx); let dpo = ((GetPlayerX - oscx)^2 + (GetPlayerY - oscy)^2)^0.5; let doe = ((oscx - ex)^2 + (oscy - ey)^2)^0.5; rdpo = (dpo/10)*counter; rdoe = (doe/10)*counter; let lx = GetPlayerX + rdpo*cos(apo); let ly = GetPlayerY + rdpo*sin(apo); let kx = oscx + rdoe*cos(aoe); let ky = oscy + rdoe*sin(aoe); let alk = atan2(ky - ly, kx - lx); let dlk = ((kx - lx)^2 + (ky - ly)^2)^0.5; rdlk = (dlk/10)*counter; let rx = lx + rdlk*cos(alk); let ry = ly + rdlk*sin(alk); Obj_SetPosition(obj, rx, ry); Obj_SetAngle(obj, alk); ObjEffect_SetVertexXY(elec, 2, rx + 5*cos(alk + 90), ry + 5*sin(alk + 90)); ObjEffect_SetVertexXY(elec, 5, rx + 5*cos(alk - 90), ry + 5*sin(alk - 90)); let apo = atan2(oscy - GetPlayerY, oscx - GetPlayerX); let aoe = atan2(ey - oscy, ex - oscx); let dpo = ((GetPlayerX - oscx)^2 + (GetPlayerY - oscy)^2)^0.5; let doe = ((oscx - ex)^2 + (oscy - ey)^2)^0.5; rdpo = (dpo/10)*(counter + 1); rdoe = (doe/10)*(counter + 1); let lx = GetPlayerX + rdpo*cos(apo); let ly = GetPlayerY + rdpo*sin(apo); let kx = oscx + rdoe*cos(aoe); let ky = oscy + rdoe*sin(aoe); let alk = atan2(ky - ly, kx - lx); let dlk = ((kx - lx)^2 + (ky - ly)^2)^0.5; rdlk = (dlk/10)*(counter + 1); let rx = lx + rdlk*cos(alk); let ry = ly + rdlk*sin(alk); ObjEffect_SetVertexXY(elec, 0, rx + 5*cos(alk - 90), ry + 5*sin(alk - 90)); ObjEffect_SetVertexXY(elec, 1, rx + 5*cos(alk + 90), ry + 5*sin(alk + 90)); let apo = atan2(oscy - GetPlayerY, oscx - GetPlayerX); let aoe = atan2(ey - oscy, ex - oscx); let dpo = ((GetPlayerX - oscx)^2 + (GetPlayerY - oscy)^2)^0.5; let doe = ((oscx - ex)^2 + (oscy - ey)^2)^0.5; rdpo = (dpo/10)*(counter - 1); rdoe = (doe/10)*(counter - 1); let lx = GetPlayerX + rdpo*cos(apo); let ly = GetPlayerY + rdpo*sin(apo); let kx = oscx + rdoe*cos(aoe); let ky = oscy + rdoe*sin(aoe); let alk = atan2(ky - ly, kx - lx); let dlk = ((kx - lx)^2 + (ky - ly)^2)^0.5; rdlk = (dlk/10)*(counter - 1); let rx = lx + rdlk*cos(alk); let ry = ly + rdlk*sin(alk); ObjEffect_SetVertexXY(elec, 3, rx + 5*cos(alk + 90), ry + 5*sin(alk + 90)); ObjEffect_SetVertexXY(elec, 4, rx + 5*cos(alk - 90), ry + 5*sin(alk - 90)); }else{ Obj_Delete(obj); } if(counter==10){ Obj_Delete(elec); } counter++; yield; } Obj_Delete(elec);}`
The while loop runs fourty times per frame. m i eefishant pro gramar?

#### Azure Lazuline ##### Re: Things that slow Danmakufu down
« Reply #10 on: January 26, 2010, 01:24:35 AM »
Well, as a non-joke version of that, large bullets do seem to use more processing power than small ones, though it might just be my imagination (or only apply on a large scale like that). Additive blending also seems to cause some problems, since a player character with ADD-blended bullets caused more slowdown than a player without it, even when the second player shot more bullets overall. (I didn't explicitly test though, so more research should be done before it's added to the list.)

#### Blargel ##### Re: Things that slow Danmakufu down
« Reply #11 on: January 26, 2010, 01:28:45 AM »
wat

Code: [Select]
`task bullat1(anglee, osc, vv, ell){ let oscx = GetPlayerX + 200*cos(anglee); let oscy = GetPlayerY + 200*sin(anglee); let enemy = 1000; let i = 0; let ex = vv + 100*cos(osc); let ey = 0; let counter = 0; let fdis = 0; let rdpo = 0; let rdoe = 0; let rdlk = 0; let obj = Obj_Create(OBJ_SHOT); Obj_SetPosition(obj, GetPlayerX, GetPlayerY); Obj_SetAngle(obj, 0); ObjShot_SetGraphic(obj, 1); ObjShot_SetDamage(obj, 1); ObjShot_SetPenetration(obj, 1); let elec = Obj_Create(OBJ_EFFECT); ObjEffect_SetTexture(elec, GetCurrentScriptDirectory~"elec.png"); ObjEffect_CreateVertex(elec, 6); ObjEffect_SetRenderState(elec, ADD); ObjEffect_SetPrimitiveType(elec, PRIMITIVE_TRIANGLEFAN); if(ell==0){ ObjEffect_SetVertexUV(elec, 0, 0, 0); ObjEffect_SetVertexUV(elec, 1, 15, 0); ObjEffect_SetVertexUV(elec, 2, 15, 14); ObjEffect_SetVertexUV(elec, 3, 15, 27); ObjEffect_SetVertexUV(elec, 4, 0, 27); ObjEffect_SetVertexUV(elec, 5, 0, 13); } if(ell==1){ ObjEffect_SetVertexUV(elec, 0, 0 + 16, 0); ObjEffect_SetVertexUV(elec, 1, 15 + 16, 0); ObjEffect_SetVertexUV(elec, 2, 15 + 16, 14); ObjEffect_SetVertexUV(elec, 3, 15 + 16, 27); ObjEffect_SetVertexUV(elec, 4, 0 + 16, 27); ObjEffect_SetVertexUV(elec, 5, 0 + 16, 13); } if(ell==2){ ObjEffect_SetVertexUV(elec, 0, 0 + 32, 0); ObjEffect_SetVertexUV(elec, 1, 15 + 32, 0); ObjEffect_SetVertexUV(elec, 2, 15 + 32, 14); ObjEffect_SetVertexUV(elec, 3, 15 + 32, 27); ObjEffect_SetVertexUV(elec, 4, 0 + 32, 27); ObjEffect_SetVertexUV(elec, 5, 0 + 32, 13); } if(ell==3){ ObjEffect_SetVertexUV(elec, 0, 0 + 48, 0); ObjEffect_SetVertexUV(elec, 1, 15 + 48, 0); ObjEffect_SetVertexUV(elec, 2, 15 + 48, 14); ObjEffect_SetVertexUV(elec, 3, 15 + 48, 27); ObjEffect_SetVertexUV(elec, 4, 0 + 48, 27); ObjEffect_SetVertexUV(elec, 5, 0 + 48, 13); } while(!Obj_BeDeleted(obj)){ oscx = GetPlayerX + 200*cos(anglee - 30); oscy = GetPlayerY + 200*sin(anglee - 30); osc+=3; if(GetEnemyNum>0){ if(!IsBossExisting){ ascent(i in EnumEnemyBegin..EnumEnemyEnd) { enemy=EnumEnemyGetID(i); i=EnumEnemyEnd; } }else{ i = EnumEnemyBegin; enemy=EnumEnemyGetID(i); } ex = GetEnemyInfo(enemy, ENEMY_X); ey = GetEnemyInfo(enemy, ENEMY_Y); }else{ ex = vv + 100*cos(osc); ey = 0; } if(counter<=10){ let apo = atan2(oscy - GetPlayerY, oscx - GetPlayerX); let aoe = atan2(ey - oscy, ex - oscx); let dpo = ((GetPlayerX - oscx)^2 + (GetPlayerY - oscy)^2)^0.5; let doe = ((oscx - ex)^2 + (oscy - ey)^2)^0.5; rdpo = (dpo/10)*counter; rdoe = (doe/10)*counter; let lx = GetPlayerX + rdpo*cos(apo); let ly = GetPlayerY + rdpo*sin(apo); let kx = oscx + rdoe*cos(aoe); let ky = oscy + rdoe*sin(aoe); let alk = atan2(ky - ly, kx - lx); let dlk = ((kx - lx)^2 + (ky - ly)^2)^0.5; rdlk = (dlk/10)*counter; let rx = lx + rdlk*cos(alk); let ry = ly + rdlk*sin(alk); Obj_SetPosition(obj, rx, ry); Obj_SetAngle(obj, alk); ObjEffect_SetVertexXY(elec, 2, rx + 5*cos(alk + 90), ry + 5*sin(alk + 90)); ObjEffect_SetVertexXY(elec, 5, rx + 5*cos(alk - 90), ry + 5*sin(alk - 90)); let apo = atan2(oscy - GetPlayerY, oscx - GetPlayerX); let aoe = atan2(ey - oscy, ex - oscx); let dpo = ((GetPlayerX - oscx)^2 + (GetPlayerY - oscy)^2)^0.5; let doe = ((oscx - ex)^2 + (oscy - ey)^2)^0.5; rdpo = (dpo/10)*(counter + 1); rdoe = (doe/10)*(counter + 1); let lx = GetPlayerX + rdpo*cos(apo); let ly = GetPlayerY + rdpo*sin(apo); let kx = oscx + rdoe*cos(aoe); let ky = oscy + rdoe*sin(aoe); let alk = atan2(ky - ly, kx - lx); let dlk = ((kx - lx)^2 + (ky - ly)^2)^0.5; rdlk = (dlk/10)*(counter + 1); let rx = lx + rdlk*cos(alk); let ry = ly + rdlk*sin(alk); ObjEffect_SetVertexXY(elec, 0, rx + 5*cos(alk - 90), ry + 5*sin(alk - 90)); ObjEffect_SetVertexXY(elec, 1, rx + 5*cos(alk + 90), ry + 5*sin(alk + 90)); let apo = atan2(oscy - GetPlayerY, oscx - GetPlayerX); let aoe = atan2(ey - oscy, ex - oscx); let dpo = ((GetPlayerX - oscx)^2 + (GetPlayerY - oscy)^2)^0.5; let doe = ((oscx - ex)^2 + (oscy - ey)^2)^0.5; rdpo = (dpo/10)*(counter - 1); rdoe = (doe/10)*(counter - 1); let lx = GetPlayerX + rdpo*cos(apo); let ly = GetPlayerY + rdpo*sin(apo); let kx = oscx + rdoe*cos(aoe); let ky = oscy + rdoe*sin(aoe); let alk = atan2(ky - ly, kx - lx); let dlk = ((kx - lx)^2 + (ky - ly)^2)^0.5; rdlk = (dlk/10)*(counter - 1); let rx = lx + rdlk*cos(alk); let ry = ly + rdlk*sin(alk); ObjEffect_SetVertexXY(elec, 3, rx + 5*cos(alk + 90), ry + 5*sin(alk + 90)); ObjEffect_SetVertexXY(elec, 4, rx + 5*cos(alk - 90), ry + 5*sin(alk - 90)); }else{ Obj_Delete(obj); } if(counter==10){ Obj_Delete(elec); } counter++; yield; } Obj_Delete(elec);}`
The while loop runs fourty times per frame. m i eefishant pro gramar?

In the test I did, it took me 10,000 uses of sin in the same frame to cause 1 fps drop. 20,000 uses dropped me to 34 fps. You'll be fine. Unless you use like 250 of those at once.
Well, as a non-joke version of that, large bullets do seem to use more processing power than small ones, though it might just be my imagination (or only apply on a large scale like that). Additive blending also seems to cause some problems, since a player character with ADD-blended bullets caused more slowdown than a player without it, even when the second player shot more bullets overall. (I didn't explicitly test though, so more research should be done before it's added to the list.)

ALPHA vs ADD blending needs to be tested. I'll take a quick look when I have the time later. Larger bullets definitely take more processing power than smaller ones though because larger graphics in general are harder for Danmakufu to process.
<WorkingKeine> when i get home i just go to the ps3 and beat people up in blazblue with a loli
<Azure> Keine: Danmakufu helper by day, violent loli by night.

#### Naut ##### Re: Things that slow Danmakufu down
« Reply #12 on: January 26, 2010, 01:37:51 AM »
In the test I did, it took me 10,000 uses of sin in the same frame to cause 1 fps drop. 20,000 uses dropped me to 34 fps. You'll be fine. Unless you use like 250 of those at once. ALPHA vs ADD blending needs to be tested. I'll take a quick look when I have the time later. Larger bullets definitely take more processing power than smaller ones though because larger graphics in general are harder for Danmakufu to process.

ADD blending destroys Danmakufu, think CreateLaserC.

#### Blargel ##### Re: Things that slow Danmakufu down
« Reply #13 on: January 26, 2010, 01:46:25 AM »
If you pay attention to how Danmakufu builds CreateLaserC type lasers, it appears to be made of segments. The length of the laser determines how many of those segments there are and I believe each segment's required processing power is greater than that of a single normal bullet.

I'll test the ADD/ALPHA thing by drawing enough images with ALPHA to slow down my computer to around 30-40 fps. Then I will switch over to ADD and then see if I an observe a drop in framerate.

UPDATE: 2000 ExRumia graphics with rectangles set at (0, 0, 64, 64) drawn with ALPHA drops my framerate and makes it hover around 35-40fps With average being around 38fps. Adding in SetRenderState(ADD); right before my loop(2000){DrawGraphic(rand(100, 300), rand(100, 300));} has no noticeable effect with the framerate.

Azure: It could be that your player that is using ADD blending requires more processing power per bullet, possibly due to sin/cos. Another factor could be the size of the bullets.

UPDATE 2: Setting render state to MULTIPLY and SUBTRACT has no effect on frame rate either. So render states in general will not affect framerate.
« Last Edit: January 26, 2010, 01:54:15 PM by Blargel »
<WorkingKeine> when i get home i just go to the ps3 and beat people up in blazblue with a loli
<Azure> Keine: Danmakufu helper by day, violent loli by night.

#### Kylesky ##### Re: Things that slow Danmakufu down
« Reply #14 on: January 26, 2010, 01:55:36 PM »
Is using too many vertices for an effect object included here?
(also... I'm not sure if this should be here, and I guess this is already common knowledge, but... too many reflecting bullets?)
Danmakufu Script Thread :V Latest Script: Intertwining Mechanical Intervention (temp name)

Yooooouuutuuuubeeee Channel Latest Video: Contest #8 Entry

#### Blargel ##### Re: Things that slow Danmakufu down
« Reply #15 on: January 26, 2010, 01:57:21 PM »
I think it's pretty obvious that more vertices on an object effect means more processing power. Reflecting bullets fall under the category of too many bullets/loops which should be common knowledge.