Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Strange bug with SFML when rendering sprites close together.  (Read 5431 times)

0 Members and 1 Guest are viewing this topic.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Strange bug with SFML when rendering sprites close together.
« on: April 15, 2014, 05:41:51 am »
Noticed that after a while they simply vanish and never reappear again for some odd reason.  I've been working on an AI using vectors and the sprites currently after some time line up on top of their target but after a while they just vanish for some strange reason when they stay close long enough but also never reappear.    Don't know what's going on here and no clue if it is my code of SFML. ??? ??? ???




Will post code if needed later but right now checking if anyone else has had this issue.
I have many ideas but need the help of others to find way to make use of them.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Strange bug with SFML when rendering sprites close together.
« Reply #1 on: April 15, 2014, 05:49:43 am »
99.999% chance its entirely your code.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Strange bug with SFML when rendering sprites close together.
« Reply #2 on: April 15, 2014, 01:06:48 pm »
Indeed. And when you post code, make sure it's a minimal complete example.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Strange bug with SFML when rendering sprites close together.
« Reply #3 on: April 15, 2014, 03:55:21 pm »
Problem is the minimal example would still be too long so I'll do some hunting to see if I can locate the likely source first.  Hopefully when I start moving some of my code over to my game from the testing area I've made some of my bugs will go away. :)


Meantime while I'm trying to narrow down the source here's one that is just as annoying.

Seems when I'm using my constructor to set the vector direction of my sprite it zeros out the vector for some odd reason. ???

public FullMovingSprite(Texture texture, Vector2f loc, Vector2f vec, float mspeed)
            : base(texture)
        {
            VectorDirection = vec * mspeed;
            this.Position = loc;
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
            MaxSpeed = mspeed;
            CenterOrigin();
        }
 
Yes I've extended the Sprite Class of SFML for one reason or another but this error drives me battier than the sprites going poof.  In my update code I'm just adding the movement vector to the position like anyone would do but what's strange is when using the constructor I get no movement vector but if I set the vector for moving outside the constructor it works just fine. ???
« Last Edit: April 15, 2014, 04:04:02 pm by StormWingDelta »
I have many ideas but need the help of others to find way to make use of them.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Strange bug with SFML when rendering sprites close together.
« Reply #4 on: April 15, 2014, 07:20:21 pm »
I don't think I got you there, please give a complete and minimal example and at the same time please fully explain what the problem is. I really doubt this is an issue with SFML.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Strange bug with SFML when rendering sprites close together.
« Reply #5 on: April 16, 2014, 01:51:41 am »
I don't think I got you there, please give a complete and minimal example and at the same time please fully explain what the problem is. I really doubt this is an issue with SFML.

Busy narrowing things down.  Will post it in a moment since the amount of code right now is over 400 lines in the main file and most of it is getting removed or moved about at the moment.

This is what I got with just what isn't in use edited out and after some huge amount of console spam it seems that if a sprite stays lined up with another for too long it gets set to null for some odd reason.

