Is it possible to draw on a sprite?

Started by MiteWiseacreLives!, Wed 07/12/2016 08:14:12

Previous topic - Next topic

MiteWiseacreLives!

So what I'm trying to do is use dynamic sprites to help me alter sprites in my game, then those sprites will be used in character views.
ie: I want to draw a hat on each frame of a walk cycle.
I searched the forums and manual, and created this abomination that makes the game crash:
Code: ags

void Swapper(int swapX, int swapY)
{
 Character *SwapChar;
 SwapChar = Character.GetAtScreenXY(swapX, swapY); 
 if (SwapChar == cNpc)
 {
   DynamicSprite *frame1 = DynamicSprite.CreateFromExistingSprite(37);
   DrawingSurface *surface = frame1.GetDrawingSurface();
   surface.DrawImage(35, 110, 17);
   surface.Release();
   ViewFrame *head = Game.GetViewFrame(SwapChar.View, 0, 0);
   head.Graphic = frame1.Graphic;
   frame1.Delete();
   Display("drew on sprite");
 }
}


help.

MiteWiseacreLives!

Here's what i was able to make work:

Code: ags

// main global script file
DynamicSprite *frame1;

void Swapper(int swapX, int swapY)
{
 Character *SwapChar;
 SwapChar = Character.GetAtScreenXY(swapX, swapY); 
 if (SwapChar == cNpc)
 {
   frame1 = DynamicSprite.CreateFromExistingSprite(37);
   DrawingSurface *surface = frame1.GetDrawingSurface();
   surface.DrawImage(32, -23, 17);
   surface.Release();
   ViewFrame *head = Game.GetViewFrame(SwapChar.View, 0, 0);
   head.Graphic = frame1.Graphic;
   //frame1.Delete();
   Display("drew on sprite");
 }
}

-declared the DynamicSprite outside of the function
-did not delete it.

so now the questions are:
1) Can I do this for a dozen frames for a dozen characters without some kind of memory leak?
2) Is it possible to write over the sprite slot and then delete the dynamic sprite so I don't have to hold them in RAM? and don't have to have arrays of DynamicSprites?

Thanks for your help

Crimson Wizard

#2
Quote from: MiteWiseacreLives! on Wed 07/12/2016 08:34:03
so now the questions are:
1) Can I do this for a dozen frames for a dozen characters without some kind of memory leak?
I do not quite understand the reason behind this question (nevermind, I think I got where it was coming from), but technically DynamicSprites cannot cause memory leaks, because they are automatically deleted as soon as the last reference to them is gone.
That is:
Code: ags

DynamicSprite *spr;
spr = DynamicSprite.Create(100,100); // create sprite 1
spr = DynamicSprite.Create(200,200); // sprite 1 is deleted at this point, because its only reference is lost.


Quote from: MiteWiseacreLives! on Wed 07/12/2016 08:34:03
2) Is it possible to write over the sprite slot and then delete the dynamic sprite so I don't have to hold them in RAM? and don't have to have arrays of DynamicSprites?
You MUST keep all the DynamicSprites. The frame itself does not hold the actual sprite. When you assign frame's Graphic, you do not copy DynamicSprite, neither draw it, you assign its ID. That frame will show up properly only so long as DynamicSprite is not deleted. If you delete DynamicSprite without changing frame's Graphic to something else, your game may crash.

MiteWiseacreLives!

Thanks for your help CR
I think I get it now. Was hoping to be able to manipulate the original sprites, but now I see that is not possible.

What I think I will do is make a large array of DynamicSprites to correspond with each ViewFrame of the characters so that I can redraw them as I need
(end goal is to be able to layer on different hats and glasses, like Mr Potato Head :P )

MiteWiseacreLives!

So now I've built this function, to iterate through each frame of the four walking loops of a view and draw the sprite from the corresponding frame of another loop onto the walking-loop-frame-sprite (replace the graphic with a new Dynamic Sprite)

Code: ags

// main global script file
DynamicSprite *frame[1000];

void Swapper(int swapX, int swapY)
{
 Character *SwapChar;
 SwapChar = Character.GetAtScreenXY(swapX, swapY); 
 if (SwapChar == null || SwapChar == player)
  return;
 //if (cRat.ActiveInventory == iHat1) 
 int hatV = 3;
  
 if (SwapChar == cNpc)
 {
   int vs = SwapChar.NormalView;
   
   for (int l = 0; l < 3; l++)
   {     
     for (int f = 0; f < Game.GetFrameCountForLoop(vs, l); f++)
     {
     ViewFrame *head = Game.GetViewFrame(vs, l, f);  // selects the correct viewframe for this new dynamicSprite
     ViewFrame *hatF = Game.GetViewFrame(hatV, l, f); // selects the correct viewframe for this new hat
     Display("printing Hat: View%d Loop%d Frame%d onto Character: View%d Loop%d Frame%d", hatV, l, f, vs, l, f);
     if (head == null || hatF == null) 
      Display("Pointing to No Frame");
     int sp = head.Graphic; // locates the original sprite# for this viewframe  
     frame[sp] = DynamicSprite.CreateFromExistingSprite(sp); // make dynamicsprite with same index# as original, use a stock sprite for the DynamicSprite
     DrawingSurface *surface = frame[sp].GetDrawingSurface();
     Display("got the sprite to draw on %d", sp);
     surface.DrawImage(37, -23, hatF.Graphic); //draws the correct hat position onto the DynamicSprite
     surface.Release();
     
     head.Graphic = frame[sp].Graphic;  //changes this viewframe to new dynamicSprite  
     }
   }
 }
}


But then after a few moments I get this crash/error..

Quote---------------------------
Illegal exception
---------------------------
An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x0041E779 ; program pointer is +3330, ACI version 3.4.0.13, gtags (0,74)

AGS cannot continue, this exception was fatal. Please note down the numbers above, remember what you were doing at the time and post the details on the AGS Technical Forum.



Most versions of Windows allow you to press Ctrl+C now to copy this entire message to the clipboard for easy reporting.

An error file CrashInfo.dmp has been created. You may be asked to upload this file when reporting this problem on the AGS Forums. (code 0)
---------------------------
OK   
---------------------------

It seems as if I am having too many dynamic sprites going on, can someone help explain this to me?
It looks like it would point to a dynamic sprite instead of the original graphic on a second pass if there was any re-use of sprites/graphics in subsequent loops, but my test indicates the original sprite-slot for each pass.

Crimson Wizard

There is a bug in AGS. Can you upload CrashInfo.dmp?

MiteWiseacreLives!

#6
It seems that my code was creating a new set of sprites-slots each pass of dynamic sprites (even though I was reusing the same dynamic sprite), I assume that's normal, then I was pointing to the dynamic sprite itself and using it as the surface - drawing onto itself. If that makes sense  ??? it seem to kind of overload..
So wrote some new code that indexes the original sprite for the viewframe and resets the viewframe to regular the sprite before drawing onto that (instead of countless dynamic sprites drawing over top on another).

My internet is slow right now, can't seem to get mediafire to work, I will get that crash file up soon.

Question, aside from my oddball way of referencing ViewFrames:
Code: ags

       os = (v*100 + l*10 + f); // no more than 9 frames or 9 loops or 100 views!! gives a unique number to each viewframe.
       ViewFrame *origFrame = Game.GetViewFrame(v, l, f);
       OriginalSprite[os] = origFrame.Graphic; 

Do viewframes have their own unique ID#'s?

SMF spam blocked by CleanTalk