Godot: problems with objects and integers - godot

I have a basic system for an RTS in place. I have a central manager and a drag select which works. I have it in place that if you right click on an enemy, whatever is selected will "hunt" the enemy. The enemy will transmit it's position to those selected troops and the troops will then constantly follow it. The problem that I have lies in my trying to create an attack system for the troops. I have an Area2D that if it comes in contact with an enemy it will print a debug for me, here is the code for that:
#on Area2D entered(body)
if body == target:
print_debug("attacked")
target is the enemy, and is set when you click on the enemy with:
for item in selected_list:
item.hunt
for enemy in enemy_list:
if enemy.hovering:
item.target = enemy
Now here is the problem. In the first code snippet, Godot is giving me an error, something about objects and ints. This happens because I am setting target to 0 at the start, before you click on the enemy, but the body is classified as an object. So, when the troop is instanced in the scene, this basically turns to
#on Area2D entered(object)
if object == 0:
print_debug("attacked")
So I understand what is wrong, I just don't know how to fix this. Can anyone help?

Related

Collision in Godot Engine, 2D game

I want the inscription "hello" to be displayed in case of a collision with an object! How to do it? And what should be used?
I tried to do this using the Area2D node, but nothing worked :(
I tried to use the following code:
func print_msg():
print("Hello")
func _on_area_entered(): (I attached it)
print_msg()
Before that, I made a player using KinematicBody2D and made him move. And made blocks for walking
Since you've left things very ambiguous I'll try to explain it to the best of what I understood
Here I have the basic setup with a RigidBody2D and Area2D:
And here's the main script:
extends Node2D
func message_area(thing):
print("Hello! (Area Entered)")
func message_body(thing): # you were probably missing this
print("Hello! (Body Entered)")
func _ready():
$Area2D.connect("area_entered",self,"message_area")
$Area2D.connect("body_entered",self,"message_body")
Now when you press play the rigid body will fall into Area2D and when it does it will output this:
Hello! (Body Entered)
My best guess is you only connected the area_entered signal but not the body_entered which is why nothing was being printed when the object entered the Area2D
You can further follow on how to connect signals & How Area2D works
And I'd recommend you post code or explain what you've tried (preferably with images) so people can understand your problem better and help better :)
Edit:
If you want to change the visibility of the thing entered/collided you have 2 options:
...
func message_body(thing):
print("Hello! (Body Entered)")
thing.visible=true #option 1
thing.modulate.a=0.0 #option 2 (you can also use self_modulate)
Option 1 is the equivalent of pressing the eye icon
Option 2 changes the alpha value i.e. decides how much transparent your object should be and lies between 0 & 1 where 0=completely invisible, 1=completely visible, 0.5=50% visible and so on...
Equivalent of changing :
However, since you said "with a certain object" you can add a condition before toggling the visibility:
func message_body(thing):
print("Hello! (Body Entered)")
if(thing is KinematicBody2D): # or you can create a custom class and use it's `class_name`
thing.visible=true
thing.modulate.a=0.0
# or
if(thing.name =="Main Player"):
thing.visible=true
thing.modulate.a=0.0
# etc etc
I recommend you read this if you already haven't

Godot - Staticbody3d collision normal issue

I am having problem figure out how the normal work.
I am using godot4 RC1.
I created a staticbody3D and want to place a 3dobject standing upright like how we stand on earth.
this is my code for the staticbody3d:
func _on_input_event(camera, event, position, normal, shape_idx):
player.global_position = position
var q = Quaternion.from_euler(normal)
player.basis = q
basically I use the code to capture the mouse_over position on the staticbody3d and place my player(Mesh3d) at the position, and align the player basis to the normal.
if mouse at the top of the planet, it turn out ok.
but anywhere else, it just gone hay wire:
How can I resolve this?

Why doesn't my Raycast2Ds detect walls from my tilemap