class SFMLMovementAndShootingTest
    {
        RenderWindow window;
        View movingview;
        Font exfont;
        FullMovingSprite movingspriteplayer;
        List<FullMovingSprite> spritelist = new List<FullMovingSprite>();
        Text extext, extext2, extext3;
        Boolean forward = false, breaking = false, turnleft = false, turnright = false, firegun = false;
        FullMovingSprite enemy, enemy2, enemy3, enemy4;
        public SFMLMovementAndShootingTest()
        {
           
            exfont = new Font("Fonts/00Starmap/00TT.TTF");
            uint fontsize = 15;
            extext = new Text("Player Pos: ", exfont, 15);
            extext2 = new Text("Key Pressed: ", exfont, fontsize);
            extext3 = new Text("Key Released: ", exfont, fontsize);
            movingspriteplayer = new ShootingSprite(ToSFMLTexture(TestImages.TestShip),
                new Vector2f(0, 0), new Vector2f(1, 0), 100);
        }

        public void StartSFMLProgram4()
        {
            try
            {
                VideoMode vm = new VideoMode(800, 800);
                window = new RenderWindow(vm, "SFML C# Moving and Shooting!");
                movingview = new View(new FloatRect(0, 0, vm.Width, vm.Height));
                window.SetView(movingview);
               
                movingspriteplayer.Position = new Vector2f(0,0);
                View viewcopyretarget = window.GetView();
                viewcopyretarget.Center = movingspriteplayer.Position;
                window.SetView(viewcopyretarget);
                spritelist.Add(movingspriteplayer);
                enemy = new FullMovingSprite(ToSFMLTexture(TestImages.TestShip), new Vector2f(1000, 0), new Vector2f(10, 0), 55);
                enemy.IsAIActive = true;
                spritelist.Add(enemy);

                enemy2 = new FullMovingSprite(ToSFMLTexture(TestImages.TestShip), new Vector2f(-1000, 0), new Vector2f(-10, 0), 150);
                enemy2.IsAIActive = true;
                spritelist.Add(enemy2);

                enemy3 = new FullMovingSprite(ToSFMLTexture(TestImages.TestShip), new Vector2f(0, 1000), new Vector2f(0, -10), 40);
                enemy3.IsAIActive = true;
                spritelist.Add(enemy3);

                enemy4 = new FullMovingSprite(ToSFMLTexture(TestImages.TestShip), new Vector2f(0, -1000), new Vector2f(0, 10), 50);
                enemy4.IsAIActive = true;
                spritelist.Add(enemy4);
                extext2.Position = new Vector2f(0, 30);
                extext3.Position = new Vector2f(0, 45);
                fpstext.Position = new Vector2f(0,60);
                window.Closed += new EventHandler(OnClosed);
                window.KeyPressed += new EventHandler<KeyEventArgs>(KeyEventPressed);
                window.KeyReleased += new EventHandler<KeyEventArgs>(KeyEventReleased);
               
                window.SetFramerateLimit(60);
                while (window.IsOpen())
                {
                    window.DispatchEvents();
                    UpdateListOfSprites(ref spritelist);
                    UpdateHUD(ref window);
                    window.Clear();
                    RenderListOfSprites(ref window,ref spritelist);
                    RenderHUD(ref window);
                    window.Display();
                    CheckConstantInputs();
                }
            }
            catch (Exception ex)
            {

                System.Windows.Forms.MessageBox.Show(ex.Message);
            }


        }

        void OnClosed(object sender, EventArgs e)
        {
            window.Close();
        }

        void KeyEventPressed(object sender, KeyEventArgs e)
        {
            extext2.DisplayedString = "Key Pressed: " + e.Code;
            if (e.Code == Keyboard.Key.W || e.Code == Keyboard.Key.Up)
            {
                forward = true;
            }
            if (e.Code == Keyboard.Key.S || e.Code == Keyboard.Key.Down)
            {
                breaking = true;
            }
            if (e.Code == Keyboard.Key.D || e.Code == Keyboard.Key.Right)
            {
                turnright = true;
            }
            if (e.Code == Keyboard.Key.A || e.Code == Keyboard.Key.Left)
            {
                turnleft = true;
            }
            if (e.Code == Keyboard.Key.Space)
            {
                movingspriteplayer.VectorDirection = new Vector2f(0, 0);
            }
        }
        void KeyEventReleased(object sender, KeyEventArgs e)
        {
            extext3.DisplayedString = "Key Released: " + e.Code;
            if (e.Code == Keyboard.Key.W || e.Code == Keyboard.Key.Up)
            {
                forward = false;
            }
            if (e.Code == Keyboard.Key.S || e.Code == Keyboard.Key.Down)
            {
                breaking = false;
            }
            if (e.Code == Keyboard.Key.D || e.Code == Keyboard.Key.Right)
            {
                turnright = false;
            }
            if (e.Code == Keyboard.Key.A || e.Code == Keyboard.Key.Left)
            {
                turnleft = false;
            }

        }
        private void UpdateSingleSprite(ref FullMovingSprite sprite)
        {
            if (sprite.IsAIActive)
            {
                sprite.AISeeking(movingspriteplayer.Position);
                Console.WriteLine(sprite.Position + ", " + sprite.VectorDirection);
            }
            sprite.UpdateSelf();
        }
        private void UpdateListOfSprites(ref List<FullMovingSprite> mspritelist)
        {
            List<FullMovingSprite> onlycurrent = new List<FullMovingSprite>(mspritelist);
            for (int i = 0; i < onlycurrent.Count(); i++)
            {
                FullMovingSprite refsprite = onlycurrent[i];
                UpdateSingleSprite(ref refsprite);
            }
        }

        private void UpdateHUD(ref RenderWindow win)
        {
            View viewcopy = win.GetView();
            viewcopy.Center = movingspriteplayer.Position;
            win.SetView(viewcopy);
            Vector2f topleft = new Vector2f(viewcopy.Center.X - (viewcopy.Size.X / 2), viewcopy.Center.Y - (viewcopy.Size.Y / 2)),
                topright = new Vector2f(viewcopy.Center.X + (viewcopy.Size.X / 2), viewcopy.Center.Y - (viewcopy.Size.Y / 2)),
                bottomleft = new Vector2f(viewcopy.Center.X - (viewcopy.Size.X / 2), viewcopy.Center.Y + (viewcopy.Size.Y / 2)),
                bottomright = new Vector2f(viewcopy.Center.X + (viewcopy.Size.X / 2), viewcopy.Center.Y + (viewcopy.Size.Y / 2));
            extext.Position = topleft;
            extext.DisplayedString = "Player Coords: " + movingspriteplayer.Position.ToString();
            fpstext.DisplayedString = "FPS: " + currentfps;
            extext2.Position = new Vector2f(topleft.X,topleft.Y + 15);
            extext3.Position = new Vector2f(topleft.X, topleft.Y + 30);
        }
        private void RenderHUD(ref RenderWindow win)
        {
            win.Draw(extext);
            win.Draw(extext2);
            win.Draw(extext3);
            win.Draw(fpstext);
        }

        private void RenderSingleSprite(ref RenderWindow win, ref FullMovingSprite sprite)
        {
            win.Draw(sprite);
        }
        private void RenderListOfSprites(ref RenderWindow win, ref List<FullMovingSprite> mspritelist)
        {
            List<FullMovingSprite> onlycurrent = new List<FullMovingSprite>(mspritelist);
            for (int i = 0; i < onlycurrent.Count(); i++)
            {
                FullMovingSprite refsprite = onlycurrent[i];
                RenderSingleSprite(ref win,ref refsprite);
            }
        }

        private void CheckConstantInputs()
        {
           
            if (forward)
            {
                movingspriteplayer.MoveSpriteByDirection(movingspriteplayer.Rotation, 0.25f, false);
            }
            if (breaking)
            {
                movingspriteplayer.VectorDirection *= 0.3f;
            }
            if (turnright)
            {
                movingspriteplayer.Rotation += 5;
            }
            if (turnleft)
            {
                movingspriteplayer.Rotation -= 5;
            }
        }

        private SFML.Graphics.Image ToSFMLImage(System.Drawing.Bitmap bmp)
        {
            SFML.Graphics.Color[,] sfmlcolorarray = new Color[bmp.Height, bmp.Width];
            SFML.Graphics.Image newimage = null;
            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    System.Drawing.Color csharpcolor = bmp.GetPixel(x, y);
                    sfmlcolorarray[y,x] = new SFML.Graphics.Color(csharpcolor.R, csharpcolor.G, csharpcolor.B, csharpcolor.A);
                }
            }
            newimage = new SFML.Graphics.Image(sfmlcolorarray);
            return newimage;
        }

        private SFML.Graphics.Texture ToSFMLTexture(System.Drawing.Bitmap bmp)
        {
            return new Texture(ToSFMLImage(bmp));
        }

    }
 

