Author Topic: Danmakufu Q&A/Problem Thread v3  (Read 213422 times)

Iryan

  • Ph?nglui mglw?nafh
  • Cat R?lyeh wgah?nagl fhtagn.
Re: Danmakufu Q&A/Problem Thread v3
« Reply #420 on: March 13, 2010, 12:09:59 AM »
Hmmm, do you summon more than one of these enemies at once? If so, both enemies would use the same common data, which would cause problems...


If you get an actual error message, it would help to see it. You can use Ctrl+C to copy it and then post it here. It may also help to see the updated code as well.
Old Danmakufu stuff can be found here!

"As the size of an explosion increases, the numbers of social situations it is incapable of solving approaches zero."

Drake

  • *
Re: Danmakufu Q&A/Problem Thread v3
« Reply #421 on: March 13, 2010, 01:20:15 AM »
As for the common data problem, you set the common data in the parent enemy as an array, before the others spawn. Instead of using new common data, you concatenate stuff onto the previous array.

Or something similar.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Re: Danmakufu Q&A/Problem Thread v3
« Reply #422 on: March 13, 2010, 07:11:39 PM »
Okay, I think I have some kind of fundamental misunderstanding about how Common Data works. My understanding is that they act as 'global' variables - set a Common Data by a string in one place, and then anyone else who accesses it will get the data, regardless of where or how many places it's accessed. Is this wrong? And if not, how would having multiple slaves make this a problem?


Here's the current code:
Code: [Select]
script_enemy_main
{ //Slave-having enemy
let imgEnemy=GetCurrentScriptDirectory~"img\Enemy.png";
let imgAngle=0;
let shotAngle=0;
let id = GetArgument;

function wait(n) {
loop(n) { yield; }
}

task TMove {
while(GetX < GetClipMaxX + 51 && GetX > GetClipMinX - 51) {
if(GetSpeed > 0.5) {
SetSpeed(GetSpeed - 0.05);
}
yield;
}
VanishEnemy;
}

@Initialize
{
SetLife(500);
SetGraphicRect(1,1,32,32);

if(id) {
SetCommonData("Enemy01LeftX", GetX);
SetCommonData("Enemy01LeftY", GetY);
SetCommonData("Enemy01LeftDead", false);
SetAngle(30);
SetSpeed(5);
} else {
SetCommonData("Enemy01RightX", GetX);
SetCommonData("Enemy01RightY", GetY);
SetCommonData("Enemy01RightDead", false);
SetAngle(150);
SetSpeed(5);
}

SetCommonData("Enemy01Side", GetArgument);
ascent(i in 0..4) {
CreateEnemyFromScript("Familiar", GetX, GetY, 0, 0, i*90);
}
TMove;
}

@MainLoop
{
    SetCollisionA(GetX, GetY, 16);
        SetCollisionB(GetX, GetY, 16);
if(id) {
SetCommonData("Enemy01LeftX", GetX);
SetCommonData("Enemy01LeftY", GetY);
} else {
SetCommonData("Enemy01RightX", GetX);
SetCommonData("Enemy01RightY", GetY);
}
yield;
}

@Finalize
{//読みこんだファイルを削除
if(id) {
SetCommonData("Enemy01LeftDead", true);
} else {
SetCommonData("Enemy01RightDead", true);
}
CreateItem(ITEM_SCORE, GetX + rand(-10,10), GetY + rand(10,10));
}

@DrawLoop
{//描画
SetTexture(imgEnemy);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetGraphicAngle(0,0,imgAngle);
DrawGraphic(GetX(),GetY());
SetRenderState(ADD);
SetGraphicAngle(0,0,-imgAngle);
DrawGraphic(GetX(),GetY());
imgAngle+=4;
if(imgAngle>360){imgAngle=0;}
}
}

script_enemy Familiar {
let ImgFam = GetCurrentScriptDirectory ~ "img\Enemy.png";
let imgAngle=0;
let angle = GetArgument;
let id = false;

function wait(w) {
loop(w) { yield; }
}


    @Initialize {
        SetLife(100);
        SetScore(0);
        SetDamageRateEx(100, 100, 50, 50);

        LoadGraphic(ImgFam);
        SetTexture(ImgFam);
SetGraphicRect(1,1,32,32);

id = GetCommonData("Enemy01Side");

        TRotate;
        TFire;
    }

    @MainLoop {
    SetCollisionA(GetX, GetY, 8);
        SetCollisionB(GetX, GetY, 8);
if(id) {
if(GetCommonDataDefault("Enemy01LeftDead", true)) {
VanishEnemy;
}
} else {
if(GetCommonDataDefault("Enemy01RightDead", true)) {
VanishEnemy;
}
}
       yield;
    }

@DrawLoop
{//描画
SetTexture(ImgFam);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetGraphicAngle(0,0,imgAngle);
DrawGraphic(GetX(),GetY());
SetRenderState(ADD);
SetGraphicAngle(0,0,-imgAngle);
DrawGraphic(GetX(),GetY());
imgAngle+=4;
if(imgAngle>360){imgAngle=0;}
}

  @Finalize
{//読みこんだファイルを削除
CreateItem(ITEM_SCORE, GetX + rand(-10,10), GetY + rand(10,10));
}

// rotate around the boss
    task TRotate {
let eX = 0;
let eY = 0;
loop {
if(id) {
eX = GetCommonDataDefault("Enemy01LeftX", -50);
eY = GetCommonDataDefault("Enemy01LeftY", -50);
} else {
eX = GetCommonDataDefault("Enemy01RightX", -50);
eY = GetCommonDataDefault("Enemy01RightY", -50);
}
SetX(eX + cos(angle) * 50);
SetY(eY + sin(angle) * 50);
yield;
angle += 1.5;
}
}

    task TFire {
        loop {
CreateShot01(GetX, GetY, 1.5, angle+180, RED01, 10);
CreateShot01(GetX, GetY, 2, angle+180, ORANGE01, 10);
            wait(36);
        }
    }
}

