How to clip a 2D sprite?

One of the things that I very much like about MonoGame (and why I’m a Patreon) is the community is helping (yes, as opposed to Stack Overflow).

I have a PhD in computer science, but I’m a complete newbie with MonoGame. I’m going to ask stupid questions and I appreciate not being ridiculed.

I also hope that the MonoGame Community remains friendly, and helpful. I think it’s crucial if MonoGame is going to survive.

2 Likes

what

I mean, sure, we are not his mom, but there is such a thing as harm done by help (as we can already see by that circle, like, seriously, at least downscale it from a bigger texture), and when helping somebody, you need to be aware of the bigger picture and if the question asked is even the one you need to answer. And instead of nudging the guy into restructuring his code properly, you’ve shown him the spaghetti way that will, over time, make his game harder to continue and maintain, which in turn, may lead to him either not meeting his deadlines or in the worst case, abandoning it. And sure, any game turns into spaghetti eventually, but not being able to put a circle in-between your UI and your game? This smells like a fundamental problem that needs fixing ASAP, before more piles on.

(if you want to reply tell me how wrong I am, maybe better to move to ✔ ☕ General Conversation Thread since this is getting way too offtopic)

What you most likely want to do is just put the playfield draws and the UI in separate begin/end calls and draw the UI at the end. That way the UI is always in the foreground and you never have to even think about clipping.

In your current solution when you open a game menu (as I’ve seen in some other screenshots before) you may still have the circle overlapping. I think with your current solution with the scissoring you’re issuing even more draw calls than with just 2 separate begin/end blocks.

What I normally want to do is have the playfield stuff batched, but have the UI drawn in Immediate-Mode (so I have full control of what is over what).

And yes - just supply a higher resolution circle texture to get rid of the pixel look, it’s just not looking right :slight_smile: There is literally no drawback by supplying a single bigger texture. Make the circle in some imaging software which does proper anti-alias and your circle will look perfectly round all the time.

Maybe you’re right or maybe you aren’t, but the bottom line is that it’s not our place to judge. You may not like the solution, but ultimately you aren’t responsible for the outcome, he is. None of the solutions provided in this thread are unacceptable, they just might not be optimal.

To be completely honest, I think what he ultimately landed on is the best possible solution for his project. It achieves the desired result and doesn’t require significant refactor. Whether or not that significant refactor should happen is largely irrelevant.

Good luck with your project, Ezra, I look forward to seeing the result :slight_smile:

2 Likes

I’m posting what I would consider the most ‘egregious’ example of what we used to call ‘stair casing’.


But, for my purposes, it’s more than good enough. All this is supposed to do is give the user an idea of what the range of this unit is. The fact that it’s a bit jagged around the edges is irrelevant. It almost looks cooler.

A lot of what I do might be considered ‘meatball surgery game coding’. I write massively large games that include standalone editors for armies, maps and scenarios. I’m one guy and I’m trying to get this game out and on the market in the next six months.

Thanks for all the help!

Honestly the best way forward is to use viewports. A viewport is a rectangle that when drawing, will only draw to that part of the rendertarget (or screen)

This is great for making sure there is no overdraw on your different ui components. If you try to draw something outside of the viewport it will not draw it. There is no performance loss using view ports either (unlike switching rendertargets)

For example, your scenario frame on the left hand side of the screen should be a viewport. Your heading bar should be a viewport. Your game screen view should be a viewport

To use a viewport, first you create one
Viewport gameScreen = new Viewport(200,50, 800, 600)

Then you set the view port
graphicsDevice.Viewport = gameScreen

Then you do you drawing

Then you set your viewport to the next viewport, do more drawing etc.

If you didnt want to completely restructure your code to get this to work. Then just simply make your map view use a viewport. Before you call spritebatch.begin on your drawing for this, switch to your gameScreen viewport. Once that drawing is done, then just switch to a viewport that matches your screen resolution to draw all your UI

You need to make sure you change the GraphicsDevice.Viewport = newViewport outside of the spritebatch calls.

I did some experimenting with viewports but I got the exact opposite of what I wanted. I’m sure in time I could have sorted it out. But, this solution works for me.

It’s good you found a solution but like a lot of people here have said, you might want to separate your gamplay draw and your gui draw. It’s normally considered best practice to do that. As you are learning monogame you will discover new things like shader. Let’s say in the future want to do a ripple shader effect on the gameplay screen only. You can’t do that now because you are doing gui and gamplay draw together. Just a thought. Good luck with the game.

1 Like

At some point you you will want to get into shaders.

Even if I coded professionally for like 20 years in Silicon valley cad comapany it took me 3 weeks or more to make this clip mask shader for any shape…it’s a pixel shader so you will have to rasterize or provide a raster mask. Antialias isn’t in there. It’s just comparing pixels on two textures…I couldn’t get s0 buffer to work…both are passed inas texture params .even that is tricky between platforms.

See the code that draws an image with a mask. The clipshader.fx.

This is one fx , for N platforms. .touch a mask, or image to be clipped or shader fx code,set target and it will build and show the change.

I spent weeks trying to clip with a mask using .the old stack exchange advice and the old xna samples and the stencil s and black box solutions didn’t work so I made a simple Shader got it to work on gl and dx android. Also so I can fully see what’s happening and to start using them… basically you provide two textures,
one is a mask,whatever is not on a white pixel isn’t drawn and it works also with transparency and holes… You can do whatever else u want at 1000x faster and I included other collected effects that at least build bit I haven’t tested…

in wpf it is one line of xaml specifyy a clip shader but it’s 60fps max…

Honestly, prefer it to a perfect circle :o:, keep going buddy :sake: :sparkles: