KinematicBody2D moves only to left and right - 2d

So i'm a complete newbie to coding and so i followed this tutorial:
https://www.youtube.com/watch?v=BeSJgUTLmk0
And the i cant move KinematicBody2D up nor down
Here's the code
extends KinematicBody2D
var MaxSpeed = 500
var Accel = 5000
var Motion = Vector2.ZERO
func _physics_process(delta):
var Axis = GetInputAxis()
if Axis == Vector2.ZERO:
ApplyFriction(Accel * delta)
else:
ApplyMovement(Axis * Accel * delta)
Motion = move_and_slide(Motion)
func GetInputAxis():
var Axis = Vector2.ZERO
Axis.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
Axis.y - Input.get_action_strength("ui_up") - Input.get_action_strength("ui_down")
return Axis.normalized()
func ApplyFriction(amount):
if Motion.length() > amount:
Motion -= Motion.normalized() * amount
else:
Motion = Vector2.ZERO
func ApplyMovement(acceleration):
Motion += acceleration
Motion = Motion.clamped(MaxSpeed)
and yes my keybinds are set properly

Related

Move and rotate object around pivot and resume from where it stopped

I'd like to move an object around another - just as if the one object was a child of the other. This is GDscript - Godot Engine 3.2, but the logic should be very similar to other game engines.
Whenever I hold spacebar the green cube follows the blue cubes rotation.
First GIF demonstrates the green cube starting at position Vector3(0, 4, 0) without any rotation applied. This works perfectly fine.
In the second GIF I'm holding and releasing spacebar repeatedly. I would expect the green cube to continue from where it left, but instead it "jumps" to a new position and continues from there.
Code below does not include the actual rotation of the blue cube (pivot point), but only the calculations needed to move/rotate the green cube. Rotation of the blue cube is not an issue. Also, rotation is just for the sake of demonstration - in real scenario the blue cube would be moving around as well.
Rotations are calculated using quaternion, but this is not a requirement.
extends Node
var _parent
var _child
var _subject
var _positionOffset: Vector3
var _rotationOffset: Quat
func _ready():
_parent = get_parent()
_child = $"/root/Main/Child"
func _input(event):
if event is InputEventKey:
if event.scancode == KEY_SPACE:
if event.is_action_pressed("ui_accept") and _child != null:
_subject = _child
_set_subject_offset(_parent.transform, _child.transform)
elif event.is_action_released("ui_accept"):
_subject = null
func _set_subject_offset(pivot: Transform, subject: Transform):
_positionOffset = (pivot.origin - subject.origin)
_rotationOffset = pivot.basis.get_rotation_quat().inverse() * subject.basis.get_rotation_quat()
func _rotate_around_pivot(subject_position: Vector3, pivot: Vector3, subject_rotation: Quat):
return pivot + (subject_rotation * (subject_position - pivot))
func _physics_process(_delta):
if _subject == null: return
var target_position = _parent.transform.origin - _positionOffset
var target_rotation = _parent.transform.basis.get_rotation_quat() * _rotationOffset
_subject.transform.origin = _rotate_around_pivot(target_position, _parent.transform.origin, target_rotation)
_subject.set_rotation(target_rotation.get_euler())
I feel like I'm missing something obvious.
You can easily achieve this by temporarily parenting the subject to the pivot point while preserving the global transform:
extends Spatial
onready var obj1: Spatial = $Object1
onready var obj2: Spatial = $Object2
func reparent(obj: Spatial, new_parent: Spatial):
# Preserve the global transform while reparenting
var old_trans := obj.global_transform
obj.get_parent().remove_child(obj)
new_parent.add_child(obj)
obj.global_transform = old_trans
func _physics_process(delta: float):
obj1.rotate_z(delta)
func _input(event: InputEvent):
if event.is_action_pressed("ui_accept"):
reparent(obj2, obj1)
elif event.is_action_released("ui_accept"):
reparent(obj2, self)
If reparenting isn't feasible, you could instead parent a RemoteTransform to the pivot, and have that push its transform to the object you want to rotate:
extends Spatial
onready var remote_trans: RemoteTransform = $RemoteTransform
func _process(delta):
rotate_z(delta)
func attach(n: Node):
# move the remote so the target maintains its transform
remote_trans.global_transform = n.global_transform
remote_trans.remote_path = n.get_path()
func detach():
remote_trans.remote_path = ""
repost, Thank You path9263, answered Jun 4, 2019 by path9263 (134 points)
func rotate_around(obj:Spatial, point:Vector3, axis:Vector3, phi:float):
# https://godotengine.org/qa/45609/how-do-you-rotate-spatial-node-around-axis-given-point-space?show=45970#a45970
obj.global_translate(-point)
obj.transform = obj.transform.rotated(axis, phi)
obj.global_translate(point)
the below functions do not work
func rotate_around_point(transform_me:Spatial, pivot_point:Vector3, axis:Vector3, phi:float):
# #4: busted, no rotation
# https://stackoverflow.com/a/59939086/1695680
# Preserve the global transform while reparenting
var pivot_spatial = Spatial.new()
pivot_spatial.translation = pivot_point
var parent_orig = transform_me.get_parent()
var transform_orig = transform_me.global_transform
parent_orig.remove_child(transform_me)
pivot_spatial.add_child(transform_me)
transform_me.global_transform = transform_orig
pivot_spatial.rotate(axis, phi)
var transform_rotated = transform_me.global_transform
pivot_spatial.remove_child(transform_me)
parent_orig.add_child(transform_me)
transform_me.global_transform = transform_orig
func rotate_around_point(transform_me:Spatial, pivot_point:Vector3, axis:Vector3, phi:float):
# busted, no rotate
# https://stackoverflow.com/a/59939086/1695680
var remote_trans : RemoteTransform = RemoteTransform.new()
remote_trans.global_transform = transform_me.global_transform
remote_trans.remote_path = transform_me.get_path()
remote_trans.rotate(axis, phi)
remote_trans.remote_path = ""
func rotate_around_point(transform_me:Spatial, pivot_point:Vector3, axis:Vector3, phi:float):
# busted, local rotate
# https://godotforums.org/discussion/comment/43335/#Comment_43335
var gto_orig = transform_me.global_transform.origin
transform_me.global_transform.origin = pivot_point
transform_me.rotate(axis, phi)
transform_me.global_transform.origin = gto_orig
func rotate_around_point(transform_me:Spatial, pivot_point:Vector3, axis:Vector3, phi:float):
# busted, no rotate
# https://godotengine.org/qa/34248/rotate-around-a-fixed-point-in-3d-space?show=38928#a38928
var start_position : Vector3 = transform_me.translation
var pivot_radius : Vector3 = start_position - pivot_point
var pivot_transform : Transform = Transform(transform.basis, pivot_point)
var transform = pivot_transform.rotated(axis, phi).translated(pivot_radius)
transform.xform(transform_me)