And it's not any error message - Danmakufu just crashes and quits with a generic "this program has stopped functioning" windows message.

Iryan

  • Ph?nglui mglw?nafh
  • Cat R?lyeh wgah?nagl fhtagn.
Re: Danmakufu Q&A/Problem Thread v3
« Reply #423 on: March 13, 2010, 08:06:05 PM »
Afaik, that is how it works. The problem with having multiples of the slave spawning enemy out at once is the following:

If I read your script correctly, then you have Common Data that keeps track of whether or not each of the slave (and the main enemy) is alive. If you have more than one of the slave spawning enemies on the field at once, both enemies (and their slaves) will use the same common data. Thus the death of the first enemy (or one of its slaves) will affect the behaviour of the second enemy and its slaves, and vice versa.


Hm, on why your script keeps crashing... what happens if you don't shoot the enemy but instead let it just ponder out of the playing field? Since you vanish it when it leaves the field, it could be that the familiars need to haveif(BeParentVanished==true){VanishEnemy;} or something similar inside their main loops.
Old Danmakufu stuff can be found here!

"As the size of an explosion increases, the numbers of social situations it is incapable of solving approaches zero."

Re: Danmakufu Q&A/Problem Thread v3
« Reply #424 on: March 14, 2010, 04:15:53 AM »
Afaik, that is how it works. The problem with having multiples of the slave spawning enemy out at once is the following:

If I read your script correctly, then you have Common Data that keeps track of whether or not each of the slave (and the main enemy) is alive. If you have more than one of the slave spawning enemies on the field at once, both enemies (and their slaves) will use the same common data. Thus the death of the first enemy (or one of its slaves) will affect the behaviour of the second enemy and its slaves, and vice versa.
I see where you're coming from, but I only ever have two of that enemy on the field at once - one on the left, and one on the right. Thus, the argument makes sure they're segregated to separate sets of Common Data.

Quote
Hm, on why your script keeps crashing... what happens if you don't shoot the enemy but instead let it just ponder out of the playing field? Since you vanish it when it leaves the field, it could be that the familiars need to haveif(BeParentVanished==true){VanishEnemy;} or something similar inside their main loops.
If they drift off the side of the screen and autovanish, the game doesn't complain. The only thing that seems to trigger the destruction is if the player kills the master enemy while it's off the edge of the field, in the buffer zone between leaving the field and vanishing.

Iryan

  • Ph?nglui mglw?nafh
  • Cat R?lyeh wgah?nagl fhtagn.
Re: Danmakufu Q&A/Problem Thread v3
« Reply #425 on: March 14, 2010, 10:53:33 AM »
On another note, remove the SetScore(0); from the familiars. If you leave it out your enemy won't have a score, and leaving it in may in fact cause other casualties if danmakufu is as stupid as I think it is. And it ususally is.


Hmm, I have an idea. Change the SetDamageRateEx in your script to regular SetDamageRate commands. It could be that danmakufu goes nuts if you damage the familiar while the parent enemy is already vanished.
And besides, afaik SetDamageRateEx didn't really work the way it should, anyways. At least it didn't for me when the parent enemy was a boss enemy. I had to transfer the damage from the familiars to the boss by storing it in CommonData.

In the slim chance that SetDamageRateEx actually is what causes the crashing, this method would also circumvent this peculiar problem since the damage is first transferred from the slaves to a CommonData that continues to exist when the enemy is dead. The damaging of the master enemy is part of its own script, so it won't be called anymore once it is vanished and couldn't cause trouble anymore.

Here are some code example from my own scripts.

In the script of the master enemy:
Code: [Select]
//at the beginning of the script

    SetCommonData("Damage", 0);

//in the @MainLoop
AddLife(GetCommonData("Damage"));
SetCommonData("Damage", 0);
In the script of the slaves:
Code: [Select]
//at the beginning of the script

    let hp=50;
    let hpcheck=false;

 //in the @Initialize
hpcheck=true;
hp=GetLife;

//in the @MainLoop
if(hpcheck==true){
if(OnBomb==false){ SetCommonData("Damage", GetCommonData("Damage")+GetLife-hp); }
hp=GetLife;
}

Of course, in your case you would need one separate CommonData for each of the enemies that are on screen at once, in this case one "DamageLeft" and "DamageRight", for example.
If you want to reduce the damage the slaves do to the parent enemy, you can simply include a factor of 0.5 or something to either the damage transferring or the damage receiving part of the script.
« Last Edit: March 14, 2010, 10:59:52 PM by Iryan »
Old Danmakufu stuff can be found here!

