0 votes

Back when I used Game Maker, I used surfaces to make holes inside sprites and primitives. My question is how can I make hole (draw_circle), inside a rectangle (draw_rect) in Godot.

in Engine by (81 points)
edited by

1 Answer

0 votes

You'll need to use a 2D node and the _draw() func.

This function is inherent of all CanvasItem nodes and draws things to the Viewport, it also has some unique methods that you'll want to use, here is an example:

extends Node2D

func _ready():

func _draw():

    var pos = get_viewport().get_rect().size/2 #get center of the screen
    var rect_size = Vector2(80,60) #the size of your rectangle

    #because the rectangle origin is his top-left
    #does some correction to make it centered
    var rect_pos = pos - rect_size/2 

    #create your Rect2
    var rect = Rect2(rect_pos, rect_size )

    #drawn Rect
    draw_rect( rect, Color(1,1,1) )

    #drawn circle (origin is center by default)
    draw_circle( pos, 10, Color(1,.2,.5) )

Done, you just drew the Japanese flag with this, sorta, lol. For further reading: _draw()

by (39 points)

I think I should have made my question more clearer, I want to make a hole in the sense of being able to see what's behind the rectangle through the hole.

Uh... If there's something like that in Godot, I don't know. I know however this should be possible using shading language, but I'm no expert at it. But I have a "trick" for you.

Create a sprite, texture it and in it's Material propriety, create a CanvasItemMaterial and set Shading Mode to Light Only, making it invisible.

Next, make a Light2D child, texture it with a white square image that engulfs the sprite, and set its Mode propriety to Mask. The main sprite now is visible as long as the mask is opaque.

Also make the same white square image but with an alpha hole at the center, make an AnimationPlayer with a track that scales the mask till a certain point, then in the main sprite script, put:

extends Sprite

var sprite
var mask
var anim

func _ready():

    sprite = get_node(".") #main sprite
    mask = get_node("Light2D")
    anim = get_node("AnimationPlayer")

func _fixed_process(delta):

    #create the hole
    if Input.is_key_pressed(KEY_SPACE):

        var hole = load("res://mask_hole.png") #load the mask with the hole 
        mask.set_texture(hole) #change the one without the hole for it
        anim.play("hole_expand") #plays the animation that scales the mask

In this example a hole will appear in the center of the mask, that'll be scaling up, thus making a hole at the center of the main sprite too.

The problem lies in the fact that the mask can affect other sprites in the same light mask layer, so be sure to change both sprite light mask and the mask item mask to prevent this from affecting undesired sprites.

Although it's probably not what you wanted, it should serve as a placeholder till you find a better method.

I already have a placeholder method, by using a Polygon2D node, and an algorithm to draw circles:

var polygon_positions = PoolVector2Array()
var segments = 64
var viewport_size = get_tree().get_root().get_size()
var radius = (viewport_size.y / 2) + 29
for i in range(segments):
    var angle = (i * (PI * 2)) / segments
    polygon_positions.append(Vector2(cos(angle), sin(angle)) * radius)

polygon = polygon_positions
invert_border = viewport_size.x / 3
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.