I edited out all the code that wasn't in use yet on that file.  Here's the movingsprite file too since it is the only other one that I can think of that might be causing this.

class FullMovingSprite : Sprite
    {
        private double movedirectionangle, maxspeed, mass = 1.5;
        private Vector2f velocity;
        Boolean isaiactive;
        public FullMovingSprite() : base()
        {
            VectorDirection = new Vector2f(0, 0);
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
        }
        public FullMovingSprite(Texture texture)
            : base(texture)
        {
            VectorDirection = new Vector2f(0,0);
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
            CenterOrigin();
        }
        public FullMovingSprite(Texture texture, IntRect intrect)
            : base(texture, intrect)
        {
            VectorDirection = new Vector2f(0, 0);
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
            CenterOrigin();
        }
        public FullMovingSprite(Vector2f loc, Vector2f vec, float mspeed)
            : base()
        {
            this.Position = loc;
            VectorDirection = vec * mspeed;//ConsistantSettingOfVector(new Vector2f(vec.X, vec.Y), mspeed);
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
            MaxSpeed = mspeed;
        }
        public FullMovingSprite(Texture texture, Vector2f loc, Vector2f vec, float mspeed)
            : base(texture)
        {
            this.Position = loc;
            VectorDirection = vec * mspeed;//ConsistantSettingOfVector(new Vector2f(vec.X, vec.Y), mspeed);
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
            MaxSpeed = mspeed;
            CenterOrigin();
        }
        public FullMovingSprite(Texture texture, IntRect intrect, Vector2f loc, Vector2f vec, float mspeed)
            : base(texture, intrect)
        {
            this.Position = loc;
            VectorDirection = vec * mspeed;//ConsistantSettingOfVector(new Vector2f( vec.X,vec.Y),mspeed);
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y);
            MaxSpeed = mspeed;
            CenterOrigin();
        }
        public FullMovingSprite(FullMovingSprite copy)
            : base(copy)
        {
            VectorDirection = new Vector2f(copy.VectorDirection.X, copy.VectorDirection.Y);
        }

        public void CenterOrigin()
        {
            if(this.Texture != null && !this.TextureRect.Equals(null))
            {
                this.Origin = new Vector2f(this.TextureRect.Width / 2, this.TextureRect.Height / 2);
            }
        }

        private Vector2f ConsistantSettingOfVector(Vector2f vec, float mspeed)
        {
            return MissingMathFunctions.TruncateVector(new Vector2f(vec.X + mspeed, vec.Y + mspeed), (float)maxspeed);
        }

        public Vector2f VectorDirection { get { return velocity; } set { velocity = MissingMathFunctions.TruncateVector(value,(float)MaxSpeed); } }
        public double MoveDirectionAngle { get { return movedirectionangle; } set { movedirectionangle = value; } }
        public double MaxSpeed { get { return maxspeed; } set { maxspeed = value; } }
       
        public void UpdateSelf()
        {
            MoveSprite(velocity);
        }
        public Boolean IsAIActive { get { return isaiactive; } set { isaiactive = value; } }
        private Vector2f targetloc;
        public Vector2f Targetloc { get { return targetloc; } set { targetloc = value; } }
        public void MoveSprite(float xvec, float yvec)
        {
            this.Position += new Vector2f(xvec,yvec);
        }
        public void MoveSprite(Vector2f vec)
        {
            this.Position += vec;
        }
        public void MoveSpriteByDirection(float angledirection, float speed, bool turnvisually)
        {
            float xvec = (float)MissingMathFunctions.calcXOnlyVector(angledirection % 360) * speed,
                yvec = (float)MissingMathFunctions.calcYOnlyVector(angledirection % 360) * speed;
           
            if(turnvisually)
            {
                this.Rotation = angledirection % 360;
            }
            VectorDirection += new Vector2f(xvec, yvec);
        }
        public void MoveSpriteByDirection(float angledirection, float speed, bool turnvisually, bool setoradd)
        {
            float xvec = (float)MissingMathFunctions.calcXOnlyVector(angledirection % 360) * speed,
                yvec = (float)MissingMathFunctions.calcYOnlyVector(angledirection % 360) * speed;

            if (turnvisually)
            {
                this.Rotation = angledirection % 360;
            }
            System.Console.WriteLine("Move Angle: " + VectorDirection.ToString());
            if (setoradd)
            {
                VectorDirection = new Vector2f(xvec, yvec);
            }
            else
            {
                VectorDirection += new Vector2f(xvec, yvec);
            }
        }
        public void AISeeking(Vector2f targetloc)
        {
            Vector2f targetvec = MissingMathFunctions.normallizedVector(targetloc - this.Position) * (float)this.MaxSpeed;
            Vector2f steering = targetvec - VectorDirection;
            steering = MissingMathFunctions.TruncateVector(steering, (float)this.MaxSpeed * 2);
            float mass = this.Texture.Size.X * this.Texture.Size.Y / 2;
            steering /= mass;

            VectorDirection += steering;
            this.Rotation = (float)MissingMathFunctions.AngleTo(VectorDirection.X, VectorDirection.Y) % 360;
        }
       

    }
 

