My physics system won't work

Godot Version

4.6.1

Question

I’m trying to make a system where if the player flings an object too hard against another, it will make an “impact”. However, this system

  • Does not record impacts normally most of the time
  • Records impacts even when the object I am dragging is not being thrown (unless I let go of it without moving my mouse)
  • Still thinks the object I am dragging is on other objects while dragging it

Here’s my GDScript that I got so far (note that, unfortunately, I used ChatGPT to help me program this script, in which it has proven itself useless), so could someone please help me?

class_name object_drag
extends RigidBody2D

var dragging = false
var was_dragging = false
var mouse_out = true
var mouse_vel = Vector2.ZERO
var mouse_prev_pos = Vector2.ZERO
var mouse_cur_pos = Vector2.ZERO
var mouse_lclick = false
var min_force = Vector2(25, 10)

var had_contact_last_frame = false
var impacts = 0
var min_impact_speed = 25.0
var impact_cooldown = 0.1
var impact_timer = 0.0

func _ready():
	input_pickable = true
	contact_monitor = true
	max_contacts_reported = 10

func _physics_process(delta):
	var mouse_pos = get_global_mouse_position()
	mouse_vel = (mouse_pos - mouse_prev_pos) / max(delta, 0.0001)
	mouse_prev_pos = mouse_pos

	if dragging:
		freeze = true
		linear_velocity = Vector2.ZERO
	else:
		if was_dragging:
			if mouse_vel.length() > min_force.length():
				linear_velocity = mouse_vel
		freeze = false

	was_dragging = dragging

	impact_timer -= delta

	if dragging:
		had_contact_last_frame = false
		return
	
	var has_contact = (get_contact_count() > 0)

	if has_contact and not had_contact_last_frame and impact_timer <= 0:
		if linear_velocity.length() >= min_impact_speed:
			impact_timer = impact_cooldown
			impacts += 1
			print("Impact:", impacts)

	had_contact_last_frame = has_contact

func _input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton:
		if event.button_index == MOUSE_BUTTON_LEFT:
			dragging = event.pressed
			mouse_lclick = event.pressed

	elif event is InputEventMouseMotion:
		mouse_vel = event.velocity

func _process(delta):
	mouse_cur_pos = get_global_mouse_position()

	if dragging:
		freeze = true
		linear_velocity = Vector2.ZERO
		angular_velocity = 0

		var ext = $CollisionShape2D.shape.extents
		var c = abs(cos(rotation))
		var s = abs(sin(rotation))

		var half_x = ext.x * c + ext.y * s
		var half_y = ext.x * s + ext.y * c

		position.x = clamp(mouse_cur_pos.x, -290 + half_x, 290 - half_x)
		position.y = clamp(mouse_cur_pos.y, -150 + half_y, 150 - half_y)
		
	else:
		freeze = false

I really recommend you start from scratch and learn how Godot works. Follow some YouTube tutorials, and go from there. Your code is a mess and it’s not even that long. It is way overcomplicated, and it’s trying to wrest control of the physics engine that Godot already has.

Also, start simple. Just make a little cannon that shoots and object into another one. You can do that with a few lines of code. Then add deforming the object that is hit. Learn about Physics Materials and how changing them in the Inspector will get you different results.

Or, if you don’t really want to learn Godot, switch to Claude and try again.

1 Like

This is exactly why I don’t like LLM code.

You won’t like my suggestion, but here it is - start over.

When you do, do every step yourself. Find tutorials that will show you how do each step. Tutorials usually have working code you can use as a base for your own.

I suspect that if you search public projects on Git you might be able to find projects that demonstrate dragging and/or throwing. Those would be another place to find code that shows you how something is actually done.

Think of it as being an aspiring author. Before you write your own masterpiece you read the works others have done to teach and inspire yourself.

I appreciate that you want to create a video game. I just think you need to learn how to do it yourself.

3 Likes

You may prefer to override _integrate_forces You can get much more contact information from it’s passed in state variable.

func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
	for i in state.get_contact_count():
		var impulse := state.get_contact_impulse(i)
		if impulse.length() > MINIMUM_HIT_FORCE:
			print("Impact has occured!")

You should similarly use state to alter the linear velocity, removing any need for physics process and likely also process

1 Like