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

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!

Related

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.

SnapSVG rotation issue after first rotation

I have created a small demo in this codepen.
When clicking any of the four buttons, the object is rotated to the correct position using the following...
function rotateTo(angle) {
var ring = paper.select("#INNER_RING");
var bbox = ring.getBBox();
var cx = bbox.cx;
var cy = bbox.cy;
var trans = 'r' + angle + ' ' + cx + ' ' + cy; // + 's1,1,' + cx + ',' + cy;
console.log(trans);
ring.stop().animate({
transform: trans
},
750,
mina.linear,
function() {
settings.currentRotation = angle;
});
}
On the first rotation, everything goes great. However, subsequent rotations not only rotate but appear to scale as the rotation takes place. The object does end up in the correct final position, but the scaling is not wanted.
What could be happening as part of the first transformation that would cause subsequent ones to do this?
Animating matrices from a previous matrix typically gets pretty messy, as they often don't do things that we think they do (I asked a previous similar question in the past here which may be of use, getting your head around matrix animation if you wanted a deeper understanding). At the start of the first animation, there is no transform matrix to animate from, so it's all pretty straightforward.
However, at the end of the 1st animation, there is a transform matrix left there applying to the element, which causes a problem, as the next animation it tries to animate from that last matrix.
It isn't quite clear what you actually want to do, on a subsequent button press. Whether you want to rotate 'another' 90 degrees, or just rotate 90 from scratch again.
If you just want to repeat the animation, you could just reset the transform to scratch, which simply gets around the problem (but note, there may be an issue if you press the button mid animate).
ring.attr('transform','')
jsbin
If you want to do more complex things, and need to animate from a previous state, I would use a slightly different method of animate, and not animate on an element, but use Snap.animate and build your transform string each time. So the could could look more like this...
var rotateFrom = settings.currentRotation;
var rotateTo = rotateFrom + parseInt(angle)
Snap.animate(rotateFrom, rotateTo, function( val ) {
ring.transform( 'r' + val + ',' + cx + ',' + cy )
}, 750, mina.linear, function() {
settings.currentRotation = rotateTo;
});
jsbin2
Snap.animate() takes 2 initial arguments that are a starting value and an end value, and then interpolates between them, passing that as 'val' to the function which is passed in. The docs for that can be found here
This way, you don't care about animating from previous transforms (which are stored as matrices), and you control the real specifics of whats happening each animation loop.
You may just need to tweak it and store the rotation each time the func is called (rather than just when it finishes), depending on what you want to do mid-animation if the button is pressed before it's finished.

How to clamp the output of CIPerspectiveTransformWithExtent filter?

I'm using a CIPerspectiveTransformWithExtent filter to apply homographies (perspective warp) to images on OS X. So far, so good, and I can get the desired warping applied to my images.
I'm still struggling however with the border behavior. I would like the output of the filter to be clipped outside the original image domain:
I managed to do it for the lower and left borders by shifting the origin of the inputExtent rectangle of the correct amount. For example, if the lower left corner is projected to x = -10 then using extent.origin.x = 10 will correctly clip the left border;
on the other hand, the upper and right borders are always shown in the output image. For example, if the rightmost corner is projected to x = width + 10, setting the extent via extent.origin.x = 0, extent.size.width = width; does not work an the rightmost corner remains visible.
Am I doing anything wrong here? or maybe I'm not trying the right way to achieve my goal?

Angle calculation resulting in strange behavior

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 :)

Resources