Why isn't my code working for basic Movement in Godot?

I just started a new project in godot. So far I have one png which is the main player. I have added a sprite and CollisionShape2D to the player. When i run the game the player does not move (using keys). Does anyone know what is going on here? Heres my code:
extends KinematicBody2D
export var speed = 10.0
export var tileSize = 32.0
var initpos = Vector2()
var dir = Vector2()
var facing = 'down'
var counter = 0.0
var moving = false
func _ready():
initpos = position
func _process(delta):
if not moving:
set_dir()
elif dir != Vector2():
move(delta)
else:
moving = false
func set_dir(): #set moving
dir = get_dir()
if dir.x != 0 or dir.y != 0:
moving = true
initpos = position
func get_dir(): #user input
var x = 0
var y = 0
if dir.y == 0:
x = int(Input.is_action_pressed("ui_right")) - int(Input.is_action_pressed("ui_left"))
if dir.x == 0:
y = int(Input.is_action_pressed("ui_down")) - int(Input.is_action_pressed("ui_up"))
return Vector2(x, y)
func move(delta): #move player linearly
counter += delta + speed
if counter >= 1.0:
position = initpos + dir * tileSize
counter = 0.0
moving = false
else:
position = initpos + dir * tileSize * counter
EDIT:
I have also tried copying and pasting the code directly from Godots documentation and the player still does not move:
extends KinematicBody2D
export (int) var speed = 200
var velocity = Vector2()
func get_input():
velocity = Vector2()
if Input.is_action_pressed('right'):
velocity.x += 1
if Input.is_action_pressed('left'):
velocity.x -= 1
if Input.is_action_pressed('down'):
velocity.y += 1
if Input.is_action_pressed('up'):
velocity.y -= 1
velocity = velocity.normalized() * speed
func _physics_process(delta):
get_input()
velocity = move_and_slide(velocity)
I figured it out. When adding a new script I did not add it to the Player but to the scene.

parallel links between nodes

