Drag and Drop - Dragging all items, that overlap instead of the top-most.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Kegs
:warning: Old Version Published before Godot 3 was released.

Hello, I am trying to recreate solitaire to get some practice in with the engine and also it being my first game I am making more or less.

I’ve started small and just wanted to be able to drag and drop some cards. I’ve got most of it down, however when two cards overlap I will drag both of them if the mouse is over the overlapping section.

I have tried to increase the Z-Axis, when the cards overlap then check the Z-Axis when moving. This kinda works, but it needs a little refinement. I just can’t figure out this logic properly. This also doesn’t allow me to select the non-overlapping part of a card that is on the lower Z-Axis.

I have an Area2D, with a child Sprite and CollisionShape2D.

Here is my script:

extends Area2D

const TEXTURE_WIDTH = 30
const TEXTURE_HEIGHT = 45

var pos_offset = Vector2()
var mouse_pressed = false

func _ready():
	set_process_input(true)

func _input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			mouse_pressed = true
			pos_offset = self.position - get_global_mouse_position()
			
		if event.button_index == BUTTON_LEFT and not event.pressed:
			mouse_pressed = false

func _process(delta):
	if mouse_pressed and self.get_z() == 1:
		self.position = get_global_mouse_position() + pos_offset
		
		# Left
		if self.position.x < TEXTURE_WIDTH:
			self.position.x = TEXTURE_WIDTH
		# Right
		if self.position.x + TEXTURE_WIDTH > get_viewport().size.x:
			self.position.x = get_viewport().size.x - TEXTURE_WIDTH
		# Top
		if self.position.y < TEXTURE_HEIGHT:
			self.position.y = TEXTURE_HEIGHT
		# Bottom
		if self.position.y + TEXTURE_HEIGHT > get_viewport().size.y:
			self.position.y = get_viewport().size.y - TEXTURE_HEIGHT


func _on_Area2D_area_entered(area):
	if mouse_pressed and self.get_z() == 1:
		area.set_z(0)

func _on_Area2D_area_exited(area):
	if mouse_pressed:
		area.set_z(1)
:bust_in_silhouette: Reply From: Kegs

After having a think about it over-night, I’ve managed to come up with a slight solution. So I’m posting my answer to help others who have the same problem.

I needed to change the _on_Area2D_area_exited function.

It is currently this:

func _on_Area2D_area_exited(area):
	if self.get_z() == 0:
		mouse_pressed = false
		self.set_z(1)

Currently this allows me to move cards that overlap, even when clicking on the overlapping section. There is a drawback in that you will be unable to click on the bottom card without moving the top card first.

How’d you go with your game? Did you finish it? Making a solitaire game myself right now and came across this whilst looking for Drag and Drop. Be keen to share what I’m up to as I go, I have only started though.

Robster | 2018-10-22 02:12