• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Drawing holes in shapes SOLVED

T

Toxicosis

Guest
Greetings,

I'd like to draw a crosshair composed of the area sandwiched between two rounded rectangles. I think the easiest way to do this would be to draw two rounded rectangles, and make the inner one transparent, a cutout so to speak.

What's the best way to make this happen? With the draw functions, I mean. I'd really like not to create a sprite for this.
 

obscene

Member
Well to cut one shape out of another requires the use of blend modes and surfaces, which is super-overkill for something like this. Make a sprite. It's insanely faster than setting surfaces, drawing rectangles, changing blend modes, changing colors, etc. Insanely faster. You're going to be causing a minimum of 2 vertex batches and texture swaps and take a FPS hit instead of spending 30 seconds making (or googling) a sprite.
 
T

Toxicosis

Guest
For anyone who tries to do this in the future, the easiest way to cut one image out of another is to use draw_set_blend_mode_ext. Draw the shape to cut out in full (or not so full) alpha to the surface you wish to cut it out of.

The blend mode necessary is draw_set_blend_mode_ext(bm_inv_src_alpha, bm_inv_src_alpha).

It'll draw the src image to the dest surface at inverse alpha, i.e., only contribute anything where there's nothing being contributed, and ignore any part of the image being drawn where the alpha is 1. Meanwhile, the destination image will have its alpha reduced to 0 wherever the image you are drawing has an alpha of 1.

Took some trial and error. Yeesh!
 
G

grymmjack

Guest
For anyone who tries to do this in the future, the easiest way to cut one image out of another is to use draw_set_blend_mode_ext. Draw the shape to cut out in full (or not so full) alpha to the surface you wish to cut it out of.

The blend mode necessary is draw_set_blend_mode_ext(bm_inv_src_alpha, bm_inv_src_alpha).

It'll draw the src image to the dest surface at inverse alpha, i.e., only contribute anything where there's nothing being contributed, and ignore any part of the image being drawn where the alpha is 1. Meanwhile, the destination image will have its alpha reduced to 0 wherever the image you are drawing has an alpha of 1.

Took some trial and error. Yeesh!
Hi there, do you have a code sample you could share?

I'm trying to do this:

Code:
/// draw_circ(x1, y1, radius, line_color, line_width, line_inside, fill_color, fill)
/// @arg x1 x position
/// @arg y1 y position
/// @arg radius of circle
/// @arg line_color of outline
/// @arg line_width of outline
/// @arg line_inside?
/// @arg fill_color of fill
/// @arg fill rectangle?
var x1            = argument0;
var y1            = argument1;
var radius        = argument2;
var line_color    = argument3;
var line_width    = argument4;
var line_inside = argument5;
var fill_color  = argument6;
var fill        = argument7;
var lc            = line_color;
var cw          = c_white;
var cb          = c_black;
var lw            = line_width;
var fc            = fill_color;

// OUTLINE
for (var i=0; i <= lw; i++) {
    if (!line_inside) {
        draw_circle_color(x1, y1, radius+i, lc, lc, false);
        gpu_set_blendmode_ext(bm_inv_src_alpha, bm_inv_src_alpha);
        draw_circle_color(x1, y1, radius, cw, cw, false);
        gpu_set_blendmode_ext(bm_normal, bm_normal);
    } else {
        draw_circle_color(x1, y1, radius-i, lc, lc, false);
        gpu_set_blendmode_ext(bm_inv_src_alpha, bm_inv_src_alpha);
        draw_circle_color(x1, y1, radius, cw, cw, false);
        gpu_set_blendmode_ext(bm_normal, bm_normal);
    }
}
// FILL
if (fill) {
    draw_circle_color(x1, y1, radius, fc, fc, false);
}

The idea is so I could do something like this:
Code:
// FILLED RECTANGLE WITH OUTER BORDER
draw_rect(10, 10, 100, 100, c_red, 5, false, c_blue, true);

// HOLLOW RECTANGLE WITH OUTER BORDER
draw_rect(150, 10, 250, 100, c_red, 5, false, c_blue, false);

// FILLED RECTANGLE WITH NO BORDER
draw_rect(300, 10, 400, 100, c_red, 0, false, c_blue, true);

// FILLED RECTANGLE WITH INNER BORDER
draw_rect(10, 150, 100, 250, c_blue, 5, true, c_red, true);

// HOLLOW RECTANGLE WITH INNER BORDER
draw_rect(150, 150, 250, 250, c_blue, 5, true, c_red, false);

// FILLED RECTANGLE WITH NO BORDER
draw_rect(300, 150, 400, 250, c_blue, 0, true, c_red, true);

// FILLED CIRCLE WITH OUTER BORDER
draw_circ(500, 55, 45, c_red, 5, false, c_blue, true);

// HOLLOW CIRCLE WITH OUTER BORDER
draw_circ(500, 55, 45, c_red, 5, false, c_blue, false);
I have the rectangle ones working, and I was using the outline mode of the draw_circle_color but the way I was doing it in a for loop was creating little pixel holes based on my 💩💩💩💩ty math :) So I was hoping to basically do a subtraction - draw the first circle the size I need, punch another one out of it. I am hopeful you can help me.

Code:
// FILLED RECTANGLE WITH OUTER BORDER
draw_rect(10, 10, 100, 100, c_red, 5, false, c_blue, true);

// HOLLOW RECTANGLE WITH OUTER BORDER
draw_rect(150, 10, 250, 100, c_red, 5, false, c_blue, false);

// FILLED RECTANGLE WITH NO BORDER
draw_rect(300, 10, 400, 100, c_red, 0, false, c_blue, true);

// FILLED RECTANGLE WITH INNER BORDER
draw_rect(10, 150, 100, 250, c_blue, 5, true, c_red, true);

// HOLLOW RECTANGLE WITH INNER BORDER
draw_rect(150, 150, 250, 250, c_blue, 5, true, c_red, false);

// FILLED RECTANGLE WITH NO BORDER
draw_rect(300, 150, 400, 250, c_blue, 0, true, c_red, true);

// FILLED CIRCLE WITH OUTER BORDER
draw_circ(500, 55, 45, c_red, 5, false, c_blue, true);

// HOLLOW CIRCLE WITH OUTER BORDER
draw_circ(500, 55, 45, c_red, 5, false, c_blue, false);
 

Attachments

Last edited by a moderator:
G

grymmjack

Guest
Well to cut one shape out of another requires the use of blend modes and surfaces, which is super-overkill for something like this. Make a sprite. It's insanely faster than setting surfaces, drawing rectangles, changing blend modes, changing colors, etc. Insanely faster. You're going to be causing a minimum of 2 vertex batches and texture swaps and take a FPS hit instead of spending 30 seconds making (or googling) a sprite.
How do you know all of this? I'm not questioning you :) I would like to know what all of these things you're saying mean and how you know so much about optimization and so on - can you share your source information? So I can educate myself?

I know I can use sprites I was just learning some GML stuff and was practicing being fancy with scripts. This seemed like something I'd want to do - create boxes and circles for GUI elements, etc. from code. Since the functions are there, why not, right? Was thinking dialogs, etc. But I guess I could use 9-slice sprites and fancy stuff too that way to keep the processing lower. What is a vertex batch or a texture swap? Thank you!
 
Top