1
\$\begingroup\$

I have a problem: I am learning the Per Pixel Collision, because I am very new to Monogame. Everything works thine, but my texture (image) is too big, so I scaled it down to 0.5f. Now it doesn't work correctly. I really would love to see a good explained answere with a solution.

Game.cs code

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    List<GameItem> gameItems = new List<GameItem>();
    Color backgroundColor = Color.CornflowerBlue;

    int mouseX;
    int mouseY;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";   
    }

    protected override void Initialize()
    {            
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);

        var texture = Content.Load<Texture2D>("star");

        this.gameItems.Add(new GameItem(texture, "player"));
        this.gameItems.Add(new GameItem(texture, "enemy"));           
    }

    protected override void UnloadContent()
    {

    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        var player = this.gameItems.Where(o => o.Type == "player").FirstOrDefault();

        foreach (var gameItem in gameItems)
        {
            if (gameItem.Type == "player")
            {
                continue;
            }

            if (IntersectsPixel(player.rectangle, player.textureData, gameItem.rectangle, gameItem.textureData))
            {
                backgroundColor = Color.Red;
            }
            else
            {
                backgroundColor = Color.CornflowerBlue;
            }
        }


        var mouse = Mouse.GetState();
        this.mouseX = mouse.X;
        this.mouseY = mouse.Y;


        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(backgroundColor);

        spriteBatch.Begin();

        foreach (var gameItem in gameItems)
        {
            if (gameItem.Type == "player")
            {
                gameItem.UpdatePosition(this.mouseX, this.mouseY);
            }

            gameItem.Draw(spriteBatch);
        }

        spriteBatch.End();

        base.Draw(gameTime);
    }

    static bool IntersectsPixel(Rectangle rect1, Color[] data1, Rectangle rect2, Color[] data2)
    {
        int top = MathHelper.Max(rect1.Top, rect2.Top);
        int bottom = MathHelper.Min(rect1.Bottom, rect2.Bottom);
        int left = MathHelper.Max(rect1.Left, rect2.Left);
        int right = MathHelper.Min(rect1.Right, rect2.Right);

        for (int y = top; y < bottom; y++)
        {
            for (int x = left; x < right; x++)
            {
                Color colour1 = data1[(x - rect1.Left) + (y - rect1.Top) * rect1.Width];
                Color colour2 = data2[(x - rect2.Left) + (y - rect2.Top) * rect2.Width];

                if (colour1.A != 0 && colour2.A != 0)
                {
                    return true;
                }
            }
        }

        return false;
    }
}

GameItem.cs (class)

public class GameItem
{
    private Texture2D texture2D { get; set; }
    public string Type { get; private set; }
    private int x;
    private int y;
    float scale = 1f;

    //Collision detection
    public Color[] textureData;
    public Rectangle rectangle;

    public GameItem(Texture2D texture2D, string type)
    {
        this.texture2D = texture2D;
        this.Type = type;
        this.x = 100;
        this.y = 100;

        //Collision detection
        textureData = new Color[texture2D.Width * texture2D.Height]; 
        texture2D.GetData(textureData);

        rectangle = new Rectangle(x, y, this.texture2D.Width, this.texture2D.Height); 

        var count = textureData.Where(o => o.A != 0).ToList();
    }

    public void UpdatePosition(int x, int y)
    {
        this.x = x; 
        this.y = y;

        rectangle = new Rectangle(x, y, this.texture2D.Width, this.texture2D.Height); 
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture2D, new Vector2(this.x, this.y), null, Color.White, 0f, new Vector2(0, 0), scale, SpriteEffects.None, 0f);            
    }
}

}

\$\endgroup\$
  • \$\begingroup\$ I suspect that your textureData-Array has the original size,? (100 entries for a 10x1px Image) You draw the texture only in half the size and compare the collision with the textureData from the full size Image, right? Does not sound right to me. If your collision object is only 5x5 px large, the textureData should be 25 entries large. \$\endgroup\$ – Pavel Slesinger Jul 24 '18 at 9:17
  • \$\begingroup\$ "Now it doesn't work correctly." Would there be a way to describe what you expect and what you get instead? \$\endgroup\$ – Alexandre Vaillancourt Jul 26 '18 at 3:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.