13 Replies - 2198 Views - Last Post: 23 June 2016 - 02:11 AM

#1 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

MonoGame: odd flickering effect by drawing

Posted 16 June 2016 - 01:55 AM

Good morning coders,

This is my first post here, so I need to set things up :)/>

I'm making a little game, since making those are a good start of enjoying to program.
This is the first time trying Monogame, and the game is based on a tiled dungeon crawl/roguelike genre.
After implementing a camera Matrix, I noticed some crazy flickering while walking around:
Attached Image
And sometimes when standing still.
Attached Image
I don't know the exact cause of it, but the flickering is linked when drawing the tiles, not in the update method.

Here's the code I use in the game1 drawing class:
public void CameraMovement(GameTime gameTime, int i)
        {
            camera.Position = new Vector2(players[i].rect.X + players[i].rect.Width / 2 - graphics.PreferredBackBufferWidth / 2, players[i].rect.Y + players[i].rect.Height / 2 - graphics.PreferredBackBufferHeight / 2);
            if (Keyboard.GetState().IsKeyDown(Keys.OemPlus))
            {
                camera.Zoom = 1;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.OemMinus))
            {
                camera.Zoom = 0.5f;
            }
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            var viewMatrix = camera.GetViewMatrix();
            spriteBatch.Begin(transformMatrix: viewMatrix);
            switch (gameState)
            {
                case GameState.OVERWORLD:
                    {
                        regen.Draw(spriteBatch);
                        foreach (Enemy e in enemies)
                        {
                            e.Draw(spriteBatch);
                        }
                        foreach (Effect e in effects)
                        {
                            e.Draw(spriteBatch);
                        }
                        foreach (Darkness dark in regen.darkrooms)
                        {
                            dark.Draw(spriteBatch);
                        }
                        for (int i = 0; i < amountOfPlayers; i++ )
                        {
                            players[i].Draw(spriteBatch);
                            hud.DrawPlayerStats(spriteBatch, players[i], activePlayer, camera, tileSize, turn);
                        }
                        hud.Draw(spriteBatch, amountOfPlayers, camera, players); 
                        break;
                    }
                case GameState.COMBAT:
                    {
                        combat.Draw(spriteBatch);
                        break;
                    }
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }


Currently only mentioning the camera and drawing method because I think the problem lies there.
Since the flickering still occur when commenting out the whole update method.

I hope that there's a solution to this problem, because this really discourage me to continue working on the project.

Is This A Good Question/Topic? 0
  • +

Replies To: MonoGame: odd flickering effect by drawing

#2 SixOfEleven  Icon User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: MonoGame: odd flickering effect by drawing

Posted 18 June 2016 - 04:24 AM

It would be helpful if you posted some of the Draw methods so we can see if it is one of those that is causing the problem.

For now it is time to do some basic debugging to see if we can figure out what exactly is causing this. What I suggest is commenting out all of the Draw calls and see if you still experience the problem with the flashes. If you do then it has something to do with the camera. If you don't then it is one of the function calls. Now, uncomment out one of the Draw calls and see if the problem occurs. If it does not comment it out and then do the next one. Repeat until all of the Draw calls have been tested. If this does not reveal the error try enabling two Draw calls in different combinations, then three Draw calls, etc.
Was This Post Helpful? 0
  • +
  • -

#3 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 12:15 AM

Thanks for the reply,
I'm gonna debug this a bit while testing out. so far I know is that it's related when drawing the tiles.
I though the other draw classes would be lesser important, but I'm gonna mention them here below:

the regen.draw(spriteBatch); (the regenerator that creates the map, they draw the tiles one by one in the right position)
public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Tile t in tiles)
            {
                t.Draw(spriteBatch);
            }
        }


darkness Draw method (a black texture that covers the room untill you entered)
public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, rect, new Color(255, 255, 255, (byte)MathHelper.Clamp(alphaValue, 0, 255)));
        }



the hud.Draw Method
public void Draw(SpriteBatch spriteBatch, int amountOfPlayers, Camera2D camera, Player[] players)
        {
            if (camera.Zoom == 1)
            {
                for (int i = 0; i < amountOfPlayers; i++)
                {

                    spriteBatch.Draw(players[i].texture, new Rectangle(camera.Position.ToPoint() + new Point(150 + 40 * i, 10), new Point(40, 40)), players[i].color);
                    spriteBatch.DrawString(font, "" + (i + 1), camera.Position + new Vector2(180 + 40 * i, 10), players[i].color);
                    spriteBatch.DrawString(font, "hp:" + players[i].health, camera.Position + new Vector2(158 + 40 * i, 50), Color.White);
                }
            }
        }