Can post the missing math function file if needed to but all it is, is a few vector math equations for changing a vector into an angle and back again.  Some I'm planning on replacing with what I found in NetEXT since it also does them.
I have many ideas but need the help of others to find way to make use of them.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Solved! Was Vector Normalization Error
« Reply #6 on: April 18, 2014, 09:11:59 pm »
Turns out the bug was in my Missing Math Class after all.

It was in the Normalize equation.  What happens to an SFML vector when you do this number?  Vector(0,0) / Magnitude of 0 = Vector(NaN,NaN).  >.>


public static Vector2f normallizedVector(Vector2f vec)
        {
            float mag = Vector2Algebra.Length(vec);//(float)VectorMagnitude(vec);
            if (Math.Abs(mag) > Math.Abs(0) || (vec.X != 0 && vec.Y != 0))
            {
                return vec / mag; // without the if statement should mag ever become 0 or close enough to it to cause a rounding to 0 this would fail
            }
            else
            {
                return vec;
            }
        }
 

Also zsbzsb your UnitVector code in NetEXT has the same error in it. :)  If Magnitude ever becomes 0 or close enough it rounds to 0 it'll spit out a new Vector of (NaN,NaN). 
I have many ideas but need the help of others to find way to make use of them.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Solved! Was Vector Normalization Error
« Reply #7 on: April 18, 2014, 09:17:12 pm »
Also zsbzsb your UnitVector code in NetEXT has the same error in it. :)  If Magnitude ever becomes 0 or close enough it rounds to 0 it'll spit out a new Vector of (NaN,NaN).
There is no meaningful result when computing the unit vector of a zero vector. In particular, returning the zero vector is wrong.

