



Reply From: 
avencherus 
You might get a more pleasing and simpler result, if you get a point of impact, convert it to a percentage based on the current height, and use that in an interpolation formula to decide the weights.
Another idea is to also get a point, then map it to a range between 1 and 1. From there you can use these values to multiply into some weight. The sign should also help split the angle directions from hitting the center.
Thank you for this.
I’ll go with your first idea for now.
I have a ball (RidigBody2D) and it now has collision testing so it knows what object it’s hitting.
I have a test bit of code attached to the ball like so:
func checkCollisions(delta):
var collisionList = get_colliding_bodies()
if(get_colliding_bodies().size()>0 ):
#check if bat
if collisionList[0].get_name() == "batL":
findCollisionAreaOnBat("batL")
elif collisionList[0].get_name() == "batR":
findCollisionAreaOnBat("batL")
So I also have a function called findCollisionAreaOnBat(bat)
but I’m not sure on the approach to take.
How can I go about finding that collision area on the bat?
For example, is there a function that lets you know what local space you (the ball) collided with (object/bat)?
If not, is there some programming mojo I must learn (am I’m happy to learn it!)?
Robster  20170222 00:47
There are many ways to do this.
If you want more information about the physics events on a RigidBody, you’ll want to implement the _integrate_forces(state):
function. The state object contains many things you can query from.
The setup in your case you can use it fine without actually creating your own integration, you can just have it do queries. But if you want to do custom integration as well, you have to make sure you check the custom integration option on the properties, or set it in script.
Outside of that you want to make sure your RigidBody has at least 1 reported contact, their default is 0.
Then a simple example might look like:
func _ready():
set_max_contacts_reported(1)
func _integrate_forces(state):
if(state.get_contact_count() > 0):
print(state.get_contact_local_pos(0))
If you want to see what else is on hand for the state, I’d refer you to the docs here: http://docs.godotengine.org/en/stable/classes/class_physics2ddirectbodystate.html#classphysics2ddirectbodystate
Another alternative is to use a raycast that has it’s direction continually aligned to the ball’s heading. You should be able to extract collision details from it.
If you’re determined to use _fixed_process(delta)
, there are no methods that give you easy queries to the physics state. You can make calls to the Physics2DServer and do special queries, like ray casts and shape intersections.
Outside of that, inside the processing loop you can detect the collision, but you’re on your own as to calculating the collision point. A simple method might getting the collision object from the array returned by get_colliding_bodies()
, then doing a line intersect test on the heading of the ball (to some length beyond it’s radius) against the line draw from the top and bottom points of that bat’s contacting edge. Since it’s a straight rectangle and circle, the point of intersection is probably roughly accurate.
avencherus  20170222 02:25
Firstly thank you for such a detailed answer, it’s very much appreciated.
I’m really not good at math, or programming so I’ve been toying with ideas you’ve presented as well as research from around the net. This is what I’ve come up with.
I can detect the position of the ball hitting the bat now (where on the bat it hits) and I have now normalised it to a 1 +1 range which is great. Now onto the next part.
Thanks again
func findCollisionAreaOnBat(bat):
#Where is the bat pos?
var batLocString = str("/root/gameLevel/",bat)
var batLoc = get_node(batLocString).get_transform().get_origin()
#Where is the ball pos?
var ballLoc = self.get_transform().get_origin()
#what is the bat Height?
var batHeightString = "/root/gameLevel/%s/Spritebat"
var actualBatHeightString = batHeightString % bat
var batHeight = get_node(actualBatHeightString).get_texture().get_height()
#work out where the ball has hit the bat by subtracting the location of each (bat and ball) origins
#hitLocation will have a negative or positive number, based on how many pixels from bat centre we are
var hitLocation = ballLoc.y  batLoc.y
# #The line below turns the + pixel count into a normalised value. So it's between 1 and +1 at each extreme of the bat, depending on where it hits
#This gives me a specific number I can work with each time, regardless of bat size. Nice!
var normalisedhitLocationY = (hitLocation/(batHeight/2));
Robster  20170224 03:11
Sure thing. It looks like you’re off to a good start.
If you want some visual understanding of the cosine and sine, it will generate a unit length vector (a vector that has a length of 1) that swings around a circle.
A good demo for seeing the line’s X/Y lengths can be found here: Interactive Unit Circle
cosine is for X and sine is for Y
Unit length vectors are useful because you can multiply in some distance to change it’s length while keeping it’s direction intact. In your case that unit vector can be imagined as a heading and the scalar as the length it will travel in that game frame.
var velocity = Vector2(cos(angle), sin(angle)) * speed
avencherus  20170224 03:27
Thank you. I have to admit I feel … a little challenged here. I started reading the godot vector tutorial and just about died. I understand the idea of direction and magnitude and also I feel I understand a unit vector but it will take me time to really learn it. I’ll do some basic courses online over the next few months.
I’ll ask a new qeustions RE the rest as it’s a different topic and I will aim to keep it focused. Thanks again so very much.
Robster  20170224 03:36