SOLVED - DynamicSprite basics - save dynamic sprite to sprite slot

Started by WHAM, Tue 04/09/2012 18:44:15

Previous topic - Next topic

WHAM

The subject says it all:

Can I replace the sprite in a sprite slot with a dynamic sprite on the fly?

What I'm trying to do:
- Take sprite from slot X, create new dynamic sprite from that sprite.
- Rotate and fuss about with the sprite
- Save the sprite so that the player's current sprite (has only 1 sprite) is overwritten

Can this be done, or do I need to go for some kind of sorcery?
Wrongthinker and anticitizen one. Utterly untrustworthy. Pending removal to memory hole.

Khris

You can't overwrite sprite slots afaik, but you can change the frames in a view.
Code: ags
  ViewFrame*vf = Game.GetViewFrame(player.NormalView, player.Loop, 0);
  vf.Graphic = dyn_sprite.Graphic;

This changes the frame's sprite slot permanently.

WHAM

I get a seemingly uninformative exeption error and a crash now. :D

My guess is I still need to do something to prep the dynamic sprite, but so far no idea. Will keep reading the manual, but since the thread is already started...

Below is some code with one specific line commented to clarify situation.

Code: AGS


  DynamicSprite* Dsprite = DynamicSprite.CreateFromExistingSprite(9, true);
  if (rotateangle > 359) {
    rotateangle = rotateangle - 359;
  }
  Dsprite.Rotate(rotateangle, 50, 50);
  
  ViewFrame*vf = Game.GetViewFrame(player.NormalView, player.Loop, 0);
  vf.Graphic = Dsprite.Graphic; // <--- THIS LINE CRASHES THE GAME, IF COMMENTED OUT, NO CRASH
   
  Dsprite.Delete();
Wrongthinker and anticitizen one. Utterly untrustworthy. Pending removal to memory hole.

Calin Leafshade


WHAM

No, they start at 0.
Why do I have the feeling I can't edit the viewframe while it is being displayed?
Wrongthinker and anticitizen one. Utterly untrustworthy. Pending removal to memory hole.

Khris

It shouldn't matter whether the frame is currently displayed; you're simply changing AGS's internal "database", a view is just a collection of numbers after all, and when the screen is redrawn at the end of the loop, the new sprite slot is used.
However, you can't declare the DynamicSprite inside the function; if you do that, it's a local variable and will get destroyed at the end of the function, including the sprite data.

WHAM

Well that should have been obvious even to me...

Changed the dynamicsprite into a global one, no more crashing. :)

EDIT: Nevermind, still crashing like a pro. Here is the entire function, which I have tried running (agains manual instruction) in repeatedly execute, as well as on keypress, both with same results. The players view only has 1 frame to it.

---------------------------
Illegal exception
---------------------------
An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x004140CC ; program pointer is +3330, ACI version 3.21.1115, gtags (0,150)

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.

Code: AGS
function RotateChar() {
  
  Dsprite = DynamicSprite.CreateFromExistingSprite(9, true);
  
  while (rotateangle > 359) {
    rotateangle = rotateangle - 359;
  }
  
  Dsprite.Rotate(rotateangle, 50, 50);
  
  ViewFrame *vf = Game.GetViewFrame(player.NormalView, player.Loop, 0);
  vf.Graphic = Dsprite.Graphic;
    
  rotateangle += FloatToInt(Gspeed / 20.0, eRoundNearest);
  
  Dsprite.Delete();
  
}


EDIT 2: Been fiddling for a while now, I have no idea whatsoever why that crash is happening.
If I assign the rotated sprite to a different loop (created for that purpose), no crash. The above code works just well, but when I later set the player character to use that loop, same crash.
Wrongthinker and anticitizen one. Utterly untrustworthy. Pending removal to memory hole.

Khris

Just for the hell of it, try adding at least one frame to the other three loops (so that player.NormalView has at least one frame in each of its first four loops).

WHAM

Done, no change in situation.
I am already pondering on the amount of work involved in having 180 or-so sprites of the character, and then spinning it by animating the loop(s). :D

What I mean to say is: HALP!
Wrongthinker and anticitizen one. Utterly untrustworthy. Pending removal to memory hole.

monkey0506

vf.Graphic = Dsprite.Graphic;
Dsprite.Delete();
Does this not occur to anyone else as being problematic?

Yes, excuse me AGS, could you display on-screen that sprite that I just told you to blow up? kthx

Khris

Sure, it did. :)

The problem is, with that issue out of the way, why is AGS still crashing.
It's the dreaded "exception 0xC0000005"; maybe somebody who's familiar with the source can take a look (EIP = 0x004140CC)?

monkey0506

No, I did see where you pointed that out, but when WHAM responded to you, and included what is presumably the latest code snippet, it would appear that he is still deleting the sprite:

Quote from: WHAM on Tue 04/09/2012 20:35:30Changed the dynamicsprite into a global one, no more crashing. :)

EDIT: Nevermind, still crashing like a pro. Here is the entire function...

Code: ags
function RotateChar() {
  
  Dsprite = DynamicSprite.CreateFromExistingSprite(9, true); // DynamicSprite* is defined globally...
  // ...
  ViewFrame *vf = Game.GetViewFrame(player.NormalView, player.Loop, 0);
  vf.Graphic = Dsprite.Graphic; // assign dynamic sprite into view frame, to be drawn on the next game loop
  // ...
  Dsprite.Delete(); // delete the sprite we just asked to have drawn, even though it's still in use
  
}

Quote from: Khris on Wed 05/09/2012 02:52:37The problem is, with that issue out of the way...

The code that WHAM has posted still suggests that "that issue" is very much not "out of the way". If that code was just outdated and he did already remove that line (or rather, do the correct thing and check if the pointer is null at the beginning of the function, if it's not, assign 0 to the view frame and delete the sprite), then it warrants further investigation. Still looks like a user programming error to me (despite the lack of a meaningful error message).

Khris

Sorry, you're right of course, I didn't even check the amended code. And I missed what your post was actually about to boot. Guess I should have rather gone to bed hours ago like I had planned and not roam around here while being severely sleep-deprived :-D

WHAM

Aye, mr Monkey was righ about that one.
I forgot to remove the delete line from the end after making the dynamicsprite global.

No more crashy-crashy, and the code works like a charm now. :)
Wrongthinker and anticitizen one. Utterly untrustworthy. Pending removal to memory hole.

Crimson Wizard

Sorry to bother, just a small note FYI.

Quote from: Khris on Wed 05/09/2012 02:52:37
It's the dreaded "exception 0xC0000005"; maybe somebody who's familiar with the source can take a look (EIP = 0x004140CC)?

In the engine crash message the "program pointer" and "gtags" are more useful, these values are AGS debug helpers, they are being set throughout the code. Specifically program pointer = 3330 is pointing at this section of code:
Spoiler

Code: cpp

        coldept = bitmap_color_depth(spriteset[sppic]);

        // adjust the sppic if mirrored, so it doesn't accidentally
        // cache the mirrored frame as the real one
        if (views[chin->view].loops[chin->loop].frames[chin->frame].flags & VFLG_FLIPSPRITE) {
            isMirrored = 1;
            specialpic = -sppic;
        }

[close]

Well, the issue was resolved without all this info, telling just in case.

Calin Leafshade

A crash like that is clearly a bug though. AGS should crash much more gracefully with regards to a missing sprite.

SMF spam blocked by CleanTalk