UnitVector()'s postcondition is that the vector has unit length, as implied by the name. I'm not sure about the C# policy of handling such errors, but in Thor, I use an assertion to prevent zero-vector input (in C++, I do not use exceptions for logic errors).
« Last Edit: April 18, 2014, 09:19:14 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Solved! Was Vector Normalization Error
« Reply #8 on: April 18, 2014, 09:26:22 pm »
Also zsbzsb your UnitVector code in NetEXT has the same error in it. :)  If Magnitude ever becomes 0 or close enough it rounds to 0 it'll spit out a new Vector of (NaN,NaN).
There is no meaningful result when computing the unit vector of a zero vector. In particular, returning the zero vector is wrong.

UnitVector()'s postcondition is that the vector has unit length, as implied by the name. I'm not sure about the C# policy of handling such errors, but in Thor, I use an assertion to prevent zero-vector input (in C++, I do not use exceptions for logic errors).

hmm strange though since I know your Thor Lib stops these errors but I checked the code for UnitVector on his C# copy of Thor and it doesn't have anything stopping this error from happening.  ???  It just does the division and no divide by 0 check or 0 vector check at least in the version I'm seeing anyways. ???
I have many ideas but need the help of others to find way to make use of them.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Strange bug with SFML when rendering sprites close together.
« Reply #9 on: April 18, 2014, 11:14:40 pm »
I just added the missing assertions.  :D
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor