Code Monkey home page Code Monkey logo

ashley's Introduction

GitHub Actions build status

Sonatype Nexus (Releases) Sonatype Nexus (Snapshots)

A tiny entity framework written in Java. It's inspired by frameworks like Ash (hence the name) and Artemis. Ashley tries to be a high-performance entity framework without the use of black-magic and thus making the API easy and transparent to use.

Ashley is awesome, if you don't believe it, check out some games made with it!

Ashley lives under the libGDX family but it does not force you to use that specific framework if you do not wish to do so.

libGDX Discord : Discord Chat

Get started

News and community

Stay up to date in Ashley matters by following @d_saltares and reading saltares.com. Check the libGDX blog as well for additional updates.

Report issues

Something not working quite as expected? Do you need a feature that has not been implemented yet? Check the issue tracker and add a new one if your problem is not already listed. Please try to provide a detailed description of your problem, including the steps to reproduce it.

Contribute

Awesome! If you would like to contribute with a new feature or submit a bugfix, fork this repo and send a pull request. Please, make sure all the unit tests are passing before submitting and add new ones in case you introduced new features.

License

Ashley is licensed under the Apache 2 License, meaning you can use it free of charge, without strings attached in commercial and non-commercial projects. We love to get (non-mandatory) credit in case you release a game or app using Ashley!

ashley's People

Contributors

adeluiz avatar andresaraujo avatar badlogic avatar brentdewe avatar carlislefox avatar crykn avatar dfumosa avatar dsaltares avatar dwursteisen avatar fabiitch avatar jkly avatar junkdog avatar lukz avatar mars3142 avatar metaphore avatar mgsx-dev avatar mrstahlfelge avatar nauktis avatar quillraven avatar ram042 avatar sgtcodfish avatar sonirico avatar stbachmann avatar thealexhoar avatar tom-ski avatar undefinedhuman avatar viet54 avatar vlaaad avatar warmwaffles avatar xaguzman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ashley's Issues

Issue Deleting Entities During System Update and Using Listeners in 1.2

Hi,

I have an unusual issue discovered in Ashley 1.2. I discovered it while trying to incorporate the new Family option for the Listeners. I started getting NullPointerExceptions when the Entity entered the entityRemoved() method of the Listener. I later determined that a component was always missing if the Entity was deleted during the update. I am not sure if this is a bug - but it does appear to be inconsistent -since the component is present when deleted outside of the System update.

Here is an example of the issue:

package com.badlogic.ashley.tests;

import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.ashley.core.EntitySystem;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.core.PooledEngine;
import com.badlogic.ashley.tests.components.MovementComponent;
import com.badlogic.ashley.tests.components.PositionComponent;
import com.badlogic.ashley.utils.ImmutableArray;
import com.badlogic.gdx.utils.Array;


public class DeleteDuringUpdateListenerTest
{


    public static void main(String[] args)
    {
        PooledEngine engine = new PooledEngine();

        CombinedSystem combinedSystem = new CombinedSystem(engine);

        engine.addSystem(combinedSystem);
        engine.addEntityListener(Family
                .getFor(PositionComponent.class), new MyPositionListener());


        for (int i = 0; i < 10; i++)
        {
            Entity entity = engine.createEntity();
            entity.add(new PositionComponent(10, 0));
            entity.add(new MovementComponent(10, 2));

            engine.addEntity(entity);

        }

        log("system has: " + combinedSystem.allEntities.size() + " entities.");

        for (int i = 0; i < 10; i++)
        {
            engine.update(0.25f);

        }
        engine.removeAllEntities();
    }

    public static class MyPositionListener implements EntityListener
    {
        public static ComponentMapper<PositionComponent> positionMapper = ComponentMapper.getFor(PositionComponent.class);

        int counter = 0;

        @Override
        public void entityAdded(Entity entity)
        {

        }

        @Override
        public void entityRemoved(Entity entity)
        {

            PositionComponent position = positionMapper.get(entity);
            if (position == null)
            {
                log("there is no position component while removing, is this a bug?");
            }
            else
            {
                log("position component detected while removing");
            }

        }

    }

    public static class CombinedSystem extends EntitySystem
    {
        PooledEngine engine;
        protected CombinedSystem(PooledEngine engine)
        {
            this.engine = engine;
        }

