Drawing an animated image from a sprite?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • HaLo2FrEeEk
    Contributor
    • Feb 2007
    • 404

    Drawing an animated image from a sprite?

    I like to go through the Windows files in a resource editor, just to see what's there. I notice a lot of sprite images that are actually animations. For example, a file 32x256 has 8 tiles each 32x32 right next to each other. I assume that the program gets each of thoe tiles and displays them in sequence, I just want to know how to do it myself. I have a sprite that I'd like to use as a loading animation while I'm connecting to a database. Google is turning up nothing. Can anyone help me out?
  • GaryTexmo
    Recognized Expert Top Contributor
    • Jul 2009
    • 1501

    #2
    I'm not sure. If I had to take a stab at it, I'd use a timer to change the tile I was displaying and then display the appropriate frame. I used to do this kind of thing way back when I programmed graphics stuff in QBasic, but I'm not sure how you'd do it in C#.

    Maybe you can run through the image's memory and put it into an Image class, then put those images into a List<Image> object. Then you can use your timer to display the appropriate image.

    I feel like there's a better way of doing this, or even something built into .NET, I just don't know what it is :)

    Comment

    • HaLo2FrEeEk
      Contributor
      • Feb 2007
      • 404

      #3
      I'll wat for someone else to give me some advice on this. Someone has to know how to do it. It can't be possible in C++ and not in C# (windows is programmed in C++ right, or is it C?)

      Comment

      • GaryTexmo
        Recognized Expert Top Contributor
        • Jul 2009
        • 1501

        #4
        If they don't, it's not terribly hard. I'll admit to being intrigued... after a short trip (via Google) to a site with spite sheets from classic video games, I built myself a running mega man animation (from Mega Man X, whoo!).

        It was pretty easy to implement, though I did use the Bitmap class (instead of the Image class) so it doesn't do transparency. The only reason for that though is that I didn't want to figure out how the image was stored in memory ;)

        So you there you go, you've got a fallback... it's pretty easy to do manually. Though out of curiosity, you mentioned there's something in C++ that does it. What is that?

        Comment

        • HaLo2FrEeEk
          Contributor
          • Feb 2007
          • 404

          #5
          Either C++ or C, whichever Windows is programmed in. I know that because searching through the DLL files in Windows/system32, there are a ton of these image strips scattered throughout the files.

          And Gary, if you got it to work in C#, please tell me how!

          Comment

          • GaryTexmo
            Recognized Expert Top Contributor
            • Jul 2009
            • 1501

            #6
            Oh, you mean windows is doing it? Well, they might be manually doing it as well :D

            I'd be more than happy to help you work though it, but I don't want to straight up give you the code for it. It's better to learn how to do it anyway, right?

            Here's some steps to get you started...
            * Read in the source image
            * Decide what the dimensions of the individual sprites will be, thus defining how many frames are in your image
            * For each frame, create a new image and copy the data from the appropriate location in the source (NOTE: I did this pixel by pixel, but I'd be willing to bet the Bitmap class has some cropping in there... have a look around)
            * Add the created frame to some kind of image list

            Now you have a list of frames, you can animate them. I'd suggest a picture box and a timer.

            Hopefully that's enough to get you started :)

            Comment

            • Frinavale
              Recognized Expert Expert
              • Oct 2006
              • 9749

              #7
              I haven't done this myself but from what I understand, there is usually a "master" image that contains a whole bunch of tiny images (aka sprites).

              You are going to have to retrieve the sprites from the master image.

              To do this you'll have to load the main "master" image (with all of the sprites in it) and then create a series of tiny images by copying the sprites out of the master image.

              Take a look at the .NET tools available to you in the System.Drawing namespace like the Bitmap class, the Graphics.FromIm age method, the Drawing.Rectang le structure and the Graphics.DrawIm age method.

              -Frinny

              Comment

              • HaLo2FrEeEk
                Contributor
                • Feb 2007
                • 404

                #8
                I already have the sprite image sheet that I want to use. There are 8 frames in a 16x256 image, meaning each frame is 16x32. So I could create a method that loads in the sprite sheet and I'll supply it with the number of frames, that way it can automatically determine the height and width of the image and know where it needs to cut. For example, if I feed it the above mentioned image and tell it there are 8 frames, it'll know that each frame is 16 x (256/8), right. Then I could have it save each frame in memory so I don't have to save them as files...or could I have it simply change the portion of the image it's showing, meaning I would load the whole sprite sheet but only display from (0,0) - (15,31) in the image box, then when it's time to change frame I just change the display to (0,32) - (15,63) and so on...would that be possible? Or would it be smarter ( / simpler) to just put each frame into it's own memorystream? I would think it'd be more resource effective to use the first method.

                Another method I could do would be to just cut the sprite sheet up in Photoshop and load each frame as a resource, but that sorta removes the automation aspect of the whole thing, especially if I want to use a different sprite down the line.

                Comment

                • GaryTexmo
                  Recognized Expert Top Contributor
                  • Jul 2009
                  • 1501

                  #9
                  I think you can do the cropping method but you'd have to write your own cropping stuff. I took a look at the Image and Bitmap classes in MSDN and so far as I can tell, there's no built in crop. I think there might be something in XNA that does it though, but I'm not 100% sure.

                  In the implementation I did, I broke out the image and copied the data into separate Bitmap objects, which I then stored in a list.

                  Imagined with strings, it would have gone from: "ABCD" to {"A", "B", "C", "D"}. If you made your own cropper, you would need to return a Bitmap object that contained the pixel data for the range you specified. Bounds checking aside, it should be pretty doable...

                  (pseudo code)
                  Code:
                  (would probably want some bounds checking to make sure you're getting data from a valid location in the source image)
                  for y = 0 to height
                    for x = 0 to width
                      sourcePixel = sourceImage.GetPixel(startX + x, startY + y);
                      croppedImage.SetPixel(x, y, sourcePixel);
                    next x
                  next y

                  Comment

                  • HaLo2FrEeEk
                    Contributor
                    • Feb 2007
                    • 404

                    #10
                    Good grief, I'd have to do it pixel by pixel? There must be a better way, I'll google it. Something like "csharp image cropping" should do the trick...

                    Comment

                    • GaryTexmo
                      Recognized Expert Top Contributor
                      • Jul 2009
                      • 1501

                      #11
                      Pffft, you're no fun ;)

                      Actually, apparently the Bitmap.Clone method takes a crop area... what a goofy place to put it (if you ask me). That will also work. Though I will say, don't be afraid to get your hands dirty with stuff like this. Doing it yourself can not only save you a lot of time in finding/understanding someone else's code, but you also stand to learn a lot when figuring out how to implement things.

                      Not that I'm advocating reinventing the wheel every time either ;)

                      (Here's a helpful link... http://www.switchonthecode.com/tutor...g-and-resizing)

                      Lastly, I'll say this about the cropping method. I wouldn't crop and animate on the fly, as you have to do those cropping calculations every time you get the frame to display in the animation. Use the crop to generate each frame and store that frame in an object list, then when you want to display you just have to get the frame. If you made your own image storage location I suppose you could do it with pointers and just advance the pointer (which would only use a source image, no extra memory) but lets focus on one thing at a time :D

                      Comment

                      • HaLo2FrEeEk
                        Contributor
                        • Feb 2007
                        • 404

                        #12
                        Ok, I am trying SO hard to get this to work, but I just canNOT get the image to display from the imagelist. So far I have a form that loads an image and displays it for an "original image" view, then there's a textbox that you enter the number of frames in the image into. If the number entered isn't divisible by the width of the loaded picture it throws an error, but if it's ok then it continues with breaking up the image into numFrames pieces and putting each piece into an ImageList. Then I pass that imagelist into another method that also has the width and height of the images in the list. in that method there is an instance of another form as a child form, I tried using a picturebox but I guess you have to use a Graphics object to display an image from an imagelist, so I tried this:

                        Code:
                        Graphics g = animForm.CreateGraphics();
                        animList.Draw(g, 50, 50, 0); // This should draw the first item in the imagelist to the g Graphics object
                        And I get an error. It's long and for some reason it shows up in a messagebox (I have no clue why) but here's a screenshot of it:



                        I have no idea what's going on, I followed the instructions from another site to the letter, I didn't know how to access ImageList's so I had to get help. Well, I still need help.

                        Comment

                        • GaryTexmo
                          Recognized Expert Top Contributor
                          • Jul 2009
                          • 1501

                          #13
                          To be honest, I don't know much about GDI/GDI+. Though it does look like your code is missing a parameter. Do you maybe want...

                          Code:
                          animList.Draw(g, 50, 50, 0, 0);
                          ?

                          Maybe try drawing it to a PictureBox object first to test it? That's what I used in the program I did.

                          Comment

                          • HaLo2FrEeEk
                            Contributor
                            • Feb 2007
                            • 404

                            #14
                            Oh, my GOD. Why do I make everything so complicated?



                            This. the AddStrip() method. Allows you to import an image strip into the imagelist, you supply the width and height and it automatically gets each frame out and puts it into it's own imagelist item. That pisses me off.

                            Ok, now I just need to figure out how to display the animation, since now I can get all the frames. Stupid visual studio, hiding things in stupid places.

                            ImageList.Image s.AddStrip(Bitm ap image);

                            Comment

                            • HaLo2FrEeEk
                              Contributor
                              • Feb 2007
                              • 404

                              #15
                              Ok, here's my completed program:



                              I included a few image sheets to test it out with. Let me know if you find anything. It doesn't let you save the image, but it lets you view them...so I guess it's not TOTALLY useless. It was more a learning exercise for me anyway.

                              Also, if you want the source code, I'll see what I can do about that.

                              Comment

                              Working...