And the hud.drawplayerstats Method:
public void DrawPlayerStats(SpriteBatch spriteBatch, Player p, int activeplayer, Camera2D camera, Point tileSize, int turn)
        {
            if (camera.Zoom == 1)
            {
                if (p.charID == activeplayer)
                {
                    spriteBatch.DrawString(font, "" + p.name, camera.Position + new Vector2(10, 10), Color.White);
                    spriteBatch.DrawString(font, "HP: " + p.health, camera.Position + new Vector2(10, 30), hpColor);
                    spriteBatch.DrawString(font, "moves: " + p.move, camera.Position + new Vector2(10, 50), moveColor);
                    spriteBatch.DrawString(font, "turn: " + turn, camera.Position + new Vector2(10, 70), Color.White);
                    //spriteBatch.DrawString(font, "Combat: " + p.inCombat, camera.Position + new Vector2(10, 90), Color.White);
                    walkArrowPos[0] = p.rect.Location + new Point(-5, 21); //left
                    walkArrowPos[1] = p.rect.Location + new Point(50, 21); //right
                    walkArrowPos[2] = p.rect.Location + new Point(21, -5); //up
                    walkArrowPos[3] = p.rect.Location + new Point(21, 50); //down
                    for (int d = 0; d < 4; d++)
                    {
                        if (p.canWalkInDirection[d] == true && p.isWalking == false && p.active == true)
                        {
                            spriteBatch.Draw(walkArrows[d], walkArrowPos[d].ToVector2(), arrowColor);
                        }
                    }
                }
                spriteBatch.DrawString(font, instructionText, camera.Position + new Vector2(10, 300), Color.White);
            }
        }



The other draw methods are the same as this one below:
public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, rect, color);
        }


Was This Post Helpful? 0
  • +
  • -

#4 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 12:42 AM

After a few debugging, I notice that if I disable multiple draw methods, the flickering disappears. I'm also assuming that, seeing the flickering's colors, that it's related with the floortiles.

So, my assuming is that if it's already drawing the parts of the tiles before they are in the right position.
I think that this is happening because of my custom room regenerator. which calculates the tile position before and after it's added to the list.

