diff --git a/entity-component-system/README.md b/entity-component-system/README.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/entity-component-system/etc/entity-component-system.urm.puml b/entity-component-system/etc/entity-component-system.urm.puml new file mode 100644 index 000000000000..1213969d7c8e --- /dev/null +++ b/entity-component-system/etc/entity-component-system.urm.puml @@ -0,0 +1,121 @@ +@startuml +package com.iluwatar { + class App { + + App() + + main(args : String[]) {static} + } + abstract class Component { + - isEnabled : boolean + - name : String + - parent : Entity + + Component() + + getEnabled() : boolean + + getName() : String + + getParent() : Entity + + setEnabled(isEnabled : boolean) + + setName(name : String) + + setParent(parent : Entity) + + update(float) {abstract} + } + class Entity { + - children : List + - components : List + - entityId : UUID + - gameSystem : GameSystem + - isEnabled : boolean + - name : String + - parent : Entity + - transform : TransformComponent + + Entity(entityName : String) + + addChild(child : Entity) + + addComponent(component : Component) + + getChildren() : List + + getComponent(componentName : String) : Component + + getEntityId() : UUID + + getGameSystem() : GameSystem + + getMeshRenderComponents() : List + + getName() : String + + getParent() : Entity + + getTransformComponent() : TransformComponent + + isEnabled() : boolean + + removeChild(child : Entity) + + removeComponent(component : Component) + + renderEntity() + + setEnabled(enabled : boolean) + + setGameSystem(gameSystem : GameSystem) + + setIsEnabled(isEnabled : boolean) + + setName(name : String) + + setParent(newParent : Entity) + + update(deltaTime : float) + } + class GameSystem { + - entities : List + + GameSystem() + + addEntity(entity : Entity) + - calculateDistance(point1 : float[], point2 : float[]) : float + + getSystemMatrix(entity : Entity) : float[][] + + getSystemPosition(entity : Entity) : float[] + - multiplyMatrices(matrix1 : float[][], matrix2 : float[][]) : float[][] + + removeEntity(entity : Entity) + + renderSystem() + + sortEntitiesByDistance(referencePoint : float[]) + + update(deltaTime : float) + } + class HealthComponent { + - currentHealth : float + - isAlive : boolean + - logger : Logger {static} + - maxHealth : float + + HealthComponent(maxHealth : float) + + applyDamage(damage : float) + + getCurrentHealth() : float + + getMaxHealth() : float + + heal(amount : float) + + isAlive() : boolean + + setAlive(isAlive : boolean) + + setCurrentHealth(currentHealth : float) + + setMaxHealth(maxHealth : float) + + update(deltaTime : float) + } + class TransformComponent { + - position : float[] + - rotation : float[] + - scale : float[] + + TransformComponent() + + TransformComponent(initPosition : float[], initRotation : float[], initScale : float[]) + - applyRotation(matrix : float[][]) + + getPosition() : float[] + + getRotation() : float[] + + getScale() : float[] + + getTransformMatrix() : float[][] + + setPosition(position : float[]) + + setRotation(eulerAngles : float[]) + + setScale(scale : float[]) + + update(deltaTime : float) + } + class VelocityComponent { + - logger : Logger {static} + - velocityX : float + - velocityY : float + - velocityZ : float + + VelocityComponent(velocityX : float, velocityY : float, velocityZ : float) + + applyForce(forceX : float, forceY : float, forceZ : float) + + applyFriction(frictionCoefficient : float) + + getVelocityX() : float + + getVelocityY() : float + + getVelocityZ() : float + + setVelocityX(velocityX : float) + + setVelocityY(velocityY : float) + + setVelocityZ(velocityZ : float) + + update(deltaTime : float) + } +} +Entity --> "-transform" TransformComponent +Entity --> "-parent" Entity +Entity --> "-children" Entity +Entity --> "-gameSystem" GameSystem +Entity --> "-components" Component +HealthComponent --|> Component +TransformComponent --|> Component +VelocityComponent --|> Component +@enduml \ No newline at end of file diff --git a/entity-component-system/pom.xml b/entity-component-system/pom.xml new file mode 100644 index 000000000000..cc5ae82d3ff3 --- /dev/null +++ b/entity-component-system/pom.xml @@ -0,0 +1,74 @@ + + + + + java-design-patterns + com.iluwatar + 1.26.0-SNAPSHOT + + com.iluwatar + 1.26.0-SNAPSHOT + 4.0.0 + entity-component-system + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.entity-component-system.Main + + + + + + + + + diff --git a/entity-component-system/src/main/java/com/iluwatar/App.java b/entity-component-system/src/main/java/com/iluwatar/App.java new file mode 100644 index 000000000000..58ab4cc083cd --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/App.java @@ -0,0 +1,80 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +/** + * The main entry point for the application. + * This class simulates a game loop where entities are created, updated, and their states are modified. + */ +public class App { + + /** + * The main method that runs the application. + * It creates entities, adds components, updates them over several frames, + * and demonstrates applying damage and forces to entities. + * + * @param args Command-line arguments (not used in this application) + */ + public static void main(String[] args) { + + + Entity entity1 = new Entity("Entity1"); + Entity entity2 = new Entity("Entity2"); + + TransformComponent transform1 = new TransformComponent(new float[]{0.0f, 0.0f, 0.0f}, + new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + TransformComponent transform2 = new TransformComponent(new float[]{5.0f, 0.0f, 0.0f}, + new float[]{0.0f, 45.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + + entity1.addComponent(transform1); + entity2.addComponent(transform2); + + HealthComponent health1 = new HealthComponent(100); // Ensure HealthComponent is implemented + entity1.addComponent(health1); + + VelocityComponent velocity1 = new VelocityComponent(1.0f, 0.0f, 0.0f); + entity1.addComponent(velocity1); + + GameSystem gameSystem = new GameSystem(); + gameSystem.addEntity(entity1); + gameSystem.addEntity(entity2); + + float deltaTime = 1.0f / 60.0f; + + for (int i = 0; i < 10; i++) { + + gameSystem.update(deltaTime); + + if (i == 5) { + health1.applyDamage(30); + } + + if (i == 3) { + velocity1.applyForce(0.5f, 0.0f, 0.0f); + } + + } + } +} diff --git a/entity-component-system/src/main/java/com/iluwatar/Component.java b/entity-component-system/src/main/java/com/iluwatar/Component.java new file mode 100644 index 000000000000..847a48883da9 --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/Component.java @@ -0,0 +1,88 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +/** + * Abstract class representing a component in the ECS system. + * Each component can be enabled or disabled and associated with an entity. + * Subclasses of this class must implement the update method. + */ +public abstract class Component { + + private String name; + private boolean isEnabled; + + /** + * Default constructor for the component. + * Initializes a new component with default values. + */ + protected Component() { + // Constructor left empty intentionally, no specific initialization required + } + + /** + * Gets the name of the component. + * + * @return the name of the component + */ + public String getName() { + return name; + } + + /** + * Sets the name of the component. + * + * @param name the name of the component + */ + public void setName(String name) { + this.name = name; + } + + /** + * Gets the enabled state of the component. + * + * @return true if the component is enabled, false otherwise + */ + public boolean getEnabled() { + return isEnabled; + } + + /** + * Sets the enabled state of the component. + * + * @param isEnabled true to enable the component, false to disable it + */ + public void setEnabled(boolean isEnabled) { + this.isEnabled = isEnabled; + } + + /** + * Abstract method to update the component. + * Subclasses must implement this method to define their update behavior. + * + * @param deltaTime the time elapsed since the last update + */ + public abstract void update(float deltaTime); +} diff --git a/entity-component-system/src/main/java/com/iluwatar/Entity.java b/entity-component-system/src/main/java/com/iluwatar/Entity.java new file mode 100644 index 000000000000..fa1e2e60fba4 --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/Entity.java @@ -0,0 +1,281 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +/** + * Represents an entity in the ECS system. + * Each entity can have components, children entities, and a parent entity. + * Entities can be enabled or disabled, and their components can be updated. + */ +public class Entity { + + private String name; + private boolean isEnabled; + private TransformComponent transform; + private Entity parent; + private List components; + private List children; + + /** The unique identifier for the entity. */ + private UUID entityId; + + /** + * Constructs a new entity with a specified name. + * + * @param entityName the name of the entity + */ + public Entity(String entityName) { + name = entityName; + components = new ArrayList<>(); + children = new ArrayList<>(); + entityId = UUID.randomUUID(); // Generates a unique UUID for this entity + transform = new TransformComponent(new float[] {0.0f, 0.0f, 0.0f}, new float[] {0.0f, 0.0f, 0.0f}, new float[] {1.0f, 1.0f, 1.0f}); + addComponent(transform); + + } + + /** + * Adds a component to the entity. + * + * @param component the component to be added + */ + public void addComponent(Component component) { + if (component != null) { + components.add(component); + component.setEnabled(isEnabled); + } + } + + /** + * Removes a component from the entity. + * + * @param component the component to be removed + */ + public void removeComponent(Component component) { + components.remove(component); + } + + /** + * Retrieves a component by its name. + * + * @param componentName the name of the component + * @return the component matching the specified name, or null if not found + */ + public Component getComponent(String componentName) { + for (Component component : components) { + if (Objects.equals(component.getName(), componentName)) { + return component; + } + } + return null; + } + + /** + * Sets the parent entity for this entity. + * + * @param newParent the new parent entity + */ + public void setParent(Entity newParent) { + if (parent != null) { + parent.removeChild(this); + } + + parent = newParent; + + if (parent != null) { + parent.addChild(this); + } + } + + /** + * Adds a child entity to this entity. + * + * @param child the child entity to be added + */ + public void addChild(Entity child) { + if (child != null && !children.contains(child)) { + children.add(child); + // Set the parent only if it isn't already set. + if (child.getParent() != this) { + child.setParent(this); + } + } + } + + /** + * Finds a Child Entity in Children List. + * + * @param entityId the child entity to be removed + */ + public Entity findChildEntity(UUID entityId) { + for (Entity child : children) { + if (Objects.equals(child.getEntityId(), entityId)) { + return child; + } + } + return null; + } + + /** + * Removes a child entity from this entity. + * + * @param child the child entity to be removed + */ + public void removeChild(Entity child) { + children.remove(child); + } + + /** + * Enables or disables the entity and all its components and children. + * + * @param enabled whether the entity should be enabled or not + */ + public void setEnabled(boolean enabled) { + isEnabled = enabled; + + for (Component component : components) { + component.setEnabled(enabled); + } + + for (Entity child : children) { + child.setEnabled(enabled); + } + } + + /** + * Updates the entity and its components. + * + * @param deltaTime the time elapsed since the last update + */ + public void update(float deltaTime) { + if (!isEnabled) { + return; + } + + for (Component component : components) { + if (component.getEnabled()) { + component.update(deltaTime); + } + } + + for (Entity child : children) { + child.update(deltaTime); + } + } + + /** + * Gets the transform component of the entity. + * + * @return the transform component + */ + public TransformComponent getTransformComponent() { + return transform; + } + + /** + * Gets the transform component of the entity. + * + */ + public void setTransformComponent(TransformComponent transform) { + this.transform = transform; + } + + /** + * Retrieves the mesh render components associated with this entity. + * + * @return a list of mesh render components + */ + public List getComponents() { + + return components; + } + + // Getters and Setters for fields + + /** + * Gets the name of the entity. + * + * @return the name of the entity + */ + public String getName() { + return name; + } + + /** + * Gets the unique identifier of the entity. + * + * @return the unique entity identifier + */ + public UUID getEntityId() { + return entityId; + } + + /** + * Gets the current enabled state of the entity. + * + * @return true if the entity is enabled, false otherwise + */ + public boolean isEnabled() { + return isEnabled; + } + + /** + * Sets the current enabled state of the entity. + * + * @param isEnabled true to enable the entity, false to disable it + */ + public void setIsEnabled(boolean isEnabled) { + + this.isEnabled = isEnabled; + + for (Entity child : children) { + child.setIsEnabled(isEnabled); + + } + } + + /** + * Gets the parent entity of this entity. + * + * @return the parent entity + */ + public Entity getParent() { + return parent; + } + + /** + * Gets the children entities of this entity. + * + * @return the list of children entities + */ + public List getChildren() { + return children; + } +} diff --git a/entity-component-system/src/main/java/com/iluwatar/GameSystem.java b/entity-component-system/src/main/java/com/iluwatar/GameSystem.java new file mode 100644 index 000000000000..2511b5ae4706 --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/GameSystem.java @@ -0,0 +1,161 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import java.util.ArrayList; +import java.util.List; + +/** + * System class that manages entities within the system. + * It handles adding and removing entities, updating them, rendering, + * and sorting them by distance from a reference point. + */ +public class GameSystem { + + private List entities; + + /** + * Constructor for initializing the system with an empty list of entities. + */ + public GameSystem() { + entities = new ArrayList<>(); + } + + /** + * Adds an entity to the system, including its children recursively. + * + * @param entity the entity to be added + */ + public void addEntity(Entity entity) { + if (entity != null) { + entities.add(entity); + // Recursively add children entities + for (Entity child : entity.getChildren()) { + addEntity(child); + } + } + } + + /** + * Removes an entity from the system. + * + * @param entity the entity to be removed + */ + public void removeEntity(Entity entity) { + entities.remove(entity); + } + + /** + * Gets the system matrix for a specific entity by considering its transform and the transform of its parent. + * + * @param entity the entity whose system matrix is to be calculated + * @return the 4x4 system transformation matrix + */ + public float[][] getSystemMatrix(Entity entity) { + float[][] systemMatrix = entity.getTransformComponent().getTransformMatrix(); + + if (entity.getParent() != null) { + float[][] parentMatrix = getSystemMatrix(entity.getParent()); + systemMatrix = multiplyMatrices(parentMatrix, systemMatrix); + } + + return systemMatrix; + } + + /** + * Gets the system position of an entity from its transformation matrix. + * + * @param entity the entity whose position is to be retrieved + * @return an array representing the entity's position [x, y, z] + */ + public float[] getSystemPosition(Entity entity) { + float[][] systemMatrix = getSystemMatrix(entity); + return new float[] { systemMatrix[0][3], systemMatrix[1][3], systemMatrix[2][3] }; // Position is in the 4th column + } + + /** + * Updates all entities in the system by calling their update methods. + * + * @param deltaTime the time elapsed since the last update + */ + public void update(float deltaTime) { + for (Entity entity : entities) { + entity.update(deltaTime); + } + } + + /** + * Sorts the entities by their distance from a given reference point in descending order. + * + * @param referencePoint the point from which the distance is measured + */ + public void sortEntitiesByDistance(float[] referencePoint) { + entities.sort((e1, e2) -> { + float[] pos1 = getSystemPosition(e1); + float[] pos2 = getSystemPosition(e2); + float distance1 = calculateDistance(pos1, referencePoint); + float distance2 = calculateDistance(pos2, referencePoint); + return Float.compare(distance2, distance1); // Sort in descending order + }); + } + + public List getEntities() { + return entities; + } + + /** + * Helper method to calculate the distance between two points in 3D space. + * + * @param point1 the first point + * @param point2 the second point + * @return the distance between the two points + */ + private float calculateDistance(float[] point1, float[] point2) { + float dx = point1[0] - point2[0]; + float dy = point1[1] - point2[1]; + float dz = point1[2] - point2[2]; + return (float) Math.sqrt(dx * dx + dy * dy + dz * dz); + } + + /** + * Helper method to multiply two 4x4 matrices. + * + * @param matrix1 the first matrix + * @param matrix2 the second matrix + * @return the resulting matrix after multiplication + */ + private float[][] multiplyMatrices(float[][] matrix1, float[][] matrix2) { + float[][] result = new float[4][4]; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + result[i][j] = 0; + for (int k = 0; k < 4; k++) { + result[i][j] += matrix1[i][k] * matrix2[k][j]; + } + } + } + return result; + } +} diff --git a/entity-component-system/src/main/java/com/iluwatar/HealthComponent.java b/entity-component-system/src/main/java/com/iluwatar/HealthComponent.java new file mode 100644 index 000000000000..224b9c842a09 --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/HealthComponent.java @@ -0,0 +1,119 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + + + +/** + * Abstract class representing a health component in the ECS system. + * This component tracks the current health, max health, and whether the entity is alive. + * Subclasses must implement the updateHealth method to define custom behavior for updating health. + */ +public class HealthComponent extends Component { + + private float currentHealth; + private float maxHealth; + private boolean isAlive; + + /** + * Constructor for initializing the health component with a maximum health value. + * The current health is set to the maximum health, and the entity is considered alive. + * + * @param maxHealth the maximum health of the entity + */ + public HealthComponent(float maxHealth) { + this.maxHealth = maxHealth; + this.currentHealth = maxHealth; + this.isAlive = true; + } + + /** + * Abstract method for updating the health component. + * Subclasses must implement this method to define how health is updated. + * + * @param deltaTime the time elapsed since the last update + */ + @Override + public void update(float deltaTime) { + //update health + } + + /** + * Applies damage to the entity. If the entity is alive, the damage is subtracted from the current health. + * If health drops to zero or below, the entity is marked as dead. + * + * @param damage the amount of damage to apply + */ + public void applyDamage(float damage) { + if (isAlive) { + currentHealth -= damage; + if (currentHealth <= 0) { + currentHealth = 0; + isAlive = false; + } + } + } + + /** + * Heals the entity by a specified amount. If the entity is alive, the current health is increased, + * but it cannot exceed the maximum health. + * + * @param amount the amount to heal + */ + public void heal(float amount) { + if (isAlive) { + currentHealth += amount; + if (currentHealth > maxHealth) { + currentHealth = maxHealth; + } + } + } + + // Setters and Getters + + public float getCurrentHealth() { + return currentHealth; + } + + public void setCurrentHealth(float currentHealth) { + this.currentHealth = currentHealth; + } + + public float getMaxHealth() { + return maxHealth; + } + + public void setMaxHealth(float maxHealth) { + this.maxHealth = maxHealth; + } + + public boolean isAlive() { + return isAlive; + } + + public void setAlive(boolean isAlive) { + this.isAlive = isAlive; + } +} diff --git a/entity-component-system/src/main/java/com/iluwatar/TransformComponent.java b/entity-component-system/src/main/java/com/iluwatar/TransformComponent.java new file mode 100644 index 000000000000..e28113ccfb8e --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/TransformComponent.java @@ -0,0 +1,171 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +/** + * A component that handles the transformation of an entity in 3D space. + * This includes position, scale, and rotation (represented by Euler angles). + */ +public class TransformComponent extends Component { + + private float[] position; // Position of the entity (x, y, z) + private float[] scale; // Scale of the entity (x, y, z) + private float[] rotation; // Rotation of the entity (pitch, yaw, roll) + + /** + * Constructs a TransformComponent with the specified position, rotation, and scale. + * + * @param initPosition the initial position of the entity + * @param initRotation the initial rotation (Euler angles: pitch, yaw, roll) + * @param initScale the initial scale of the entity + */ + public TransformComponent(float[] initPosition, float[] initRotation, float[] initScale) { + super(); + this.position = initPosition != null ? initPosition : new float[]{0.0f, 0.0f, 0.0f}; + this.scale = initScale != null ? initScale : new float[]{1.0f, 1.0f, 1.0f}; + this.rotation = initRotation != null ? initRotation : new float[]{0.0f, 0.0f, 0.0f}; + } + + /** + * Default constructor that initializes the transform component with default values. + */ + public TransformComponent() { + this(new float[]{0.0f, 0.0f, 0.0f}, new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + } + + /** + * Updates the transform component (add any transformations here if needed). + * + * @param deltaTime the time elapsed since the last update + */ + @Override + public void update(float deltaTime) { + // No specific updates in this implementation + } + + /** + * Returns the 4x4 transformation matrix that represents the position, scale, and rotation of the entity. + * + * @return a 4x4 transformation matrix + */ + public float[][] getTransformMatrix() { + float[][] matrix = new float[4][4]; + + // Initialize as an identity matrix + matrix[0][0] = 1.0f; + matrix[0][1] = 0.0f; + matrix[0][2] = 0.0f; + matrix[0][3] = 0.0f; + + matrix[1][0] = 0.0f; + matrix[1][1] = 1.0f; + matrix[1][2] = 0.0f; + matrix[1][3] = 0.0f; + + matrix[2][0] = 0.0f; + matrix[2][1] = 0.0f; + matrix[2][2] = 1.0f; + matrix[2][3] = 0.0f; + + matrix[3][0] = 0.0f; + matrix[3][1] = 0.0f; + matrix[3][2] = 0.0f; + matrix[3][3] = 1.0f; + + // Apply scaling + matrix[0][0] *= scale[0]; + matrix[1][1] *= scale[1]; + matrix[2][2] *= scale[2]; + + // Apply rotation (pitch, yaw, roll) + applyRotation(matrix); + + // Apply translation (position) + matrix[0][3] = position[0]; + matrix[1][3] = position[1]; + matrix[2][3] = position[2]; + + return matrix; + } + + /** + * Applies the rotation to the transformation matrix based on the Euler angles. + * + * @param matrix the transformation matrix to be modified + */ + private void applyRotation(float[][] matrix) { + // Matrix transformations using rotation directly + matrix[1][1] = (float) Math.cos(rotation[0]); // pitch + matrix[1][2] = (float) -Math.sin(rotation[0]); + matrix[2][1] = (float) Math.sin(rotation[0]); + matrix[2][2] = (float) Math.cos(rotation[0]); + + matrix[0][0] = (float) Math.cos(rotation[1]); // yaw + matrix[0][2] = (float) Math.sin(rotation[1]); + matrix[2][0] = (float) -Math.sin(rotation[1]); + matrix[2][2] = (float) Math.cos(rotation[1]); + + matrix[0][0] = (float) Math.cos(rotation[2]); // roll + matrix[0][1] = (float) -Math.sin(rotation[2]); + matrix[1][0] = (float) Math.sin(rotation[2]); + matrix[1][1] = (float) Math.cos(rotation[2]); + } + + /** + * Sets the rotation of the entity using Euler angles (pitch, yaw, roll). + * + * @param eulerAngles an array of Euler angles [pitch, yaw, roll] + */ + public void setRotation(float[] eulerAngles) { + this.rotation = eulerAngles != null ? eulerAngles : new float[]{0.0f, 0.0f, 0.0f}; // pitch, yaw, roll + } + + /** + * Gets the rotation of the entity as Euler angles (pitch, yaw, roll). + * + * @return the rotation as an array of Euler angles [pitch, yaw, roll] + */ + public float[] getRotation() { + return rotation; + } + + // Getters and Setters for position and scale + + public float[] getPosition() { + return position; + } + + public void setPosition(float[] position) { + this.position = position != null ? position : new float[]{0.0f, 0.0f, 0.0f}; + } + + public float[] getScale() { + return scale; + } + + public void setScale(float[] scale) { + this.scale = scale != null ? scale : new float[]{1.0f, 1.0f, 1.0f}; + } +} diff --git a/entity-component-system/src/main/java/com/iluwatar/VelocityComponent.java b/entity-component-system/src/main/java/com/iluwatar/VelocityComponent.java new file mode 100644 index 000000000000..85f04dcae33e --- /dev/null +++ b/entity-component-system/src/main/java/com/iluwatar/VelocityComponent.java @@ -0,0 +1,166 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + + +/** + * A component that handles the velocity of an entity in 3D space. + * It allows updating velocity, applying forces, and friction. + */ +public class VelocityComponent extends Component { + + + private float velocityX; // The velocity in the X direction + private float velocityY; // The velocity in the Y direction + private float velocityZ; // The velocity in the Z direction + + private final float initialVelocityX; + private final float initialVelocityY; + private final float initialVelocityZ; + + /** + * Constructs a VelocityComponent with the given velocity values in the X, Y, and Z directions. + * + * @param velocityX the initial velocity in the X direction + * @param velocityY the initial velocity in the Y direction + * @param velocityZ the initial velocity in the Z direction + */ + public VelocityComponent(float velocityX, float velocityY, float velocityZ) { + this.velocityX = velocityX; + this.velocityY = velocityY; + this.velocityZ = velocityZ; + + this.initialVelocityX = velocityX; + this.initialVelocityY = velocityY; + this.initialVelocityZ = velocityZ; + } + + /** + * update the velocity of the entity. + * This method resets the velocity + * + */ + public void resetVelocity() { + this.velocityX = this.initialVelocityX; + this.velocityY = this.initialVelocityY; + this.velocityZ = this.initialVelocityZ; + } + + + /** + * Updates the velocity of the entity based on delta time. + * This method multiplies the current velocity by the delta time to simulate movement. + * + * @param deltaTime the time elapsed since the last update + */ + public void update(float deltaTime) { + velocityX += velocityX * deltaTime; + velocityY += velocityY * deltaTime; + velocityZ += velocityZ * deltaTime; + + } + + /** + * Applies a force to the entity, updating its velocity. + * The force values will be added to the current velocity. + * + * @param forceX the force applied in the X direction + * @param forceY the force applied in the Y direction + * @param forceZ the force applied in the Z direction + */ + public void applyForce(float forceX, float forceY, float forceZ) { + this.velocityX += forceX; + this.velocityY += forceY; + this.velocityZ += forceZ; + } + + /** + * Applies friction to the entity's velocity. The velocity is reduced by the friction coefficient. + * A friction coefficient of 0 means no friction, and 1 means full friction (stopping the entity). + * + * @param frictionCoefficient the coefficient of friction applied to the velocity + */ + public void applyFriction(float frictionCoefficient) { + this.velocityX *= (1 - frictionCoefficient); + this.velocityY *= (1 - frictionCoefficient); + this.velocityZ *= (1 - frictionCoefficient); + } + + // Getters and setters for velocityX, velocityY, and velocityZ + + /** + * Returns the velocity in the X direction. + * + * @return the velocity in the X direction + */ + public float getVelocityX() { + return velocityX; + } + + /** + * Sets the velocity in the X direction. + * + * @param velocityX the velocity in the X direction + */ + public void setVelocityX(float velocityX) { + this.velocityX = velocityX; + } + + /** + * Returns the velocity in the Y direction. + * + * @return the velocity in the Y direction + */ + public float getVelocityY() { + return velocityY; + } + + /** + * Sets the velocity in the Y direction. + * + * @param velocityY the velocity in the Y direction + */ + public void setVelocityY(float velocityY) { + this.velocityY = velocityY; + } + + /** + * Returns the velocity in the Z direction. + * + * @return the velocity in the Z direction + */ + public float getVelocityZ() { + return velocityZ; + } + + /** + * Sets the velocity in the Z direction. + * + * @param velocityZ the velocity in the Z direction + */ + public void setVelocityZ(float velocityZ) { + this.velocityZ = velocityZ; + } +} diff --git a/entity-component-system/src/test/java/com/iluwatar/AppTest.java b/entity-component-system/src/test/java/com/iluwatar/AppTest.java new file mode 100644 index 000000000000..2f427bdf7783 --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/AppTest.java @@ -0,0 +1,209 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class AppTest { + + private Entity entity1; + private Entity entity2; + private HealthComponent health1; + private VelocityComponent velocity1; + TransformComponent transform1 = new TransformComponent(new float[]{0.0f, 0.0f, 0.0f}, + new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + TransformComponent transform2 = new TransformComponent(new float[]{5.0f, 0.0f, 0.0f}, + new float[]{0.0f, 45.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + + @BeforeEach +void setUp() { + entity1 = new Entity("Entity1"); + entity2 = new Entity("Entity2"); + + entity1.addComponent(transform1); + entity2.addComponent(transform2); + + health1 = new HealthComponent(100); + entity1.addComponent(health1); + + velocity1 = new VelocityComponent(1.0f, 0.0f, 0.0f); + entity1.addComponent(velocity1); + } + @Test +void testMain_DoesNotThrowException() { + assertDoesNotThrow(() -> App.main(new String[]{}), "Child entity should not throw an exception if the parent is disabled."); + } + + @Test +void testHealthComponentApplyDamage() { + + health1.applyDamage(30); + + assertEquals(70, health1.getCurrentHealth(), "Health should be reduced by 30"); + } + + @Test +void testVelocityComponentApplyForce() { + + velocity1.applyForce(0.5f, 0.0f, 0.0f); + + assertEquals(1.5f, velocity1.getVelocityX(), "Velocity X should be updated by the applied force"); + assertEquals(0.0f, velocity1.getVelocityY(), "Velocity Y should remain unchanged"); + assertEquals(0.0f, velocity1.getVelocityZ(), "Velocity Z should remain unchanged"); + } + + @Test +void testEntityUpdate() { + + float deltaTime = 1.0f / 60.0f; + velocity1.setVelocityY(12.0f); + float initialVelocityY = velocity1.getVelocityY(); + velocity1.update(deltaTime); + + assertTrue(velocity1.getVelocityY() > initialVelocityY, "Velocity should increase over time"); + } + + @Test +void testEntityHealthAfterDamageAndForce() { + + health1.applyDamage(40); + + velocity1.applyForce(0.2f, 0.0f, 0.0f); + + entity1.update(1.0f / 60.0f); + + assertEquals(60, health1.getCurrentHealth(), "Health should be reduced by 40"); + assertEquals(1.2f, velocity1.getVelocityX(), "Velocity X should be updated by the applied force"); + } + + @Test +void testFinalEntityStateAfterSimulation() { + + GameSystem gameSystem = new GameSystem(); + gameSystem.addEntity(entity1); + gameSystem.addEntity(entity2); + TransformComponent testTransform = new TransformComponent(new float[]{5.0f, 0.0f, 0.0f}, + new float[]{0.0f, 45.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + entity1.setTransformComponent(testTransform); + + for (int i = 0; i < 10; i++) { + gameSystem.update(1.0f / 60.0f); + if (i == 5) { + health1.applyDamage(30); + } + if (i == 3) { + velocity1.applyForce(0.5f, 0.0f, 0.0f); + } + } + + assertEquals(70, health1.getCurrentHealth(), "Final health should be 70 after applying 30 damage"); + assertEquals(1.5f, velocity1.getVelocityX(), "Final velocity X should be 1.5 after applying force"); + assertNotNull(entity1.getTransformComponent(), "Entity1 should have a transform component"); + + } + + @Test +void testAddTransformComponent() { + entity1.addComponent(transform1); + assertTrue(entity1.getComponents().contains(transform1), "Entity1 should contain the added TransformComponent."); + } + + @Test +void testGameLoopUpdatesEntityState() { + GameSystem gameSystem = new GameSystem(); + gameSystem.addEntity(entity1); + + for (int i = 0; i < 5; i++) { + gameSystem.update(1.0f / 60.0f); + } + + // Check the updated health and velocity + assertEquals(100, health1.getCurrentHealth(), "Health should not be affected yet."); + assertEquals(1.0f, velocity1.getVelocityX(), "Velocity X should remain the same as no force is applied."); + } + + @Test +void testHealthReductionOverMultipleDamages() { + health1.applyDamage(20); + health1.applyDamage(30); + + assertEquals(50, health1.getCurrentHealth(), "Health should be reduced by 50 after two damage applications."); + } + + @Test +void testEntityRemovalFromGameSystem() { + GameSystem gameSystem = new GameSystem(); + gameSystem.addEntity(entity1); + + gameSystem.removeEntity(entity1); + + // Assert that entity1 is no longer in the system + assertFalse(gameSystem.getEntities().contains(entity1), "Entity1 should no longer be in the GameSystem after removal."); + } + + @Test +void testEntityWithoutComponents() { + Entity entity = new Entity("EmptyEntity"); + entity.removeComponent(entity.getTransformComponent()); + assertTrue(entity.getComponents().isEmpty(), "Entity should have no components."); + assertEquals("EmptyEntity", entity.getName(), "Entity should have the correct name."); + } + + @Test +void testSetParentAndChildren() { + Entity parentEntity = new Entity("ParentEntity"); + Entity childEntity = new Entity("ChildEntity"); + + parentEntity.addChild(childEntity); + + assertTrue(parentEntity.getChildren().contains(childEntity), "Parent entity should contain the child entity."); + assertEquals(parentEntity, childEntity.getParent(), "Child entity should have the parent entity set."); + } + + @Test +void testVelocityComponentReset() { + velocity1.applyForce(1.0f, 0.0f, 0.0f); + + velocity1.resetVelocity(); + + assertEquals(1.0f, velocity1.getVelocityX(), "Velocity should be reset to its initial value."); + assertEquals(0.0f, velocity1.getVelocityY(), "Velocity Y should remain reset."); + assertEquals(0.0f, velocity1.getVelocityZ(), "Velocity Z should remain reset."); + } + + @Test +void testHealthAndForceAppliedTogether() { + health1.applyDamage(20); + velocity1.applyForce(0.5f, 0.0f, 0.0f); + + // Update entity state after applying damage and force + entity1.update(1.0f / 60.0f); + + assertEquals(80, health1.getCurrentHealth(), "Health should be reduced by 20 after damage."); + assertEquals(1.5f, velocity1.getVelocityX(), "Velocity X should increase by 0.5 after applying force."); + } +} \ No newline at end of file diff --git a/entity-component-system/src/test/java/com/iluwatar/ComponentTest.java b/entity-component-system/src/test/java/com/iluwatar/ComponentTest.java new file mode 100644 index 000000000000..8a04bf357e0f --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/ComponentTest.java @@ -0,0 +1,59 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + class ComponentTest { + @Test + void testGetName() { + Component component = new HealthComponent(10); + component.setName("Health"); + + assertEquals("Health", component.getName(), "getName should return 'Health'"); + } + + @Test + void testSetName() { + Component component = new HealthComponent(100); + component.setName("Velocity"); + component.setName("Transform"); + assertEquals("Transform", component.getName(), "getName should return 'Transform'"); + } + + @Test + void testComponentEnabled() { + Component component = new HealthComponent(100); + component.setEnabled(true); + + assertTrue(component.getEnabled(), "The component should be enabled."); + + component.setEnabled(false); + assertFalse(component.getEnabled(), "The component should be disabled."); + } + +} diff --git a/entity-component-system/src/test/java/com/iluwatar/EntityTest.java b/entity-component-system/src/test/java/com/iluwatar/EntityTest.java new file mode 100644 index 000000000000..a8a0cc0ec546 --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/EntityTest.java @@ -0,0 +1,226 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + class EntityTest { + + private Entity entity1; + private Entity entity2; + TransformComponent transform1; + TransformComponent transform2; + + @BeforeEach + void setUp() { + entity1 = new Entity("Entity1"); + entity2 = new Entity("Entity2"); + + transform1 = new TransformComponent(new float[]{0.0f, 0.0f, 0.0f}, + new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + transform2 = new TransformComponent(new float[]{5.0f, 0.0f, 0.0f}, + new float[]{0.0f, 45.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + } + + @Test + void testAddComponent() { + Component component = new HealthComponent(100); + entity1.addComponent(component); + + assertEquals(2, entity1.getComponents().size(), "Entity1 should have 1 component."); + } + + @Test + void testRemoveComponent() { + Component component = new HealthComponent(100); + + entity2.removeComponent(component); + + assertEquals(1, entity2.getComponents().size(), "Entity1 should have no components."); + } + + @Test + void testAddChild() { + entity1.addChild(entity2); + + assertTrue(entity1.getChildren().contains(entity2), "Entity1 should have Entity2 as its child."); + } + + @Test + void testGetComponent() { + + Component component = new HealthComponent(100); + component.setName("HealthComponent"); + Entity entity = new Entity("Entity1"); + entity.addComponent(component); + Component retrievedComponent = entity.getComponent("HealthComponent"); + + assertEquals(component, retrievedComponent, "The component returned should match the added component."); + + Component nonExistentComponent = entity.getComponent("NonExistentComponent"); + assertNull(nonExistentComponent, "The component should return null if it doesn't exist."); + } + + @Test + void testSetEnabled() { + + Component component = new HealthComponent(100); + Entity entity = new Entity("MyEntity"); + entity.addComponent(component); + + assertFalse(component.getEnabled(), "Component should be disabled initially."); + + entity.setEnabled(false); + + assertFalse(component.getEnabled(), "Component should be disabled after calling setEnabled(false)."); + + entity.setEnabled(true); + + assertTrue(component.getEnabled(), "Component should be enabled after calling setEnabled(true)."); + } + + @Test + void testSetParent() { + + Entity parent = new Entity("parent"); + Entity child = new Entity("child"); + + child.setParent(parent); + + assertTrue(parent.getChildren().contains(child), "Parent should contain child in its children list."); + + Entity newParent = new Entity("newParent"); + child.setParent(newParent); + + assertFalse(parent.getChildren().contains(child), "Parent should no longer contain child after setting a new parent."); + + assertTrue(newParent.getChildren().contains(child), "New parent should contain child in its children list."); + } + + @Test + void testUpdate() { + float deltaTime = 1.0f / 60.0f; + entity1.update(deltaTime); + + assertNotNull(entity1, "Entity1 should be updated."); + } + + + @Test + void testGetName() { + Entity entity = new Entity("MyEntity"); + + assertEquals("MyEntity", entity.getName(), "The entity name should match the given name."); + } + + @Test + void testSetIsEnabled() { + Entity entity = new Entity("MyEntity"); + Entity entityChild = new Entity("child"); + entity.addChild(entityChild); + entity.setIsEnabled(false); + + assertFalse(entity.isEnabled(), "The entity should be disabled after calling setIsEnabled(false)."); + assertFalse(entityChild.isEnabled(), "The entity child should be disabled after calling setIsEnabled(false)."); + + entity.setIsEnabled(true); + + assertTrue(entity.isEnabled(), "The entity should be enabled after calling setIsEnabled(true)."); + assertTrue(entityChild.isEnabled(), "The entity child should be enabled after calling setIsEnabled(true)."); + } + + @Test + void testUpdate_whenEntityDisabled_shouldReturnImmediately() { + + + Entity parent = new Entity("parent"); + Entity child = new Entity("child"); + + child.setParent(parent); + + parent.setEnabled(false); + parent.addComponent(transform1); + + parent.update(1.0f); + + assertFalse(transform1.getEnabled(), "Component should not be enabled."); + assertDoesNotThrow(() -> transform1.update(1.0f), "Component update should not throw an exception when entity is disabled."); + + assertDoesNotThrow(() -> child.update(1.0f), "Child entity should not throw an exception if the parent is disabled."); + } + + @Test + void testUpdate_shouldUpdateEnabledComponents() { + entity1.setEnabled(true); + entity2.setEnabled(false); + entity1.addComponent(transform1); + entity2.addComponent(transform2); + entity1.update(1.0f); + entity2.update(1.0f); + + assertTrue(transform1.getEnabled(), "Transform1 should be enabled after update when the parent entity is enabled."); + assertDoesNotThrow(() -> transform1.update(1.0f), "Transform1 update should not throw an exception when the parent entity is enabled."); + + assertFalse(transform2.getEnabled(), "Transform2 should remain disabled after update when it is added but disabled."); + assertDoesNotThrow(() -> transform2.update(1.0f), "Transform2 update should not throw an exception even though it's disabled."); + } + + @Test + void testUpdate_shouldUpdateChildEntities() { + Entity child = new Entity("child"); + entity1.setEnabled(true); + entity1.addChild(child); + child.setParent(entity1); + entity1.update(1.0f); + assertDoesNotThrow(() -> child.update(1.0f)); + } + + @Test + void testFindChildEntity() { + Entity parent = new Entity("parent"); + Entity child = new Entity("child"); + child.setParent(parent); + parent.addChild(child); + + assertEquals(parent.findChildEntity(child.getEntityId()),child, "The child object should match the one found."); + + } + + @Test + void testNotFindChildEntity() { + Entity parent = new Entity("parent"); + Entity child = new Entity("child"); + + assertNull(parent.findChildEntity(child.getEntityId()), "The child object should match the one found."); + + } + + +} + + diff --git a/entity-component-system/src/test/java/com/iluwatar/GameSystemTest.java b/entity-component-system/src/test/java/com/iluwatar/GameSystemTest.java new file mode 100644 index 000000000000..454526354425 --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/GameSystemTest.java @@ -0,0 +1,102 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + + class GameSystemTest { + + private GameSystem gameSystem; + private Entity entity1; + private Entity entity2; + private Entity childEntity; + + @BeforeEach + void setUp() { + gameSystem = new GameSystem(); + + entity1 = new Entity("Entity1"); + entity2 = new Entity("Entity2"); + childEntity = new Entity("ChildEntity"); + + entity1.addChild(childEntity); + + gameSystem.addEntity(entity1); + gameSystem.addEntity(entity2); + } + + @Test + void testAddEntity() { + assertEquals(3, gameSystem.getEntities().size(), "There should be three entities in the system."); + } + + @Test + void testRemoveEntity() { + gameSystem.removeEntity(entity2); + assertEquals(2, gameSystem.getEntities().size(), "Entity2 should be removed from the system."); + } + + @Test + void testGetSystemMatrix() { + // Set a mock transform for entity1 and childEntity + float[][] matrix1 = gameSystem.getSystemMatrix(entity1); + float[][] matrix2 = gameSystem.getSystemMatrix(childEntity); + + assertNotNull(matrix1, "System matrix for entity1 should not be null."); + assertNotNull(matrix2, "System matrix for childEntity should not be null."); + assertNotEquals(matrix1, matrix2, "Matrices should be different due to different transformations."); + } + + @Test + void testGetSystemPosition() { + float[] position1 = gameSystem.getSystemPosition(entity1); + float[] position2 = gameSystem.getSystemPosition(entity2); + + assertNotNull(position1, "Position for entity1 should not be null."); + assertNotNull(position2, "Position for entity2 should not be null."); + assertEquals(3, position1.length, "Position should be a 3D vector."); + assertEquals(3, position2.length, "Position should be a 3D vector."); + } + + @Test +void testSortEntitiesByDistance() { + + float[] referencePoint = {0.0f, 0.0f, 0.0f}; + + entity1.getTransformComponent().setPosition(new float[] {1.0f, 0.0f, 0.0f}); + entity2.getTransformComponent().setPosition(new float[] {3.0f, 0.0f, 0.0f}); + + gameSystem.sortEntitiesByDistance(referencePoint); + + List sortedEntities = gameSystem.getEntities(); + + assertEquals(entity2, sortedEntities.get(0), "Entity2 should be closer to the reference point than Entity1."); + assertEquals(entity1, sortedEntities.get(1), "Entity1 should be farther from the reference point than Entity2."); + } + } + diff --git a/entity-component-system/src/test/java/com/iluwatar/HealthComponentTest.java b/entity-component-system/src/test/java/com/iluwatar/HealthComponentTest.java new file mode 100644 index 000000000000..1a8086a5f743 --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/HealthComponentTest.java @@ -0,0 +1,123 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + + class HealthComponentTest { + + private HealthComponent healthComponent; + + @BeforeEach + void setUp() { + healthComponent = new HealthComponent(100); + } + + @Test + void testInitialHealth() { + assertEquals(100, healthComponent.getCurrentHealth(), "Initial health should be 100."); + } + + @Test + void testApplyDamage() { + healthComponent.applyDamage(30); + assertEquals(70, healthComponent.getCurrentHealth(), "Health should decrease by 30 after damage."); + + healthComponent.applyDamage(100); + assertEquals(0, healthComponent.getCurrentHealth(), "Health should not go below 0."); + } + + @Test + void testHeal() { + healthComponent.applyDamage(50); + healthComponent.heal(30); + assertEquals(80, healthComponent.getCurrentHealth(), "Health should increase by 30 after healing."); + + healthComponent.heal(50); + assertEquals(100, healthComponent.getCurrentHealth(), "Health should not exceed maximum (100)."); + } + @Test + void testUpdateFunction() { + healthComponent = new HealthComponent(100); + + assertDoesNotThrow(() -> healthComponent.update(1.0f), "update function should not throw an exception"); + } + + @Test + void testGetMaxHealth() { + HealthComponent testHealthComponent = new HealthComponent(100f); + + assertEquals(100f, testHealthComponent.getMaxHealth(), "Max health should be 100."); + } + + @Test + void testSetMaxHealth() { + HealthComponent testHealthComponent = new HealthComponent(100f); + testHealthComponent.setMaxHealth(120f); + + assertEquals(120f, testHealthComponent.getMaxHealth(), "Max health should be updated to 120."); + } + + @Test + void testIsAlive() { + + HealthComponent testHealthComponent = new HealthComponent(100f); + assertTrue( testHealthComponent.isAlive(), "Entity should be alive initially."); + testHealthComponent.applyDamage(100f); + + assertFalse( testHealthComponent.isAlive(), "Entity should be dead after taking 100 damage."); + } + + @Test + void testSetAlive() { + + HealthComponent testHealthComponent = new HealthComponent(100f); + assertTrue( testHealthComponent.isAlive(), "Entity should be alive initially."); + testHealthComponent.setAlive(false); + + assertFalse( testHealthComponent.isAlive(), "Entity should be dead after setting alive to false."); + } + + @Test + void testSetCurrentHealth() { + HealthComponent testHealthComponent = new HealthComponent(100f); + testHealthComponent.setCurrentHealth(80f); + + assertEquals(80f, testHealthComponent.getCurrentHealth(), "Current health should be updated to 80."); + } + @Test + void testHealthCannotGoAboveMax() { + healthComponent.heal(150); + assertEquals(100, healthComponent.getCurrentHealth(), "Health should not exceed the max value (100)."); + } + + @Test + void testHealthCannotGoBelowZero() { + healthComponent.applyDamage(200); + assertEquals(0, healthComponent.getCurrentHealth(), "Health should not go below 0."); + } +} diff --git a/entity-component-system/src/test/java/com/iluwatar/TransformComponentTest.java b/entity-component-system/src/test/java/com/iluwatar/TransformComponentTest.java new file mode 100644 index 000000000000..efbb0bac5bcf --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/TransformComponentTest.java @@ -0,0 +1,104 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + class TransformComponentTest { + + private TransformComponent transform; + + @BeforeEach + void setUp() { + transform = new TransformComponent(new float[]{0.0f, 0.0f, 0.0f}, + new float[]{0.0f, 0.0f, 0.0f}, new float[]{1.0f, 1.0f, 1.0f}); + } + + + @Test + void testTransformComponentConstructor() { + TransformComponent testTransform = new TransformComponent(); + + float[] expectedPosition = new float[]{0.0f, 0.0f, 0.0f}; + float[] expectedRotation = new float[]{0.0f, 0.0f, 0.0f}; + float[] expectedScale = new float[]{1.0f, 1.0f, 1.0f}; + + assertArrayEquals(expectedPosition, testTransform.getPosition(), "Position should be initialized to [0.0f, 0.0f, 0.0f]"); + assertArrayEquals(expectedRotation, testTransform.getRotation(), "Rotation should be initialized to [0.0f, 0.0f, 0.0f]"); + assertArrayEquals(expectedScale, testTransform.getScale(), "Scale should be initialized to [1.0f, 1.0f, 1.0f]"); + } + + @Test + void testGetPosition() { + float[] position = transform.getPosition(); + + assertArrayEquals(new float[]{0.0f, 0.0f, 0.0f}, position, "The position should be initialized correctly."); + } + + @Test + void testSetPosition() { + transform.setPosition(new float[]{10.0f, 20.0f, 30.0f}); + + assertArrayEquals(new float[]{10.0f, 20.0f, 30.0f}, transform.getPosition(), "Position should be updated correctly."); + } + + @Test + void testGetRotation() { + float[] rotation = transform.getRotation(); + + assertArrayEquals(new float[]{0.0f, 0.0f, 0.0f}, rotation, "The rotation should be initialized correctly."); + } + + @Test + void testSetRotation() { + transform.setRotation(new float[]{90.0f, 0.0f, 0.0f}); + + assertArrayEquals(new float[]{90.0f, 0.0f, 0.0f}, transform.getRotation(), "Rotation should be updated correctly."); + } + + @Test + void testGetScale() { + float[] scale = transform.getScale(); + + assertArrayEquals(new float[]{1.0f, 1.0f, 1.0f}, scale, "The scale should be initialized correctly."); + } + + @Test + void testUpdateFunction() { + TransformComponent testTransform = new TransformComponent(); + + assertDoesNotThrow(() -> testTransform.update(1.0f), "update function should not throw an exception"); + } + + @Test + void testSetScale() { + transform.setScale(new float[]{2.0f, 2.0f, 2.0f}); + + assertArrayEquals(new float[]{2.0f, 2.0f, 2.0f}, transform.getScale(), "Scale should be updated correctly."); + } +} diff --git a/entity-component-system/src/test/java/com/iluwatar/VelocityComponentTest.java b/entity-component-system/src/test/java/com/iluwatar/VelocityComponentTest.java new file mode 100644 index 000000000000..1eb4ba6e8479 --- /dev/null +++ b/entity-component-system/src/test/java/com/iluwatar/VelocityComponentTest.java @@ -0,0 +1,98 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + class VelocityComponentTest { + + private VelocityComponent velocity; + + @BeforeEach + void setUp() { + velocity = new VelocityComponent(1.0f, 0.0f, 0.0f); + } + + @Test + void testApplyForce() { + velocity.applyForce(2.0f, 0.0f, 0.0f); + + assertEquals(3.0f, velocity.getVelocityX(), "VelocityX should increase after applying force."); + } + + @Test + void testApplyFriction() { + velocity.applyFriction(0.1f); // Applying friction coefficient of 0.1 + + assertEquals(0.9f, velocity.getVelocityX(), "VelocityX should be reduced by the friction coefficient."); + } + + @Test + void testReset_shouldResetVelocityToZero() { + + velocity.setVelocityX( 5.0f); + velocity.setVelocityY( 10.0f); + velocity.setVelocityZ( 15.0f); + velocity.resetVelocity(); + + assertEquals(1.0f, velocity.getVelocityX(), "Velocity X should be reset to 1.0f"); + assertEquals(0.0f, velocity.getVelocityY(), "Velocity Y should be reset to 0"); + assertEquals(0.0f, velocity.getVelocityZ(), "Velocity Z should be reset to 0"); + } + + @Test + void testUpdateVelocity() { + float deltaTime = 1.0f / 60.0f; + + float initialVelocityX = velocity.getVelocityX(); + velocity.update(deltaTime); + + assertTrue(velocity.getVelocityX() > initialVelocityX, "VelocityX should increase after updating."); + } + + @Test + void testSetVelocityX() { + + velocity = new VelocityComponent(1.0f, 0.0f, 0.0f); + velocity.setVelocityX(5.0f); + assertEquals(5.0f, velocity.getVelocityX(), "The velocityX should be set to 5.0f"); + + velocity.setVelocityX(10.0f); + assertEquals(10.0f, velocity.getVelocityX(), "The velocityX should now be set to 10.0f"); + } + @Test + void testSetVelocityZ() { + + velocity = new VelocityComponent(1.0f, 0.0f, 0.0f); + velocity.setVelocityZ(5.0f); + assertEquals(5.0f, velocity.getVelocityZ(), "The velocityZ should be set to 5.0f"); + + velocity.setVelocityZ(10.0f); + assertEquals(10.0f, velocity.getVelocityZ(), "The velocityZ should now be set to 10.0f"); + } +} diff --git a/pom.xml b/pom.xml index 5cc512b7de94..deb4514b7e6e 100644 --- a/pom.xml +++ b/pom.xml @@ -223,6 +223,7 @@ templateview money table-inheritance + entity-component-system diff --git a/update-header.sh b/update-header.sh index 48da4dcd6125..568d00d52a03 100755 --- a/update-header.sh +++ b/update-header.sh @@ -1,4 +1,29 @@ #!/bin/bash +# +# This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). +# +# The MIT License +# Copyright © 2014-2022 Ilkka Seppälä +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + # Find all README.md files in subdirectories one level deep # and replace "### " with "## " at the beginning of lines