"As the size of an explosion increases, the numbers of social situations it is incapable of solving approaches zero."

Kylesky

  • *The Unknown*
  • Local Unbalanced Danmakufu Idiot Scripter
    • My useless youtube account... (will be useful in the future *I promise*)
Re: Danmakufu Q&A/Problem Thread v3
« Reply #426 on: March 15, 2010, 02:51:34 PM »
How do you get a certain number of random integer variables and make sure that they're not equal?

let's say we have this

Code: [Select]
let a=rand_int(1, 6);
let b=rand_int(1, 6);
let c=rand_int(1, 6);
let d=rand_int(1, 6);

how can you make sure that a!=b!=c!=d?

All I can think of is

Code: [Select]
let a=rand_int(1, 6);
let b;
ascent(i in 1..7)
{
let num=rand_int(1, 6);
if(num!=i)
{
b=num;
}
}
...

or something like that... but it doesn't always guarantee a proper outcome... :ohdear:

EDIT: or is this something that can make use of the Break function? I'm not sure how it's used

Code: [Select]

let a;
let b;
a=rand_int(1, 6);
loop
{
b=rand_int(1, 6);
if(a!=b)
{
break;
}
}
???

EDIT2: nevermind! I got it working!!! It actually IS the break function :D
« Last Edit: March 15, 2010, 02:58:14 PM by Kylesky »
Danmakufu Script Thread :V Latest Script: Intertwining Mechanical Intervention (temp name)

Yooooouuutuuuubeeee Channel Latest Video: Contest #8 Entry

Blargel

  • RAWR!
  • I'M AN ANGRY LOLI!
Re: Danmakufu Q&A/Problem Thread v3
« Reply #427 on: March 15, 2010, 03:06:31 PM »
How do you get a certain number of random integer variables and make sure that they're not equal?

let's say we have this

Code: [Select]
let a=rand_int(1, 6);
let b=rand_int(1, 6);
let c=rand_int(1, 6);
let d=rand_int(1, 6);

how can you make sure that a!=b!=c!=d?

All I can think of is

Code: [Select]
let a=rand_int(1, 6);
let b;
ascent(i in 1..7)
{
let num=rand_int(1, 6);
if(num!=i)
{
b=num;
}
}
...

or something like that... but it doesn't always guarantee a proper outcome... :ohdear:

EDIT: or is this something that can make use of the Break function? I'm not sure how it's used

Code: [Select]

let a;
let b;
a=rand_int(1, 6);
loop
{
b=rand_int(1, 6);
if(a!=b)
{
break;
}
}
???

The quickest way to do it is like this:
Code: [Select]
let a = rand_int(1, 5);
let b = rand_int(1, 5);
let c = rand_int(1, 5);
let d = rand_int(1, 5);
while(a == b){b = rand_int(1, 5);}
while(a == c || b == c){c = rand_int(1, 5);}
while(a == d || b == d || c == d){d = rand_int(1, 5);}

However, if you end up needing to make sure a large amount of variables are unique, you'll need a different method or else you'll have to write a bunch of extra redundant code. The "better" way to handle this would be like this:
Code: [Select]
let randomArray;
ascent(i in 1..6){
    randomArray ~ [i];
}
// randomArray now contains the numbers from 1 to 5. Obviously you can
// change the numbers in the ascent to suit your purposes.

let a = unique_rand_int;
let b = unique_rand_int;
let c = unique_rand_int;
let d = unique_rand_int;

// This function removes a value from the randomArray before returning it so
// it will guarantee uniqueness. However, beware of when the array becomes
// empty because you will get an error when using the function.
function unique_rand_int {
    let indx = rand_int(0, length(randomArray)-1);
    let value = randomArray[indx];
    erase(randomArray, indx);
    return value;
}
This is a lot of extra code for what you were going for, but if you needed to pick an integer between 1 and 100 for 50 variables or something like that, this would be shorter.
<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

  • *The Unknown*
  • Local Unbalanced Danmakufu Idiot Scripter
    • My useless youtube account... (will be useful in the future *I promise*)
Re: Danmakufu Q&A/Problem Thread v3
« Reply #428 on: March 15, 2010, 03:09:29 PM »
The quickest way to do it is like this:
Code: [Select]
let a = rand_int(1, 5);
let b = rand_int(1, 5);
let c = rand_int(1, 5);
let d = rand_int(1, 5);
while(a == b){b = rand_int(1, 5);}
while(a == c || b == c){c = rand_int(1, 5);}
while(a == d || b == d || c == d){d = rand_int(1, 5);}

However, if you end up needing to make sure a large amount of variables are unique, you'll need a different method or else you'll have to write a bunch of extra redundant code. The "better" way to handle this would be like this:
Code: [Select]
let randomArray;
ascent(i in 1..6){
    randomArray ~ [i];
}
// randomArray now contains the numbers from 1 to 5. Obviously you can
// change the numbers in the ascent to suit your purposes.

let a = unique_rand_int;
let b = unique_rand_int;
let c = unique_rand_int;
let d = unique_rand_int;

// This function removes a value from the randomArray before returning it so
// it will guarantee uniqueness. However, beware of when the array becomes
// empty because you will get an error when using the function.
function unique_rand_int {
    let indx = rand_int(0, length(randomArray)-1);
    let value = randomArray[indx];
    erase(randomArray, indx);
    return value;
}
This is a lot of extra code for what you were going for, but if you needed to pick an integer between 1 and 100 for 50 variables or something like that, this would be shorter.

