Angle calculation resulting in strange behavior - trigonometry

So, I found some code to essentially have a rectangle follow the mouse around my player object at a set distance. On a 2D plane, I have the character, and when the player clicks the mouse button, a shield will appear between the mouse and the character. This part works, and here is the code:
var angle;
var track_radius = 10;
// find the angle to the mouse
angle = point_direction(self.x, self.y, mouse_x, mouse_y);
// turn the shield to look at the mouse
image_angle = angle;
// convert to radians for the math functions
angle = degtorad(angle);
// place the shield on a circular track about the player
// . track_radius is set in the create event
x = global.playerX + 50 * cos(angle);
y = global.playerY - 50 * sin(angle); // minus
So, the problem comes in when the mouse comes close to the shield. The shield splits into two, mirrored across the mouse pointer, flickering back and forth. The problem continues basically anytime the mouse is near or within the radius where the shield exists. It's also probably worth noting that the shield is created AT the position of the player when the mouse is clicked, and then moved using the above code. Thoughts?

angle = point_direction(self.x, self.y, mouse_x, mouse_y);
This code is calculating the angle from the shield to the mouse pointer, because self currently refers to the shield.
x = global.playerX + 50 * cos(angle);
y = global.playerY - 50 * sin(angle); // minus
Here you set the position of the shield relative to the player, so that the angle from the player to the shield equals the angle that you calculated above.
Now consider the situation where the mouse is close to the shield, and the direction from the shield to the mouse is different than the direction from the player to the mouse. In the bad ASCII graphic below, imagine the O is the player, the ) is the shield and the ^ is the mouse cursor.
O ------ )
^
The shield is directly to the right of the player (0°), but the mouse is directly below the shield (270°). Therefore your code will place the shield directly below the player (remember, angle in your code is the direction from the shield to the mouse)
O
| ^
|
|
)
In the next step, the code again takes the direction from the shield to the mouse. This time it's more like 45° above the shield, so the shield will be placed 45° above and to the right of the player.
This jumping back and forth happens a few times with changing positions, until the shield "settles" in two alternating positions around the mouse cursor.
To come to the solution, you want to use the direction from the player to the mouse cursor to determine your shield position, not the direction from the shield to the mouse cursor. But I have to say that the dynamics of the system you accidentally created are somewhat interesting :)

Related

(2D) Trying to make the player smoothly rotate to the mouse position but it rotates backwards when it becomes a negative number

I am trying to rotate my top down player to the mouse position, I got it working but when it reaches the edge of the rotation degress it goes from a positive number into a negative number causing the rotation to go backwards instead of continuing the rotation, now I know why it happens but I cant figure out how to fix it. (reason to not use look_at is because I cant make it smooth to the mouse position.)
func apply_rotation(_delta):
var mouse_direction = position - get_global_mouse_position() # Get the direction
var correction_angle = 90 # make it so the player is facing correctly to the mouse
var angle = rad2deg(-atan2(mouse_direction.x, mouse_direction.y)) - correction_angle # Angle to the mouse
$Rotation.rotation_degrees = lerp($Rotation.rotation_degrees,angle,5 * _delta) # Lerp the angle smoothly
$CollisionShape2D.rotation_degrees = $Rotation.rotation_degrees
I tried your code, and it works fine.
I think the problem is in the first line of the function, you should changeposition, to $Rotation.position.
It should work fine then!

Godot - Enemy does not move to player when player is on the left

The enemy in my game will not move towards the left when player is on the left but will move to the right. Then when the player is on the right the enemy will move to the player.
code for enemy:
extends KinematicBody2D
var run_speed = 100
var velocity = Vector2.ZERO
var collider = null
func _physics_process(delta):
velocity = Vector2.ZERO
if collider:
velocity = position.direction_to(collider.position) * run_speed
velocity = move_and_slide(velocity)
func _on_DetectRadius_body_entered(body):
collider = body
func _on_DetectRadius_body_exited(body):
collider = null
I suspect you are using an Area2D and it is detecting something other than the player character. I remind you can use collision_mask and collision_layer to narrow what objects are detected. For example, are you sure the Area2D is not detecting the enemy itself? For a quick check you can have Godot print the collider to double check it is what you expect.
Furthermore, notice that wen an object leaves the Area2D it will set collider to null regardless if there is still some object inside the Area2D or not. I remind you that an alternative approach is using get_overlapping_bodies.
And, of course, you can query each body you get to see if it is the player character (for example by checking its node group, name, class, etc...). I go over filtering in more detail in another answer.
If you are getting the player character, there is another possible source of problems: position vs global_position. The code you have like this:
position.direction_to(collider.position)
Is correct if both the enemy and the collider it got have the same parent. In that case their positions are in the same space. Otherwise, you may want to either work on global coordinates:
global_position.direction_to(collider.global_position)
Or you can bring the collider position to local coordinates:
position.direction_to(to_local(collider.global_position))
And of course, double check that the Area2D is positioned correctly. You can enable "Visible Collision Shapes" on the "Debug" menu, which will show it when running the game from the editor.

Collision detection & resolution: circle in a playfield of other circles and polygons