So I'll now show the whole Regenerator class, this class makes the entire field where your can walk around, including the tiles:
It's a self-made class. and also my first attempt at making a tiled dungeon-crawl. So I can understand that I've messed up a few parts here:
namespace Dungeons_Depths
{
    //I've made a lot of notes here since it's quite complicated
    class Regenerator
    {
        int[] randomSpawn;
        int spawnPosition;
        int rr = -1; //RandomRoom
        public List<Darkness> darkrooms;
        public int[] room;
        Tile[] tileType;
        public List<Tile> tiles;
        public List<Room> roomList;
        Random rnd = new Random();
        Point roomPos = new Point(0, 0);
        Point tilePos = new Point(0, 0);
        Rectangle tileRect;
        int roomSize;
        int floorSize;
        public void Load(ContentManager Content, Point tileSize, List<Enemy> enemies, SpawnHandler spawn)
        {
            roomList = new List<Room>();
            darkrooms = new List<Darkness>();
            tileRect = new Rectangle(tilePos, tileSize);
            Room.Load();
            roomSize = 5; //amount of tiles in a room row
            floorSize = 4; //amount of rooms in a floor row
            tileType = new Tile[]{
                new Tile(Content.Load<Texture2D>("Wall"), tileRect, false), //wall
                new Tile(Content.Load<Texture2D>("Tile"), tileRect, true), //normal
                new Tile(Content.Load<Texture2D>("Tile")/*("spawntile")*/, tileRect, true), //spawnpoint
                new Tile(Content.Load<Texture2D>("Black Tile"), tileRect, false), //pit
            };
            tiles = new List<Tile>();
            BuildFloor(tileSize, Content, enemies, spawn);
        }
        public void BuildFloor(Point tileSize, ContentManager Content, List<Enemy> enemies, SpawnHandler spawn)
        {
            CalculateRandomRoom();
            //generate rooms in the floor
            for (int r = 0; r < room.Length; r++)
            {
                Room roomObject = new Room(r);
                roomList.Add(roomObject);
                Darkness d = new Darkness(Content.Load<Texture2D>("Black tile"), new Rectangle(roomPos, tileSize * new Point(5,5)));
                darkrooms.Add(d);
                //prepares spawnpositions for the enemy
                randomSpawn = new int[]{
                    rnd.Next(1, 10), 
                    rnd.Next(1, 10), 
                };
                CalculateSpawnposition(randomSpawn);
                //generate tiles in order of the room
                for (int i = 0; i < Room.tile[0].Length; i++)
                {
                    //creates new tile
                    Tile t = new Tile(
                        tileType[Room.tile[room[r]][i]].texture, //texture
                        tileType[Room.tile[room[r]][i]].rect, //rectangle
                        tileType[Room.tile[room[r]][i]].isWalkable //iswalkable
                    );
                    //calculates the position of the tile
                    t.rect.Location = new Point(
                        roomPos.X + tileSize.X * tilePos.X,
                        roomPos.Y + tileSize.Y * tilePos.Y);
                    //adds an enemy if the conditions are met
                    if (r != 0 && Room.tile[room[r]][i] == 2 && roomList[r].monsterCount < 2 && i == spawnPosition)
                    {
                        spawn.spawnEnemy(enemies, tileSize, t);
                        roomList[r].monsterCount += 1;
                    }
                    //adds the tile
                    tiles.Add(t);
                    //calculates the next position of the tile after adding
                    tilePos.X += 1;
                    if (tilePos.X == roomSize)
                    {
                        tilePos.X = 0;
                        if (i != Room.tile[room[r]].Length - 1)
                        {
                            tilePos.Y += 1; //adds a new row
                        }
                        else
                        {
                            tilePos.Y = 0; //starts from top
                        }
                    }
                }
                //calculates the next room after creating the previous one
                roomPos.X += (tileSize.X * roomSize);
                if (roomPos.X == (tileSize.X * roomSize * floorSize))
                {
                    roomPos.X = 0;
                    roomPos.Y += (tileSize.Y * roomSize);
                }
            }
            roomPos.Y = 0; //resets the value once the floor is created
        }
        public void CalculateSpawnposition(int[] randomSpawn)
        {
            foreach (int i in randomSpawn)
            {
                switch (i)// 6 - 19
                {
                    case 1:
                        {
                            spawnPosition = 6;
                            break;
                        }
                    case 2:
                        {
                            spawnPosition = 7;
                            break;
                        }
                    case 3:
                        {
                            spawnPosition = 8;
                            break;
                        }
                    case 4:
                        {
                            spawnPosition = 11;
                            break;
                        }
                    case 5:
                        {
                            spawnPosition = 12;
                            break;
                        }
                    case 6:
                        {
                            spawnPosition = 13;
                            break;
                        }
                    case 7:
                        {
                            spawnPosition = 16;
                            break;
                        }
                    case 8:
                        {
                            spawnPosition = 17;
                            break;
                        }
                    case 9:
                        {
                            spawnPosition = 18;
                            break;
                        }
                }
            }
        }
        public void CalculateRandomRoom()
        {
            room = new int[]
            {
                0, 1, 1, 2,
                3, rr, rr, 5,
                3, rr, rr, 5,
                6, 7, 7, 8,
            };
            for (int i = 0; i < room.Length; i++)
            {
                if (room[i] == rr)
                {
                    int random = rnd.Next(1, 10);
                    switch (random)
                    {
                        default:
                            {
                                room[i] = 4;
                                break;
                            }
                        case 2:
                            {
                                room[i] = 9;
                                break;
                            }
                        case 3:
                            {
                                room[i] = 10;
                                break;
                            }
                    }
                }
            }
        }
        public void UnloadContent()
        {
            tiles.Clear();
            darkrooms.Clear();
            roomList.Clear();
        }
        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Tile t in tiles)
            {
                t.Draw(spriteBatch);
            }
        }
    }
}



I can understand that reading a compilated class can be confusing, even I had to make many comments to make sure I understand it myself.
Was This Post Helpful? 0
  • +
  • -

#5 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 01:07 AM