oh... why didn't I think of using while... it's just for a small number of variables anyway... at least I solved it using a different way myself :D Thanks!
Danmakufu Script Thread :V Latest Script: Intertwining Mechanical Intervention (temp name)

Yooooouuutuuuubeeee Channel Latest Video: Contest #8 Entry

Re: Danmakufu Q&A/Problem Thread v3
« Reply #429 on: March 15, 2010, 03:46:28 PM »
Posting code for bullets that properly reflect along the border for doods on IRC. Delete any undesirable chunk of reflect code.

task RShot(orix, oriy, velocity, angletaken, graphic, bounces){
   let getxa;
   let getya;
   let anglereflex;
   let reflectcount = 0;
   let objshot = Obj_Create(OBJ_SHOT); //Set all information.
   Obj_SetPosition(objshot, orix, oriy);
   ObjShot_SetGraphic(objshot, graphic);
   Obj_SetSpeed(objshot, velocity);
   Obj_SetAngle(objshot, angletaken);
   while(!Obj_BeDeleted(objshot)){ //While the object shot exists, do all this.
      getxa = Obj_GetX(objshot); //Store the object shot's coordinates in variables for easy reference.
      getya = Obj_GetY(objshot);
      if(getxa < GetClipMinX && reflectcount < bounces){ //Reflect on the left border.
         anglereflex = -angletaken+180; //Reflection formula for x axis.
         let position = GetClipMinX - Obj_GetX(objshot); //Adjust for any lost distance beyond the border.
         Obj_SetX(objshot, GetClipMinX + position);
         Obj_SetAngle(objshot, anglereflex);
         angletaken = anglereflex;
         reflectcount++;
      }
      if(getxa > GetClipMaxX && reflectcount < bounces){ //Reflect on the right border.
         anglereflex = -angletaken+180; //Reflection formula for x axis.
         let position = GetClipMaxX - Obj_GetX(objshot); //Adjust for any lost distance beyond the border.
         Obj_SetX(objshot, GetClipMaxX + position);
         Obj_SetAngle(objshot, anglereflex);
         angletaken = anglereflex;
         reflectcount++;
      }
      if(getya < GetClipMinY && reflectcount < bounces){ //Reflect on the top border.
         anglereflex = -angletaken; //Reflection formula for y axis.
         let position = GetClipMinY - Obj_GetY(objshot); //Adjust for any lost distance beyond the border.
         Obj_SetY(objshot, GetClipMinY + position);
         Obj_SetAngle(objshot, anglereflex);
         angletaken = anglereflex;
         reflectcount++;
      }
      if(getya > GetClipMaxY && reflectcount < bounces){ //Reflect on the bottom border.
         anglereflex = -angletaken; //Reflection formula for y axis.
         let position = GetClipMaxY - Obj_GetY(objshot); //Adjust for any lost distance beyond the border.
         Obj_SetY(objshot, GetClipMaxY + position);
         Obj_SetAngle(objshot, anglereflex);
         angletaken = anglereflex;
         reflectcount++;
      }
      yield;
   }
}


The variable bounces is highlighted, this is to show that you may change how many times you want a bullet to bounce.
« Last Edit: March 16, 2010, 09:16:00 PM by Naut »

Chronojet ⚙ Dragon

  • The Oddity
  • 今コソ輝ケ、我ガ未来、ソノ可能性!!
Re: Danmakufu Q&A/Problem Thread v3
« Reply #430 on: March 18, 2010, 04:37:22 AM »
Gah, how do you make a loading screen, with a background, a "this much has loaded" bar, etc.?

Re: Danmakufu Q&A/Problem Thread v3
« Reply #431 on: March 18, 2010, 04:46:49 AM »
Stage script, effect objects/drawn images in @BackGround. Effect objects will allow you to draw over the STG_Frame though, so I recommend those. For the loading bar, you'll just want to Load all your shit in different frames, like this:

yield;
LoadGraphic(bigspritesheet.png);
yield;
LoadMusic(awesomemusic.mp3);
yield;
CompileEnemyFromFile(boss.txt);
yield;
StartStage;

During all those yield statements, have a graphic that slowly gets larger to "show" the user how much has loaded. This is really the only way to accomplish this effect.

Stuffman

  • *
  • We're having a ball!
Re: Danmakufu Q&A/Problem Thread v3
« Reply #432 on: March 18, 2010, 08:33:11 AM »
I'm pretty sure Naut is right about that being the only way, since even if you load stuff as a task the code can't get around to the drawloop without a yield.

It seems like a dumb thing to do since all those yields will just increase loading time.

As a side note, I have no idea why CtC takes so long to load, it doesn't seem like it uses that much media.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
Re: Danmakufu Q&A/Problem Thread v3
« Reply #433 on: March 18, 2010, 12:17:28 PM »
Normally a loading bar is a useful thing, but seeing that in Danmakufu's case it is only annoyance I don't see why people are trying to implement it. Rather have a loading animation like in UB (bubbling sake gourd) or some kind of spinning stuff just to make the loading screen more enjoyable.

