float bodyPartxoffset(bBodyPart bodyPart, float x)
 {
     // gets natural or mirrored offset
     if (!bodyPart.bodyPart.flipped)
     {
         return x + bodyPart.pos[currentAnim.frame].X + bodyPart.xoffset - bodyPart.bodyPart.hotspot.X;
     }
     else
     {
         return x + spriteWidth - bodyPart.pos[currentAnim.frame].X - bodyPart.xoffset + bodyPart.bodyPart.hotspot.X - bodyPart.bodyPart.spriteWidth;
     }
 }
        public bool parseMasks(string src)
        {
            using (var sr = System.IO.File.OpenText(src))
            {
                string line = sr.ReadLine();

                // get bMask list size
                if (line != null)
                {
                    int nmasks = 0;
                    int msize = 0;

                    // mask initialization
                    try
                    {
                        msize = Convert.ToInt32(line.Split(Constants.bCharSeparators, StringSplitOptions.RemoveEmptyEntries)[0]);
                        masks = new bMask[msize];
                        hotspots = new Point[msize];
                    }
                    catch (Exception e)
                    {
                        if (e is FormatException || e is OverflowException || e is IndexOutOfRangeException)
                        {
                            Console.WriteLine("Could not read masks from file " + src + ", size attribute has errors: " + e.Message);
                            return false;
                        }
                        else
                            // not our division
                            throw;
                    }

                    int apsize = 0;
                    int naps = 0;
                    // attach points initialization
                    try
                    {
                        if ((line = sr.ReadLine()) == null) return false;
                        apsize = Convert.ToInt32(line.Split(Constants.bCharSeparators, StringSplitOptions.RemoveEmptyEntries)[0]);

                        while (naps < apsize && (line = sr.ReadLine()) != null)
                        {
                            string id = line.Split(Constants.bCharSeparators, StringSplitOptions.RemoveEmptyEntries)[0];
                            bBodyPart bodyPart = new bBodyPart();
                            bodyPart.bodyPart = null;  // body is initially non-existent
                            bodyPart.pos = new Point[msize];  // as many positions as frames
                            attached.Add(id, bodyPart);
                            naps++;
                        }

                        if (naps < apsize)
                        {
                            Console.WriteLine("Could not read masks from file " + src + ", some attach points are missing");
                            return false;
                        }
                    }
                    catch (Exception e)
                    {
                        if (e is FormatException || e is OverflowException || e is IndexOutOfRangeException)
                        {
                            Console.WriteLine("Could not read masks from file " + src + ", attach point attribute has errors: " + e.Message);
                            return false;
                        }
                        else
                            // not our division
                            throw;
                    }

                    // fill bMask list
                    while (nmasks < msize)
                    {
                        // Read frame hotspot
                        if ((line = sr.ReadLine()) == null) return false;
                        try
                        {
                            string[] items = line.Split(Constants.bCharSeparators, StringSplitOptions.RemoveEmptyEntries);
                            hotspots[nmasks] = new Point(Convert.ToInt32(items[0]), Convert.ToInt32(items[1]));
                        }
                        catch (Exception e)
                        {
                            if (e is FormatException || e is OverflowException || e is IndexOutOfRangeException)
                            {
                                Console.WriteLine("Could not read masks from file " + src + ", hotspot attribute has errors: " + e.Message);
                                return false;
                            }
                            else
                                // not our division
                                throw;
                        }

                        // Read frame mask
                        bMask mask = bMask.MaskFromFile(sr, src, nmasks);
                        if (mask != null)
                            masks[nmasks] = mask;
                        else
                            return false;

                        parseAttachPoints(sr, nmasks, apsize, src);
                        nmasks++;
                    }

                    return true;
                }
                else
                    return false;
            }
        }