        public ImmutableArray<Entity> allEntities;
        int counter = 0;


        @Override
        public void addedToEngine(Engine engine)
        {
            allEntities = engine.getEntitiesFor(Family
                    .getFor(PositionComponent.class));
        }

        @Override
        public void removedFromEngine(Engine engine)
        {
        }

        @Override
        public void update(float deltaTime)
        {
            //delete some of the entities during the update - note: this is when the 
            //bug (or feature) occurs!
            if (counter >= 6 && counter <=8)
            {
                engine.removeEntity(allEntities.get(2));
            }
            counter++;   
        }  
    }

    public static void log(String string)
    {
        System.out.println(string);
    }
}

output:
system has: 10 entities.
there is no position component while removing, is this a bug?
there is no position component while removing, is this a bug?
there is no position component while removing, is this a bug?
position component detected while removing
position component detected while removing
position component detected while removing
position component detected while removing
position component detected while removing
position component detected while removing
position component detected while removing

Thanks,

Dana

ComponentMapper - Is there any way to avoid creating these?

It seems weird to have to instantiate a third object to pull components out of entities. I am still learning about the ECS methodologies, but a method on the Entity class for retrieving components seems a lot more straightforward. Regardless, keep up the good work!

Double brace initialization not working

I just did a quick test with ashley today, and couldn't get it working. Engine.getEntitiesFor simply didn't return any entities.
After some time pulling my hair I found out that it was the double brace initialization of my components that was the cause. I had the following:

Entity e = new Entity();
e.add(new Position() {{ x = 10; y = 10; }});

Once I changed it to this, Engine.getEntitiesFor started returning the entities I expected:

Entity e = new Entity();
e.add(new Position(100, 100));

It is not a major thing. I just thought I'd let you guys know.
Thanks for the fine work :)

Daniel

Usage of java.util.BitSet

Hi!