Otherwise the classic black screen + Loading... suffices more than enough.

Gc

  • youtu.be/pRZpjlrKM8A
Re: Danmakufu Q&A/Problem Thread v3
« Reply #434 on: March 18, 2010, 02:29:29 PM »
Gah, how do you make a loading screen, with a background, a "this much has loaded" bar, etc.?
Here's how I made mine:
Code: [Select]
task LoadScreen {
Wait(1);

LoadGraphic(CSD ~ "img\LOADING.BG.png");
LoadGraphic(CSD ~ "img\LOADING.BAR.png");

let content = length(img) + length(sfx) + length(bgm);
let progress = 0;

LoadScreenBackground(content);

ascent(i in 0..length(img)) {
LoadGraphic(img[i]);
LoadScreenLoader(430, 395, 610, 410, progress + 1, content);
LoadScreenLoader(430, 435, 610, 450, i + 1, length(img));
progress ++;
Wait(1);
}

ascent(i in 0..length(sfx)) {
LoadSE(sfx[i]);
LoadScreenLoader(430, 395, 610, 410, progress + 1, content);
LoadScreenLoader(430, 435, 610, 450, i + 1, length(sfx));
progress ++;
Wait(1);
}

ascent(i in 0..length(bgm)) {
LoadMusic(bgm[i]);
LoadScreenLoader(430, 395, 610, 410, progress + 1, content);
LoadScreenLoader(430, 435, 610, 450, i + 1, length(bgm));
progress ++;
Wait(1);
}

DeleteGraphic(CSD ~ "img\LOADING.BG.png");
DeleteGraphic(CSD ~ "img\LOADING.BAR.png");

MenuScreen(1);

task LoadScreenBackground(let length) {
let obj = Obj_Create(OBJ_EFFECT);
Obj_SetPosition(obj, 0, 0);

ObjEffect_SetTexture(obj, CSD ~ "img\LOADING.BG.png");
ObjEffect_SetRenderState(obj, ALPHA);
ObjEffect_SetPrimitiveType(obj, PRIMITIVE_TRIANGLEFAN);
ObjEffect_SetLayer(obj, 8);
ObjEffect_CreateVertex(obj, 4);

ObjEffect_SetVertexUV(obj, 0, 0, 0);
ObjEffect_SetVertexUV(obj, 1, 640, 0);
ObjEffect_SetVertexUV(obj, 2, 640, 480);
ObjEffect_SetVertexUV(obj, 3, 0, 480);

loop(length) {
ObjEffect_SetVertexXY(obj, 0, 0, 0);
ObjEffect_SetVertexXY(obj, 1, 640, 0);
ObjEffect_SetVertexXY(obj, 2, 640, 480);
ObjEffect_SetVertexXY(obj, 3, 0, 480);
Wait(1);
}

Obj_Delete(obj);
}

task LoadScreenLoader(let x1, let y1, let x2, let y2, let progress, let total) {
let totalWidth = x2 - x1;
let currentWidth = (progress / total) * totalWidth;

let obj = Obj_Create(OBJ_EFFECT);
Obj_SetPosition(obj, 0, 0);

ObjEffect_SetTexture(obj, CSD ~ "img\LOADING.BAR.png");
ObjEffect_SetRenderState(obj, ALPHA);
ObjEffect_SetPrimitiveType(obj, PRIMITIVE_TRIANGLEFAN);
ObjEffect_SetLayer(obj, 8);
ObjEffect_CreateVertex(obj, 4);

ObjEffect_SetVertexUV(obj, 0, 0, 0);
ObjEffect_SetVertexUV(obj, 1, 16, 0);
ObjEffect_SetVertexUV(obj, 2, 16, 16);
ObjEffect_SetVertexUV(obj, 3, 0, 16);

ObjEffect_SetVertexXY(obj, 0, x1, y1);
ObjEffect_SetVertexXY(obj, 1, x1 + currentWidth, y1);
ObjEffect_SetVertexXY(obj, 2, x1 + currentWidth, y2);
ObjEffect_SetVertexXY(obj, 3, x1, y2);

Wait(1);

Obj_Delete(obj);
}
}

The problem with that is that img, sfx and bgm (all arrays) can't be empty otherwise you get a division by 0.

It DOES make the loading longer, but I'd much rather have a longer load time than a crash because I try to load everything in one frame.

Also, inefficient code blah blah blah weird indenting blah blah blah

Here are all 3 arrays I used as an example :
Code: [Select]
let img = [
CSD ~ "img\MENU.BG.png",
CSD ~ "img\MENU.CHOICE.1.png",
CSD ~ "img\MENU.CHOICE.2.png",
CSD ~ "img\STAGE.CHANGE.BG.png",
CSD ~ "img\STAGE.CHANGE.BONUS.png",
CSD ~ "img\STAGE.CHANGE.PRESS.png"
];