I've a Webcola&D3 svg graph with Nodes and Links between them.
Till today, between nodes the Links could be One way, if B was connected to A, it was only one way Link.
Today i was told i need to support having 2 way Links, meaning A can send a Link to B and B can send a link to A.
Now i'm stuck about the math and how to accomplish it, i used some algorithm i found to draw links till today which i guess draw the Links from the center of the Node, i need to show the 2 way links in parallel like this :
here is the algorithm i use to calculate Links position:
let parent = connection.parent;
const sx = parent.source.x;
const sy = parent.source.y;
const tx = parent.target.x;
const ty = parent.target.y;
let angle = Math.atan2(ty - sy, tx - sx);
const radiusSource = parent.source.radius;
const radiusTarget = parent.target.radius;
let x1 = sx + Math.cos(angle) * radiusSource;
let x2 = tx - Math.cos(angle) * radiusTarget;
let y1 = sy + Math.sin(angle) * radiusSource;
let y2 = ty - Math.sin(angle) * radiusTarget;
angle = angle * 180 / Math.PI;
let opposite = Math.abs(angle) > 90;
if (opposite)
angle -= 180;
connection.coords = [x1, y1, x2, y2, angle, opposite];
return connection.coords;
This is a part of a function which the result goes into the 'd' attr of the path like this:
.attr('d', `M${x1} ${y1} L ${x2} ${y2}`)
The result of 2 way Links right now is that they override each other, can anyone help me improve this algorithm so it will make 2 way Links be parallel?
Update: position of the Links need to be calculated by new radian considering offset, like:
let parent = connection.parent;
const sx = parent.source.x;
const sy = parent.source.y;
const tx = parent.target.x;
const ty = parent.target.y;
const radiusSource = parent.source.radius;
const radiusTarget = parent.target.radius;
let radian = Math.atan2(ty - sy, tx - sx);
let offset = 0.1 // Offset ratio of radian, can be adjusted
let offsetRadian;
let angle = radian * 180 / Math.PI;
let opposite = Math.abs(angle) > 90;
if (opposite) {
angle -= 180;
offsetRadian = radian * (1 + offset);
} else {
offsetRadian = radian * (1 - offset);
}
let x1 = sx + Math.cos(offsetRadian) * radiusSource;
let y1 = sy + Math.sin(offsetRadian) * radiusSource;
let x2 = tx - Math.sin(offsetRadian) * radiusTarget;
let y2 = ty - Math.cos(offsetRadian) * radiusTarget;
connection.coords = [x1, y1, x2, y2, angle, opposite];
return connection.coords;

How to draw a gps marker on a rotated custom image map

I need to draw a custom image map of a park in my App and add show gps markers on it.
However my problem is that the map should be drawn as a straight rectangle in my app (see below left), but in real life the park is rotated (see example below right)
I have the GPS coordinates of all the 4 corners of the real-live map together with the GPS coordinates of the markers but i'm stuck on how to calculate the (x,y) position for each marker for the map in my app where the map is displayed as a straight rectangle.
Any suggestions are welcome!
Code i have so far:
public class GeoLocation
{
public double Lattitude { get; set; }
public double Longitude { get; set; }
public GeoLocation()
{
}
public GeoLocation(double lat, double lon)
{
Lattitude = lat;
Longitude = lon;
}
public double Angle(GeoLocation point)
{
var deltaX = point.Lattitude - Lattitude;
var deltaY = point.Longitude - Longitude;
return (Math.Atan2(deltaY, deltaX));
}
public GeoLocation Rotate(GeoLocation center, double angleInRad)
{
var s = Math.Sin(angleInRad);
var c = Math.Cos(angleInRad);
// translate point back to origin:
var x = (double)(Lattitude - center.Lattitude);
var y = (double)(Longitude - center.Longitude);
// rotate point
var xnew = x * c - y * s;
var ynew = x * s + y * c;
// translate point back:
x = xnew + center.Lattitude;
y = ynew + center.Longitude;
return new GeoLocation(x, y);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var url = "file://c:\\db\\mapgrab.jpg";
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(url, UriKind.Absolute);
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
mapImg.Source = bitmap;
var TopLeftGps = new GeoLocation(52.11070994543701, 4.411896866166349);
var TopRightGps = new GeoLocation(52.11475153599096, 4.415646979517055);
var BottomRightGps = new GeoLocation(52.1117075980591, 4.424232274309553);
var currentPosGps = new GeoLocation(52.11129692591393, 4.4174530542349295);
var imageWidth = 702;
var imageHeight = 924;
var angle = TopLeftGps.Angle(TopRightGps);
var topRight = TopRightGps.Rotate(TopLeftGps, -angle);
var bottomRight = BottomRightGps.Rotate(TopLeftGps, -angle);
var maxX = topRight.Lattitude - TopLeftGps.Lattitude;
var maxY = bottomRight.Longitude - topRight.Longitude;
var markerPos = new GeoLocation(currentPosGps.Lattitude, currentPosGps.Longitude).Rotate(TopLeftGps, -angle);
var diffX = markerPos.Lattitude - TopLeftGps.Lattitude;
var diffY = markerPos.Longitude - TopLeftGps.Longitude;
var percentageX = diffX / maxX;
var percentageY = diffY / maxY;
var posX = percentageX * imageWidth;
var posY = percentageY * imageHeight;
var markerImg = new Border();
markerImg.Background = new SolidColorBrush(Colors.Red);
markerImg.Width = 32;
markerImg.Height = 32;
Canvas.SetLeft(markerImg, posX);
Canvas.SetTop(markerImg, posY);
canvas.Children.Add(markerImg);
}
}
}
What you'r looking for is a 2D rotation transformation from the north aligned coordinates (x,y) to your rotated coordinates (x',y')
The rotation can be represented as a 2x2 matrix R and if we represent the coordinates as column vectors, then the computation will be:
[x',y']=R*[x,y]
Where * is matrix multiplication, R is
And the angle theta is the desired rotation angle.
Marking the corner points thus:
theta can be computed be solving (for example in wolframAlpha):
tan(theta) = (Ay-Dy) / (Ax-Dx)
I had a similar problem. Here is a javascript example how to rotate points on a map. The coordinates are measured from the center point. The angle is in radiants.
var x_new_centered = -1 * y_centered * Math.sin(a) + x_centered * Math.cos(a)
var y_new_centered = y_centered * Math.cos(a) + x_centered * Math.sin(a);
And here you find a jsfiddle where a point is drawn on a not rotated, a rotated and rotated and cropped map: https://jsfiddle.net/vienom/4ger35uq/