I just stumbled upon this project and like it! One thought though: I once wrote a simple entity system too and had problems compiling it for HTML via GWT because apparantly GWT does not have an equivalent for java.util.BitSet. There is a GWT bug report here but I think it is not closed yet. Eventually I switched to my own BitSet implementation but there is also an implementation in the GDX sources called Bits. I have no PR for you :(

Michael

entity.add with PooledEngine

Correct me if I'm wrong:
When you add a component to an entity, while a component of that type already exists, the PooledEngine will not know about it, thus the old component will not be freed correctly.

First stable release?

Where does Ashley stand on the road to its first release? I'm really interested in integrating it into my projects as a (mostly) drop-in Artemis replacement, though I'm sort of leery about doing so until there's a stable API release. What's left to get done before that happens?

Performance improvements

This is a call to all Ashley contributors. After all this bug fixing it seems we have a pretty stable, easy to use ECS. Now it's time to focus on performance.

Any performance improvement PRs will be most welcome, especially if they do not change the API and do not add any extra complexity to our users.

Thanks!

Make IteratingSystem's entities member field accessible from subclass

It would be useful to have access to the private member field, entities, from within subclasses of IteratingSystem.

Currently, in some of my classes that extend IteratingSystem, I override update() to carry out some initialisation before processEntity() gets called for each entity. I'd like to skip the initialisation altogether for each engine update that has no relevant entities to process. However, with the entities member field being private, I can't simply check with entities.size().

Could entities be made protected, to allow a subclass to access it directly? Or if not, maybe a protected getter?

License?

Hello! I'm interested in using ashley in my game, but I noticed the lack of a license. Am I missing something? If not, can I recommend the MIT License?

Cheers!

Ability to group entity systems so different groupings can be updated independantly

I have a number of systems that update various game physics, and another bunch of systems to take care of rendering. I need to call update() on my rendering systems every 1/60 seconds but only need to update the physics systems every 1/30 seconds. For arguments sake, there may be other logical groupings of systems that should be updated at a totally different frequency.

As it is at the moment, my choices seem to be:-

  1. Call Engine.update() in my game loop so all systems update at the same frequency but add logic in my individual EntitySystem.update() methods to decide whether or not to actually do anything this time around.

  2. Enable / disable individual systems with EntitySystem.setProcessing(), one by one, in each game loop iteration as needed.

  3. Don't call Engine.update() at all and instead call EntitySystem.update() directly on each individual system as needed.

I'm currently opting for option 3 but this seems a little bit clumsy, or at least longwinded, to me. I think a nicer solution would be to have something like an EntitySystemGroup so at the time of adding a system to the engine we can specify which group it belongs to, and then in the game loop trigger an update on a specific group of systems with something like Engine.update(deltaTime, entitySystemGroup).

What do people think? I appreciate Ashley is really lightweight and simple to use so maybe this just overcomplicates things, but I'd guess this would be quite a popular addition seeing as physics and rendering are often called with different time steps.

maven integration

It would be really good, if you would upload your library to mavencentral, so it can be used in gradle as dependency. Maybe you can combine this with travis.

Ashley Family.getFamilyFor & ComponentType.getBitsFor Issue

Hi,

To expain my issue I'll give you an example :

      PooledEngine engine = new PooledEngine();
      Entity entity;
      for (int i = 0; i < 10; i++) {
         entity = engine.createEntity();
         entity.add(engine.createComponent(CompA.class));
         if(i>4)
            entity.add(engine.createComponent(CompB.class));
         engine.addEntity(entity);
      }

With this code I have 5 entities with the component A et 5 entities with the components A and B.

To see my entities I use :

ImmutableIntMap<Entity> lstWithCompAOnly = engine.getEntitiesFor(Family.getFamilyFor(ComponentType.getBitsFor(CompA.class),new Bits(),ComponentType.getBitsFor(CompB.class)));
ImmutableIntMap<Entity> lstWithCompB = engine.getEntitiesFor(Family.getFamilyFor(CompB.class));

And the sizes are 5 and 5 => it is OK.

Now I do that :

for (Entry<Entity> entry : lstWithCompB)
         entry.value.remove(CompB.class);

I have lstWithCompB with 0 entity => Its OK because no entity has the Component B anymore.
But I expected to have : lstWithCompAOnly with 10 entities because all my entities have the component A without the component B. => I have still 5 entities :(

Why it do that ?
Thank you

Exclude filter does not work when a component has been added after the Entity has been added to the Engine

+I just confirmed that this has been fixed in Ashley 1.2.0.. It is probably a duplicate of the other filter issue.

Hi, The exclude filter does not work in Ashley when the component to be excluded has been added after the Entity has been added to the Engine.

package com.badlogic.ashley.tests;

import com.badlogic.ashley.core.ComponentType;
import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntitySystem;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.core.PooledEngine;
import com.badlogic.ashley.tests.components.MovementComponent;
import com.badlogic.ashley.tests.components.PositionComponent;
import com.badlogic.ashley.utils.ImmutableArray;


public class ExcludeTest
{
    public static void main(String[] args)
    {
        PooledEngine engine = new PooledEngine();

        CombinedSystem combinedSystem = new CombinedSystem();
        engine.addSystem(combinedSystem);

        for (int i = 0; i < 10; i++)
        {
            Entity entity = engine.createEntity();
            entity.add(new PositionComponent(10, 0));
            engine.addEntity(entity);

            //bug occurs when a new component is added to the Entity
            //after the Entity has been added to the engine             
            if (i > 0)
                entity.add(new MovementComponent(10, 2));

        }

        log("system has: " + combinedSystem.allEntities.size()
                + " allEntities entities.");


        log("system has: " + combinedSystem.entitiesExcludingMovement.size()
                + " entitiesExcludingMovement entities.");

        for (int i = 0; i < 10; i++)
        {
            engine.update(0.25f);
        }
    }

    public static class CombinedSystem extends EntitySystem
    {
        public ImmutableArray<Entity> allEntities;
        public ImmutableArray<Entity> entitiesExcludingMovement;


        @Override
        public void addedToEngine(Engine engine)
        {
            allEntities = engine.getEntitiesFor(Family
                    .getFor(PositionComponent.class));

            entitiesExcludingMovement =  engine.getEntitiesFor(Family.getFor(ComponentType
                    .getBitsFor(PositionComponent.class),
                    ComponentType.getBitsFor(PositionComponent.class),
                    ComponentType.getBitsFor(MovementComponent.class)));
        }

        @Override
        public void removedFromEngine(Engine engine)
        {
        }
    }

    public static void log(String string)
    {
        System.out.println(string);
    }
}

actual test output:
system has: 10 allEntities entities.
system has: 10 entitiesExcludingMovement entities.

expected output:
system has: 10 allEntities entities.
system has: 1 entitiesExcludingMovement entities.

Iterate over systems in engine? And disable them?

Hello,

I was going to iterate over systems and disable them and realized that there's not a quick way to do either of these things. How can I generically do this in a quick manner?

My use case is, I've just opened a UI, and I want to disable most of my systems but leave my user interface system running. So, I figured that I would iterate over all systems and disable anything that wasn't the UI system. But there didn't seem to be a clear way to do this.

If this was something ashley wanted to implement, what would we want the API to look like?

Also, I noticed there is a system method checkProcessing() that always returns true - currently I've extended the system class to leverage it, but I don't see any reason why there's not enable()/disable() or setProcessing(bool) methods on the system base class.

Depend on gdx-core

Until we move out the utils from core :) The duplication of utility classes is suboptimal atm.

API simplifications

Hi guys, what do you think about doing the following.

  • Rename Family.getFamilyFor() to Family.getFor(). It will be homogeneous with the new ComponentMapper class.
  • Make Family a final class. I don't see the use case to extend it at all.

Complete wiki

TODO:

  • About Entity Systems
  • Benchmarks
  • Update the demo to work with the latest changes

Add entities to families on removal of component (and reversal too)

Not sure I'm doing things correctly but this is what I've done:
I have a RenderingSystem which processes all the entities that have a Renderable and a Position component BUT NOT have an InvisibleComponent. Yeah, I know, that's a bit tricky but it's just an example.
What's the problem? That I have an entity which should become invisible and I do that by adding to it the InvisibleComponent. But it remain on screen, it doesn't disappear...

Debugging I've noticed this, not sure it's the cause but I'd like to contribute. In the Engine class, on the componentAdded listener, only new entities get added to the families that match, there seems to be no logic to remove entities on the addition of a component (the InvisibleComponent for example). Here is the code:

private void componentAdded(Entity entity){
    for (Entry<Family, Array<Entity>> entry : families.entries()) {
        if(!entity.getFamilyBits().get(entry.key.getIndex())){
            if(entry.key.matches(entity)){
                entry.value.add(entity);
                entity.getFamilyBits().set(entry.key.getIndex());
            }
        }   
    }
}

On the other side, in the componentRemoved listener, entities get only removed from each family if they don't match. What is missing is the adding of new entities if the family matches.

GWT compatibility

The commit 30bd379 adds a gwt.xml file to try make Ashley GWT compatible.

To test this, I've done the following:

  1. Created a Libgdx project with the gdx-setup tool
  2. Added the following dependencies to the core project: compile fileTree(dir: 'libs', include: '*.jar')
  3. Run the jar task in Ashley and placed the jar file inside the Libgdx core libs folder.
  4. Add the following line to GdxDefinition.gwt.xml and GdxDefinitionSuperdev.gwt.xml: <inherits name='com.badlogic.ashley_gwt' />
  5. Run gwtSuperDev in the Libgdx html project.

I'm getting the following error:

Compiling module com.siondream.ashley.GdxDefinitionSuperdev
   [ERROR] Errors in 'file:/E:/projects/ashley-test/core/src/com/siondream/ashley/AshleyTest.java'
      [ERROR] Line 16: No source code is available for type com.badlogic.ashley.core.Component; did you forget to inherit a required module?
      [ERROR] Line 23: No source code is available for type com.badlogic.ashley.core.Engine; did you forget to inherit a required module?
      [ERROR] Line 25: No source code is available for type com.badlogic.ashley.core.Entity; did you forget to inherit a required module?

This is weird because it's not complaining about the gwt.xml file not existing and yet it fails to find the classes.

This guide illustrates the process of how to make libraries GWT compatible.

Any ideas guys? I would very much appreciate a PR that solves this issue!

PooledEntity: entity not fully reset

I posted this in another issue thread (#69 now closed) but I thought it was better to open a separate issue.

When an entity is added to an Engine, the engine attach to the Entity two listeners and one handler (componentAdded, componentRemoved and componentOperationHandler):

public void addEntity(Entity entity){
        entities.add(entity);

        updateFamilyMembership(entity);

        entity.componentAdded.add(componentAdded);
        entity.componentRemoved.add(componentRemoved);
        entity.componentOperationHandler = componentOperationHandler;

        Object[] items = listeners.begin();
        for (int i = 0, n = listeners.size; i < n; i++) {
            EntityListener listener = (EntityListener)items[i];
            listener.entityAdded(entity);
        }
        listeners.end();        
    }

These fields should be reset when the entity is put back in the pool or listeners will be duplicated (+1 each time the entity is added to the engine) while the componentOperationHandler will prevent new components from being added directly (the addition will be posticipated) during a System update, even if the entity has not yet been added to the engine. For this last point I'm referring to the add method of Entity:

public Entity add(Component component){
        if (componentOperationHandler != null) {
            componentOperationHandler.add(this, component);
        }
        else {
            addInternal(component);
        }
        return this;
    }

Actually I stumbled in this last issue and then I also noticed the duplicated listeners issue.

Just to make it more clear: I found this issue because I did the following: I created an entity (and debugging I've seen that it was taken by the pool), then I added a few components to it and finally I tried to get one of the just added components with a ComponentMapper but I got a null reference.

Component as an interface?

Hi,

In my project, due to the fact that components are created through composition, I am frequently using patterns like these: positionComponent.position, radiusComponent.value etc. This has made me curious why Component is implemented as an abstract class rather than an interface. If it was an interface, it would be possible to create components from existing types, for example:

class PositionComponent
    extends Vector2
    implements Component
{

}

Was this disallowed as a design decision, or is there some other reason for it?

(I've made the relevant changes in my fork if you wanted to look at them but it was literally just changing "abstract class" to "interface" in Component.java and "extends" to "implements" in tests.)

(Of course, I understand if this being an interface is just too much of a limit on future development.)

Cat

Readme.md addition for clarity.

Groovy
Gradle dependency declaration
compile "com.badlogicgames.ashley:ashley:1.0.1"

This section should mention for libgdx projects to add the gradle dependency to the build.gradle in your -core project for clarity.

Family match failure

I have the following tests:

public static void test1() {

                System.out.println("running test1");
        PooledEngine engine = new PooledEngine();

        engine.addSystem(new TestSystemA("A"));
        engine.addSystem(new TestSystemC("C"));

        Entity e = engine.createEntity();
        e.add(new TestComponentC());
        e.add(new TestComponentA());

        Family f = Family.getFor(
                ComponentType.getBitsFor(TestComponentC.class),
                ComponentType.getBitsFor(),
                ComponentType.getBitsFor(TestComponentA.class));
        System.out.println(f.matches(e));
        Assert.assertFalse(f.matches(e));
    }

    public static void test2() {

        System.out.println("running test2");
        PooledEngine engine = new PooledEngine();

        Entity e = engine.createEntity();
        e.add(new TestComponentC());
        e.add(new TestComponentA());

        engine.addSystem(new TestSystemA("A"));
        engine.addSystem(new TestSystemC("C"));

        Family f = Family.getFor(
                ComponentType.getBitsFor(TestComponentC.class),
                ComponentType.getBitsFor(),
                ComponentType.getBitsFor(TestComponentA.class));
        System.out.println(f.matches(e));
        Assert.assertFalse(f.matches(e));
    }

when i am running test2, everything is fine. But when i am running test1, the family matches the entity.

I am using version 1.3.0

Added filtering to Family

Hello, I just thought having the ability to filter on the family could be a useful feature. I am migrating from artemis to ashley some old code and I found the need for this.

I forked and pretty much adapted artemis's implementation. Would you be interested in such a feature? (I know I should have raised a PR instead...I am just not at my home computer now and thought that asking about it woul be nice)

IteratingSystem

The entities array is populated when you add the system but unless I'm missing something it never updates when entities are added or removed. This means that the system tries to process entities that are now null and crashes. Using the entity listener interface should fix this.

Let me know if I'm mistaken and if not I'll fix it and submit a pull request.

Entity with removed component keeps appearing in Engine.getEntitiesFor the deleted component

1 - create entity
2 - add entity of type X.class to entity
3 - add entity to engine
4 - call Engine.getEntitiesFor(Family.getFamilyFor(X.class))
5a - call Engine.removeEntity on the entity
5b - call Entity.removeComponent on the component
6 - repeat step 4, the entity will be returned when it shouldn't

Either with doing 5 or 5b, every other call to Engine.getEntitiesFor(Family.getFamilyFor(X.class)) will return the IntMap with the deleted entity/entity without the component

Clear PooledEngine

Would be great to add public clear method to PooledEngine that would clear entity and component pools of free objects.

Question about implementation of behavior trees in ashley

Hi,
I see in pull request there is an implementation of finite state machine proposed.
Do you think it's possible in a near future to see an implementation of the more flexible behavior trees algorithm in the library ?
Thanks a lot,
SR

IllegalArgumentException when removing entity and then removing components

Hi!

i have made a litte test and i got an IllegalArgumentException. First i remove the entity and after this i remove some components from the entity.

public class Test {
    /**
     * @param args
     */
    public static void main(String[] args) {

        PooledEngine engine = new PooledEngine();

        engine.addSystem((new Issue206SystemTest()).new TestSystemA("A"));
        engine.addSystem((new Issue206SystemTest()).new TestSystemAB("AB"));

        Entity e = engine.createEntity();
        e.add(new TestComponentA());
        e.add(new TestComponentB());
        engine.addEntity(e);

        int d = 0;

        engine.update(d++);
        System.out.println(d + "=------------------------------------------");

        engine.update(d++);
        System.out.println(d + "=------------------------------------------");

        System.out.println(d + "= deleting " + e);
        engine.removeEntity(e);

        System.out.println(d + "= removing components from " + e);
        e.remove(TestComponentB.class);
        e.remove(TestComponentA.class);

        engine.update(d++);
        System.out.println(d + "=------------------------------------------");

    }

    public static class TestComponentA extends Component {
    }

    public static class TestComponentB extends Component {
    }

    public static class TestComponentC extends Component {
    }

    class TestSystemA extends IteratingSystem {

        private String name;

        public TestSystemA(String name) {
            super(Family.getFor(TestComponentA.class));
            this.name = name;
        }

        @Override
        public void processEntity(Entity e, float d) {
            System.out.println("System [" + name + "] processed: " + e);
        }

    }

    class TestSystemAB extends IteratingSystem {

        private String name;

        public TestSystemAB(String name) {
            super(Family.getFor(TestComponentA.class, TestComponentB.class));
            this.name = name;
        }

        @Override
        public void processEntity(Entity e, float d) {
            System.out.println("System [" + name + "] processed: " + e);
        }

    }

}

1=------------------------------------------
2=------------------------------------------
2= deleting com.badlogic.ashley.core.PooledEngine$PooledEntity@0
2= removing components from com.badlogic.ashley.core.PooledEngine$PooledEntity@0
Exception in thread "main" java.lang.IllegalArgumentException: object cannot be null.
at com.badlogic.ashley.core.PooledEngine$ComponentPools.free(PooledEngine.java:160)
at com.badlogic.ashley.core.PooledEngine$PooledEntity.remove(PooledEngine.java:113)
at com.krautfactory.tests.ashley.Test.main(Test.java:44)

Question about scala porting of ashley

Hi,

I'm just curious and really interested to make a port of ashley in scala in a near future.

Do you have information about somebody who already try to make such portage ?
Do you think this is possible to maintain compatibility with GWT in this case ?

Thanks a lot for your work
SR

Slight performance problem

Hi,

I've been playing around with the SpeedTest and especially with the NUMBER_ENTITIES values.
I noticed that when increasing it there are non linear increases in some of the monitored times.

Here are my observations:
Number of entities: 100000
Entities added time: 811ms
Component removed time: 2310ms
Component added time: 79ms
System processing times 31ms
Entity removed time: 6645ms

Number of entities: 200000
Entities added time: 1575ms
Component removed time: 13058ms
Component added time: 142ms
System processing times 47ms
Entity removed time: 33243ms

Number of entities: 1000000
Entities added time: 6115ms
Component removed time: 437466ms
Component added time: 588ms
System processing times 221ms
Entity removed time: 915162ms

I did a little investigation and found out that although these are commented to be not ordered:

public class Engine {
....
/** An unordered array that holds all entities in the Engine /
private Array entities;
/
* An unordered list of EntitySystem */
private Array systems;

they are created with the default constructor:
entities = new Array();
systems = new Array();
which makes them ordered and from there the problem emerges.
I changed the code like so:
entities = new Array(false, 16);
systems = new Array(false, 16);

After this change the times look like this:
Number of entities: 100000
Entities added time: 806ms
Component removed time: 1981ms
Component added time: 64ms
System processing times 31ms
Entity removed time: 140ms

Number of entities: 200000
Entities added time: 1401ms
Component removed time: 7753ms
Component added time: 118ms
System processing times 55ms
Entity removed time: 203ms

Number of entities: 1000000
Entities added time: 6252ms
Component removed time: 231751ms
Component added time: 578ms
System processing times 223ms
Entity removed time: 782ms

I saw com.badlogic.gdx.utils.Array.Array usage and creation in few other places but I am not sure whether it needs to be ordered or not.

I hope my findings helped.

Regards

PooledEngine and Engine: Entity removal inconsistency

On an entity removal request, the Engine class checks if any system is updating and, if it's the case, the removal is posticipated.

Engine code:

public void removeEntity(Entity entity){
        if (updating) {
            pendingRemovalEntities.add(entity);
        }
        else {
            removeEntityInternal(entity);
        }
    }

In the PooledEngine, the Engine behaviour is not taken into account and the entity is reset and put back into the pool.

PooledEngine code:

public void removeEntity(Entity entity){
        super.removeEntity(entity);

        if (ClassReflection.isAssignableFrom(PooledEntity.class, entity.getClass())) {
            PooledEntity pooledEntity = (PooledEntity) entity;
            entityPool.free(pooledEntity);
        }
    }

In my game I have an IteratingSystem which creates new entities and removes other entities. Suddenly I started to have strange behavior and I think that the reason relies in how the PooledEngine handles the pool.
This is the interesting code of my IteratingSystem:

public void processEntity(Entity entity, float deltaTime) {
        TimerComponent timerComp = timerMap.get(entity);

        timerComp.timeToEnd -= deltaTime;

        if(timerComp.timeToEnd <= 0) {
            if(timerComp.listener != null)
                timerComp.listener.act(); //Here a new Entity is created

            engine.removeEntity(entity); //Here an Entity is put back in the pool
        }
    }

It happened that, in the same update, two timers have come to completion and their listeners have created two entities. After the first one is created successfully, the entity containing the timer component is put back in the pool but at the same time it is put in the pendingRemovalEntities list. When the second one is created, it is taken from the pool, but its reference is still in the pendingRemovalEntities list so at the end of the System update it gets erroneously removed.

It's complicated so I'm not sure I've explained well the issue. If needed I can write a test to explain better.

New getComponent overload for Entity

It would be a nice addition if the component on an entity could also be retrieved just using the component class:

myEntityInstance.getComponent( MyComponentClass.class );

The implementation should be pretty easy using the method:

ComponentType.getFor()

In other words, it should just be an alias for:

myEntityInstance.getComponent( ComponentType.getFor( MyComponentClass.class ) );

Exception when adding an entity in EntityListener.entityRemoved

Hi all, this time I've created a JUnit test to be more helpful:

package wingman.tests;

import org.junit.Test;

import com.badlogic.ashley.core.Component;
import com.badlogic.ashley.core.Engine;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntityListener;
import com.badlogic.ashley.core.Family;

public class AshleyTests {

    @Test
    public void addEntityListener_Family_Remove() {
        final Engine engine = new Engine();

        Entity e = new Entity();
        e.add(new PositionComponent());
        engine.addEntity(e);

        @SuppressWarnings("unchecked")
        Family family = Family.getFor(PositionComponent.class);
        engine.addEntityListener(family, new EntityListener() {

            public void entityRemoved(Entity entity) {
                engine.addEntity(new Entity());
            }

            public void entityAdded(Entity entity) {

            }
        });

        engine.removeEntity(e);
    }

    @Test
    public void addEntityListener_Family_Add() {
        final Engine engine = new Engine();

        Entity e = new Entity();
        e.add(new PositionComponent());

        @SuppressWarnings("unchecked")
        Family family = Family.getFor(PositionComponent.class);
        engine.addEntityListener(family, new EntityListener() {

            public void entityRemoved(Entity entity) {

            }

            public void entityAdded(Entity entity) {
                engine.addEntity(new Entity());
            }
        });

        engine.addEntity(e);
    }

    @Test
    public void addEntityListener_NoFamily_Remove() {
        final Engine engine = new Engine();

        Entity e = new Entity();
        e.add(new PositionComponent());
        engine.addEntity(e);

        @SuppressWarnings("unchecked")
        final Family family = Family.getFor(PositionComponent.class);
        engine.addEntityListener(new EntityListener() {

            public void entityRemoved(Entity entity) {
                if(family.matches(entity))
                    engine.addEntity(new Entity());
            }

            public void entityAdded(Entity entity) {

            }
        });

        engine.removeEntity(e);
    }

    @Test
    public void addEntityListener_NoFamily_Add() {
        final Engine engine = new Engine();

        Entity e = new Entity();
        e.add(new PositionComponent());

        @SuppressWarnings("unchecked")
        final Family family = Family.getFor(PositionComponent.class);
        engine.addEntityListener(new EntityListener() {

            public void entityRemoved(Entity entity) {

            }

            public void entityAdded(Entity entity) {
                if(family.matches(entity))
                    engine.addEntity(new Entity());
            }
        });

        engine.addEntity(e);
    }

    public class PositionComponent extends Component { }

}

If you run this tests, the addEntityListener_Family_Remove (and _Add) will fail with the following exception:

com.badlogic.gdx.utils.GdxRuntimeException: #iterator() cannot be used nested.
    at com.badlogic.gdx.utils.ObjectMap$Entries.hasNext(ObjectMap.java:690)
    at com.badlogic.ashley.core.Engine.removeEntityInternal(Engine.java:285)
    at com.badlogic.ashley.core.Engine.removeEntity(Engine.java:130)
    at wingman.tests.AshleyTests.addEntityListener_Family(AshleyTests.java:34)

As you can see the addEntityListener_NoFamily_Remove (and _Add) will not fail so I think the exception must be related to how the families are iterated when handling the entity removal event.

Sort Entities

A common scenario in a RenderSystem is to have Entities with VisualComponents sorted by zOrder.
Of course it is possible to create a new Array and sort it.

But is it possible to have ImmutableArray also wrap Array#sort(..), to avoid creating new references and/or arrays?

Bug: Entity uuid never reassigned when using PooledEngine

When an entity gets pooled, the uuid will be set to 0. But the uuid is only ever set in the constructor.
So all recycled entities will have a 0 id.

On a sidenote: The uuid will start at 0, but when the entity gets reset, it will be set to 0 as well. It would be nice to set it to -1 on reset instead.

Inform system when entity is added or removed

Hi, is it possible to inform a system when an entity ist removed or added to the system?

Im currently using artemis and i have systems which are building there own index of entites, for example to receive all entities in an spatial area. Those systems needs to update their index when an entity is added or removed.

Thx,
Christian

Nested iteration with ImmutableIntMap

Hi,

Thank you for the library. I'm using it in my project as an alternative to artemis and I'm liking it a lot so far.

Forgive me if I'm mistaken, but I can't find any way to do nested iteration in my systems. ImmutableIntMap.values() always returns the same iterator, and I could not find a way to construct a new iterator outside of the class.

Any assistance would be appreciated.

Cat

GWT: Exception for Listener class

When running a GWT project with ashley, it keeps throwing the exception:
Couldn't find Type for class 'com.badlogic.ashley.signals.Listener'

I can't reproduce this problem in version 1.1.0.
But in version 1.2.0 this occurs as soon as I use an Engine.

Component Dependency Matrix

Been a real busy past couple of days - I'll probably have some time tomorrow though, but I wanted to check some things first.

Since Artemis and Ashley are anatomically more or less the same, I'm pretty sure we could get away with replacing strings for class and method signatures, stock classes etc, only requiring a minimum of changes to the code itself. As such, it feels stupid to split the code into two, as I'm assuming that neither framework will undergo radical changes to its foundation/core conceptual design.

Would it be ok, meaning would you be comfortable, with the CDM code continuing to reside in its current artemis-odb repo? I could move it out, into its own repo ofc, but if you don't mind, I don't mind (less maven repos to maintain).

If so, the only things required for ashley - except the aforementioned modifications - would be a maven plugin, simple cli tool and maybe gradle plugin - so that it can be jacked into the build process. I've never dabbled with gradle before, but it should be relatively easy - all the work is in handled by the CDM codebase. CLI and maven were super-simple.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.