let sfx = [
CSD ~ "sfx\MENU.MOVE.wav",
CSD ~ "sfx\MENU.SELECT.wav",
CSD ~ "sfx\STAGE.CHANGE.wav",
CSD ~ "sfx\BOSS.SNIPER.KILL.0.wav",
CSD ~ "sfx\BOSS.SNIPER.KILL.1.wav",
CSD ~ "sfx\BOSS.SNIPER.KILL.2.wav",
CSD ~ "sfx\BOSS.SNIPER.DEATH.wav",
CSD ~ "sfx\BOSS.SPY.KILL.0.wav",
CSD ~ "sfx\BOSS.SPY.KILL.1.wav",
CSD ~ "sfx\BOSS.SPY.KILL.2.wav",
CSD ~ "sfx\BOSS.SPY.DEATH.wav",
CSD ~ "sfx\BOSS.SCOUT.KILL.0.wav",
CSD ~ "sfx\BOSS.SCOUT.KILL.1.wav",
CSD ~ "sfx\BOSS.SCOUT.KILL.2.wav",
CSD ~ "sfx\BOSS.SCOUT.DEATH.wav",
CSD ~ "sfx\BOSS.MEDIC.DEATH.wav",
CSD ~ "sfx\BOSS.ENGINEER.DEATH.wav",
CSD ~ "sfx\BOSS.DEMOMAN.KILL.0.wav",
CSD ~ "sfx\BOSS.DEMOMAN.KILL.1.wav",
CSD ~ "sfx\BOSS.DEMOMAN.KILL.2.wav",
CSD ~ "sfx\BOSS.DEMOMAN.DEATH.wav",
CSD ~ "sfx\BOSS.PYRO.DEATH.wav",
CSD ~ "sfx\BOSS.DEMOMAN.KILL.0.wav",
CSD ~ "sfx\BOSS.DEMOMAN.KILL.1.wav",
CSD ~ "sfx\BOSS.DEMOMAN.KILL.2.wav",
CSD ~ "sfx\BOSS.DEMOMAN.DEATH.wav",
CSD ~ "sfx\BOSS.HEAVY.KILL.0.wav",
CSD ~ "sfx\BOSS.HEAVY.KILL.1.wav",
CSD ~ "sfx\BOSS.HEAVY.KILL.2.wav",
CSD ~ "sfx\BOSS.HEAVY.DEATH.wav",
];

let bgm = [
CSD ~ "bgm\MENU.BGM.mp3"
];
(I can't say I'm done making images or finding sfx and bgm...)

Re: Danmakufu Q&A/Problem Thread v3
« Reply #435 on: March 18, 2010, 08:42:31 PM »
Replacing SetDamageRateEx with SetDamageRate did not solve the problem. Also, problem was observed when killing an enemy that was fully on screen.

At this point, if it wasn't for the fact that CtC works without this error, I'd chalk it up to unreconciliable flaws in Danmakufu's internal logic. Maybe if I make them all independent enemies instead of slaves, and associate them purely by common data?

Iryan

  • Ph?nglui mglw?nafh
  • Cat R?lyeh wgah?nagl fhtagn.
Re: Danmakufu Q&A/Problem Thread v3
« Reply #436 on: March 18, 2010, 09:51:46 PM »
@ professor_scissors

Ha!

After tinkering around with your script I think I figured out where the problem lies.

Apparently, danmakufu goes insane when you call CreateEnemyFromScript in the @Initialize part of the parent enemy. I "outsourced" the slave creation from the @Initialize to a task that simply read
Code: [Select]
task TSpawn{
yield;
ascent(i in 0..4) {
SetCommonData("Enemy01Side", id);
CreateEnemyFromScript("Familiar", GetX, GetY, 0, 0, i*90);
}
}
And now the error doesn't seem to appear anymore.

What got my attention was a strange occurance when I played around with the enemies' health. After making the main enemy tough and the slaves weak, I noticed that one of the slaves was much tougher than the others. So I tried this, and it seemed to work.

To be precise, the full code that is working for me right now is this:
Code: [Select]
script_enemy_main
{ //Slave-having enemy
   let imgEnemy=GetCurrentScriptDirectory~"img\Enemy.png";
   let imgAngle=0;
   let shotAngle=0;
   let id = GetArgument;
   
   function wait(n) {
      loop(n) { yield; }
   }

   task TMove {
      while(GetX < GetClipMaxX + 51 && GetX > GetClipMinX - 51) {
         if(GetSpeed > 0.5) {
            SetSpeed(GetSpeed - 0.05);
         }
         yield;
      }
      VanishEnemy;
   }

task TSpawn{
yield;

ascent(i in 0..4) {
SetCommonData("Enemy01Side", id);
CreateEnemyFromScript("Familiar", GetX, GetY, 0, 0, i);
}
}


   @Initialize
   {
      SetLife(10);
SetDamageRate(100, 100);

LoadGraphic(imgEnemy);
     
      if(id) {
         SetCommonData("Enemy01LeftX", GetX);
         SetCommonData("Enemy01LeftY", GetY);
         SetCommonData("Enemy01LeftDead", false);
         SetAngle(30);
         SetSpeed(5);
      } else {
         SetCommonData("Enemy01RightX", GetX);
         SetCommonData("Enemy01RightY", GetY);
         SetCommonData("Enemy01RightDead", false);
         SetAngle(150);
         SetSpeed(5);
      }
      TSpawn;
      TMove;
   }
   
   @MainLoop
   {
       SetCollisionA(GetX, GetY, 16);
        SetCollisionB(GetX, GetY, 16);
      if(id) {
         SetCommonData("Enemy01LeftX", GetX);
         SetCommonData("Enemy01LeftY", GetY);
      } else {
         SetCommonData("Enemy01RightX", GetX);
         SetCommonData("Enemy01RightY", GetY);
      }
      yield;
   }
   
   @Finalize
   {
//      if(id) {
//         SetCommonData("Enemy01LeftDead", true);
//      } else {
//         SetCommonData("Enemy01RightDead", true);
//      }
      CreateItem(ITEM_SCORE, GetX + rand(-10,10), GetY + rand(10,10));
   }
   
   @DrawLoop
   {//
      SetTexture(imgEnemy);
      SetGraphicRect(1,1,32,32);
      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetGraphicAngle(0,0,imgAngle);
      DrawGraphic(GetX(),GetY());

      SetTexture(imgEnemy);
      SetGraphicRect(1,1,32,32);
      SetColor(255,255,255);
      SetRenderState(ADD);
      SetGraphicAngle(0,0,-imgAngle);
      DrawGraphic(GetX(),GetY());
      imgAngle+=4;
      if(imgAngle>360){imgAngle-=360;}
   }
}