I am currently trying to make a small top-down RPG with grid movement.
To simplify things, when i need to make something move one way, I use a RayCast2D Node and see if it collides, to know if i can move said thing.
However, it does not seem to detect the walls ive placed until I am inside of them.
Ive already checked for collision layers, etc and they seem to be set up correctly.
What have i done wrong ?
More info below :
Heres the code for the raycast check :
func is_path_obstructed_by_obstacle(x,y):
$Environment_Raycast.set_cast_to(Vector2(GameVariables.case_width * x * rayrange, GameVariables.case_height * y * rayrange))
return $Environment_Raycast.is_colliding()
My walls are from a TileMap, with collisions set up. Everything that uses collisions is on the default layer for now
Also heres the function that makes my character move :
func move():
var direction_vec = Vector2(0,0)
if Input.is_action_just_pressed("ui_right"):
direction_vec = Vector2(1,0)
if Input.is_action_just_pressed("ui_left"):
direction_vec = Vector2(-1,0)
if Input.is_action_just_pressed("ui_up"):
direction_vec = Vector2(0,-1)
if Input.is_action_just_pressed("ui_down"):
direction_vec = Vector2(0,1)
if not is_path_obstructed(direction_vec.x, direction_vec.y):
position += Vector2(GameVariables.case_width * direction_vec.x, GameVariables.case_height * direction_vec.y)
grid_position += direction_vec
return
With ray casts always make sure it is enabled.
Just in case, I'll also mention that the ray cast cast_to is in the ray cast local coordinates.
Of course collision layers apply, and the ray cast has exclude_parent enabled by default, but I doubt that is the problem.
Finally, remember that the ray cast updates on the physics frame, so if you are using it from _process it might be giving you outdated results. You can call call force_update_transform and force_raycast_update on it to solve it. Which is also what you would do if you need to move it and check multiple times on the same frame.
For debugging, you can turn on collision shapes in the debug menu, which will allow you to see them when running the game, and see if the ray cast is positioned correctly. If the ray cast is not enabled it will not appear. Also, by default, they will turn red when they collide something.

Teleporting node

I am trying to teleport my player node(kinematicbody2d) when it hits my finish node (area2d) from the side of the Finish node
BTW I'm using godot 3
What I tried:Change the location using get_node("player").set_pos and get_node("player").location
code:
extends Area2D
func _on_Finish12_body_entered(body):
if body.get_name() == "player":
print("%s touched the finish on level %s" % [body.get_name(), get_tree().get_current_scene().get_name()])
get_node("player").position = Vector2(1504, 1896)
pass
So what I need:
The playing being teleported to 1504, 1896
There's a lot of unknowns here that can be the problem
Is the player's location updated in other parts of the code? and if so, could it be possible you did move to 1504, 1896 but then immediately get clobbered by said code?
What is the current behavior when you apply the new position? Does your player move at all? Does it go somewhere unintended?
Does your print statement execute?
Have you tried using move_and_slide/move_and_collide for the kinematicBody to check for collision?
Just a few ideas on how to go about figuring it out.
This is what works with Area and KinematicBody (i.e. 3D):
extends Area
func _on_Area_body_entered(body):
body.look_at_from_position(spawn, Vector3(0,0,0), Vector3(0,0,0))
with spawn being an empty spatial to define the point in space to teleport to.

Phaser.js - how do I take an object out of a group?

I'm playing around with phasers invaders example game.
When the object is shot, instead of killing it I'm changing the sprite and moving it to the bottom of the screen. However, it can now be shot again. I don't want it to be shootable a 2nd time. I'm thinking that because the gamephysics are on the group 'aliens', there are probably two options.
a) Either I can take the single shot alien out of the group 'aliens' and hope that stops it from being shot a 2nd time.
b) Or there's some way of saying ' alien just shot = now protected from being shot again' , I tried the following to no avail.
alien.physicsBodyType = null;
This is my collision handler right now
function collisionHandler (bullet, alien) {
// When a bullet hits an alien we kill them both
bullet.kill();
alien.loadTexture("cured");
// move alien to bottom
var tween2 = game.add.tween(alien).to( { y: 300 }, 1000, Phaser.Easing.Linear.EaseIn, true);
tween2.onComplete.add(doNext, this);
tween2.start();
So, basically the changed sprite can still be shot at, I need to make it so it cannot be shot at.
I tried this.
game.world.add(happy);
It changed the position of the sprite and it was still shootable. Hmmm...
Is there a way to take collision off the single shot alien?
Ok, I figured out my answer, just deactivate the body of the sprite, you don't need to take it out of the group.
sprite.body.enable = false;
Where 'sprite' is the name of your actual sprite. Tested and works.

Resources