Entity
After the cave.Scene
, cave.Entity
if the main thing in Cave. Because this class is the one that you'll be using to build your scenes, characters, enemies, interfaces and much more. That's why it's essential that you have a solid understanding of how it works. So let's jump to it!
cave.Entity
Variables
Cave's Entity only have those two variables. But they all serve a specific purpose, as you can see below.
Variable | Description |
---|---|
name | The entity name. |
properties | This is a python dictionary that you can use to store everything related to your entity. |
Here is the Python API for Reference:
name : str
properties : dict
Methods
To kill an entity, you can either do it immediately or schedule it to be done in the future, as you can see below. If you schedule a kill, you'll need to pass a time, in seconds, that the engine will start counting to delete the Entity. That's very useful if you want to drop an item that will dissapear after some time or create an UI element for a tutorial that will least on screen for 10 seconds, as an example.
kill()
scheduleKill(timeInSeconds: float)
Keep in mind that killing an Entity is an action that only gets done by the end of the Engine's frame. So when you call the Entity's kill()
method or even the scene.remove(entity)
, it will be scheduled to be done at the end of the current frame. That's why the following function, isAlive
, is very important: most of the times, it will return True
, but when the Entity gets marked for deletion in the end of the frame, it will return False
.
A good use case of this method os when you are handling damage and deleting the objects that take damage, adding it to the player's score. As you saw in the Scene's Documentation (read the CollisionInfo notes), a collision hit may happen multiple times for the same entities. So if you're iterating over all the entities to perform this damage and kill action and don't check to see if each entity is still alive, you may count the same kill twice!
Important: If you schedule a Kill using scheduleKill
, the entity will still be alive until its last frame, when it will actually be deleted.
There is the method API for reference:
isAlive() -> bool
If you need to see if the entity has a specific Tag or Property, use one of those methods:
hasTag(tag: str) -> bool
hasProperty(property: str) -> bool
If you want to get the Entity's ID, you can call the getID
method:
getID() -> int
It's a good idea to store the entity ID if you constantly wants to query the scene to retrieve the entity back, since it's faster to get the entity by its ID than it is by its name. And why not storing the Entity directly? Because if the entity gets deleted, you may cause a big problem if you still have it in your code. During a single frame, it's not a problem to store entities in a variable because as you already saw, the Engine will not immediately delete any entity while there is still code being running for the frame.
If you want to get the Entity's scene, use this:
getScene() -> cave.Scene
- Submitting the Transform to the World
THIS IS VERY IMPORTANT: If you change an entity's transform during the game, like moving, rotating or scaling it, you'll have to submit the new transform to the world, otherwise the physics and potentially the rendering will look wrong (it will remain using the old transform). This is not performed automatically due to Engine optimizations. So whenever you change a transform, call the method bellow. You don't need to call it after EVERY transform operation, calling it once in the end of the frame is enough.
SubmitTransformToWorld()
- Working with Components
As you already know, Cave Engine lets you customize your Entities by adding and manipulating components in it. When working with components using the Python API, you'll always refer to them by typing their names as strings. Adding the "Component" sufix is not mandatory, meaning that if you want to get the Entity's RigidBodyComponent
for example, you can call it: "RigidBodyComponent"
or just "RigidBody"
.
The Entity supports having multiple components of the same Type. In this case, getting it (with get
) will return the first hit. That's why you can also use getAll
to return all of them (same type). Here is the full API:
# Adds a new component:
add(componentName: str) -> cave.Component
# Returns a specific component:
get(componentName: str) -> cave.Component
# Returns all the components with this same type:
getAll(componentName: str) -> list of cave.Component
There is one component type that you'll likely to use a lot, which is the Transform Component. That's why Cave provides this method below for you to get them more easily. Keep in mind that an Entity may not have a transform (and it will return None).
getTransform() -> cave.TransformComponent
- Parenting System
As explained in the Scene documentation, Cave Engine organizes the scene into a Tree structure, where entities can be child of other entities. With that in mind, it's important that you know how to use and manipulate the parenting system.
To get the parent and children, you can use one of those methods below:
getParent() -> cave.Entity
# Get a Specific Child, by name
getChild(name: str, recursive=True) -> cave.Entity
# Gets all the children:
getChildren() -> list of cave.Entity
# Gets all the children recursively, meaning that all the
# children of the Entity's children will be included (and so on):
getChildrenRecursive() -> list of cave.Entity
In order to make a new parent, you can use one of those methods below. They will return True
of the parenting attempt was sucessful.
setParent(parent: cave.Entity) -> bool
setParentLocal(parent: cave.Entity) -> bool
Parenting an entity with None
will remove its parent. But in order to remove a parent, it's best to use one of those methods:
removeParent()
removeParentLocal()
Regarding the parenting system, there is some common questions that we'll address here:
-
What if I want to make an entity a child of another? You may have noticed that we don't have a
setChild
ormakeChildOf
method, onlysetParent
. If you want the entity A to be a child of the entity B, then what you actually want is B to be the parent of A. So instead of thinking of it asB.makeChildOf(A)
, think aboutA.setParent(B)
. -
What is this "local" thing? You also may have noticed that some methods have a "local" variant. If you set or remove a Parent using the "local" variants, it will try to preserv the entity's Transform, meaning that you'll not see it changing position, rotation or scale during this operation. Most of the time, this is what you want.
-
Will the Children move with their parent? Yes! When you create a parenting system, moving, rotating or scaling the parent will also affect their children. For reference, Entities with a parent will have their Transforms local to their parent's Transform. Unless the parent don't have a transform, of course. :)
-
If I delete or disable the parent, will it affect the children? Yes! :)
- Activating an Entity
You might want to disable (deactivate) an entity for some occasions. All the entities are activated by default, meaning that they will be rendered, execute logic and be taken into account in the Physics World. But some times, you just need to disable them for some time or until something happens, then re enable.
This is useful, for example, to create UI. Think about a pause menu. Instead of having to create an Entity Template for the menu and adding and removing it to the scene every time, you could just make the menu always there and just deactivate it when the game is running, activating it back if the player hits pause.
NOTE: Setting an entity to active or not will also recursively change this to all its children.
To see if the entity is Activated or Deactivated, you can use one of those methods:
isActive() -> bool
getActive() -> bool
In order to change this, you can also use the method provided below. But there is something important to know here: When you disable an Entity, it will call its end method (that will call the Component ones) and the same thing applies for activating them back (but with the start method). And due to how the engine works internally, those methods requires the scene you're in in order to work. So to activate or deactivate an entity, you'll need to pass the scene as an argument. You can simply get it using cave.getCurrentScene()
and it will work just fine.
# Activates the entity:
activate(scene: cave.Scene)
# Deactivates the entity:
deactivate(scene: cave.Scene)
# You can use this one if you want to set it with a boolean variable:
setActive(value: bool, scene: cave.Scene)
- Duplicating an Entity
You can create a copy of the entity and add it to the scene by doing this:
scene = cave.getCurrentScene()
# Creating a copy of the current entity...
entityCopy = cave.Entity(self.entity)
# Manually adding it to the scene:
scene.add(entityCopy)
You can also create a new one from scratch and add it to the scene like this:
newEntity = cave.Entity()
scene.add(newEntity)
But we strongly recommend, for the ease of use, that you build a new one by using the Entity Template system. Check the Scene's documentation for more details on how to do it.