script_enemy Familiar {
   let ImgFam = GetCurrentScriptDirectory ~ "img\Enemy.png";
   let imgAngle=0;
   let angle = (GetArgument)*90;
   let id = GetCommonData("Enemy01Side");
   
   function wait(w) {
      loop(w) { yield; }
   }


    @Initialize {
        SetLife(10);
        SetDamageRate(100, 100);

        TRotate;
        TFire;
    }

    @MainLoop {
       SetCollisionA(GetX, GetY, 8);
        SetCollisionB(GetX, GetY, 8);
      if(id) {
         if(GetCommonDataDefault("Enemy01LeftDead", true)||BeParentVanished==true) {
            VanishEnemy;
         }
      } else {
         if(GetCommonDataDefault("Enemy01RightDead", true)||BeParentVanished==true) {
            VanishEnemy;
         }
      }
       yield;
    }

   @DrawLoop
   {//
      SetTexture(ImgFam);
      SetGraphicRect(1,1,32,32);
      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetGraphicAngle(0,0,imgAngle);
      DrawGraphic(GetX(),GetY());

      SetTexture(ImgFam);
      SetGraphicRect(1,1,32,32);
      SetColor(255,255,255);
      SetRenderState(ADD);
      SetGraphicAngle(0,0,-imgAngle);
      DrawGraphic(GetX(),GetY());
      imgAngle+=4;
      if(imgAngle>360){imgAngle=0;}
   }

    @Finalize
   {//
      CreateItem(ITEM_SCORE, GetX + rand(-10,10), GetY + rand(10,10));
   }

   // rotate around the boss
    task TRotate {
      let eX = 0;
      let eY = 0;
      loop {
         if(id) {
            eX = GetCommonDataDefault("Enemy01LeftX", -50);
            eY = GetCommonDataDefault("Enemy01LeftY", -50);
         } else {
            eX = GetCommonDataDefault("Enemy01RightX", -50);
            eY = GetCommonDataDefault("Enemy01RightY", -50);
         }
         SetX(eX + cos(angle) * 50);
         SetY(eY + sin(angle) * 50);
         yield;
         angle += 1.5;
      }
   }

    task TFire {
        loop {
         CreateShot01(GetX, GetY, 1.5, angle+180, RED01, 10);
         CreateShot01(GetX, GetY, 2, angle+180, ORANGE01, 10);
            wait(36);
        }
    }
}

It contains a number of other small differences, some of which may have had a positive effect on the performance of the script, so when you still get errors, copypaste the entire script. I didn't implement the damaging of the main enemy through the slaves yet, though.

Among other things, you had SetGraphicRect and other drawing related functions inside the @Initialize parts of the scripts. Generally, you call these in the @DrawLoop once for each individual call of DrawGraphic. Also, you still had SetScore(0); in your slave scripts, which as I said doesn't do anything except maybe cause additinal problems.

Also, you should load the data for the enemies (graphics and sounds) at the beginning of the stage you want to use them in. Otherwise you'll load the stuff into memory mutliple times and cause slight slow down when the enemies appear.
« Last Edit: March 18, 2010, 10:02:15 PM by Iryan »
Old Danmakufu stuff can be found here!

"As the size of an explosion increases, the numbers of social situations it is incapable of solving approaches zero."

Iryan

  • Ph?nglui mglw?nafh
  • Cat R?lyeh wgah?nagl fhtagn.
Re: Danmakufu Q&A/Problem Thread v3
« Reply #437 on: March 18, 2010, 10:00:47 PM »
Old Danmakufu stuff can be found here!

"As the size of an explosion increases, the numbers of social situations it is incapable of solving approaches zero."

Drake

  • *
Re: Danmakufu Q&A/Problem Thread v3
« Reply #438 on: March 18, 2010, 10:52:21 PM »
In general, it is not a good idea to throw in any function that doesn't "have" to go into @Initialize, in it. (Read: SetLife, SetTimer, SetScore, etc)
Just wait a frame or two and use a task.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Chronojet ⚙ Dragon

  • The Oddity
  • 今コソ輝ケ、我ガ未来、ソノ可能性!!
Re: Danmakufu Q&A/Problem Thread v3
« Reply #439 on: March 18, 2010, 11:27:18 PM »
I'd like to refer you to the GetPointToLine(ox, oy, p1x, p1y, p2x, p2y); function.
W-w-what?
..... I'm wrapping my brain around how to use this function in this, so help me, Eirin.

