How to get an enemy's information? - godot

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

Related

Moving character to spawn point on scene change

My node setup for my game is:
I have a scene called RoomExit (seen in images below as the blue "door paths") and a scene called SpawnPosition (shown by the little crosshairs next to the door paths)
Level1 has a RoomExit on the right
Level2 has two RoomExits, one on the left of the room and one on the right)
Level3 has a single RoomExit on the left side (NOTE same coordinates as the left RoomExit on Level2)
When the player exits Level3 via the RoomExit on the left he appears in Level2 on the right-hand side as expected, however it then triggers the RoomExit collision on the LEFT hand side of Level2 which brings me to Level1....
The way my RoomExit works is when collided, I emit a "OnGotoRoom" on a "SignalBus" Singleton along with the room I wish to go to (ex "res://Rooms/TestLevel2.tscn") and the name of the Spawn Point node in that room (ex "Spawn002")
The "Game" node listens on that "OnGotoRoom" signal and
Instances the newRoom
Finds the GlobalPosition of the spawn object based on the name ("Spawn002")
Set's the player's GlobalPosition = spawn.GlobalPosition
Adds the newRoom to the "CurrentLevel" node
Calls QueueFree on the previous level
public void gotoRoom(string roomPath, string spawnPoint){
// Instance the new room
var newRoomScene = (PackedScene)ResourceLoader.Load(roomPath);
Room newRoom = (Room)newRoomScene.Instance();
//Set the Global Position of the character = Spawn point global position
PlayableCharacter player = GetNode<Node2D>("Player").GetChild<PlayableCharacter>(0);
player.GlobalPosition = newRoom.GetNode<Node2D>("PlayerSpawnPoints").GetNode<Node2D>(spawnPoint).GlobalPosition;
if (this.playerStats.character == "Robot"){
player.GlobalPosition = new Vector2(player.GlobalPosition.x, player.GlobalPosition.y-32);
}
//Add the newRoom to the "CurrentLevel" Node
GetNode<Node2D>("CurrentLevel").AddChild(newRoom);
//If there was already a level, Remove that node
if (GetNode<Node2D>("CurrentLevel").GetChildCount() != 1){
var current_room = GetNode<Node2D>("CurrentLevel").GetChild<Room>(0);
current_room.QueueFree();
}
//Move the current level to the first index
GetNode<Node2D>("CurrentLevel").MoveChild(newRoom, 0);
}
My Thoughts
I think what's going wrong is that when it moves the character from Level3 to Level2, the player's GlobalPosition isn't updated fast enough so he's colliding with the door on the left hand side (that's in the same position as the door he just exited on Level3).
So I briefly see him in Level2 on the right hand side where I want him, but he already collided with the door on the left because his position wasn't updated fast enough...
I verified this by moving the Left hand door on Level2 away and it works as expected.
I tried updating the character's GlobalPosition to new Vector2(-10000, -10000) BEFORE I emit the "OnGotoRoom" signal hoping that he'd not hit the door on the transition, but that didn't fix the problem.
I'm stumped on what to try next... any help will be much appreciated!

How do I make a kinematic body (3d) follow a player

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

Create Dimensions from edge of wall, to sides of openings, to other edge of wall

I've been struggling with this issue off and on for the better part of a year.
As the title says, i wish to dimension from one side of a wall, to both sides of openings (door openings), then terminate at the other end of the wall (vertically and horizontally). I also wish to dimension to all families hosted in the wall, but i have been able to accomplish this using ScottWilson's voodo magic helper class. Found Here: http://thebuildingcoder.typepad.com/blog/2016/04/stable-reference-string-magic-voodoo.html
foreach (ElementId ele in selSet) {
FamilyInstance fi = doc.GetElement(ele) as FamilyInstance;
Reference reference = ScottWilsonVoodooMagic.GetSpecialFamilyReference(fi,ScottWilsonVoodooMagic.SpecialReferenceType.CenterLR,doc);
refs.Append(reference);
pts[i] = ( fi.Location as LocationPoint ).Point;
i++;
}
XYZ offset = new XYZ(0,0,4);
Line line = Line.CreateBound( pts[0]+offset, pts[selSet.Count - 1]+offset );
using( Transaction t = new Transaction( doc ) )
{
t.Start( "dimension embeds" );
Dimension dim = doc.Create.NewDimension(doc.ActiveView, line, refs );
t.Commit();
}
The problem lies in determining the appropriate stable references to the wall faces. I am able to find all faces on a wall, but this gives me 100+ faces to sort through.
If anyone can help me it would be greatly appreciated!
Side note: The closest of gotten is using a casting a ray trace through my panel, then using a reference intersector method to determine references. But i'm really struggling with implementation: http://thebuildingcoder.typepad.com/blog/2015/12/retrieving-wall-openings-and-sorting-points.html
These two posts should provide more than enough to solve all your issues:
Dimension walls by iterating their faces
Dimension walls by shooting a ray
Basically, you need to obtain references to the faces or edges that you wish to attach the dimensioning to. These references can be obtained in several ways. Two common and easy approaches are:
Retrieve the element geometry using the option ComputeReferences set to true and extract the specific face required.
Shoot a ray through the model to determine the required element and its face using the 2017
ReferenceIntersector Class.

How do I add the movie clip inside my data object to the stage? AS3

I'm currently programming a card game using AS3 and I'm using a data object to store the card data (Movie Clip Object, Card Value, and Card Suit). Code below (aceOfHearts is the name of my movie clip object in my library):
var aceOfHeartsCard:Object = {cardObject: aceOfHearts, faceValue: "ACE", suit: "HEARTS"};
I am doing this for all 52 cards in the deck. I am then pushing each of these objects into an array which I am using to shuffle and deal the cards. Code below.
cardArray.push(aceOfHeartsCard);
At this point, everything works fine. I can reference cardArray[0].faceValue and it will correctly return "ACE", etc. However, when I try to add the movie clip object to the stage using this code:
cardArray[0].cardObject.x = 0;
cardArray[0].cardObject.y = 0;
addChild(cardArray[0].cardObject);
I am getting this error:
TypeError: Error #1034: Type Coercion failed: cannot convert aceOfHearts$ to flash.display.DisplayObject.
Can someone please explain what I'm doing wrong?
Aha! Turns out all I needed to do was edit the first line of code I had posted above and add the word "new" before my movie clip name.
var aceOfHeartsCard:Object = {cardObject: new aceOfHearts, faceValue: "ACE", suit: "HEARTS"};

How to end a 2 player turn based Game Center match when player quit out of trun

I have searched about everywhere and not found an anwer for this problem:
I have a 2 player game, turn based, via Game Center.
After a player has done his move, he has the ability in Game Center to quit the game. In my case, this automatically means the game has ended and the other player has won. However, I can not find a Game Centermethod to make this happen.
I can not use endMatchInTurnWithMatchData because it is not this players turn.
And if I try to use endMatchInTurnWithMatchData when it is the other player's turn, this isn't possible either, because there is no other player to send the endMatchInTurnWithMatchData to (because the other player already quit).
Is there anyone who knows the solution to this?
Thanks,
Martyn
You have to implement turnBasedMatchmakerViewController:playerQuitForMatch: method of GKTurnBasedMatchmakerViewControllerDelegate. Here is an example code:
-(void)turnBasedMatchmakerViewController: (GKTurnBasedMatchmakerViewController *)viewController playerQuitForMatch:(GKTurnBasedMatch *)match {
NSUInteger currentIndex = [match.participants indexOfObject:match.currentParticipant];
GKTurnBasedParticipant *next = [match.participants objectAtIndex:(currentIndex + 1)%[match.participants count]];
[match participantQuitInTurnWithOutcome:GKTurnBasedMatchOutcomeQuit nextParticipants:#[next] turnTimeout:MAXFLOAT matchData:match.matchData completionHandler:nil];
[next setMatchOutcome:GKTurnBasedMatchOutcomeWon];
[match endMatchInTurnWithMatchData:match.matchData completionHandler:nil];
}
I was struggling with the same issue. What ended up working for me is to set yourself as the next participant when calling participantQuitInTurnWithOutcome.
Hope it helps!

Resources