I am working on a game that has a player sprite surrounded by a collision circle of a known radius. The player sprite can move about a playfield that consists of other sprites with their own collision circles and other obstacles made up of polygons. The other obstacles are rectangles at a 45 degree angle.
In addition, I want the player to adjust its movement when it does collide. I want the player to try to "push through" past the object instead of being stopped by it.
For example, if the player were to collide with another sprite's bounding circle, it would be stopped if its vector was exactly perpendicular to the tangent of the two circles' intersection.
However, if not perfectly perpendicular, the player would be, slowly at first, then faster, pushed along the tangent of the circle until it can continue past it unimpeded.
This works similarly when encountering one of the 45 degree rectangles.
What I need help with is the following: I am trying to find an analytic solution to detect both other sprites and obsticles, have the player's movement adjusted, and possibly stopped when adjusted to wedge between two or more objects.
I can do the collision detection and deflection for one object type at a time, but am struggling to put everything together into a comprehensive algorithm. I am currently working on an iterative pairwise resolution approach that "tries" different locations to result in a best-guess solution, but I really want a mathematically analytic solution. I'm hoping to have a function something like what appears in this psuedocode.
x = [player's x location]
y = [player's y location]
r = [player's collision radius]
// Array of other sprites on the playfield,
spr = [other sprites array]
// which contains 3 parameters, x, y, r. E.g., spr[3].x or spr[3].r,
// for the x position or collision radius for the fourth sprite in the
// array.
// Array of 45 degree rectangles on the playfield,
rect = [array of rectangles]
// which contain 4 parameters, x1, y1, x2, y2, the two opposite points
// of the rectangle. E.g., rect[0].x1, for the x position of the first
// point of the first rectangle.
// For simplicity, assume the above variables are all directly accessable
// in the function below.
// requestX and requestY is the position to which the player would
// like to move the player sprite.
definefunction collisionAdjustor(requestX, requestY) {
// Here I'd like to adjust the requested position if needed because
// of an intersection with one or more other sprites or rectangles.
// Finally return the location at which the player will actually be
// arriving.
return destinationX, destinationY
}
Any advice or suggestions would be much appreciated.
--Richard

Moving an object in the opposite direction to the cursor

I am trying to accomplish a simple task using a 2D graphics library called paperscript. I have a grid of dots and I would like to recalculate the position of those dots based on the position of the mouse cursor so that the dot is displaced from it's original position in the opposite direction that the mouse cursor is from the original position, and displaced by a distance that is inversely proportional to the distance of the mouse cursor to the original position. Hopefully this diagram makes it a little clearer:
I know how to get the current position of the mouse, as well as the position of each dot. What I have been having trouble with, is creating a function that will take those two variables and use it to calculate a new position for each dot that will create the above described effect.
I have a jsfiddle here with what I've created so far.
https://jsfiddle.net/yc62k/247xwh8q/4/
function onFrame(event) {
//Loop through all the dots
for (i = 0; i < count; i++) {
var item = project.activeLayer.children[i];
//Update the position of the dot based on the mouse position
??????
item.position = new Point(
(newPosition.x),
(newPosition.y)
);
}
}
Can anyone suggest an algorithm I can use in this function to get this effect? Or point me in the direction of the maths I would use to solve this problem? Any help would be greatly appreciated!
If the old position of the dot is pDot and the position of the mouse is pMouse, then the direction of movement is
dir = pDot - pMouse
To establish the desired scale (inversely proportional to the distance), just divide by the squared length. Then, the new position is:
pDotNew = pDot + dir * (1.0 / squaredLength(dir))
Be careful about how often you update the positions. If you update them very frequently, the points might move very fast. If this is the case, multiply the direction with a small number (between 0 and 1). Ideally, this number should depend on the update interval in order to maintain a consistent movement speed.

iOS Detect Circular Touches (Clockwise and Counter Clockwise)

I am working on an iOS/iPad educational app that will display a clock with 2 hands (hour and minute). When the user spins there finger on the clock face I want to move the time either forward or backward. This will be a single finger gesture or spinning motion.
Any ideas on how to tell if the user is spinning their finger clockwise or counter clockwise around the circular clock face?
I thought about calculating the angle, then translating the angle into a "section" of say 30 degrees. Then watching the pattern of sections that are tripping.
Just wondering if anyone has a "whiz bang" solution that I am not considering?
Something elegant perhaps?
Thanks.
What you need to do is keep at least three points, then just calculate the area of the "triangle" they form.
CGPoint a = lastStart;
CGPoint b = start;
CGPoint c = end;
float area = a.x * b.y - a.y * b.x + a.y * c.x - a.x * c.y + b.x * c.y - c.x * b.y;
if(area > 0) {
// you're moving CCW
}
Make starting point of the gesture nominal 0,0 and divide the screen into four quadrants with x and y axes running through your nominal 0,0. Note which quadrants get visited, in turn. After the first two, you have the directionality:
Movement into lower right quadrant followed by movement into upper right is counterclockwise
Movement into lower right quadrant followed by movement into lower left is clockwise
Movement into lower left quadrant followed by movement into lower right is counterclockwise
Movement into lower left quadrant followed by movement into upper left is clockwise
Movement into upper left quadrant followed by movement into lower left is counterclockwise
Movement into upper left quadrant followed by movement into upper right is clockwise
etc etc

Resources