EDIT: Ah, fuck. I can't get it. I'll use Collision_Line_Circle instead...
EDIT!!: It* works!

* Collision_Line_Circle
« Last Edit: March 19, 2010, 12:19:35 AM by Always 無⑨ »

Iryan

  • Ph?nglui mglw?nafh
  • Cat R?lyeh wgah?nagl fhtagn.
Re: Danmakufu Q&A/Problem Thread v3
« Reply #440 on: March 19, 2010, 12:15:00 PM »
My idea would've been...

Code: [Select]
function Killzone(x, y, ang, length, width){

//the distance from the center in the direction of the length
let d1= (| GetPointToLine(GetPlayerX, GetPlayerY, x, y, x+cos(ang+90), y+sin(ang+90)) |);

//the distance from the center in the direction of the width
let d2= (| GetPointToLine(GetPlayerX, GetPlayerY, x, y, x+cos(ang), y+sin(ang)) |);

//if the player is in the boundaries, he is killed
if(d1<0.5*length && d2<0.5*width){ ShootDownPlayer; }

}
...where (x|y) is the center of the zone and the zone has the dimensions of length*width and is aligned according to the angle.

But if your code works... nevermind...


Edit: Blargh, put GetX instead of GetPlayerX in the code. Should work now.
« Last Edit: March 19, 2010, 12:28:46 PM by Iryan »
Old Danmakufu stuff can be found here!

"As the size of an explosion increases, the numbers of social situations it is incapable of solving approaches zero."

Azure Lazuline

  • Looooove!!
  • PM me for free huggles and love!
    • Entanma Project - indie game development
Re: Danmakufu Q&A/Problem Thread v3
« Reply #441 on: March 19, 2010, 06:55:42 PM »
You should first make sure the player's not invincible before you kill them.

Re: Danmakufu Q&A/Problem Thread v3
« Reply #442 on: March 19, 2010, 10:48:46 PM »
wall o' text
Aha! This worked, finally. Thank you very much!

TwiliAezure

Re: Danmakufu Q&A/Problem Thread v3
« Reply #443 on: March 20, 2010, 12:42:51 AM »
I just wanna ask, is it possible to Fire one kind of shot from one option and fire a different type on the other?
Like this... (Fire on left, Knives on right)

Gc

  • youtu.be/pRZpjlrKM8A
Re: Danmakufu Q&A/Problem Thread v3
« Reply #444 on: March 20, 2010, 12:47:27 AM »
I just wanna ask, is it possible to Fire one kind of shot from one option and fire a different type on the other?
Like this... (Fire on left, Knives on right)

Add an argument to your option task
Code: [Select]
task WhateverYourOptionTaskIs(bullet) {then use "bullet" without quotes to use the predefined bullet graphic

TwiliAezure

Re: Danmakufu Q&A/Problem Thread v3
« Reply #445 on: March 20, 2010, 03:01:28 AM »
Add an argument to your option task
Code: [Select]
task WhateverYourOptionTaskIs(bullet) {then use "bullet" without quotes to use the predefined bullet graphic

Thanks a lot, MokouTan!
I'm not sure what argument to put in and I don't know exactly where to put it... Sorry, I'm such a noob.  :ohdear:
(There's FOUR options!)
« Last Edit: March 20, 2010, 03:28:32 AM by TwiliAezure »

Re: Danmakufu Q&A/Problem Thread v3
« Reply #446 on: March 20, 2010, 04:01:08 AM »
Well he mains something like this:

task Option(bullet){
   let objoption = Obj_Create(OBJ_EFFECT);
   //etc.
   while(!Obj_BeDeleted(objoption)){
      //etc.
      FireShot(x, y, velocity, angle, bullet);
      yield;
   }
}


Then, in @Initialize or wherever you call your Options, you can say:

Option(1);
Option(2);
Option(3);
Option(4);

So that one option will use the bullet graphic 1, the other 2, the next 3, the last 4. The arguments you create in your tasks can be passed around within that task, which makes it useful for modifying the task without actually rewriting it. For more on tasks, read up on them in the Intermediate Tutorial.

FireShot isn't actually a function in player scripting, by the way.

Blargel

  • RAWR!
  • I'M AN ANGRY LOLI!
Re: Danmakufu Q&A/Problem Thread v3
« Reply #447 on: March 20, 2010, 04:08:15 AM »
task Option(bullet){
   let objoption = Obj_Create(OBJ_EFFECT);
   //etc.
   while(!Obj_BeDeleted(objoption)){
      //etc.
      FireShot(x, y, velocity, angle, bullet);
      yield;
   }
}


You know, I've noticed this in a few of your other posts, but holy shit you syntax color your fucking code on the forums. Obviously, you have too much time on your hands. As if most of us don't... we're just lazy.
<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.

Re: Danmakufu Q&A/Problem Thread v3
« Reply #448 on: March 20, 2010, 04:09:15 AM »
Took me all of thirty seconds for that post :S

TwiliAezure

Re: Danmakufu Q&A/Problem Thread v3
« Reply #449 on: March 20, 2010, 04:14:00 AM »
Oooooooooooh! Thanks, Naut!