Rotate point from a given center in Flex

I'm trying to rotate a point in my Canvas from a given point (center). In my MouseDown handler, I save the point where user click (oldPos), and in my MouseMove handler, I'm doing this:
private function onMouseMove(event:MouseEvent):void
{
// Where the user pointer right now
var endPoint:Point = new Point(event.localX,event.localY);
// Calculate angle in radians from the user pointer
var angle:Number = getLineAngleFromHorizontal(oldPos,endPoint);
var rad:Number = Math.PI * (angle / 180);
// Point which I want to rotate
pTop = new Point(oldPos.x,oldPos.y - 30);
var distance:Number = Point.distance(oldPos,pTop);
// Calculate the translation point from previously distance and angle
var translatePoint:Point = Point.polar(distance, rad);
// New point coordinates (in theory)
pTop.x += translatePoint.x;
pTop.y += translatePoint.y;
// Then, draw the line...
}
Where getLineAngleFromHorizontal is a function that returns the angle formed by a center and a give point:
private function getLineAngleFromHorizontal(p1:Point,p2:Point):Number
{
var RotVecOrigen:Point = new Point((p2.x-p1.x),(p2.y-p1.y));
var ModRot:Number = Math.sqrt((RotVecOrigen.x*RotVecOrigen.x)+(RotVecOrigen.y*RotVecOrigen.y));
var ret:Number;
if(((RotVecOrigen.x < 0) && (RotVecOrigen.y <= 0))||((RotVecOrigen.x >= 0) && (RotVecOrigen.y < 0)))
{
ret = Math.round((180.0*(Math.acos(RotVecOrigen.x/ModRot))/Math.PI));
}else{
ret = Math.round((180.0*(-Math.acos(RotVecOrigen.x/ModRot))/Math.PI));
}
return ret;
}
To see an example, watch the image below:
But I don't know why isn't work. I mean, pTop point isn't move where I want, and I think that my calcs are correct.
Can anybody help me? (maybe someone with Math knowledge)
I'm not entirely sure what you want to accomplish. Do you want your new point to be at an 330 degree offset from your center point?
If you want to move your point 330 degrees, use this:
function directionalDistance($start:Point, $direction:Number, $distance:Number, $zeroDegreesUp:Boolean = false):Point{
if($zeroDegreesUp) $direction = ( $direction + 270)%360;
var x:Number = Math.cos($direction * Math.PI / 180) * $distance;
var y:Number = Math.sin($direction * Math.PI / 180) * $distance;
return new Point($start.x +x, $start.y + y);
}
//
var newPoint:Point = directionalDistance(new Point(event.localX,event.localY), 330, 50, true);

Resources