Sorry for the doublepost (Why can't you edit posts though?), but I think I should also have added the Room class to understand things whole

...prepare your umbrella's, because I feel like this code is far away from the DRY-code.
namespace Dungeons_Depths
{
    class Room
    {
        Random rnd = new Random();
        public static int[][] tile;
        int number;
        public int monsterCount;
        public Room(int number)
        {
            this.number = number;   
        }
        public static void Load()
        {
            tile = new int[][]{
            new int[]{//top left corner room
                0,0,0,0,0,
                0,1,1,1,0,
                0,1,1,1,1,
                0,1,1,1,0,
                0,0,1,0,0,
                },
            new int[]{ //top border room
                0,0,0,0,0, 
                0,2,1,2,0,
                1,2,2,2,1,
                0,2,2,2,0,
                0,0,1,0,0,
                },
            new int[]{ //top right corner room
                0,0,0,0,0,
                0,2,1,1,0,
                1,2,2,1,0,
                0,2,2,2,0,
                0,0,1,0,0,
                },
            new int[]{ // left border room
                0,0,1,0,0,
                0,2,2,2,0,
                0,1,2,2,1,
                0,2,2,2,0,
                0,0,1,0,0,
                },
            new int[]{ //middle room
                0,0,1,0,0,
                0,2,2,2,0,
                1,2,2,2,1,
                0,2,2,2,0,
                0,0,1,0,0,
                },
            new int[]{ // right border room
                0,0,1,0,0,
                0,2,2,2,0,
                1,2,2,1,0,
                0,2,2,2,0,
                0,0,1,0,0,
                },
            new int[]{ // bottom left corner room
                0,0,1,0,0,
                0,2,2,2,0,
                0,1,2,2,1,
                0,1,1,2,0,
                0,0,0,0,0,
                },
            new int[]{ // bottom border room
                0,0,1,0,0,
                0,2,2,2,0,
                1,2,2,2,1,
                0,2,1,2,0,
                0,0,0,0,0,
                },
            new int[]{ // bottom right corner room
                0,0,1,0,0,
                0,2,2,2,0,
                1,2,2,1,0,
                0,2,1,1,0,
                0,0,0,0,0,
                },
            new int[]{ // vertical hallway
                0,0,1,0,0,
                0,3,2,3,0,
                1,3,2,3,1,
                0,3,2,3,0,
                0,0,1,0,0,
                },
            new int[]{ // horizontal hallway
                0,0,1,0,0,
                0,3,3,3,0,
                1,2,2,2,1,
                0,3,3,3,0,
                0,0,1,0,0,
                },

            };
        }
    }
}


Was This Post Helpful? 0
  • +
  • -

#6 SixOfEleven  Icon User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 03:11 AM

This sort of thing can happen with tile maps and transformation matrices. You should look at enabling SamplerState.PointClamp, at least that is what I'd do in XNA. It can stop this sort of "bleeding" when rendering with a transformation matrix.
Was This Post Helpful? 0
  • +
  • -

#7 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 03:46 AM

Currently my spritebatch.begin() looks like this:
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp,transformMatrix: viewMatrix);


The PointClamp made the textures much sharper, which is nicer to look at a pixel-art game, but unfortanely, it havn't fixed the flickering.
Was This Post Helpful? 0
  • +
  • -

#8 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 04:15 AM

(Unable to edit posts <.<)

Anyways, When I let my camera unfocus on the character and let it move freely, the flickering have not appeared yet. (Only tested for like 20 seconds though, I'll probably need some more time to see if it occurs again)

Nope, it still seems to occur at certain positions of the camera.
It's kinda weird, but I feel like the flickering is linked with the positions of the tiles, because the flickering will change depending on the tile it happens on.
Was This Post Helpful? 0
  • +
  • -

#9 SixOfEleven  Icon User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: MonoGame: odd flickering effect by drawing

Posted 21 June 2016 - 03:02 PM

It has to do with using float point offsets when and trying to map them to integer values. This can lead to strange artifacting when rendering, such as bleeding and extra effects. What worked for me when writing text is to round my vectors to integers. You could try the following.

camera.Position = new Vector2((int)camera.Position.X, (int)camera.Position.Y));



Be patient, the edit post feature unlocks after an unspecified point. Just keep posting and it will happen when it happens.

This post has been edited by SixOfEleven: 21 June 2016 - 03:02 PM

Was This Post Helpful? 0
  • +
  • -

#10 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 22 June 2016 - 01:22 AM

I've tried it, it does seem to change the flickering a bit, as it now appears on different spots.
I'll debug it some more times later and see if I discover something new.

Another question, is it wise to work further on the project? Since it's progress is more or less halted all because of that flickering bug. And while I'm temped to work on new functions, I rather want to fix the flickering too.
Was This Post Helpful? 0
  • +
  • -

