Dynamically Created Object for Bullet Splash (Solved)

Started by ryandebraal, Sun 24/02/2013 11:25:59

Previous topic - Next topic

ryandebraal

I am Trying to create a "bullet splash" where when I click somewhere on the screen a little "explosion" goes off.

Currently, each Room has an Object in it that contains the sprite, and when I click it plays the sprite.

Is it possible to dynamically create this object on the fly, play it's animation once and then dispose of it?

Here is my current implementation being executed continuously in function room_RepExec() :

Code: AGS

function CheckGunFire() {
     
//Check for GunFire
     if(Mouse.IsButtonDown(eMouseLeft) && Mouse.Mode == eModeReticle && intAmmo >= 1) {
          
      bulletspark.SetPosition(mouse.x - 14,  mouse.y + 18);
      bulletspark.SetView(4);
      bulletspark.Animate(0, 0, eOnce, eNoBlock, eForwards);
      bulletspark.Visible = true;
     }      
}
       

Khris

No, you can't add Objects during run-time.
What you can do is store the object data in arrays (or an array of structs) and display them by drawing them to the room background or a blank GUI's background.

ryandebraal

Thanks Khris, but I'm a little confused by what you mean.

Are you saying I can create Object(s) in the GlobalScript.asc file and then call them to be painted in an individual room?

Could you show me code to explain your suggestion? Thanks :)

Khris

By "object data" I meant "general entity data", not "AGS Object data".
You can't create objects in scripts, you have to add them to a room in the room editor.

Each bullet spark needs a few variables, like x and y position and animation frame. You can create a data structure that's capable of storing multiple bullet sparks.
Code: ags
int bulletspark_x[50], bulletspark_y[50], bulletspark_frame[50];


This code creates 50 x variables, 50 y variables and 50 frame variables.
Each time a bullet spark is supposed to be added, you look through all the 50 sets, looking for an unused one. When you find one, you store the data in the three variables.

In the repeatedly_execute function, again you iterate through all 50 sets, looking for active ones. Those are displayed, their frame is advanced, and when the animation has finished, frame is set to -1 to tell AGS that the set is available again.
That way you can display lots of dynamic stuff on the screen without using any of AGS's potentially limited resources like Objects.

ryandebraal

Thanks, I understand now :)

Luckily, I only need 1 bullet spark. The bullet being fired by the Player Character.

Regardless, each room will need it's own a "bullet spark" object to display, if I understood you correctly?

If for example, I wanted firefights between multiple participants you are suggesting saving the "bullet sparks" position and animation progress in arrays to quickly be able to assign and execute them, then afterward going through the array and emptying it of data?

My current implementation takes an existing object in the room and animates it while I have bullets remaining (global variable) and only executes if a mouse_up is detected so it's not auto-firing a whole clip in a fraction of a second.

Code: AGS
bool bFiring = false;
function CheckGunFire() {
   
//Check for GunFire
     if(Mouse.IsButtonDown(eMouseLeft) && Mouse.Mode == eModeReticle && !bFiring) {
          bFiring = true;
          
          if (intAmmo >= 1) {
               
          intAmmo -= 1;
          String ammo = "x "; ammo = ammo.Append(String.Format("%d", intAmmo));
          lblAmmoCount.Text = ammo;
          
          bulletspark.SetPosition(mouse.x - 14,  mouse.y + 18);
          bulletspark.SetView(4);
          bulletspark.Animate(0, 0, eOnce, eNoBlock, eForwards);
          bulletspark.Visible = true;  
               
          } else { cPlayer.SayBackground("I'm outta ammo!"); }
         
     } else if(!Mouse.IsButtonDown(eMouseLeft) && Mouse.Mode == eModeReticle) { bFiring = false; }
        
}

Khris

If there isn't more than one bullet spark at any given time, you don't need anything I mentioned in my previous post.

If you need the same object in every room, you might want to use a character instead. Unlike objects, they are room independent, so you won't end up creating the same object in every room.
You can animate characters just like objects, and you can move them to the current room like this:

Code: ags
  cBulletspark.ChangeRoom(player.Room);

ryandebraal

Nice! That is a much more elegant solution!

And since characters can be refred to from GlobalScript I can put that function in there and just call it on each room

Khris

You can reference objects from the global script btw, you have to use the object array though:

Code: ags
  object[0].X += 10;  // move first object in current room 10 pixels to the right


You can also call your function in the global script instead of putting the same code into every room script. Move it above repeatedly_execute, then inside, call:

Code: ags
  if (player.Room >= 2 && player.Room <= 10) CheckGunFire();


Rule of thumb: whenever you use the same or very similar code in multiple places, you're doing it wrong.

SMF spam blocked by CleanTalk