Results 1 to 3 of 3

Thread: Sprite Animation and Checking Collisions

  1. #1

    Question Sprite Animation and Checking Collisions

    When loading a sprite from resources, the way to check whether the user has clicked on it is by using CL_CollisionOutline and then checking to see whether the mouse pointer is inside the outline.

    That is without animation. What would be the best way to check for a point within an animated sprite?

    The sprite is loaded from a resource file that would look something like this:

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <sprite name="char001">
        <image file="images/char001.png">
          <grid pos="0,0" size="112,160" array="9,1"/>
        </image>
        <animation speed="150" />
      </sprite>
    </resources>
    Is there a way to get a pixel from a frame?

    Eh sorry, I'm not too sure how to use CL_CollisionOutline with an animated sprite.

    Thanks.

  2. #2
    ClanLib Developer
    Join Date
    Sep 2006
    Location
    Bergen, Norway
    Posts
    588

    Lightbulb

    Beware, this post became quite long - I was bored at work

    I'm afraid this is not straightforward to do - Clanlib does not support this out of the box.

    Necessary?
    The best option of course is not do to pixel perfect collision check, but rather a rectangle check. For mouse clicking this is often enough, but it depends on your type of game of course.

    Loading outlines
    Biggest problem is that you need to have a collision outline per frame. First, you need a structure to define this. Maybe you could add a custom tag in your resources file, where you tell what precalculated collision outline it should use per frame:

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
      <sprite name="char001">
        <image file="images/char001.png">
          <grid pos="0,0" size="112,160" array="9,1"/>
        </image>
        <animation speed="150" />
        <collision>  <!-- Custom tag - not supported by sprite directly -->
            <collisionframe frame="0" file="images/char001_collision0.col"/>
            <collisionframe frame="1" file="images/char001_collision1.col"/>
            <collisionframe frame="2" file="images/char001_collision2.col"/>
            <collisionframe frame="3" file="images/char001_collision3.col"/>
            <collisionframe frame="4" file="images/char001_collision4.col"/>
        </collision>
      </sprite>
    </resources>
    Custom collision tool
    Notice, if you do it this way you'll need to write a small tool that converts an image to a collision outline.

    Collision outline can either be created from a single image file, created from a pixelbuffer, or loaded from a precalculated saved outline.

    Clanlib has the code to do this:

    Code:
    CL_CollisionOutline generated1("image.png");
    generated1.save("image1.col");
    
    CL_CollisionOutline generated2(pixelbuffer);
    generated2.save("image2.col");
    Since you are using a grid to make animation, it makes it kinda hard to generate collision outlines from it directly. You might need to do some magic here. I think loading a CL_SpriteDescription from the resources, iterating through its CL_SpriteDescriptionFrame collection, and creating outlines based on each frame would do the trick.

    Code:
    CL_SpriteDescription desc(gc, "char001", resources);
    
    const std::vector<CL_SpriteDescriptionFrame> &frames = desc.get_frames();
    for(int i = 0; i < frames.size(); ++i)
    {
        CL_PixelBuffer pb;
    
        if(frames[i].type == CL_SpriteDescriptionFrame::type_pixelbuffer)
            pb = frames[i].pixelbuffer;
        else if(frames[i].type == CL_SpriteDescriptionFrame::type_texture)
            pb = frames[i].texture.get_pixeldata();
    
        CL_PixelBufferRef pb_ref = pb.get_subimage(frames[i].rect);
        CL_CollisionOutline generated(pb_ref);
    
        generated.save(cl_format("char001_collision%1.col", i));
    }
    Custom sprite class

    You could create a new Sprite class that contains both your CL_Sprite and per-frame collision info.

    HOT TIP!
    The class uses the very convenient ClanLib 2.0 XPath classes to easily fetch all collisionframes from the XML resource file.

    Code:
    class AnimatedCollisionSprite
    {
         CL_Sprite sprite;
         std::vector<CL_CollisionOutline> frame_outlines;
    
         ....
    
         void load_collision_outlines(const CL_StringRef &resource_id, CL_ResourceManager *resources)
         {
    		CL_Resource resource = resources->get_resource(resource_id);
    		CL_DomElement resourceElement = resource.get_element();
    		std::vector<CL_DomNode> nodes = resourceElement.select_nodes("collision/collisionframe");
    		for (size_t nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++)
    		{
    			CL_DomNode node = nodes[nodeIndex];
    			CL_DomElement element = node.to_element();
    
    			CL_String frame_string = element.get_attribute("frame");
    			int frame_number = CL_StringHelp::text_to_int(frame_string);
    
    			CL_String file = element.get_attribute("file");
    
    			CL_CollisionOutline outline(file);
    			frame_outlines.push_back(outline);
    		}
         }
    
         bool hit_test(int x, int y)
         {
              int frame_number = sprite.get_current_frame();
              CL_CollisionOutline outline = frame_outlines[frame_number];
              return outline.point_inside(x, y);
         }
    }
    You could also combine the tool and the loading to dynamically generate the outlines on the fly, instead of saving/loading them to disk...

    Now, there are probably many more issues to consider than what I have listed here (like sprite position), but hopefully this is a start for you to be able to figure out how solve this problem.

    Phew, that took quite along time to write. Hopefully this helps others as well that has struggled with collision and animated sprites

  3. #3

    Default

    Thank you so much sphair! It's very impressive that you've explained it in depth and provided code examples.

    I will go through it and see how to best implement it.

    Very impressive!

Similar Threads

  1. CL_Sprite animation control in Clanlib 8.1
    By mcgregor927 in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 03-29-2009, 09:58 PM
  2. Checking if NovaShell is in EditMode
    By ShadowDust in forum Novashell Game Creation System
    Replies: 3
    Last Post: 12-27-2008, 09:45 AM
  3. Simple Animation
    By ares in forum Official ClanLib SDK Forums
    Replies: 1
    Last Post: 02-27-2008, 05:20 AM
  4. sprite constructor
    By Krux in forum Official ClanLib SDK Forums
    Replies: 2
    Last Post: 09-21-2007, 06:52 AM
  5. IP Address Checking
    By File Sponge in forum Funeral Quest
    Replies: 5
    Last Post: 11-07-2006, 05:24 PM

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •