1

I was doing a game project in Windows Forms and really loved how it turned out, except for one thing that was bugging me: the new picturebox's I am adding are "eating" away from the one behind it, showind the background of its parent and not showing the image behind him, as I thought it will. Apparently that's how transparency works in Windows Forms, it copies the colors behind him, basically.

This is how it looks, and I want the animals to be seen fully.

I also tried this from another post here, but it turned out like this.

There might be no solution to this, I have other things in this little game I made. There is another picturebox with other buttons and stuff, that represents the shop. And also you can see in both images that there is a pannel in the bottom section with some details. In that case, I would leave it as it is and maybe try another time to move it to WPF.

=================== EDIT ===================

The accepted answer helped me switch from a game with overlaying PictureBoxes to a game where I "paint" each frame of the game on the background. Check that answer's comment for more details about this :) This is how it turned out.

This is specifically for my code, where I have a static Resources class. Yours could look a lot cleaner, maybe you have this Render function where you have every other rectangle and image. I hope this helps everyone that visits this page :)

    // ================ SOLUTION ================
    public static void Render()
    {
        //draw the background again. This is efficient enough, maybe because the pixels that did not changed won't be redrawn
        grp.DrawImage(Resources.gameBackground, 0, 0);

        //draw the squirrel image on the position and length of the "squirrel" Rectangle
        grp.DrawImage(Resources.currentSquirrelImage, Resources.squirrel.X, Resources.squirrel.Y, Resources.squirrel.Width, Resources.squirrel.Height);

        //after that, draw each projectile (acorns, wallnuts) the same way
        foreach (Projectile projectile in Resources.projectiles)
        {
            grp.DrawImage(projectile.image, projectile.rect.X, projectile.rect.Y, projectile.rect.Width, projectile.rect.Height);
        }

        //then draw each animal
        foreach (Enemy animal in Resources.enemies)
        {
            grp.DrawImage(animal.image, animal.rect.X, animal.rect.Y, animal.rect.Width, animal.rect.Height);
        }

        //and finally, the image that shows where the squirrel is shooting
        grp.DrawImage(Resources.selectionImge, Resources.selection.X, Resources.selection.Y, Resources.Selection.Width, Resources.Selection.Height);

        //update the image of the game picturebox
        form.TheGame.Image = bmp;
    }
Nicholas
  • 87
  • 9

1 Answers1

2

As you have noticed .net control transparency is not real transparency, it copies it's parent background, so if you have other sibiling controls the one with the higher Z index will occlude the others.

If you want to create a game avoid the usage of picture boxes, there are many options: use a game engine like Unity or roll your own.

Something easy to do is to create a Bitmap, render your game in it and then present it in your form, but beware, that can be slow.

EDIT: As you requested here is an example on how to use the Intersect function of the Rectangle struct to determine which parts of two rectangles overlap.

Rectangle R1 = new Rectangle (0,0,32,32);
Rectangle R2 = new Rectangle (16,16,32,32);

//To test if a rectangle intersects with another...
bool intersects = R1.IntersectsWith(R2); //If does not intersect then there's nothing to update

//To determine the area that two rectangles intersect
Rectangle intersection = Rectangle.Intersect(R1, R2); //In this example that would return a rectangle with (16,16,16,16).
Gusman
  • 14,905
  • 2
  • 34
  • 50
  • Thank you for your suggestion :) I won't use Unity just yet, I want to understand game mechanics as much as I can before that. With this game I learned a lot :) – Nicholas Jun 11 '20 at 02:48
  • So basically, you are saying to not use picturebox, instead "paint" each animal in order on the background. That will surely be slow since I have many animals at once and they all need to move. Plus it's way easier to check for collisions between projectiles and the animals using a picturebox. – Nicholas Jun 11 '20 at 02:52
  • It is faster than you think if you do it properly. I have managed to get 60fps at 1080 using that technique and having 50 or 60 animated objects. You don't need to redraw everything each time something changes, just the updated areas. – Gusman Jun 11 '20 at 02:54
  • I see, in that case I would love some details :) by that I mean how do I redraw the correct pixels behind an animal after it just moved? – Nicholas Jun 11 '20 at 02:59
  • You need to store each object's bounding box, I usually used the Rectangle struct as it has all the helper functions that you need. Also you store the object's image as a Bitmap. Then, on the game loop (you can use a timer, or do the form to auto-invalidate itself) you create two phases. First you do an "update" phase where you move all the objects that need to be moved and execute the game's logic. Finally you do a "render" phase where you redraw all the parts that need to be updated, for that you intersect the rectangles of ecah updated object with the rectangles of (continues) – Gusman Jun 11 '20 at 03:04
  • the other objects. The `Intersect` of the `Rectangle` struct returns the intersected rectangle so you know the part of the object that you need to redraw. If you do it properly it can be really fast. – Gusman Jun 11 '20 at 03:06
  • Wow, thank you very much! I can follow most of that, but I could use some sample code to really understand how it's done. The part with Intersect would possibly be enough :) – Nicholas Jun 11 '20 at 03:10
  • Let me add an edit with an example on how to use the `Intersect` function. – Gusman Jun 11 '20 at 03:11
  • I will go to sleep rn, it is late where I am from. But I will try out what you show me tomorrow :) I feel like I will learn a lot more from this, too! So I will Mark this as correct, once I try it out of curse :) – Nicholas Jun 11 '20 at 03:24