Package aspect.entity

Source Code of aspect.entity.Entity

/*
* Copyright (C) 2014 MillerV
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package aspect.entity;

import aspect.event.EntityEvent;
import aspect.util.Angles;
import aspect.util.Vector3;
import aspect.entity.behavior.Behavior;
import aspect.render.ViewModel;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.LinkedList;
import static aspect.core.AspectRenderer.*;
import aspect.physics.Collider;
import aspect.physics.Motion;
import aspect.physics.RigidBody;
import aspect.util.Matrix4x4;
import aspect.util.Transform;
import aspect.world.World;

/**
* An object in the 3D or 2D world. Update and render behavior is typically
* defined by Components rather than by overriding methods in the Entity itself.
*
* @author MillerV
*/
public class Entity {

    /**
     * The child Entities. Their update() and draw() methods will be called when
     * this Entity's update() and draw() methods are called, and they will be
     * drawn relative to the position of this Entity. Entities also function as
     * CameraViewpoints.
     */
    public final LinkedList<Entity> children;

    private final LinkedList<Behavior> behaviors;

    /**
     * The colliders used in this Entity's collision detection. It is not
     * recommended that you add to this list yourself.
     *
     * @see aspect.entity.component.CmpntCollider
     */

    public final Transform transform;

    /**
     * The container that holds this Entity.
     */
    public World container;

    /**
     * The name of this Entity, which is returned by it's toString() method.
     */
    public String name;

    /**
     * Whether this Entity is solid. Setting this to false does not prevent
     * collision detection, but could be used to change collision handling
     * behavior.
     */
    public boolean solid = true;
   
    private ViewModel viewModel;
    private RigidBody rigidBody;
    private Collider collider;

    /**
     * Create a new Entity.
     */
    public Entity() {
        children = new LinkedList<>();
        behaviors = new LinkedList<>();
        transform = new Transform();
    }

    /**
     * Create a new Entity with the specified ViewModel. ViewModels can also be
     * added using a CmpntViewModel.
     *
     * @param viewModel the initial ViewModel
     * @see CmpntViewModel
     */
    public Entity(ViewModel viewModel) {
        this();
        addBehavior(viewModel);
    }

    /**
     * Add a Component to this Entity.
     *
     * @param cmpnt the Component to add
     */
    public final void addBehavior(Behavior cmpnt) {
        behaviors.add(cmpnt);
        cmpnt.ent = this;
        cmpnt.onAdd();
       
        if (viewModel == null && cmpnt instanceof ViewModel) {
            viewModel = (ViewModel)cmpnt;
        } else if (rigidBody == null && cmpnt instanceof RigidBody) {
            rigidBody = (RigidBody)cmpnt;
        } else if (collider == null && cmpnt instanceof Collider) {
            collider = (Collider)cmpnt;
        }
    }

    /**
     * Construct a new Component of the given class and add it to this Entity.
     * This is very inefficient compared to adding a pre-constructed Component,
     * and therefore is deprecated. Use {@link #addBehavior(aspect.entity.behavior.Behavior)
     * }
     *
     * @param c the Class of the Component to add
     * @param args the arguments to pass to the Component's constructor
     * @deprecated
     */
    @Deprecated
    public final void addBehavior(Class<? extends Behavior> c, Object... args) {
        Constructor cons = null;
        for (Constructor check : c.getConstructors()) {
            boolean canUse = true;
            Class[] argTypes = check.getParameterTypes();
            if (argTypes.length == args.length) {
                for (int i = 0; i < args.length; i++) {
                    if (!argTypes[i].isAssignableFrom(args[i].getClass())) {
                        canUse = false;
                        break;
                    }
                }

                if (canUse) {
                    cons = check;
                    break;
                }
            }
        }

        try {
            if (cons == null) {
                throw new NoSuchMethodException();
            }
            Behavior component = (Behavior) cons.newInstance(args);
            addBehavior(component);
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Remove the specified Behavior.
     *
     * @param b the Behavior to remove
     */
    public void removeBehavior(Behavior b) {
        b.onRemove();
        b.ent = null;
        behaviors.remove(b);
       
        if (viewModel != null && b instanceof ViewModel) {
            viewModel = null;
        } else if (rigidBody != null && b instanceof RigidBody) {
            rigidBody = null;
        } else if (collider != null && b instanceof Collider) {
            collider = null;
        }
    }

    /**
     * Remove a Behavior of the specified class, or whose class is a subclass of
     * the specified class.
     *
     * @param c the Class of the Behavior to remove
     */
    public void removeBehavior(Class c) {
        if (!Behavior.class.isAssignableFrom(c)) {
            return;
        }

        Behavior toRemove = null;

        for (Behavior cmpnt : behaviors) {
            if (c.isInstance(cmpnt)) {
                toRemove = cmpnt;
                break;
            }
        }

        if (toRemove != null) {
            removeBehavior(toRemove);
        }
    }

    /**
     * Get a Behavior of the specified class.
     *
     * @param <C> the type that will be returned
     * @param c the Class to search for
     * @return the Behavior or null if that Behavior was not found
     */
    public <C extends Behavior> C getBehavior(Class<C> c) {
        for (Behavior cmpnt : behaviors) {
            if (c.isInstance(cmpnt)) {
                return (C) cmpnt;
            }
        }

        return null;
    }

    public ViewModel viewModel() {
        return viewModel;
    }

    public Collider collider() {
        return collider;
    }

    public Motion motion() {
        return getBehavior(Motion.class);
    }

    public RigidBody rigidBody() {
        return rigidBody;
    }
   
    public void onRemove() {
        for (Behavior behavior : behaviors) {
            behavior.onRemove();
        }
    }

    /**
     * Update all components and children of this Entity.
     */
    public void update() {
        for (Behavior b : behaviors) {
            b.ent = this;
            b.update();
        }

        for (Entity child : children) {
            child.transform.global = transform.concat(child.transform);
            child.update();
        }
    }

    /**
     * Add the specified Entity as a child of this Entity.
     *
     * @param child the Entity to add as a child
     */
    public void addChild(Entity child) {
        children.add(child);
    }

    /**
     * Render all components and children of this Entity.
     */
    public void render() {

        for (Behavior b : behaviors) {
            b.ent = this;
            b.render();
        }

        for (Entity child : children) {
            child.transform.global = transform.global.concat(child.transform);
            child.render();
        }
    }

    /**
     * Remove this Entity from it's container, if the container is not null.
     */
    public void destroy() {
        if (container != null) {
            container.remove(this);
        }
       
        for (Behavior behavior : behaviors) {
            behavior.ent = this;
            behavior.onEntityDestroy();
        }
    }

    /**
     * Fire an EntityEvent with the given name and data, which will be passed to
     * all components of this Entity.
     *
     * @param name the event name
     * @param args the event data
     */
    public void fireEvent(String name, Object... args) {
        fireEvent(new EntityEvent(Behavior.class, name, args));
    }

    /**
     * Fire an EntityEvent, which will be passed to all Components of this
     * Entity that are instances of the event's target class.
     *
     * @param event the EntityEvent to fire
     */
    public void fireEvent(EntityEvent event) {
        for (Behavior cmpnt : behaviors) {
            cmpnt.ent = this;
            event.fire(cmpnt);
        }
    }

    @Override
    public String toString() {
        if (name != null) {
            return name;
        } else {
            return super.toString();
        }
    }
}
TOP

Related Classes of aspect.entity.Entity

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.