I've been making a FPS in Godot and I'm having a hard time getting the kinematic body (the enemy) to go towards the player. Could someone please help?
The simplest way to do this is to get the player's position, compare it to the enemy position, and make the enemy move towards it every frame.
Full example code is at the bottom.
To get the player's position you first need a reference to it. You can usually do this through storing the reference in global singleton (autoload) or by exposing a public property.
If you are doing it with a global singleton, then you get the position by calling var player_position = my_singleton.player.global_transform.origin
If you are using an exported property, then you would get the position by calling var player_position = get_node(path_to_player).global_transform.origin
Once you have the player position, you can compare it to the enemy by writing var direction_to_target = player_position - global_transform.origin from inside the enemy node.
Now in order to follow the player, we override the _physics_process method with something like this:
### Inside the enemy script
var ENEMY_SPEED= 50
func _physics_process(delta):
var player_position = my_singleton.player.global_transform.origin
var direction_to_target = (player_position - global_transform.origin).normalized() # We normalize the vector because we only care about the direction
move_and_slide(direction_to_target * ENEMY_SPEED) # We multiply the direction by the speed
Related
I'm a beginner and I created a code where I can get my enemy's information, but I believe it is very simple and maybe wrong, since the more information I want to get, the more lines of code will be needed.
My idea is that when I get this contact between the player and the enemy (or object), I have this informations and can use it in combat math.
Another question is that the RayCast "works", however, I don't get this information in the first contact with the enemy.
Player code:
func _unhandled_input(event):
for dir in inputs.keys():
if event. is_action_pressed(dir):
move(dir)
func move(dir):
ray.cast_to = inputs[dir] * grid_size
ray.force_raycast_update()
if !ray.is_colliding():
position += inputs[dir] * grid_size
if ray.is_colliding():
if "Enemy" in ray.get_collider().get_groups():
var AC_enemy = ray.get_collider().AC
print("Colisão com inimigo")
print(AC_enemy)
In the enemy code I left only the value of the AC variable.
Thanks
hi I'm trying to make a frog that jumps when the player gets close I tried this
onready var playerpos = get_parent().get_node("player").position
And
onready var playerpos = get_parent().get_node("player").global_position
and get this error
Invaled get index 'position' (on base: 'null instance')
Null instance means that the object you are trying to get, doesn't exist. And that is, because you are asking for its position, before it even enters the scene.
However, what you are trying to do, is completely unnecessary. You already have a main scene, so that should be able to access all of its nodes global position, without having to call the entire object.
Access your player's position from the main scene, not the frog scene.
That is, if you want the players position. What you want to do, however, does not require that.
You need to have an area node attached to the frog, that detects and sends a signal, when it detects a physics object. After which you simply check, whether the physics object is player or not, and execute the appropriate action.
According to GDDoc below:
https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#literals
You can use the dollar sign to get node:
onready var player = $player
onready var player_pos = player.position
onready var player_global_pos = player.global_position
Or, you can get the player's position directly:
onready var player_pos = $player.position
onready var player_global_pos = $player.global_position
I'm trying to get a list of all the properties and the values that are being changed from an animation player node,
but how do I get the property name of node that the animation key is changing?
maybe something like this:
var ani=aniplayer.get_animation('running');
for i in range(0,ani.get_track_count()):
var key_idx=ani.track_find_key(i,0,0);
print("property=>",ani.get_key_property(i,key_idx)," new value=>",ani.track_get_key_value(i,key_idx));
Let us say you have an animation player:
var aniplayer := $AnimationPlayer as AnimationPlayer
And you get an animation by name:
var ani := aniplayer.get_animation("running")
As you know you can get the number of tracks the animations has:
var track_count := ani.get_track_count()
And, of course we can loop:
for track_id in range(0,track_count):
pass
Let us see, you want to know what property is being set. To get the property, we need to get the path, and extract the property from there:
for track_id in range(0,track_count):
var track_path := (ani.track_get_path(track_id) as String).split(":")
var node_path := track_path[0]
var property_path := track_path[1]
Addendum:
There is another way to get the property path from a NodePath: get_concatenated_subnames.
Or we can get the elements separated with get_subname.
So this is the property name:
var property_path = ani.track_get_path(track_id).get_subname(0)
I guess this is good time as any to bring attention to the fact that AnimationPlayer can animate sub-properties. With get_subname(0) you get the property, but not the sub-property.
For example, you don't have to animate position, you can animate position.y and you would do that by adding :y at the end of the track name in the Animation panel. I describe how to do it with more detail elsewhere. In this case get_subname(0) will give you position, but get_concatenated_subnames() will give you position:y.
I'm creating a little program that creates image patterns like these using line segments that rotate around each other:
image from Engare Steam store page for reference
How do I tell Godot to create instances of the Polygon2D scene I'm using as line segments with origins on Position2D nodes that exist as children in the Polygon2D scene? Here is a sample of my code:
const SHAPE_MASTER = preload("res://SpinningBar.tscn")
...
func bar_Maker(bar_num, parent_node):
for i in range(bar_num):
var GrabbedInstance = SHAPE_MASTER.instance()
parent_node.add_child(GrabbedInstance)
bar_Maker(bar_num - 1, $Polygon2D/RotPoint)
...
func _physics_process(delta):
...
if Input.is_action_just_pressed("Switch Item"): # from an older version of the program, just bound to ctrl
bar_Maker(segment_count, BarParent)
bar_num is the number of bars to instance, set elsewhere (range 1-6).
parent_node in the main scene is just a Node2D called BarParent.
The SpinningBar.tscn I'm instancing as GrabbedInstance has a Position2D node called "RotPoint" at the opposite end of the segment from the object's origin. This is the point I would like successive segments to rotate around (and also put particle emitters here to trace lines, but that is a trivial issue once this first one is answered).
Running as-is and creating more than 1 line segment returns "Attempt to call function 'add_child' in base 'null instance' on a null instance." Clearly I am adding the second (and later) segments incorrectly, so I know it's related to how I'm performing recursion/selecting new parents for segments 1+ node deep.
Bang your head against the wall and you will find the answer:
func bar_Maker(bar_num, parent_node):
for i in range(bar_num):
var GrabbedInstance = SHAPE_MASTER.instance()
parent_node.add_child(GrabbedInstance)
var new_children = GrabbedInstance.get_children()
bar_Maker(bar_num - 1, new_children[0])
If someone is aware of a more elegant way to do this please inform me and future readers. o7
I have been running SpatialUnderstandingExample scene from holo-toolkit. Couldnt figure out how to place my objects into the scene. I want to replace those small boxes that comes default with my own objects. How can I do that?
Thanks
edit: found the draw box but how do i push my object there?
edit2: finally pushed an object at the position but still code is very complicated its messing up with the size and shape of my object. Will try to make it clean and neat.
It's been a while since I've looked at that example so hopefully I remember its method name's correctly. It contains a "DrawBox" method that is called after a successful call to get a location from spatial understanding. The call that creates the box looks something like this:
DrawBox(toPlace, Color.red);
Replace this call with the following (assuming "toPlace" contains the results from the spatial understanding call and "model" contains the model you are trying to place there):
var rotation = Quaternion.LookRotation(toPlace.Normal, Vector3.up);
// Stay center in the square but move down to the ground
var position = toPlace.Postion - new Vector3(0, RequestedSize.y * .5f, 0);
// instantiate the hologram from a model
GameObject newObject = Instantiate(model, position, rotation) as GameObject;
if (newObject != null)
{
// Set the parent of the new object the GameObject it was placed on
newObject.transform.parent = gameObject.transform;
}