#11 SixOfEleven  Icon User is offline

  • Planeswalker
  • member icon

Reputation: 1055
  • View blog
  • Posts: 6,643
  • Joined: 18-October 08

Re: MonoGame: odd flickering effect by drawing

Posted 22 June 2016 - 02:20 PM

Personally, I'd keep working on it and add new features in the meantime as you will find the solution to the original issue. That said, there was recently another poster here that was having problems with his rendering in MonoGame as well. He was able to resolve them by uninstalling and reinstalling MonoGame, you might want to give that a try.

There a few other things that I can recommend. First, split up your calls to SpriteBatch.Begin and don't try to render everything at once. What I mean, is call Begin, draw a component and then call End. Repeat the process for each component because I have seen this make a difference when rending lots of objects at the same time. The other thing is instead of drawing black tiles don't render anything at all. It is cheaper no both the CPU and GPU to skip drawing them. This a very rough outline of what I'm suggesting.

public void CameraMovement(GameTime gameTime, int i)
        {
            camera.Position = new Vector2(players[i].rect.X + players[i].rect.Width / 2 - graphics.PreferredBackBufferWidth / 2, players[i].rect.Y + players[i].rect.Height / 2 - graphics.PreferredBackBufferHeight / 2);
            if (Keyboard.GetState().IsKeyDown(Keys.OemPlus))
            {
                camera.Zoom = 1;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.OemMinus))
            {
                camera.Zoom = 0.5f;
            }
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            var viewMatrix = camera.GetViewMatrix();
            
            switch (gameState)
            {
                case GameState.OVERWORLD:
                    {
                        spriteBatch.Begin();
                        regen.Draw(spriteBatch);
                        spriteBatch.End();
                        spriteBatch.Begin();
                        foreach (Enemy e in enemies)
                        {
                            e.Draw(spriteBatch);
                        }
                        spriteBatch.End();
                        spriteBatch.Begin();
                        foreach (Effect e in effects)
                        {
                            e.Draw(spriteBatch);
                        }
                        spriteBatch.End();

                        // skip this entirely if you are drawing black on black otherwise call in between a begin and end
                        foreach (Darkness dark in regen.darkrooms)
                        {
                            //dark.Draw(spriteBatch);
                        }
                        spriteBatch.Begin(transformMatrix: viewMatrix);
                        for (int i = 0; i < amountOfPlayers; i++ )
                        {
                            players[i].Draw(spriteBatch);
                            hud.DrawPlayerStats(spriteBatch, players[i], activePlayer, camera, tileSize, turn);
                        }
                        spriteBatch.End();
                        spriteBatch.Begin(transformMatrix: viewMatrix);
                        hud.Draw(spriteBatch, amountOfPlayers, camera, players);
                        spriteBatch.End();
                        break;
                    }
                case GameState.COMBAT:
                    {
                        combat.Draw(spriteBatch);
                        break;
                    }
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }


Was This Post Helpful? 1
  • +
  • -

#12 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 23 June 2016 - 12:06 AM

This seems useful, I'm gonna reïnstall it soon. and also trying out multiple begin calls.

And just in case, the black tiles are there to overlap the undiscovered rooms, they are as big as a room itself, and they'll slowly dissappear when it's intersecting/colliding with the player's rectangle.

So basically, the entire floor with all their rooms is already drawn, but it's covered with black tiles so they remain hidden.
but it's worth a try to let it draw only the parts that the character discovered. yet it'll also be a little more tricky.

This post has been edited by ppowersteef: 23 June 2016 - 12:07 AM

Was This Post Helpful? 0
  • +
  • -

#13 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 23 June 2016 - 01:23 AM

IT WORKED!

By dividing the spritebatch calls, the flickering effect is now disappeared!
Man, this feels good, really good!
Was This Post Helpful? 0
  • +
  • -

#14 ppowersteef  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 21
  • Joined: 16-June 16

Re: MonoGame: odd flickering effect by drawing

Posted 23 June 2016 - 02:11 AM

Well, the single frame start is fixed too, which is great.

Thanks for the big help, now I'm able to continue working on it again without worries.
If I'll encounter another bug where I'm unable to solve it myself, then I'll most likely post it here again. depending on if it hasn't been asked before.

Once again, Thanks a lot, and see you in another time.
:scooter:
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1