├── ashley
├── .gitignore
├── src
│ └── com
│ │ └── badlogic
│ │ ├── ashley_gwt.gwt.xml
│ │ └── ashley
│ │ ├── core
│ │ ├── Component.java
│ │ ├── EntityListener.java
│ │ ├── ComponentMapper.java
│ │ ├── SystemManager.java
│ │ ├── ComponentOperationHandler.java
│ │ ├── EntitySystem.java
│ │ ├── ComponentType.java
│ │ ├── EntityManager.java
│ │ ├── FamilyManager.java
│ │ ├── Family.java
│ │ ├── PooledEngine.java
│ │ └── Entity.java
│ │ ├── signals
│ │ ├── Listener.java
│ │ └── Signal.java
│ │ ├── systems
│ │ ├── IntervalSystem.java
│ │ ├── IntervalIteratingSystem.java
│ │ ├── IteratingSystem.java
│ │ └── SortedIteratingSystem.java
│ │ └── utils
│ │ ├── ImmutableArray.java
│ │ └── Bag.java
├── build.gradle
└── tests
│ └── com
│ └── badlogic
│ └── ashley
│ ├── utils
│ ├── BagTest.java
│ └── ImmutableArrayTests.java
│ ├── systems
│ ├── IntervalSystemTest.java
│ ├── IntervalIteratingTest.java
│ └── IteratingSystemTest.java
│ ├── core
│ ├── ComponentTypeTests.java
│ ├── ComponentClassFactory.java
│ ├── ComponentOperationHandlerTests.java
│ ├── EntityManagerTests.java
│ ├── SystemManagerTests.java
│ ├── EntityTests.java
│ └── EntityListenerTests.java
│ └── signals
│ └── SignalTests.java
├── tests
├── .gitignore
├── assets
│ ├── coin.png
│ └── crate.png
├── build.gradle
└── src
│ └── com
│ └── badlogic
│ └── ashley
│ └── tests
│ ├── components
│ ├── CameraComponent.java
│ ├── PositionComponent.java
│ ├── VisualComponent.java
│ └── MovementComponent.java
│ ├── SignalTest.java
│ ├── SystemPriorityTest.java
│ ├── utils
│ └── Timer.java
│ ├── systems
│ ├── MovementSystem.java
│ └── RenderSystem.java
│ ├── IgnoreSystemTest.java
│ ├── SpeedTest.java
│ ├── RenderSystemTest.java
│ └── BasicTest.java
├── logo.png
├── settings.gradle
├── .github
├── CODEOWNERS
└── workflows
│ ├── publish_snapshot.yml
│ ├── compile.yml
│ └── publish_release.yml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── benchmarks
├── libs
│ ├── junit-benchmarks-0.7.2.jar
│ └── artemis-a609b2076aacc0ef5ecf0b390205d01bb88ceae2.jar
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── badlogic
│ └── ashley
│ └── benchmark
│ ├── artemis
│ ├── components
│ │ ├── RemovalComponent.java
│ │ ├── RadiusComponent.java
│ │ ├── MovementComponent.java
│ │ ├── StateComponent.java
│ │ └── PositionComponent.java
│ ├── systems
│ │ ├── RemovalSystem.java
│ │ ├── CollisionSystem.java
│ │ ├── StateSystem.java
│ │ └── MovementSystem.java
│ └── ArtemisBenchmark.java
│ ├── ashley
│ ├── components
│ │ ├── RemovalComponent.java
│ │ ├── RadiusComponent.java
│ │ ├── MovementComponent.java
│ │ ├── StateComponent.java
│ │ └── PositionComponent.java
│ ├── systems
│ │ ├── CollisionSystem.java
│ │ ├── StateSystem.java
│ │ ├── RemovalSystem.java
│ │ └── MovementSystem.java
│ └── AshleyBenchmark.java
│ └── Constants.java
├── NOTICE
├── .gitignore
├── RELEASE.md
├── AUTHORS
├── gradlew.bat
├── README.md
├── publish.gradle
└── gradlew
/ashley/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/tests/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/ashley/HEAD/logo.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include 'ashley', 'tests', 'benchmarks'
2 |
3 |
--------------------------------------------------------------------------------
/tests/assets/coin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/ashley/HEAD/tests/assets/coin.png
--------------------------------------------------------------------------------
/tests/assets/crate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/ashley/HEAD/tests/assets/crate.png
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | /.github/workflows/ @libgdx/libgdx-signing
2 | /.github/CODEOWNERS @libgdx/libgdx-signing
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/ashley/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/benchmarks/libs/junit-benchmarks-0.7.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/ashley/HEAD/benchmarks/libs/junit-benchmarks-0.7.2.jar
--------------------------------------------------------------------------------
/benchmarks/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 | sourceCompatibility = 1.7
3 |
4 | eclipse.project {
5 | name = "ecs-benchmarks"
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Ashley
2 | Copyright 2013 Stefan Bachmann
3 |
4 | This software contains code derived from Ash (http://www.ashframework.org/) and Artemis (http://gamadu.com/artemis/).
--------------------------------------------------------------------------------
/benchmarks/libs/artemis-a609b2076aacc0ef5ecf0b390205d01bb88ceae2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/ashley/HEAD/benchmarks/libs/artemis-a609b2076aacc0ef5ecf0b390205d01bb88ceae2.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Sep 21 13:08:26 CEST 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
7 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley_gwt.gwt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 | sourceCompatibility = 1.7
3 |
4 | sourceSets.main.java.srcDirs = [ "src/" ]
5 | sourceSets.main.resources.srcDirs = [ "src/" ]
6 | sourceSets.test.java.srcDirs = [ "tests/" ]
7 | sourceSets.test.resources.srcDirs = [ "tests/" ]
8 |
9 | eclipse.project {
10 | name = projectGroup + "-tests"
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/ashley/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "java"
2 | sourceCompatibility = 1.7
3 |
4 | sourceSets.main.java.srcDirs = [ "src/" ]
5 | sourceSets.main.resources.srcDirs = [ "src/" ]
6 | sourceSets.test.java.srcDirs = [ "tests/" ]
7 | sourceSets.test.resources.srcDirs = [ "tests/" ]
8 |
9 | javadoc {
10 | title = 'Ashley Entity System API'
11 | }
12 |
13 | eclipse.project {
14 | name = projectGroup + "-core"
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/utils/BagTest.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.utils;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class BagTest {
7 |
8 | @Test
9 | public void testSet(){
10 | final Bag bag = new Bag();
11 | bag.add("a");
12 | bag.add("b");
13 | bag.add("c");
14 | Assert.assertEquals(3, bag.size());
15 |
16 | bag.set(1, "d");
17 | Assert.assertEquals(3, bag.size());
18 | Assert.assertEquals("d", bag.get(1));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Temporary Files
2 | *~
3 | .*.swp
4 | .DS_STORE
5 | *.mdb
6 | # per project ignores, it's cumbersome, but reduces the risk of missing something
7 |
8 | # Gradle
9 | .gradle
10 | build/
11 | dist/
12 |
13 | # Intellij
14 | .idea/
15 | *.ipr
16 | *.iws
17 | *.iml
18 | out/
19 | com_crashlytics_export_strings.xml
20 |
21 | # Eclipse
22 | .classpath
23 | .project
24 | .metadata
25 | **/bin/
26 | tmp/
27 | *.tmp
28 | *.bak
29 | *.swp
30 | *~.nib
31 | local.properties
32 | .settings/
33 | .loadpath
34 | .externalToolBuilders/
35 | *.launch
--------------------------------------------------------------------------------
/RELEASE.md:
--------------------------------------------------------------------------------
1 | Release steps for Ashley:
2 |
3 | 1. Make sure [`publish.gradle`](https://github.com/libgdx/ashley/blob/master/publish.gradle) has the correct version. API breaking releases cannot just increase the patch version.
4 | 2. Create [tag](https://github.com/libgdx/ashley/releases) with the new version.
5 | 3. Run release script and publish on Maven.
6 | 4. Increase patch version for the next release.
7 | 5. [Blog post](http://saltares.com/blog/projects/ashley-1-7-0-released/) with changes.
8 | 6. Update Ashley version on [gdx-setup](https://github.com/libgdx/libgdx/blob/master/extensions/gdx-setup/src/com/badlogic/gdx/setup/DependencyBank.java).
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | # This is the official list of the AUTHORS of Ashley
2 | # Names should be added to this file as
3 | # Name or Organization
4 | # The email address is not required for organizations.
5 |
6 | Stefan Bachmann https://github.com/stbachmann
7 | David Saltares https://github.com/siondream
8 | Peter Siegmund https://github.com/mars3142
9 | Andres Araujo https://github.com/andresaraujo
10 | Tomski https://github.com/Tom-Ski
11 | Xavier Guzman https://github.com/xaguzman
12 | adeluiz https://github.com/adeluiz
13 | Matthew Johnston https://github.com/warmwaffles
14 | Mario Zechner https://github.com/badlogic
15 | Ashley Davis https://github.com/SgtCoDFish
16 | Santo Pfingsten https://github.com/Lusito
17 |
--------------------------------------------------------------------------------
/.github/workflows/publish_snapshot.yml:
--------------------------------------------------------------------------------
1 | name: Compile and publish snapshot
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - release/**
8 | jobs:
9 | build:
10 |
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: Set up JDK 1.8
16 | uses: actions/setup-java@v1
17 | with:
18 | java-version: 1.8
19 | - name: Grant execute permission for gradlew
20 | run: chmod +x gradlew
21 | - name: Build and test
22 | run: ./gradlew clean ashley:test
23 | - name: Publish snapshot
24 | env:
25 | NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
26 | NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
27 | run: ./gradlew uploadArchives -PSNAPSHOT=true
28 |
--------------------------------------------------------------------------------
/.github/workflows/compile.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Gradle
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
3 |
4 | name: Compile and publish local
5 |
6 | on:
7 | pull_request:
8 | branches: [ master ]
9 |
10 | jobs:
11 | build:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Set up JDK 1.8
18 | uses: actions/setup-java@v1
19 | with:
20 | java-version: 1.8
21 | - name: Grant execute permission for gradlew
22 | run: chmod +x gradlew
23 | - name: Build and test
24 | run: ./gradlew clean ashley:test
25 | - name: Local install
26 | run: ./gradlew uploadArchives
27 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/components/CameraComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 |
21 | public class CameraComponent implements Component {
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/components/RemovalComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.components;
18 |
19 | import com.artemis.Component;
20 |
21 | public class RemovalComponent extends Component {
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/components/RemovalComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 |
21 | public class RemovalComponent implements Component {
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/components/RadiusComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.components;
18 |
19 | import com.artemis.Component;
20 |
21 | public class RadiusComponent extends Component {
22 | public float radius = 1.0f;
23 | }
24 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/components/RadiusComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 |
21 | public class RadiusComponent implements Component {
22 | public float radius = 1.0f;
23 | }
24 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/Component.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | /**
20 | * Interface for all Components. A Component is intended as a data holder and provides data to be processed in an
21 | * {@link EntitySystem}. But do as you wish.
22 | * @author Stefan Bachmann
23 | */
24 | public interface Component {
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/components/PositionComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 |
21 | public class PositionComponent implements Component {
22 | public float x, y;
23 |
24 | public PositionComponent (float x, float y) {
25 | this.x = x;
26 | this.y = y;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.github/workflows/publish_release.yml:
--------------------------------------------------------------------------------
1 | name: Compile and publish release
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | build:
9 |
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 | - name: Set up JDK 1.8
15 | uses: actions/setup-java@v1
16 | with:
17 | java-version: 1.8
18 | - name: Grant execute permission for gradlew
19 | run: chmod +x gradlew
20 | - name: Build and test
21 | run: ./gradlew clean ashley:test
22 | - name: Import GPG key
23 | id: import_gpg
24 | uses: crazy-max/ghaction-import-gpg@1c6a9e9d3594f2d743f1b1dd7669ab0dfdffa922
25 | with:
26 | gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
27 | passphrase: ${{ secrets.GPG_PASSPHRASE }}
28 | - name: Release build deploy
29 | env:
30 | NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
31 | NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
32 | run:
33 | ./gradlew clean uploadArchives -PRELEASE=true -Psigning.gnupg.keyId=${{ secrets.GPG_KEYID }} -Psigning.gnupg.passphrase=${{ secrets.GPG_PASSPHRASE }} -Psigning.gnupg.keyName=${{ secrets.GPG_KEYID }}
34 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/components/MovementComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.components;
18 |
19 | import com.artemis.Component;
20 | import com.badlogic.gdx.math.Vector2;
21 |
22 | public class MovementComponent extends Component {
23 | public final Vector2 velocity = new Vector2();
24 | public final Vector2 accel = new Vector2();
25 | }
26 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/components/MovementComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 | import com.badlogic.gdx.math.Vector2;
21 |
22 | public class MovementComponent implements Component {
23 | public final Vector2 velocity = new Vector2();
24 | public final Vector2 accel = new Vector2();
25 | }
26 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/components/VisualComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
21 |
22 | public class VisualComponent implements Component {
23 | public TextureRegion region;
24 |
25 | public VisualComponent (TextureRegion region) {
26 | this.region = region;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/signals/Listener.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.signals;
18 |
19 | /**
20 | * A simple Listener interface used to listen to a {@link Signal}.
21 | * @author Stefan Bachmann
22 | */
23 | public interface Listener {
24 | /**
25 | * @param signal The Signal that triggered event
26 | * @param object The object passed on dispatch
27 | */
28 | public void receive (Signal signal, T object);
29 | }
30 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/components/MovementComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 |
21 | public class MovementComponent implements Component {
22 | public float velocityX;
23 | public float velocityY;
24 |
25 | public MovementComponent (float velocityX, float velocityY) {
26 | this.velocityX = velocityX;
27 | this.velocityY = velocityY;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/components/StateComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.components;
18 |
19 | import com.artemis.Component;
20 |
21 | public class StateComponent extends Component {
22 | private int state = 0;
23 | public float time = 0.0f;
24 |
25 | public int get () {
26 | return state;
27 | }
28 |
29 | public void set (int newState) {
30 | state = newState;
31 | time = 0.0f;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/components/PositionComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.components;
18 |
19 | import com.artemis.Component;
20 | import com.badlogic.gdx.math.Vector2;
21 | import com.badlogic.gdx.math.Vector3;
22 |
23 | public class PositionComponent extends Component {
24 | public final Vector3 pos = new Vector3();
25 | public final Vector2 scale = new Vector2(1.0f, 1.0f);
26 | public float rotation = 0.0f;
27 | }
28 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/components/StateComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 |
21 | public class StateComponent implements Component {
22 | private int state = 0;
23 | public float time = 0.0f;
24 |
25 | public int get () {
26 | return state;
27 | }
28 |
29 | public void set (int newState) {
30 | state = newState;
31 | time = 0.0f;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/components/PositionComponent.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.components;
18 |
19 | import com.badlogic.ashley.core.Component;
20 | import com.badlogic.gdx.math.Vector2;
21 | import com.badlogic.gdx.math.Vector3;
22 |
23 | public class PositionComponent implements Component {
24 | public final Vector3 pos = new Vector3();
25 | public final Vector2 scale = new Vector2(1.0f, 1.0f);
26 | public float rotation = 0.0f;
27 | }
28 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/Constants.java:
--------------------------------------------------------------------------------
1 |
2 | package com.badlogic.ashley.benchmark;
3 |
4 | public class Constants {
5 | public static enum ComponentType {
6 | POSITION, MOVEMENT, RADIUS, STATE,
7 | };
8 |
9 | public static final int FRAMES = 100;
10 | public static final float DELTA_TIME = 1.0f / 60.0f;
11 |
12 | public static final int BENCHMARK_ROUNDS = 20;
13 | public static final int WARMUP_ROUNDS = 20;
14 |
15 | public static final int ENTITIES_SMALL_TEST = 10000;
16 | public static final int ENTITIES_MEDIUM_TEST = 20000;
17 | public static final int ENTITIES_BIG_TEST = 50000;
18 |
19 | public static final float MIN_RADIUS = 0.1f;
20 | public static final float MAX_RADIUS = 10.0f;
21 | public static final float MIN_POS = -10.f;
22 | public static final float MAX_POS = 10.0f;
23 | public static final float MIN_VEL = -1.0f;
24 | public static final float MAX_VEL = 1.0f;
25 | public static final float MIN_ACC = -0.1f;
26 | public static final float MAX_ACC = 0.1f;
27 |
28 | public static final int FRAMES_PER_REMOVAL = 10;
29 |
30 | public static boolean shouldHaveComponent (ComponentType type, int index) {
31 | switch (type) {
32 | case MOVEMENT:
33 | return index % 4 == 0;
34 | case RADIUS:
35 | return index % 3 == 0;
36 | case STATE:
37 | return index % 2 == 0;
38 | case POSITION:
39 | return true;
40 | }
41 |
42 | return false;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/SignalTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests;
18 |
19 | import com.badlogic.ashley.signals.Listener;
20 | import com.badlogic.ashley.signals.Signal;
21 |
22 | public class SignalTest {
23 | public static void main (String[] args) {
24 | Signal signal = new Signal();
25 |
26 | Listener listener = new Listener() {
27 | @Override
28 | public void receive (Signal signal, String object) {
29 | System.out.println("Received event: " + object);
30 | }
31 | };
32 |
33 | signal.add(listener);
34 | signal.dispatch("Hello World!");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/systems/CollisionSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.systems;
18 |
19 | import com.badlogic.ashley.benchmark.ashley.components.RadiusComponent;
20 | import com.badlogic.ashley.core.Engine;
21 | import com.badlogic.ashley.core.Entity;
22 | import com.badlogic.ashley.core.EntitySystem;
23 | import com.badlogic.ashley.core.Family;
24 | import com.badlogic.ashley.utils.ImmutableArray;
25 |
26 | public class CollisionSystem extends EntitySystem {
27 | ImmutableArray entities;
28 |
29 | @Override
30 | public void addedToEngine (Engine engine) {
31 | entities = engine.getEntitiesFor(Family.all(RadiusComponent.class).get());
32 | }
33 |
34 | @Override
35 | public void update (float deltaTime) {
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/systems/StateSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.systems;
18 |
19 | import com.badlogic.ashley.benchmark.ashley.components.StateComponent;
20 | import com.badlogic.ashley.core.ComponentMapper;
21 | import com.badlogic.ashley.core.Entity;
22 | import com.badlogic.ashley.core.Family;
23 | import com.badlogic.ashley.systems.IteratingSystem;
24 |
25 | public class StateSystem extends IteratingSystem {
26 | private ComponentMapper sm = ComponentMapper.getFor(StateComponent.class);
27 |
28 | public StateSystem () {
29 | super(Family.all(StateComponent.class).get());
30 | }
31 |
32 | @Override
33 | public void processEntity (Entity entity, float deltaTime) {
34 | sm.get(entity).time += deltaTime;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/systems/RemovalSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.systems;
18 |
19 | import com.artemis.Aspect;
20 | import com.artemis.Entity;
21 | import com.artemis.EntitySystem;
22 | import com.artemis.utils.ImmutableBag;
23 | import com.badlogic.ashley.benchmark.artemis.components.RemovalComponent;
24 |
25 | public class RemovalSystem extends EntitySystem {
26 |
27 | public RemovalSystem () {
28 | super(Aspect.getAspectForAll(RemovalComponent.class));
29 | }
30 |
31 | @Override
32 | protected void processEntities (ImmutableBag entities) {
33 | while (!entities.isEmpty()) {
34 | world.deleteEntity(entities.get(0));
35 | }
36 | }
37 |
38 | @Override
39 | protected boolean checkProcessing () {
40 | return true;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/systems/CollisionSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.systems;
18 |
19 | import com.artemis.Aspect;
20 | import com.artemis.Entity;
21 | import com.artemis.EntitySystem;
22 | import com.artemis.utils.ImmutableBag;
23 | import com.badlogic.ashley.benchmark.artemis.components.PositionComponent;
24 | import com.badlogic.ashley.benchmark.artemis.components.RadiusComponent;
25 |
26 | public class CollisionSystem extends EntitySystem {
27 |
28 | public CollisionSystem () {
29 | super(Aspect.getAspectForAll(PositionComponent.class, RadiusComponent.class));
30 | }
31 |
32 | @Override
33 | protected boolean checkProcessing () {
34 | return true;
35 | }
36 |
37 | @Override
38 | protected void processEntities (ImmutableBag entities) {
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/utils/ImmutableArrayTests.java:
--------------------------------------------------------------------------------
1 |
2 | package com.badlogic.ashley.utils;
3 |
4 | import static org.junit.Assert.*;
5 |
6 | import org.junit.Test;
7 |
8 | import com.badlogic.gdx.utils.Array;
9 | import com.badlogic.gdx.utils.GdxRuntimeException;
10 |
11 | public class ImmutableArrayTests {
12 |
13 | @Test
14 | public void sameValues () {
15 | Array array = new Array();
16 | ImmutableArray immutable = new ImmutableArray(array);
17 |
18 | assertEquals(array.size, immutable.size());
19 |
20 | for (int i = 0; i < 10; ++i) {
21 | array.add(i);
22 | }
23 |
24 | assertEquals(array.size, immutable.size());
25 |
26 | for (int i = 0; i < array.size; ++i) {
27 | assertEquals(array.get(i), immutable.get(i));
28 | }
29 | }
30 |
31 | @Test
32 | public void iteration () {
33 | Array array = new Array();
34 | ImmutableArray immutable = new ImmutableArray(array);
35 |
36 | for (int i = 0; i < 10; ++i) {
37 | array.add(i);
38 | }
39 |
40 | Integer expected = 0;
41 | for (Integer value : immutable) {
42 | assertEquals(expected++, value);
43 | }
44 | }
45 |
46 | @Test
47 | public void forbiddenRemoval () {
48 | Array array = new Array();
49 | ImmutableArray immutable = new ImmutableArray(array);
50 |
51 | for (int i = 0; i < 10; ++i) {
52 | array.add(i);
53 | }
54 |
55 | boolean thrown = false;
56 |
57 | try {
58 | immutable.iterator().remove();
59 | } catch (GdxRuntimeException e) {
60 | thrown = true;
61 | }
62 |
63 | assertEquals(true, thrown);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/EntityListener.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | /**
20 | * Gets notified of {@link Entity} related events.
21 | * @author David Saltares
22 | */
23 | public interface EntityListener {
24 | /**
25 | * Called whenever an {@link Entity} is added to {@link Engine} or a specific {@link Family} See
26 | * {@link Engine#addEntityListener(EntityListener)} and {@link Engine#addEntityListener(Family, EntityListener)}
27 | * @param entity
28 | */
29 | public void entityAdded (Entity entity);
30 |
31 | /**
32 | * Called whenever an {@link Entity} is removed from {@link Engine} or a specific {@link Family} See
33 | * {@link Engine#addEntityListener(EntityListener)} and {@link Engine#addEntityListener(Family, EntityListener)}
34 | * @param entity
35 | */
36 | public void entityRemoved (Entity entity);
37 | }
38 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/systems/StateSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.systems;
18 |
19 | import com.artemis.Aspect;
20 | import com.artemis.ComponentMapper;
21 | import com.artemis.Entity;
22 | import com.artemis.annotations.Mapper;
23 | import com.artemis.systems.EntityProcessingSystem;
24 | import com.badlogic.ashley.benchmark.artemis.components.StateComponent;
25 |
26 | public class StateSystem extends EntityProcessingSystem {
27 | @Mapper ComponentMapper sm;
28 |
29 | public StateSystem () {
30 | super(Aspect.getAspectForAll(StateComponent.class));
31 | }
32 |
33 | @Override
34 | protected void initialize () {
35 | sm = world.getMapper(StateComponent.class);
36 | };
37 |
38 | @Override
39 | protected void process (Entity entity) {
40 | sm.get(entity).time += world.getDelta();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/systems/RemovalSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.systems;
18 |
19 | import com.badlogic.ashley.benchmark.ashley.components.RemovalComponent;
20 | import com.badlogic.ashley.core.Engine;
21 | import com.badlogic.ashley.core.Entity;
22 | import com.badlogic.ashley.core.EntitySystem;
23 | import com.badlogic.ashley.core.Family;
24 | import com.badlogic.ashley.utils.ImmutableArray;
25 |
26 | public class RemovalSystem extends EntitySystem {
27 | private ImmutableArray entities;
28 |
29 | @Override
30 | public void addedToEngine (Engine engine) {
31 | entities = engine.getEntitiesFor(Family.all(RemovalComponent.class).get());
32 | }
33 |
34 | @Override
35 | public void update (float deltaTime) {
36 | while (entities.size() > 0) {
37 | getEngine().removeEntity(entities.get(0));
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/SystemPriorityTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests;
18 |
19 | import com.badlogic.ashley.core.Engine;
20 | import com.badlogic.ashley.core.EntitySystem;
21 |
22 | public class SystemPriorityTest {
23 | public static void main (String[] args) {
24 | Engine engine = new Engine();
25 |
26 | engine.addSystem(new SystemA(10));
27 | engine.addSystem(new SystemB(5));
28 | engine.addSystem(new SystemA(2));
29 |
30 | engine.update(0);
31 | }
32 |
33 | public static class SystemA extends EntitySystem {
34 | public SystemA (int priority) {
35 | super(priority);
36 | }
37 |
38 | @Override
39 | public void update (float deltaTime) {
40 | System.out.println("SystemA");
41 | }
42 |
43 | }
44 |
45 | public static class SystemB extends EntitySystem {
46 | public SystemB (int priority) {
47 | super(priority);
48 | }
49 |
50 | @Override
51 | public void update (float deltaTime) {
52 | System.out.println("SystemB");
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/utils/Timer.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.utils;
18 |
19 | import com.badlogic.gdx.utils.ObjectMap;
20 |
21 | /**
22 | * A simple Timer class that let's you measure multiple times and are identified via an id.
23 | * @author Stefan Bachmann
24 | */
25 | public class Timer {
26 | private ObjectMap times;
27 |
28 | public Timer () {
29 | times = new ObjectMap();
30 | }
31 |
32 | /**
33 | * Start tracking a time with name as id.
34 | * @param name The timer's id
35 | */
36 | public void start (String name) {
37 | times.put(name, System.currentTimeMillis());
38 | }
39 |
40 | /**
41 | * Stop tracking the specified id
42 | * @param name The timer's id
43 | * @return the elapsed time
44 | */
45 | public long stop (String name) {
46 | if (times.containsKey(name)) {
47 | long startTime = times.remove(name);
48 | return System.currentTimeMillis() - startTime;
49 | } else
50 | throw new RuntimeException("Timer id doesn't exist.");
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/systems/MovementSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.systems;
18 |
19 | import com.badlogic.ashley.core.ComponentMapper;
20 | import com.badlogic.ashley.core.Entity;
21 | import com.badlogic.ashley.core.Family;
22 | import com.badlogic.ashley.systems.IteratingSystem;
23 | import com.badlogic.ashley.tests.components.MovementComponent;
24 | import com.badlogic.ashley.tests.components.PositionComponent;
25 |
26 | public class MovementSystem extends IteratingSystem {
27 | private ComponentMapper pm = ComponentMapper.getFor(PositionComponent.class);
28 | private ComponentMapper mm = ComponentMapper.getFor(MovementComponent.class);
29 |
30 | public MovementSystem () {
31 | super(Family.all(PositionComponent.class, MovementComponent.class).get());
32 | }
33 |
34 | @Override
35 | public void processEntity (Entity entity, float deltaTime) {
36 | PositionComponent position = pm.get(entity);
37 | MovementComponent movement = mm.get(entity);
38 |
39 | position.x += movement.velocityX * deltaTime;
40 | position.y += movement.velocityY * deltaTime;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/systems/IntervalSystemTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import org.junit.Test;
20 |
21 | import com.badlogic.ashley.core.Engine;
22 |
23 | import static org.junit.Assert.*;
24 |
25 | public class IntervalSystemTest {
26 | private static final float deltaTime = 0.1f;
27 |
28 | private static class IntervalSystemSpy extends IntervalSystem {
29 | public int numUpdates;
30 |
31 | public IntervalSystemSpy () {
32 | super(deltaTime * 2.0f);
33 | }
34 |
35 | @Override
36 | protected void updateInterval () {
37 | ++numUpdates;
38 | }
39 | }
40 |
41 | @Test
42 | public void intervalSystem () {
43 | Engine engine = new Engine();
44 | IntervalSystemSpy intervalSystemSpy = new IntervalSystemSpy();
45 |
46 | engine.addSystem(intervalSystemSpy);
47 |
48 | for (int i = 1; i <= 10; ++i) {
49 | engine.update(deltaTime);
50 | assertEquals(i / 2, intervalSystemSpy.numUpdates);
51 | }
52 | }
53 |
54 | @Test
55 | public void testGetInterval () {
56 | IntervalSystemSpy intervalSystemSpy = new IntervalSystemSpy();
57 | assertEquals(intervalSystemSpy.getInterval(), deltaTime * 2.0f, 0);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/ComponentMapper.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | /**
20 | * Provides super fast {@link Component} retrieval from {@Link Entity} objects.
21 | * @param the class type of the {@link Component}.
22 | * @author David Saltares
23 | */
24 | public final class ComponentMapper {
25 | private final ComponentType componentType;
26 |
27 | /**
28 | * @param componentClass Component class to be retrieved by the mapper.
29 | * @return New instance that provides fast access to the {@link Component} of the specified class.
30 | */
31 | public static ComponentMapper getFor (Class componentClass) {
32 | return new ComponentMapper(componentClass);
33 | }
34 |
35 | /** @return The {@link Component} of the specified class belonging to entity. */
36 | public T get (Entity entity) {
37 | return entity.getComponent(componentType);
38 | }
39 |
40 | /** @return Whether or not entity has the component of the specified class. */
41 | public boolean has (Entity entity) {
42 | return entity.hasComponent(componentType);
43 | }
44 |
45 | private ComponentMapper (Class componentClass) {
46 | componentType = ComponentType.getFor(componentClass);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/IgnoreSystemTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests;
18 |
19 | import com.badlogic.ashley.core.EntitySystem;
20 | import com.badlogic.ashley.core.PooledEngine;
21 |
22 | public class IgnoreSystemTest {
23 |
24 | public static void main (String[] args) {
25 | PooledEngine engine = new PooledEngine();
26 |
27 | CounterSystem counter = new CounterSystem();
28 | IgnoredSystem ignored = new IgnoredSystem();
29 |
30 | engine.addSystem(counter);
31 | engine.addSystem(ignored);
32 |
33 | for (int i = 0; i < 10; i++) {
34 | engine.update(0.25f);
35 | }
36 | }
37 |
38 | private static class CounterSystem extends EntitySystem {
39 | @Override
40 | public void update (float deltaTime) {
41 | log("Running " + getClass().getSimpleName());
42 | }
43 | }
44 |
45 | private static class IgnoredSystem extends EntitySystem {
46 |
47 | int counter = 0;
48 |
49 | @Override
50 | public boolean checkProcessing () {
51 | counter = 1 - counter;
52 | return counter == 1;
53 | }
54 |
55 | @Override
56 | public void update (float deltaTime) {
57 | log("Running " + getClass().getSimpleName());
58 | }
59 | }
60 |
61 | public static void log (String string) {
62 | System.out.println(string);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/systems/MovementSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.ashley.systems;
18 |
19 | import com.badlogic.ashley.benchmark.ashley.components.MovementComponent;
20 | import com.badlogic.ashley.benchmark.ashley.components.PositionComponent;
21 | import com.badlogic.ashley.core.ComponentMapper;
22 | import com.badlogic.ashley.core.Entity;
23 | import com.badlogic.ashley.core.Family;
24 | import com.badlogic.ashley.systems.IteratingSystem;
25 | import com.badlogic.gdx.math.Vector2;
26 |
27 | public class MovementSystem extends IteratingSystem {
28 | private Vector2 tmp = new Vector2();
29 | private ComponentMapper pm = ComponentMapper.getFor(PositionComponent.class);
30 | private ComponentMapper mm = ComponentMapper.getFor(MovementComponent.class);
31 |
32 | public MovementSystem () {
33 | super(Family.all(PositionComponent.class, MovementComponent.class).get());
34 | }
35 |
36 | @Override
37 | public void processEntity (Entity entity, float deltaTime) {
38 | PositionComponent pos = pm.get(entity);
39 | MovementComponent mov = mm.get(entity);
40 |
41 | tmp.set(mov.accel).scl(deltaTime);
42 | mov.velocity.add(tmp);
43 |
44 | tmp.set(mov.velocity).scl(deltaTime);
45 | pos.pos.add(tmp.x, tmp.y, 0.0f);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/systems/MovementSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.benchmark.artemis.systems;
18 |
19 | import com.artemis.Aspect;
20 | import com.artemis.ComponentMapper;
21 | import com.artemis.Entity;
22 | import com.artemis.annotations.Mapper;
23 | import com.artemis.systems.EntityProcessingSystem;
24 | import com.badlogic.ashley.benchmark.artemis.components.MovementComponent;
25 | import com.badlogic.ashley.benchmark.artemis.components.PositionComponent;
26 | import com.badlogic.gdx.math.Vector2;
27 |
28 | public class MovementSystem extends EntityProcessingSystem {
29 | private Vector2 tmp = new Vector2();
30 | @Mapper ComponentMapper pm;
31 | @Mapper ComponentMapper mm;
32 |
33 | public MovementSystem () {
34 | super(Aspect.getAspectForAll(PositionComponent.class, MovementComponent.class));
35 | }
36 |
37 | @Override
38 | protected void initialize () {
39 | pm = world.getMapper(PositionComponent.class);
40 | mm = world.getMapper(MovementComponent.class);
41 | };
42 |
43 | @Override
44 | protected void process (Entity entity) {
45 | PositionComponent pos = pm.get(entity);
46 | MovementComponent mov = mm.get(entity);
47 |
48 | tmp.set(mov.accel).scl(world.getDelta());
49 | mov.velocity.add(tmp);
50 |
51 | tmp.set(mov.velocity).scl(world.getDelta());
52 | pos.pos.add(tmp.x, tmp.y, 0.0f);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/systems/IntervalSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import com.badlogic.ashley.core.EntitySystem;
20 |
21 | /**
22 | * A simple {@link EntitySystem} that does not run its update logic every call to {@link EntitySystem#update(float)}, but after a
23 | * given interval. The actual logic should be placed in {@link IntervalSystem#updateInterval()}.
24 | * @author David Saltares
25 | */
26 | public abstract class IntervalSystem extends EntitySystem {
27 | private float interval;
28 | private float accumulator;
29 |
30 | /**
31 | * @param interval time in seconds between calls to {@link IntervalSystem#updateInterval()}.
32 | */
33 | public IntervalSystem (float interval) {
34 | this(interval, 0);
35 | }
36 |
37 | /**
38 | * @param interval time in seconds between calls to {@link IntervalSystem#updateInterval()}.
39 | * @param priority
40 | */
41 | public IntervalSystem (float interval, int priority) {
42 | super(priority);
43 | this.interval = interval;
44 | this.accumulator = 0;
45 | }
46 |
47 | public float getInterval() {
48 | return interval;
49 | }
50 |
51 | @Override
52 | public void update (float deltaTime) {
53 | accumulator += deltaTime;
54 |
55 | while (accumulator >= interval) {
56 | accumulator -= interval;
57 | updateInterval();
58 | }
59 | }
60 |
61 | /**
62 | * The processing logic of the system should be placed here.
63 | */
64 | protected abstract void updateInterval ();
65 | }
66 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/SystemManager.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import java.util.Comparator;
4 |
5 | import com.badlogic.ashley.signals.Listener;
6 | import com.badlogic.ashley.signals.Signal;
7 | import com.badlogic.ashley.utils.ImmutableArray;
8 | import com.badlogic.gdx.utils.Array;
9 | import com.badlogic.gdx.utils.ObjectMap;
10 |
11 | class SystemManager {
12 | private SystemComparator systemComparator = new SystemComparator();
13 | private Array systems = new Array(true, 16);
14 | private ImmutableArray immutableSystems = new ImmutableArray(systems);
15 | private ObjectMap, EntitySystem> systemsByClass = new ObjectMap, EntitySystem>();
16 | private SystemListener listener;
17 |
18 | public SystemManager(SystemListener listener) {
19 | this.listener = listener;
20 | }
21 |
22 | public void addSystem(EntitySystem system){
23 | Class extends EntitySystem> systemType = system.getClass();
24 | EntitySystem oldSystem = getSystem(systemType);
25 |
26 | if (oldSystem != null) {
27 | removeSystem(oldSystem);
28 | }
29 |
30 | systems.add(system);
31 | systemsByClass.put(systemType, system);
32 | systems.sort(systemComparator);
33 | listener.systemAdded(system);
34 | }
35 |
36 | public void removeSystem(EntitySystem system){
37 | if(systems.removeValue(system, true)) {
38 | systemsByClass.remove(system.getClass());
39 | listener.systemRemoved(system);
40 | }
41 | }
42 |
43 | public void removeAllSystems() {
44 | while(systems.size > 0) {
45 | removeSystem(systems.first());
46 | }
47 | }
48 |
49 | @SuppressWarnings("unchecked")
50 | public T getSystem(Class systemType) {
51 | return (T) systemsByClass.get(systemType);
52 | }
53 |
54 | public ImmutableArray getSystems() {
55 | return immutableSystems;
56 | }
57 |
58 | private static class SystemComparator implements Comparator{
59 | @Override
60 | public int compare(EntitySystem a, EntitySystem b) {
61 | return a.priority > b.priority ? 1 : (a.priority == b.priority) ? 0 : -1;
62 | }
63 | }
64 |
65 | interface SystemListener {
66 | void systemAdded(EntitySystem system);
67 | void systemRemoved(EntitySystem system);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/signals/Signal.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.signals;
18 |
19 | import com.badlogic.gdx.utils.SnapshotArray;
20 |
21 | /**
22 | * A Signal is a basic event class that can dispatch an event to multiple listeners. It uses generics to allow any type of object
23 | * to be passed around on dispatch.
24 | * @author Stefan Bachmann
25 | */
26 | public class Signal {
27 | private SnapshotArray> listeners;
28 |
29 | public Signal () {
30 | listeners = new SnapshotArray>();
31 | }
32 |
33 | /**
34 | * Add a Listener to this Signal
35 | * @param listener The Listener to be added
36 | */
37 | public void add (Listener listener) {
38 | listeners.add(listener);
39 | }
40 |
41 | /**
42 | * Remove a listener from this Signal
43 | * @param listener The Listener to remove
44 | */
45 | public void remove (Listener listener) {
46 | listeners.removeValue(listener, true);
47 | }
48 |
49 | /** Removes all listeners attached to this {@link Signal}. */
50 | public void removeAllListeners () {
51 | listeners.clear();
52 | }
53 |
54 | /**
55 | * Dispatches an event to all Listeners registered to this Signal
56 | * @param object The object to send off
57 | */
58 | public void dispatch (T object) {
59 | final Object[] items = listeners.begin();
60 | for (int i = 0, n = listeners.size; i < n; i++) {
61 | Listener listener = (Listener)items[i];
62 | listener.receive(this, object);
63 | }
64 | listeners.end();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/ComponentOperationHandler.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import com.badlogic.gdx.utils.Array;
4 | import com.badlogic.gdx.utils.Pool;
5 |
6 |
7 | class ComponentOperationHandler {
8 | private BooleanInformer delayed;
9 | private ComponentOperationPool operationPool = new ComponentOperationPool();;
10 | private Array operations = new Array();;
11 |
12 | public ComponentOperationHandler(BooleanInformer delayed) {
13 | this.delayed = delayed;
14 | }
15 |
16 | public void add(Entity entity) {
17 | if (delayed.value()) {
18 | ComponentOperation operation = operationPool.obtain();
19 | operation.makeAdd(entity);
20 | operations.add(operation);
21 | }
22 | else {
23 | entity.notifyComponentAdded();
24 | }
25 | }
26 |
27 | public void remove(Entity entity) {
28 | if (delayed.value()) {
29 | ComponentOperation operation = operationPool.obtain();
30 | operation.makeRemove(entity);
31 | operations.add(operation);
32 | }
33 | else {
34 | entity.notifyComponentRemoved();
35 | }
36 | }
37 |
38 | public boolean hasOperationsToProcess() {
39 | return operations.size > 0;
40 | }
41 |
42 | public void processOperations() {
43 | for (int i = 0; i < operations.size; ++i) {
44 | ComponentOperation operation = operations.get(i);
45 |
46 | switch(operation.type) {
47 | case Add:
48 | operation.entity.notifyComponentAdded();
49 | break;
50 | case Remove:
51 | operation.entity.notifyComponentRemoved();
52 | break;
53 | default: break;
54 | }
55 |
56 | operationPool.free(operation);
57 | }
58 |
59 | operations.clear();
60 | }
61 |
62 | private static class ComponentOperation implements Pool.Poolable {
63 | public enum Type {
64 | Add,
65 | Remove,
66 | }
67 |
68 | public Type type;
69 | public Entity entity;
70 |
71 | public void makeAdd(Entity entity) {
72 | this.type = Type.Add;
73 | this.entity = entity;
74 | }
75 |
76 | public void makeRemove(Entity entity) {
77 | this.type = Type.Remove;
78 | this.entity = entity;
79 | }
80 |
81 | @Override
82 | public void reset() {
83 | entity = null;
84 | }
85 | }
86 |
87 | private static class ComponentOperationPool extends Pool {
88 | @Override
89 | protected ComponentOperation newObject() {
90 | return new ComponentOperation();
91 | }
92 | }
93 |
94 | interface BooleanInformer {
95 | public boolean value();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/ComponentTypeTests.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | import static org.junit.Assert.*;
20 |
21 | import org.junit.Test;
22 |
23 | import com.badlogic.ashley.core.Component;
24 | import com.badlogic.ashley.core.ComponentType;
25 |
26 | public class ComponentTypeTests {
27 |
28 | private static class ComponentA implements Component {
29 |
30 | }
31 |
32 | private static class ComponentB implements Component {
33 |
34 | }
35 |
36 | @Test
37 | public void validComponentType () {
38 | assertNotNull(ComponentType.getFor(ComponentA.class));
39 | assertNotNull(ComponentType.getFor(ComponentB.class));
40 | }
41 |
42 | @Test
43 | public void sameComponentType () {
44 | ComponentType componentType1 = ComponentType.getFor(ComponentA.class);
45 | ComponentType componentType2 = ComponentType.getFor(ComponentA.class);
46 |
47 | assertEquals(true, componentType1.equals(componentType2));
48 | assertEquals(true, componentType2.equals(componentType1));
49 | assertEquals(componentType1.getIndex(), componentType2.getIndex());
50 | assertEquals(componentType1.getIndex(), ComponentType.getIndexFor(ComponentA.class));
51 | assertEquals(componentType2.getIndex(), ComponentType.getIndexFor(ComponentA.class));
52 | }
53 |
54 | @Test
55 | public void differentComponentType () {
56 | ComponentType componentType1 = ComponentType.getFor(ComponentA.class);
57 | ComponentType componentType2 = ComponentType.getFor(ComponentB.class);
58 |
59 | assertEquals(false, componentType1.equals(componentType2));
60 | assertEquals(false, componentType2.equals(componentType1));
61 | assertNotEquals(componentType1.getIndex(), componentType2.getIndex());
62 | assertNotEquals(componentType1.getIndex(), ComponentType.getIndexFor(ComponentB.class));
63 | assertNotEquals(componentType2.getIndex(), ComponentType.getIndexFor(ComponentA.class));
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/systems/RenderSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests.systems;
18 |
19 | import com.badlogic.ashley.core.ComponentMapper;
20 | import com.badlogic.ashley.core.Engine;
21 | import com.badlogic.ashley.core.Entity;
22 | import com.badlogic.ashley.core.EntitySystem;
23 | import com.badlogic.ashley.core.Family;
24 | import com.badlogic.ashley.tests.components.PositionComponent;
25 | import com.badlogic.ashley.tests.components.VisualComponent;
26 | import com.badlogic.ashley.utils.ImmutableArray;
27 | import com.badlogic.gdx.graphics.OrthographicCamera;
28 | import com.badlogic.gdx.graphics.g2d.SpriteBatch;
29 |
30 | public class RenderSystem extends EntitySystem {
31 | private ImmutableArray entities;
32 |
33 | private SpriteBatch batch;
34 | private OrthographicCamera camera;
35 |
36 | private ComponentMapper pm = ComponentMapper.getFor(PositionComponent.class);
37 | private ComponentMapper vm = ComponentMapper.getFor(VisualComponent.class);
38 |
39 | public RenderSystem (OrthographicCamera camera) {
40 | batch = new SpriteBatch();
41 |
42 | this.camera = camera;
43 | }
44 |
45 | @Override
46 | public void addedToEngine (Engine engine) {
47 | entities = engine.getEntitiesFor(Family.all(PositionComponent.class, VisualComponent.class).get());
48 | }
49 |
50 | @Override
51 | public void removedFromEngine (Engine engine) {
52 |
53 | }
54 |
55 | @Override
56 | public void update (float deltaTime) {
57 | PositionComponent position;
58 | VisualComponent visual;
59 |
60 | camera.update();
61 |
62 | batch.begin();
63 | batch.setProjectionMatrix(camera.combined);
64 |
65 | for (int i = 0; i < entities.size(); ++i) {
66 | Entity e = entities.get(i);
67 |
68 | position = pm.get(e);
69 | visual = vm.get(e);
70 |
71 | batch.draw(visual.region, position.x, position.y);
72 | }
73 |
74 | batch.end();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/ComponentClassFactory.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import org.mockito.asm.ClassWriter;
4 | import org.mockito.asm.MethodVisitor;
5 | import org.mockito.asm.Opcodes;
6 |
7 | /**
8 | * Class loader allowing dynamic {@link Component} class definitions.
9 | *
10 | * Useful for tests that need several different component types.
11 | *
12 | * Adapted from https://dzone.com/articles/fully-dynamic-classes-with-asm
13 | *
14 | * @author mgsx
15 | *
16 | */
17 | public class ComponentClassFactory extends ClassLoader
18 | {
19 | /**
20 | * create new {@link Component} type
21 | * @param name name of the class to create
22 | * @return created class
23 | */
24 | @SuppressWarnings("unchecked")
25 | public Class extends Component> createComponentType(String name){
26 |
27 | ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
28 |
29 | String interfacePath = Component.class.getName().replaceAll("\\.", "/");
30 |
31 | // create public class (default package) implementing Component
32 |
33 | cw.visit(Opcodes.V1_6, // Java 1.6
34 | Opcodes.ACC_PUBLIC, // public class
35 | name, // package and name
36 | null, // signature (null means not generic)
37 | "java/lang/Object", // superclass
38 | new String[]{ interfacePath }); // interfaces
39 |
40 | // create public no-arg constructor
41 |
42 | MethodVisitor con = cw.visitMethod(
43 | Opcodes.ACC_PUBLIC, // public method
44 | "", // method name
45 | "()V", // descriptor
46 | null, // signature (null means not generic)
47 | null); // exceptions (array of strings)
48 |
49 | // define constructor body : call super constructor (java.lang.Object)
50 |
51 | con.visitCode(); // Start the code for this method
52 | con.visitVarInsn(Opcodes.ALOAD, 0); // Load "this" onto the stack
53 | con.visitMethodInsn(Opcodes.INVOKESPECIAL, // Invoke an instance method (non-virtual)
54 | "java/lang/Object", // Class on which the method is defined
55 | "", // Name of the method
56 | "()V"); // Descriptor
57 | con.visitInsn(Opcodes.RETURN); // End the constructor method
58 | con.visitMaxs(1, 1); // Specify max stack and local vars
59 |
60 | // close class definition.
61 |
62 | cw.visitEnd();
63 |
64 | // load and return class.
65 | byte[] b = cw.toByteArray();
66 | return (Class extends Component>)defineClass(name, b, 0, b.length);
67 | }
68 | }
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/ComponentOperationHandlerTests.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 |
7 | import com.badlogic.ashley.core.ComponentOperationHandler.BooleanInformer;
8 | import com.badlogic.ashley.signals.Listener;
9 | import com.badlogic.ashley.signals.Signal;
10 |
11 | public class ComponentOperationHandlerTests {
12 |
13 | private static class BooleanInformerMock implements BooleanInformer {
14 | public boolean delayed = false;
15 |
16 | @Override
17 | public boolean value () {
18 | return delayed;
19 | }
20 | }
21 |
22 | private static class ComponentSpy implements Listener {
23 | public boolean called;
24 |
25 | @Override
26 | public void receive(Signal signal, Entity object) {
27 | called = true;
28 | }
29 | }
30 |
31 | @Test
32 | public void add() {
33 | ComponentSpy spy = new ComponentSpy();
34 | BooleanInformerMock informer = new BooleanInformerMock();
35 | ComponentOperationHandler handler = new ComponentOperationHandler(informer);
36 |
37 | Entity entity = new Entity();
38 | entity.componentOperationHandler = handler;
39 | entity.componentAdded.add(spy);
40 |
41 | handler.add(entity);
42 |
43 | assertTrue(spy.called);
44 | }
45 |
46 | @Test
47 | public void addDelayed() {
48 | ComponentSpy spy = new ComponentSpy();
49 | BooleanInformerMock informer = new BooleanInformerMock();
50 | ComponentOperationHandler handler = new ComponentOperationHandler(informer);
51 |
52 | informer.delayed = true;
53 |
54 | Entity entity = new Entity();
55 | entity.componentOperationHandler = handler;
56 | entity.componentAdded.add(spy);
57 |
58 | handler.add(entity);
59 |
60 | assertFalse(spy.called);
61 | handler.processOperations();
62 | assertTrue(spy.called);
63 | }
64 |
65 | @Test
66 | public void remove() {
67 | ComponentSpy spy = new ComponentSpy();
68 | BooleanInformerMock informer = new BooleanInformerMock();
69 | ComponentOperationHandler handler = new ComponentOperationHandler(informer);
70 |
71 | Entity entity = new Entity();
72 | entity.componentOperationHandler = handler;
73 | entity.componentRemoved.add(spy);
74 |
75 | handler.remove(entity);
76 |
77 | assertTrue(spy.called);
78 | }
79 |
80 | @Test
81 | public void removeDelayed() {
82 | ComponentSpy spy = new ComponentSpy();
83 | BooleanInformerMock informer = new BooleanInformerMock();
84 | ComponentOperationHandler handler = new ComponentOperationHandler(informer);
85 |
86 | informer.delayed = true;
87 |
88 | Entity entity = new Entity();
89 | entity.componentOperationHandler = handler;
90 | entity.componentRemoved.add(spy);
91 |
92 | handler.remove(entity);
93 |
94 | assertFalse(spy.called);
95 | handler.processOperations();
96 | assertTrue(spy.called);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/utils/ImmutableArray.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.utils;
18 |
19 | import java.util.Iterator;
20 |
21 | import com.badlogic.gdx.utils.Array;
22 | import com.badlogic.gdx.utils.Array.ArrayIterable;
23 |
24 | /**
25 | * Wrapper class to treat {@link Array} objects as if they were immutable. However, note that the values could be modified if they
26 | * are mutable.
27 | * @author David Saltares
28 | */
29 | public class ImmutableArray implements Iterable {
30 | private final Array array;
31 | private ArrayIterable iterable;
32 |
33 | public ImmutableArray() {
34 | this(new Array());
35 | }
36 |
37 | public ImmutableArray (Array array) {
38 | this.array = array;
39 | }
40 |
41 | public int size () {
42 | return array.size;
43 | }
44 |
45 | public T get (int index) {
46 | return array.get(index);
47 | }
48 |
49 | public boolean contains (T value, boolean identity) {
50 | return array.contains(value, identity);
51 | }
52 |
53 | public int indexOf (T value, boolean identity) {
54 | return array.indexOf(value, identity);
55 | }
56 |
57 | public int lastIndexOf (T value, boolean identity) {
58 | return array.lastIndexOf(value, identity);
59 | }
60 |
61 | public T peek () {
62 | return array.peek();
63 | }
64 |
65 | public T first () {
66 | return array.first();
67 | }
68 |
69 | public T random () {
70 | return array.random();
71 | }
72 |
73 | public T[] toArray () {
74 | return array.toArray();
75 | }
76 |
77 | public V[] toArray (Class type) {
78 | return array.toArray(type);
79 | }
80 |
81 | public int hashCode() {
82 | return array.hashCode();
83 | }
84 |
85 | public boolean equals (Object object) {
86 | return array.equals(object);
87 | }
88 |
89 | public String toString () {
90 | return array.toString();
91 | }
92 |
93 | public String toString (String separator) {
94 | return array.toString(separator);
95 | }
96 |
97 | @Override
98 | public Iterator iterator () {
99 | if (iterable == null) {
100 | iterable = new ArrayIterable(array, false);
101 | }
102 |
103 | return iterable.iterator();
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/SpeedTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests;
18 |
19 | import com.badlogic.ashley.core.Entity;
20 | import com.badlogic.ashley.core.PooledEngine;
21 | import com.badlogic.ashley.tests.components.MovementComponent;
22 | import com.badlogic.ashley.tests.components.PositionComponent;
23 | import com.badlogic.ashley.tests.systems.MovementSystem;
24 | import com.badlogic.ashley.tests.utils.Timer;
25 | import com.badlogic.gdx.utils.Array;
26 |
27 | public class SpeedTest {
28 | public static int NUMBER_ENTITIES = 100000;
29 |
30 | public static void main (String[] args) {
31 | Timer timer = new Timer();
32 | Array entities = new Array();
33 |
34 | PooledEngine engine = new PooledEngine();
35 |
36 | engine.addSystem(new MovementSystem());
37 |
38 | System.out.println("Number of entities: " + NUMBER_ENTITIES);
39 |
40 | /** Adding entities */
41 | timer.start("entities");
42 |
43 | entities.ensureCapacity(NUMBER_ENTITIES);
44 |
45 | for (int i = 0; i < NUMBER_ENTITIES; i++) {
46 | Entity entity = engine.createEntity();
47 |
48 | entity.add(new MovementComponent(10, 10));
49 | entity.add(new PositionComponent(0, 0));
50 |
51 | engine.addEntity(entity);
52 |
53 | entities.add(entity);
54 | }
55 |
56 | System.out.println("Entities added time: " + timer.stop("entities") + "ms");
57 |
58 | /** Removing components */
59 | timer.start("componentRemoved");
60 |
61 | for (Entity e : entities) {
62 | e.remove(PositionComponent.class);
63 | }
64 |
65 | System.out.println("Component removed time: " + timer.stop("componentRemoved") + "ms");
66 |
67 | /** Adding components */
68 | timer.start("componentAdded");
69 |
70 | for (Entity e : entities) {
71 | e.add(new PositionComponent(0, 0));
72 | }
73 |
74 | System.out.println("Component added time: " + timer.stop("componentAdded") + "ms");
75 |
76 | /** System processing */
77 | timer.start("systemProcessing");
78 |
79 | engine.update(0);
80 |
81 | System.out.println("System processing times " + timer.stop("systemProcessing") + "ms");
82 |
83 | /** Removing entities */
84 | timer.start("entitiesRemoved");
85 |
86 | engine.removeAllEntities();
87 |
88 | System.out.println("Entity removed time: " + timer.stop("entitiesRemoved") + "ms");
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/EntitySystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | /**
20 | * Abstract class for processing sets of {@link Entity} objects.
21 | * @author Stefan Bachmann
22 | */
23 | public abstract class EntitySystem {
24 | /** Use this to set the priority of the system. Lower means it'll get executed first. */
25 | public int priority;
26 |
27 | private boolean processing;
28 | private Engine engine;
29 |
30 | /** Default constructor that will initialise an EntitySystem with priority 0. */
31 | public EntitySystem () {
32 | this(0);
33 | }
34 |
35 | /**
36 | * Initialises the EntitySystem with the priority specified.
37 | * @param priority The priority to execute this system with (lower means higher priority).
38 | */
39 | public EntitySystem (int priority) {
40 | this.priority = priority;
41 | this.processing = true;
42 | }
43 |
44 | /**
45 | * Called when this EntitySystem is added to an {@link Engine}.
46 | * @param engine The {@link Engine} this system was added to.
47 | */
48 | public void addedToEngine (Engine engine) {
49 | }
50 |
51 | /**
52 | * Called when this EntitySystem is removed from an {@link Engine}.
53 | * @param engine The {@link Engine} the system was removed from.
54 | */
55 | public void removedFromEngine (Engine engine) {
56 | }
57 |
58 | /**
59 | * The update method called every tick.
60 | * @param deltaTime The time passed since last frame in seconds.
61 | */
62 | public void update (float deltaTime) {
63 | }
64 |
65 | /** @return Whether or not the system should be processed. */
66 | public boolean checkProcessing () {
67 | return processing;
68 | }
69 |
70 | /** Sets whether or not the system should be processed by the {@link Engine}. */
71 | public void setProcessing (boolean processing) {
72 | this.processing = processing;
73 | }
74 |
75 | /** @return engine instance the system is registered to.
76 | * It will be null if the system is not associated to any engine instance. */
77 | public Engine getEngine () {
78 | return engine;
79 | }
80 |
81 | final void addedToEngineInternal(Engine engine) {
82 | this.engine = engine;
83 | addedToEngine(engine);
84 | }
85 |
86 | final void removedFromEngineInternal(Engine engine) {
87 | this.engine = null;
88 | removedFromEngine(engine);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | [](https://github.com/libgdx/ashley/actions/workflows/publish_snapshot.yml)
4 |
5 | [](https://search.maven.org/artifact/com.badlogicgames.ashley/ashley)
6 | [](https://oss.sonatype.org/#nexus-search;gav~com.badlogicgames.ashley~ashley)
7 |
8 |
9 | A tiny entity framework written in Java. It's inspired by frameworks like
10 | [Ash](http://www.ashframework.org/) (hence the name) and
11 | [Artemis](http://gamadu.com/artemis/). Ashley tries to be a high-performance
12 | entity framework without the use of black-magic and thus making the API easy
13 | and transparent to use.
14 |
15 | Ashley is awesome, if you don't believe it, check out some [games](https://github.com/libgdx/ashley/wiki/Games-made-with-Ashley) made with it!
16 |
17 | Ashley lives under the [libGDX](https://github.com/libgdx) family but it does not force you to use that specific framework if you do not wish to do so.
18 |
19 | libGDX Discord : [](https://libgdx.com/community/discord/)
20 |
21 | ### Get started
22 |
23 | * [Use Ashley in your project](https://github.com/libgdx/ashley/wiki/Getting-started-with-Ashley)
24 | * [Read the wiki](https://github.com/libgdx/ashley/wiki)
25 | * [Refer to the javadocs](https://javadoc.io/doc/com.badlogicgames.ashley/ashley)
26 | * [Read the examples](https://github.com/libgdx/ashley/tree/master/tests)
27 |
28 |
29 | ### News and community
30 |
31 | Stay up to date in Ashley matters by following [@d_saltares](https://twitter.com/d_saltares) and reading [saltares.com](http://saltares.com). Check the [libGDX](https://libgdx.com/) blog as well for additional updates.
32 |
33 | ### Report issues
34 |
35 | Something not working quite as expected? Do you need a feature that has not been implemented yet? Check the [issue tracker](https://github.com/libgdx/ashley/issues) 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.
36 |
37 | ### Contribute
38 |
39 | 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](https://github.com/libgdx/ashley/tree/master/ashley/tests/com/badlogic/ashley) are passing before submitting and add new ones in case you introduced new features.
40 |
41 | ### License
42 |
43 | Ashley is licensed under the [Apache 2 License](https://github.com/libgdx/ashley/blob/master/LICENSE), meaning you
44 | can use it free of charge, without strings attached in commercial and non-commercial projects. We love to
45 | get (non-mandatory) credit in case you release a game or app using Ashley!
46 |
47 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/RenderSystemTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests;
18 |
19 | import com.badlogic.ashley.core.Entity;
20 | import com.badlogic.ashley.core.PooledEngine;
21 | import com.badlogic.ashley.tests.components.MovementComponent;
22 | import com.badlogic.ashley.tests.components.PositionComponent;
23 | import com.badlogic.ashley.tests.components.VisualComponent;
24 | import com.badlogic.ashley.tests.systems.MovementSystem;
25 | import com.badlogic.ashley.tests.systems.RenderSystem;
26 | import com.badlogic.gdx.ApplicationAdapter;
27 | import com.badlogic.gdx.Gdx;
28 | import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
29 | import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
30 | import com.badlogic.gdx.graphics.GL20;
31 | import com.badlogic.gdx.graphics.OrthographicCamera;
32 | import com.badlogic.gdx.graphics.Texture;
33 | import com.badlogic.gdx.graphics.g2d.TextureRegion;
34 | import com.badlogic.gdx.math.MathUtils;
35 |
36 | public class RenderSystemTest {
37 | public static void main (String[] args) {
38 | LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
39 | config.width = 640;
40 | config.height = 480;
41 |
42 | new LwjglApplication(new MainClass(), config);
43 | }
44 |
45 | public static class MainClass extends ApplicationAdapter {
46 | PooledEngine engine;
47 |
48 | @Override
49 | public void create () {
50 | OrthographicCamera camera = new OrthographicCamera(640, 480);
51 | camera.position.set(320, 240, 0);
52 | camera.update();
53 |
54 | Texture crateTexture = new Texture("assets/crate.png");
55 | Texture coinTexture = new Texture("assets/coin.png");
56 |
57 | engine = new PooledEngine();
58 | engine.addSystem(new RenderSystem(camera));
59 | engine.addSystem(new MovementSystem());
60 |
61 | Entity crate = engine.createEntity();
62 | crate.add(new PositionComponent(50, 50));
63 | crate.add(new VisualComponent(new TextureRegion(crateTexture)));
64 |
65 | engine.addEntity(crate);
66 |
67 | TextureRegion coinRegion = new TextureRegion(coinTexture);
68 |
69 | for (int i = 0; i < 100; i++) {
70 | Entity coin = engine.createEntity();
71 | coin.add(new PositionComponent(MathUtils.random(640), MathUtils.random(480)));
72 | coin.add(new MovementComponent(10.0f, 10.0f));
73 | coin.add(new VisualComponent(coinRegion));
74 | engine.addEntity(coin);
75 | }
76 | }
77 |
78 | @Override
79 | public void render () {
80 | Gdx.gl.glClearColor(0, 0, 0, 1);
81 | Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
82 |
83 | engine.update(Gdx.graphics.getDeltaTime());
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/systems/IntervalIteratingSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import com.badlogic.ashley.core.Engine;
20 | import com.badlogic.ashley.core.Entity;
21 | import com.badlogic.ashley.core.EntitySystem;
22 | import com.badlogic.ashley.core.Family;
23 | import com.badlogic.ashley.utils.ImmutableArray;
24 |
25 | /**
26 | * A simple {@link EntitySystem} that processes a {@link Family} of entities not once per frame, but after a given interval.
27 | * Entity processing logic should be placed in {@link IntervalIteratingSystem#processEntity(Entity)}.
28 | * @author David Saltares
29 | */
30 | public abstract class IntervalIteratingSystem extends IntervalSystem {
31 | private Family family;
32 | private ImmutableArray entities;
33 |
34 | /**
35 | * @param family represents the collection of family the system should process
36 | * @param interval time in seconds between calls to {@link IntervalIteratingSystem#updateInterval()}.
37 | */
38 | public IntervalIteratingSystem (Family family, float interval) {
39 | this(family, interval, 0);
40 | }
41 |
42 | /**
43 | * @param family represents the collection of family the system should process
44 | * @param interval time in seconds between calls to {@link IntervalIteratingSystem#updateInterval()}.
45 | * @param priority
46 | */
47 | public IntervalIteratingSystem (Family family, float interval, int priority) {
48 | super(interval, priority);
49 | this.family = family;
50 | }
51 |
52 | @Override
53 | public void addedToEngine (Engine engine) {
54 | entities = engine.getEntitiesFor(family);
55 | }
56 |
57 | @Override
58 | protected void updateInterval () {
59 | startProcessing();
60 | for (int i = 0; i < entities.size(); ++i) {
61 | processEntity(entities.get(i));
62 | }
63 | endProcessing();
64 | }
65 |
66 | /**
67 | * @return set of entities processed by the system
68 | */
69 | public ImmutableArray getEntities () {
70 | return entities;
71 | }
72 |
73 | /**
74 | * @return the Family used when the system was created
75 | */
76 | public Family getFamily () {
77 | return family;
78 | }
79 |
80 | /**
81 | * The user should place the entity processing logic here.
82 | * @param entity
83 | */
84 | protected abstract void processEntity (Entity entity);
85 |
86 | /**
87 | * This method is called once on every update call of the EntitySystem, before entity processing begins. Override this method to
88 | * implement your specific startup conditions.
89 | */
90 | public void startProcessing() {}
91 |
92 | /**
93 | * This method is called once on every update call of the EntitySystem after entity processing is complete. Override this method to
94 | * implement your specific end conditions.
95 | */
96 | public void endProcessing() {}
97 | }
98 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/systems/IntervalIteratingTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import org.junit.Test;
20 |
21 | import com.badlogic.ashley.core.Component;
22 | import com.badlogic.ashley.core.ComponentMapper;
23 | import com.badlogic.ashley.core.Engine;
24 | import com.badlogic.ashley.core.Entity;
25 | import com.badlogic.ashley.core.Family;
26 | import com.badlogic.ashley.utils.ImmutableArray;
27 |
28 | import static org.junit.Assert.*;
29 |
30 | public class IntervalIteratingTest {
31 | private static final float deltaTime = 0.1f;
32 |
33 | private static class IntervalComponentSpy implements Component {
34 | public int numUpdates = 0;
35 | }
36 |
37 | private static class IntervalIteratingSystemSpy extends IntervalIteratingSystem {
38 | private ComponentMapper im;
39 | public int numStartProcessing;
40 | public int numEndProcessing;
41 |
42 |
43 | public IntervalIteratingSystemSpy () {
44 | super(Family.all(IntervalComponentSpy.class).get(), deltaTime * 2.0f);
45 |
46 | im = ComponentMapper.getFor(IntervalComponentSpy.class);
47 | }
48 |
49 | @Override
50 | public void startProcessing() {
51 | numStartProcessing++;
52 | }
53 |
54 | @Override
55 | protected void processEntity (Entity entity) {
56 | im.get(entity).numUpdates++;
57 | }
58 |
59 | @Override
60 | public void endProcessing() {
61 | numEndProcessing++;
62 | }
63 | }
64 |
65 | @Test
66 | public void intervalSystem () {
67 | Engine engine = new Engine();
68 | IntervalIteratingSystemSpy intervalSystemSpy = new IntervalIteratingSystemSpy();
69 | ImmutableArray entities = engine.getEntitiesFor(Family.all(IntervalComponentSpy.class).get());
70 | ComponentMapper im = ComponentMapper.getFor(IntervalComponentSpy.class);
71 |
72 | engine.addSystem(intervalSystemSpy);
73 |
74 | for (int i = 0; i < 10; ++i) {
75 | Entity entity = new Entity();
76 | entity.add(new IntervalComponentSpy());
77 | engine.addEntity(entity);
78 | }
79 |
80 | for (int i = 1; i <= 10; ++i) {
81 | engine.update(deltaTime);
82 |
83 | for (int j = 0; j < entities.size(); ++j) {
84 | assertEquals(i / 2, im.get(entities.get(j)).numUpdates);
85 | }
86 | }
87 | }
88 |
89 | @Test
90 | public void processingUtilityFunctions() {
91 | final Engine engine = new Engine();
92 |
93 | final IntervalIteratingSystemSpy system = new IntervalIteratingSystemSpy();
94 |
95 | engine.addSystem(system);
96 |
97 | engine.update(deltaTime);
98 | assertEquals(0, system.numStartProcessing);
99 | assertEquals(0, system.numEndProcessing);
100 |
101 | engine.update(deltaTime);
102 | assertEquals(1, system.numStartProcessing);
103 | assertEquals(1, system.numEndProcessing);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/ComponentType.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | import com.badlogic.gdx.utils.Bits;
20 | import com.badlogic.gdx.utils.ObjectMap;
21 |
22 | /**
23 | * Uniquely identifies a {@link Component} sub-class. It assigns them an index which is used internally for fast comparison and
24 | * retrieval. See {@link Family} and {@link Entity}. ComponentType is a package protected class. You cannot instantiate a
25 | * ComponentType. They can only be accessed via {@link #getIndexFor(Class extends Component>)}. Each component class will always
26 | * return the same instance of ComponentType.
27 | * @author Stefan Bachmann
28 | */
29 | public final class ComponentType {
30 | private static ObjectMap, ComponentType> assignedComponentTypes = new ObjectMap, ComponentType>();
31 | private static int typeIndex = 0;
32 |
33 | private final int index;
34 |
35 | private ComponentType () {
36 | index = typeIndex++;
37 | }
38 |
39 | /** @return This ComponentType's unique index */
40 | public int getIndex () {
41 | return index;
42 | }
43 |
44 | /**
45 | * @param componentType The {@link Component} class
46 | * @return A ComponentType matching the Component Class
47 | */
48 | public static ComponentType getFor (Class extends Component> componentType) {
49 | ComponentType type = assignedComponentTypes.get(componentType);
50 |
51 | if (type == null) {
52 | type = new ComponentType();
53 | assignedComponentTypes.put(componentType, type);
54 | }
55 |
56 | return type;
57 | }
58 |
59 | /**
60 | * Quick helper method. The same could be done via {@link ComponentType.getFor(Class extends Component>)}.
61 | * @param componentType The {@link Component} class
62 | * @return The index for the specified {@link Component} Class
63 | */
64 | public static int getIndexFor (Class extends Component> componentType) {
65 | return getFor(componentType).getIndex();
66 | }
67 |
68 | /**
69 | * @param componentTypes list of {@link Component} classes
70 | * @return Bits representing the collection of components for quick comparison and matching. See
71 | * {@link Family#getFor(Bits, Bits, Bits)}.
72 | */
73 | public static Bits getBitsFor (Class extends Component>... componentTypes) {
74 | Bits bits = new Bits();
75 |
76 | int typesLength = componentTypes.length;
77 | for (int i = 0; i < typesLength; i++) {
78 | bits.set(ComponentType.getIndexFor(componentTypes[i]));
79 | }
80 |
81 | return bits;
82 | }
83 |
84 | @Override
85 | public int hashCode () {
86 | return index;
87 | }
88 |
89 | @Override
90 | public boolean equals (Object obj) {
91 | if (this == obj) return true;
92 | if (obj == null) return false;
93 | if (getClass() != obj.getClass()) return false;
94 | ComponentType other = (ComponentType)obj;
95 | return index == other.index;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven'
2 | apply plugin: 'signing'
3 |
4 | group = 'com.badlogicgames.ashley'
5 | version = '1.8.0'
6 | ext.packaging = 'jar'
7 |
8 | def isDevBuild
9 | def isCiBuild
10 | def isReleaseBuild
11 |
12 | def sonatypeRepositoryUrl
13 |
14 | //set build variables based on build type (release, continuous integration, development)
15 | if(hasProperty("RELEASE")) {
16 | isReleaseBuild = true
17 | sonatypeRepositoryUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
18 | println "Performing release build"
19 | } else if (hasProperty("SNAPSHOT")) {
20 | isCiBuild = true
21 | version += "-SNAPSHOT"
22 | sonatypeRepositoryUrl = "https://oss.sonatype.org/content/repositories/snapshots/"
23 | println "Performing snapshot build"
24 | } else {
25 | isDevBuild = true
26 | println "Performing local build"
27 | }
28 |
29 | def getRepositoryUsername = {
30 | return project.hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "$System.env.NEXUS_USERNAME"
31 | }
32 |
33 | def getRepositoryPassword = {
34 | return project.hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "$System.env.NEXUS_PASSWORD"
35 | }
36 |
37 | repositories {
38 | mavenCentral()
39 | }
40 |
41 | task artifactDocs(type: Jar, dependsOn: javadoc) {
42 | classifier = 'javadoc'
43 | from 'build/docs/javadoc'
44 | }
45 |
46 | task artifactSources(type: Jar) {
47 | from sourceSets.main.allSource
48 | classifier = 'sources'
49 | }
50 |
51 | artifacts {
52 | archives jar
53 | archives artifactDocs
54 | archives artifactSources
55 | }
56 |
57 | if(isReleaseBuild) {
58 | signing {
59 | useGpgCmd()
60 | sign configurations.archives
61 | }
62 | } else {
63 | task signArchives {
64 | // do nothing
65 | }
66 | }
67 |
68 | uploadArchives {
69 | repositories {
70 | if (isDevBuild) {
71 | mavenLocal()
72 | }
73 | else {
74 | mavenDeployer {
75 | if(isReleaseBuild) {
76 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
77 | }
78 |
79 | repository(url: sonatypeRepositoryUrl) {
80 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
81 | }
82 |
83 | pom.version = version
84 | pom.packaging = 'jar'
85 |
86 | pom.project {
87 | name 'Ashley'
88 | description 'Ashley, a minimal entity framework inspired by Ash and Artemis'
89 | url 'https://github.com/libgdx/ashley'
90 |
91 | scm {
92 | url 'scm:git@github.com:libgdx/ashley.git'
93 | connection 'scm:git@github.com:libgdx/ashley.git'
94 | developerConnection 'scm:git@github.com:libgdx/ashley.git'
95 | }
96 |
97 | licenses {
98 | license {
99 | name 'The Apache Software License, Version 2.0'
100 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
101 | distribution 'repo'
102 | }
103 | }
104 |
105 | developers {
106 | developer {
107 | id 'stbachmann'
108 | name 'Stefan Bachmann'
109 | }
110 | developer {
111 | id 'saltares'
112 | name 'David Saltares'
113 | }
114 | }
115 | }
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/systems/IteratingSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import com.badlogic.ashley.core.Engine;
20 | import com.badlogic.ashley.core.Entity;
21 | import com.badlogic.ashley.core.EntitySystem;
22 | import com.badlogic.ashley.core.Family;
23 | import com.badlogic.ashley.utils.ImmutableArray;
24 |
25 | /**
26 | * A simple EntitySystem that iterates over each entity and calls processEntity() for each entity every time the EntitySystem is
27 | * updated. This is really just a convenience class as most systems iterate over a list of entities.
28 | * @author Stefan Bachmann
29 | */
30 | public abstract class IteratingSystem extends EntitySystem {
31 | private Family family;
32 | private ImmutableArray entities;
33 |
34 | /**
35 | * Instantiates a system that will iterate over the entities described by the Family.
36 | * @param family The family of entities iterated over in this System
37 | */
38 | public IteratingSystem (Family family) {
39 | this(family, 0);
40 | }
41 |
42 | /**
43 | * Instantiates a system that will iterate over the entities described by the Family, with a specific priority.
44 | * @param family The family of entities iterated over in this System
45 | * @param priority The priority to execute this system with (lower means higher priority)
46 | */
47 | public IteratingSystem (Family family, int priority) {
48 | super(priority);
49 |
50 | this.family = family;
51 | }
52 |
53 | @Override
54 | public void addedToEngine (Engine engine) {
55 | entities = engine.getEntitiesFor(family);
56 | }
57 |
58 | @Override
59 | public void removedFromEngine (Engine engine) {
60 | entities = null;
61 | }
62 |
63 | @Override
64 | public void update (float deltaTime) {
65 | startProcessing();
66 | for (int i = 0; i < entities.size(); ++i) {
67 | processEntity(entities.get(i), deltaTime);
68 | }
69 | endProcessing();
70 | }
71 |
72 | /**
73 | * @return set of entities processed by the system
74 | */
75 | public ImmutableArray getEntities () {
76 | return entities;
77 | }
78 |
79 | /**
80 | * @return the Family used when the system was created
81 | */
82 | public Family getFamily () {
83 | return family;
84 | }
85 |
86 | /**
87 | * This method is called on every entity on every update call of the EntitySystem. Override this to implement your system's
88 | * specific processing.
89 | * @param entity The current Entity being processed
90 | * @param deltaTime The delta time between the last and current frame
91 | */
92 | protected abstract void processEntity (Entity entity, float deltaTime);
93 |
94 | /**
95 | * This method is called once on every update call of the EntitySystem, before entity processing begins. Override this method to
96 | * implement your specific startup conditions.
97 | */
98 | public void startProcessing() {}
99 |
100 | /**
101 | * This method is called once on every update call of the EntitySystem after entity processing is complete. Override this method to
102 | * implement your specific end conditions.
103 | */
104 | public void endProcessing() {}
105 | }
106 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/ashley/AshleyBenchmark.java:
--------------------------------------------------------------------------------
1 |
2 | package com.badlogic.ashley.benchmark.ashley;
3 |
4 | import org.junit.BeforeClass;
5 | import org.junit.Test;
6 |
7 | import com.badlogic.ashley.benchmark.Constants;
8 | import com.badlogic.ashley.benchmark.Constants.ComponentType;
9 | import com.badlogic.ashley.benchmark.ashley.components.MovementComponent;
10 | import com.badlogic.ashley.benchmark.ashley.components.PositionComponent;
11 | import com.badlogic.ashley.benchmark.ashley.components.RadiusComponent;
12 | import com.badlogic.ashley.benchmark.ashley.components.StateComponent;
13 | import com.badlogic.ashley.benchmark.ashley.systems.CollisionSystem;
14 | import com.badlogic.ashley.benchmark.ashley.systems.MovementSystem;
15 | import com.badlogic.ashley.benchmark.ashley.systems.RemovalSystem;
16 | import com.badlogic.ashley.benchmark.ashley.systems.StateSystem;
17 | import com.badlogic.ashley.core.Engine;
18 | import com.badlogic.ashley.core.Entity;
19 | import com.badlogic.gdx.math.MathUtils;
20 | import com.carrotsearch.junitbenchmarks.AbstractBenchmark;
21 | import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
22 |
23 | public class AshleyBenchmark extends AbstractBenchmark {
24 | private static Engine engineSmall;
25 | private static Engine engineMedium;
26 | private static Engine engineBig;
27 |
28 | @BeforeClass
29 | public static void prepare () {
30 | engineSmall = prepareEngine(Constants.ENTITIES_SMALL_TEST);
31 | engineMedium = prepareEngine(Constants.ENTITIES_MEDIUM_TEST);
32 | engineBig = prepareEngine(Constants.ENTITIES_BIG_TEST);
33 | }
34 |
35 | @BenchmarkOptions(benchmarkRounds = Constants.BENCHMARK_ROUNDS, warmupRounds = Constants.WARMUP_ROUNDS)
36 | @Test
37 | public void ashleySmallTest () {
38 | runEngineTest(engineSmall);
39 | }
40 |
41 | @BenchmarkOptions(benchmarkRounds = Constants.BENCHMARK_ROUNDS, warmupRounds = Constants.WARMUP_ROUNDS)
42 | @Test
43 | public void ashleyMediumTest () {
44 | runEngineTest(engineMedium);
45 | }
46 |
47 | @BenchmarkOptions(benchmarkRounds = Constants.BENCHMARK_ROUNDS, warmupRounds = Constants.WARMUP_ROUNDS)
48 | @Test
49 | public void ashleyBigTest () {
50 | runEngineTest(engineBig);
51 | }
52 |
53 | private void runEngineTest (Engine engine) {
54 | for (int i = 0; i < Constants.FRAMES; ++i) {
55 | engine.update(Constants.DELTA_TIME);
56 | }
57 | }
58 |
59 | private static Engine prepareEngine (int numEntities) {
60 | Engine engine = new Engine();
61 |
62 | engine.addSystem(new MovementSystem());
63 | engine.addSystem(new StateSystem());
64 | engine.addSystem(new CollisionSystem());
65 | engine.addSystem(new RemovalSystem());
66 |
67 | for (int i = 0; i < numEntities; ++i) {
68 | Entity entity = new Entity();
69 |
70 | if (Constants.shouldHaveComponent(ComponentType.POSITION, i)) {
71 | PositionComponent pos = new PositionComponent();
72 | pos.pos.x = MathUtils.random(Constants.MIN_POS, Constants.MAX_POS);
73 | pos.pos.y = MathUtils.random(Constants.MIN_POS, Constants.MAX_POS);
74 | entity.add(pos);
75 | }
76 |
77 | if (Constants.shouldHaveComponent(ComponentType.MOVEMENT, i)) {
78 | MovementComponent mov = new MovementComponent();
79 | mov.velocity.x = MathUtils.random(Constants.MIN_VEL, Constants.MAX_VEL);
80 | mov.velocity.y = MathUtils.random(Constants.MIN_VEL, Constants.MAX_VEL);
81 | mov.accel.x = MathUtils.random(Constants.MIN_ACC, Constants.MAX_ACC);
82 | mov.accel.y = MathUtils.random(Constants.MIN_ACC, Constants.MAX_ACC);
83 |
84 | entity.add(mov);
85 | }
86 |
87 | if (Constants.shouldHaveComponent(ComponentType.RADIUS, i)) {
88 | RadiusComponent rad = new RadiusComponent();
89 | rad.radius = MathUtils.random(Constants.MIN_RADIUS, Constants.MAX_RADIUS);
90 | entity.add(rad);
91 | }
92 |
93 | if (Constants.shouldHaveComponent(ComponentType.STATE, i)) {
94 | entity.add(new StateComponent());
95 | }
96 |
97 | engine.addEntity(entity);
98 | }
99 |
100 | return engine;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/benchmarks/src/main/java/com/badlogic/ashley/benchmark/artemis/ArtemisBenchmark.java:
--------------------------------------------------------------------------------
1 |
2 | package com.badlogic.ashley.benchmark.artemis;
3 |
4 | import org.junit.BeforeClass;
5 | import org.junit.Test;
6 |
7 | import com.artemis.Entity;
8 | import com.artemis.World;
9 | import com.badlogic.ashley.benchmark.Constants;
10 | import com.badlogic.ashley.benchmark.Constants.ComponentType;
11 | import com.badlogic.ashley.benchmark.artemis.components.MovementComponent;
12 | import com.badlogic.ashley.benchmark.artemis.components.PositionComponent;
13 | import com.badlogic.ashley.benchmark.artemis.components.RadiusComponent;
14 | import com.badlogic.ashley.benchmark.artemis.components.StateComponent;
15 | import com.badlogic.ashley.benchmark.artemis.systems.CollisionSystem;
16 | import com.badlogic.ashley.benchmark.artemis.systems.MovementSystem;
17 | import com.badlogic.ashley.benchmark.artemis.systems.RemovalSystem;
18 | import com.badlogic.ashley.benchmark.artemis.systems.StateSystem;
19 | import com.badlogic.gdx.math.MathUtils;
20 | import com.carrotsearch.junitbenchmarks.AbstractBenchmark;
21 | import com.carrotsearch.junitbenchmarks.BenchmarkOptions;
22 |
23 | public class ArtemisBenchmark extends AbstractBenchmark {
24 | private static World worldSmall;
25 | private static World worldMedium;
26 | private static World worldBig;
27 |
28 | @BeforeClass
29 | public static void prepare () {
30 | worldSmall = prepareWorld(Constants.ENTITIES_SMALL_TEST);
31 | worldMedium = prepareWorld(Constants.ENTITIES_MEDIUM_TEST);
32 | worldBig = prepareWorld(Constants.ENTITIES_BIG_TEST);
33 | }
34 |
35 | @BenchmarkOptions(benchmarkRounds = Constants.BENCHMARK_ROUNDS, warmupRounds = Constants.WARMUP_ROUNDS)
36 | @Test
37 | public void worldSmallTest () {
38 | runWorldTest(worldSmall);
39 | }
40 |
41 | @BenchmarkOptions(benchmarkRounds = Constants.BENCHMARK_ROUNDS, warmupRounds = Constants.WARMUP_ROUNDS)
42 | @Test
43 | public void worldMediumTest () {
44 | runWorldTest(worldMedium);
45 | }
46 |
47 | @BenchmarkOptions(benchmarkRounds = Constants.BENCHMARK_ROUNDS, warmupRounds = Constants.WARMUP_ROUNDS)
48 | @Test
49 | public void worldBigTest () {
50 | runWorldTest(worldBig);
51 | }
52 |
53 | private void runWorldTest (World world) {
54 | for (int i = 0; i < Constants.FRAMES; ++i) {
55 | world.setDelta(Constants.DELTA_TIME);
56 | world.process();
57 | }
58 | }
59 |
60 | private static World prepareWorld (int numEntities) {
61 | World world = new World();
62 |
63 | world.setSystem(new MovementSystem());
64 | world.setSystem(new StateSystem());
65 | world.setSystem(new CollisionSystem());
66 | world.setSystem(new RemovalSystem());
67 |
68 | world.initialize();
69 |
70 | for (int i = 0; i < numEntities; ++i) {
71 | Entity entity = world.createEntity();
72 |
73 | if (Constants.shouldHaveComponent(ComponentType.POSITION, i)) {
74 | PositionComponent pos = new PositionComponent();
75 | pos.pos.x = MathUtils.random(Constants.MIN_POS, Constants.MAX_POS);
76 | pos.pos.y = MathUtils.random(Constants.MIN_POS, Constants.MAX_POS);
77 | entity.addComponent(pos);
78 | }
79 |
80 | if (Constants.shouldHaveComponent(ComponentType.MOVEMENT, i)) {
81 | MovementComponent mov = new MovementComponent();
82 | mov.velocity.x = MathUtils.random(Constants.MIN_VEL, Constants.MAX_VEL);
83 | mov.velocity.y = MathUtils.random(Constants.MIN_VEL, Constants.MAX_VEL);
84 | mov.accel.x = MathUtils.random(Constants.MIN_ACC, Constants.MAX_ACC);
85 | mov.accel.y = MathUtils.random(Constants.MIN_ACC, Constants.MAX_ACC);
86 |
87 | entity.addComponent(mov);
88 | }
89 |
90 | if (Constants.shouldHaveComponent(ComponentType.RADIUS, i)) {
91 | RadiusComponent rad = new RadiusComponent();
92 | rad.radius = MathUtils.random(Constants.MIN_RADIUS, Constants.MAX_RADIUS);
93 | entity.addComponent(rad);
94 | }
95 |
96 | if (Constants.shouldHaveComponent(ComponentType.STATE, i)) {
97 | entity.addComponent(new StateComponent());
98 | }
99 |
100 | world.addEntity(entity);
101 | }
102 |
103 | return world;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/tests/src/com/badlogic/ashley/tests/BasicTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.tests;
18 |
19 | import com.badlogic.ashley.core.ComponentMapper;
20 | import com.badlogic.ashley.core.Engine;
21 | import com.badlogic.ashley.core.Entity;
22 | import com.badlogic.ashley.core.EntityListener;
23 | import com.badlogic.ashley.core.EntitySystem;
24 | import com.badlogic.ashley.core.Family;
25 | import com.badlogic.ashley.core.PooledEngine;
26 | import com.badlogic.ashley.tests.components.MovementComponent;
27 | import com.badlogic.ashley.tests.components.PositionComponent;
28 | import com.badlogic.ashley.utils.ImmutableArray;
29 |
30 | public class BasicTest {
31 |
32 | public static void main (String[] args) {
33 | PooledEngine engine = new PooledEngine();
34 |
35 | MovementSystem movementSystem = new MovementSystem();
36 | PositionSystem positionSystem = new PositionSystem();
37 |
38 | engine.addSystem(movementSystem);
39 | engine.addSystem(positionSystem);
40 |
41 | Listener listener = new Listener();
42 | engine.addEntityListener(listener);
43 |
44 | for (int i = 0; i < 10; i++) {
45 | Entity entity = engine.createEntity();
46 | entity.add(new PositionComponent(10, 0));
47 | if (i > 5) entity.add(new MovementComponent(10, 2));
48 |
49 | engine.addEntity(entity);
50 | }
51 |
52 | log("MovementSystem has: " + movementSystem.entities.size() + " entities.");
53 | log("PositionSystem has: " + positionSystem.entities.size() + " entities.");
54 |
55 | for (int i = 0; i < 10; i++) {
56 | engine.update(0.25f);
57 |
58 | if (i > 5) engine.removeSystem(movementSystem);
59 | }
60 |
61 | engine.removeEntityListener(listener);
62 | }
63 |
64 | public static class PositionSystem extends EntitySystem {
65 | public ImmutableArray entities;
66 |
67 | @Override
68 | public void addedToEngine (Engine engine) {
69 | entities = engine.getEntitiesFor(Family.all(PositionComponent.class).get());
70 | log("PositionSystem added to engine.");
71 | }
72 |
73 | @Override
74 | public void removedFromEngine (Engine engine) {
75 | log("PositionSystem removed from engine.");
76 | entities = null;
77 | }
78 | }
79 |
80 | public static class MovementSystem extends EntitySystem {
81 | public ImmutableArray entities;
82 |
83 | private ComponentMapper pm = ComponentMapper.getFor(PositionComponent.class);
84 | private ComponentMapper mm = ComponentMapper.getFor(MovementComponent.class);
85 |
86 | @Override
87 | public void addedToEngine (Engine engine) {
88 | entities = engine.getEntitiesFor(Family.all(PositionComponent.class, MovementComponent.class).get());
89 | log("MovementSystem added to engine.");
90 | }
91 |
92 | @Override
93 | public void removedFromEngine (Engine engine) {
94 | log("MovementSystem removed from engine.");
95 | entities = null;
96 | }
97 |
98 | @Override
99 | public void update (float deltaTime) {
100 |
101 | for (int i = 0; i < entities.size(); ++i) {
102 | Entity e = entities.get(i);
103 |
104 | PositionComponent p = pm.get(e);
105 | MovementComponent m = mm.get(e);
106 |
107 | p.x += m.velocityX * deltaTime;
108 | p.y += m.velocityY * deltaTime;
109 | }
110 |
111 | log(entities.size() + " Entities updated in MovementSystem.");
112 | }
113 | }
114 |
115 | public static class Listener implements EntityListener {
116 |
117 | @Override
118 | public void entityAdded (Entity entity) {
119 | log("Entity added " + entity);
120 | }
121 |
122 | @Override
123 | public void entityRemoved (Entity entity) {
124 | log("Entity removed " + entity);
125 | }
126 | }
127 |
128 | public static void log (String string) {
129 | System.out.println(string);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/EntityManager.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 |
4 | import com.badlogic.ashley.utils.ImmutableArray;
5 | import com.badlogic.gdx.utils.Array;
6 | import com.badlogic.gdx.utils.ObjectSet;
7 | import com.badlogic.gdx.utils.Pool;
8 |
9 | class EntityManager {
10 | private EntityListener listener;
11 | private Array entities = new Array(false, 16);
12 | private ObjectSet entitySet = new ObjectSet();
13 | private ImmutableArray immutableEntities = new ImmutableArray(entities);
14 | private Array pendingOperations = new Array(false, 16);
15 | private EntityOperationPool entityOperationPool = new EntityOperationPool();
16 |
17 | public EntityManager(EntityListener listener) {
18 | this.listener = listener;
19 | }
20 |
21 | public void addEntity(Entity entity){
22 | addEntity(entity, false);
23 | }
24 |
25 | public void addEntity(Entity entity, boolean delayed){
26 | entity.scheduledForRemoval = false;
27 | if (delayed) {
28 | EntityOperation operation = entityOperationPool.obtain();
29 | operation.entity = entity;
30 | operation.type = EntityOperation.Type.Add;
31 | pendingOperations.add(operation);
32 | }
33 | else {
34 | addEntityInternal(entity);
35 | }
36 | }
37 |
38 | public void removeEntity(Entity entity){
39 | removeEntity(entity, false);
40 | }
41 |
42 | public void removeEntity(Entity entity, boolean delayed){
43 | if (delayed) {
44 | if(entity.scheduledForRemoval) {
45 | return;
46 | }
47 | entity.scheduledForRemoval = true;
48 | EntityOperation operation = entityOperationPool.obtain();
49 | operation.entity = entity;
50 | operation.type = EntityOperation.Type.Remove;
51 | pendingOperations.add(operation);
52 | }
53 | else {
54 | removeEntityInternal(entity);
55 | }
56 | }
57 |
58 | public void removeAllEntities() {
59 | removeAllEntities(immutableEntities);
60 | }
61 |
62 | public void removeAllEntities(boolean delayed) {
63 | removeAllEntities(immutableEntities, delayed);
64 | }
65 |
66 | public void removeAllEntities(ImmutableArray entities) {
67 | removeAllEntities(entities, false);
68 | }
69 |
70 | public void removeAllEntities(ImmutableArray entities, boolean delayed) {
71 | if (delayed) {
72 | for(Entity entity: entities) {
73 | entity.scheduledForRemoval = true;
74 | }
75 | EntityOperation operation = entityOperationPool.obtain();
76 | operation.type = EntityOperation.Type.RemoveAll;
77 | operation.entities = entities;
78 | pendingOperations.add(operation);
79 | }
80 | else {
81 | while(entities.size() > 0) {
82 | removeEntity(entities.first(), false);
83 | }
84 | }
85 | }
86 |
87 | public ImmutableArray getEntities() {
88 | return immutableEntities;
89 | }
90 |
91 | public boolean hasPendingOperations() {
92 | return pendingOperations.size > 0;
93 | }
94 |
95 | public void processPendingOperations() {
96 | for (int i = 0; i < pendingOperations.size; ++i) {
97 | EntityOperation operation = pendingOperations.get(i);
98 |
99 | switch(operation.type) {
100 | case Add: addEntityInternal(operation.entity); break;
101 | case Remove: removeEntityInternal(operation.entity); break;
102 | case RemoveAll:
103 | while(operation.entities.size() > 0) {
104 | removeEntityInternal(operation.entities.first());
105 | }
106 | break;
107 | default:
108 | throw new AssertionError("Unexpected EntityOperation type");
109 | }
110 |
111 | entityOperationPool.free(operation);
112 | }
113 |
114 | pendingOperations.clear();
115 | }
116 |
117 | protected void removeEntityInternal(Entity entity) {
118 | boolean removed = entitySet.remove(entity);
119 |
120 | if (removed) {
121 | entity.scheduledForRemoval = false;
122 | entity.removing = true;
123 | entities.removeValue(entity, true);
124 | listener.entityRemoved(entity);
125 | entity.removing = false;
126 | }
127 | }
128 |
129 | protected void addEntityInternal(Entity entity) {
130 | if (entitySet.contains(entity)) {
131 | throw new IllegalArgumentException("Entity is already registered " + entity);
132 | }
133 |
134 | entities.add(entity);
135 | entitySet.add(entity);
136 |
137 | listener.entityAdded(entity);
138 | }
139 |
140 | private static class EntityOperation implements Pool.Poolable {
141 | public enum Type {
142 | Add,
143 | Remove,
144 | RemoveAll
145 | }
146 |
147 | public Type type;
148 | public Entity entity;
149 | public ImmutableArray entities;
150 |
151 | @Override
152 | public void reset() {
153 | entity = null;
154 | }
155 | }
156 |
157 | private static class EntityOperationPool extends Pool {
158 | @Override
159 | protected EntityOperation newObject() {
160 | return new EntityOperation();
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/signals/SignalTests.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.signals;
18 |
19 | import static org.junit.Assert.*;
20 |
21 | import org.junit.Test;
22 |
23 | import com.badlogic.ashley.signals.Listener;
24 | import com.badlogic.ashley.signals.Signal;
25 | import com.badlogic.gdx.utils.Array;
26 |
27 | public class SignalTests {
28 |
29 | private static class Dummy {
30 |
31 | }
32 |
33 | private static class ListenerMock implements Listener {
34 |
35 | public int count = 0;
36 |
37 | @Override
38 | public void receive (Signal signal, Dummy object) {
39 | ++count;
40 |
41 | assertNotNull(signal);
42 | assertNotNull(object);
43 | }
44 | }
45 |
46 | private static class RemoveWhileDispatchListenerMock implements Listener {
47 | public int count = 0;
48 |
49 | @Override
50 | public void receive (Signal signal, Dummy object) {
51 | ++count;
52 | signal.remove(this);
53 | }
54 | }
55 |
56 | @Test
57 | public void addListenerAndDispatch () {
58 | Dummy dummy = new Dummy();
59 | Signal signal = new Signal();
60 | ListenerMock listener = new ListenerMock();
61 | signal.add(listener);
62 |
63 | for (int i = 0; i < 10; ++i) {
64 | assertEquals(i, listener.count);
65 | signal.dispatch(dummy);
66 | assertEquals(i + 1, listener.count);
67 | }
68 | }
69 |
70 | @Test
71 | public void addListenersAndDispatch () {
72 | Dummy dummy = new Dummy();
73 | Signal signal = new Signal();
74 | Array listeners = new Array();
75 |
76 | int numListeners = 10;
77 |
78 | while (listeners.size < numListeners) {
79 | ListenerMock listener = new ListenerMock();
80 | listeners.add(listener);
81 | signal.add(listener);
82 | }
83 |
84 | int numDispatchs = 10;
85 |
86 | for (int i = 0; i < numDispatchs; ++i) {
87 | for (ListenerMock listener : listeners) {
88 | assertEquals(i, listener.count);
89 | }
90 |
91 | signal.dispatch(dummy);
92 |
93 | for (ListenerMock listener : listeners) {
94 | assertEquals(i + 1, listener.count);
95 | }
96 | }
97 | }
98 |
99 | @Test
100 | public void addListenerDispatchAndRemove () {
101 | Dummy dummy = new Dummy();
102 | Signal signal = new Signal();
103 | ListenerMock listenerA = new ListenerMock();
104 | ListenerMock listenerB = new ListenerMock();
105 |
106 | signal.add(listenerA);
107 | signal.add(listenerB);
108 |
109 | int numDispatchs = 5;
110 |
111 | for (int i = 0; i < numDispatchs; ++i) {
112 | assertEquals(i, listenerA.count);
113 | assertEquals(i, listenerB.count);
114 |
115 | signal.dispatch(dummy);
116 |
117 | assertEquals(i + 1, listenerA.count);
118 | assertEquals(i + 1, listenerB.count);
119 | }
120 |
121 | signal.remove(listenerB);
122 |
123 | for (int i = 0; i < numDispatchs; ++i) {
124 | assertEquals(i + numDispatchs, listenerA.count);
125 | assertEquals(numDispatchs, listenerB.count);
126 |
127 | signal.dispatch(dummy);
128 |
129 | assertEquals(i + 1 + numDispatchs, listenerA.count);
130 | assertEquals(numDispatchs, listenerB.count);
131 | }
132 | }
133 |
134 | @Test
135 | public void removeWhileDispatch () {
136 | Dummy dummy = new Dummy();
137 | Signal signal = new Signal();
138 | RemoveWhileDispatchListenerMock listenerA = new RemoveWhileDispatchListenerMock();
139 | ListenerMock listenerB = new ListenerMock();
140 |
141 | signal.add(listenerA);
142 | signal.add(listenerB);
143 |
144 | signal.dispatch(dummy);
145 |
146 | assertEquals(1, listenerA.count);
147 | assertEquals(1, listenerB.count);
148 | }
149 |
150 | @Test
151 | public void removeAll () {
152 | Dummy dummy = new Dummy();
153 | Signal signal = new Signal();
154 |
155 | ListenerMock listenerA = new ListenerMock();
156 | ListenerMock listenerB = new ListenerMock();
157 |
158 | signal.add(listenerA);
159 | signal.add(listenerB);
160 |
161 | signal.dispatch(dummy);
162 |
163 | assertEquals(1, listenerA.count);
164 | assertEquals(1, listenerB.count);
165 |
166 | signal.removeAllListeners();
167 |
168 | signal.dispatch(dummy);
169 |
170 | assertEquals(1, listenerA.count);
171 | assertEquals(1, listenerB.count);
172 | }
173 |
174 | }
175 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/utils/Bag.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.utils;
18 |
19 | /**
20 | * Fast collection similar to Array that grows on demand as elements are accessed. It does not preserve order of elements.
21 | * Inspired by Artemis Bag.
22 | */
23 | public class Bag {
24 | private E[] data;
25 | private int size = 0;
26 |
27 | /**
28 | * Empty Bag with an initial capacity of 64.
29 | */
30 | public Bag () {
31 | this(64);
32 | }
33 |
34 | /**
35 | * Empty Bag with the specified initial capacity.
36 | * @param capacity the initial capacity of Bag.
37 | */
38 | @SuppressWarnings("unchecked")
39 | public Bag (int capacity) {
40 | data = (E[])new Object[capacity];
41 | }
42 |
43 | /**
44 | * Removes the element at the specified position in this Bag. Order of elements is not preserved.
45 | * @param index
46 | * @return element that was removed from the Bag.
47 | */
48 | public E remove (int index) {
49 | E e = data[index]; // make copy of element to remove so it can be returned
50 | data[index] = data[--size]; // overwrite item to remove with last element
51 | data[size] = null; // null last element, so gc can do its work
52 | return e;
53 | }
54 |
55 | /**
56 | * Removes and return the last object in the bag.
57 | * @return the last object in the bag, null if empty.
58 | */
59 | public E removeLast () {
60 | if (size > 0) {
61 | E e = data[--size];
62 | data[size] = null;
63 | return e;
64 | }
65 |
66 | return null;
67 | }
68 |
69 | /**
70 | * Removes the first occurrence of the specified element from this Bag, if it is present. If the Bag does not contain the
71 | * element, it is unchanged. It does not preserve order of elements.
72 | * @param e
73 | * @return true if the element was removed.
74 | */
75 | public boolean remove (E e) {
76 | for (int i = 0; i < size; i++) {
77 | E e2 = data[i];
78 |
79 | if (e == e2) {
80 | data[i] = data[--size]; // overwrite item to remove with last element
81 | data[size] = null; // null last element, so gc can do its work
82 | return true;
83 | }
84 | }
85 |
86 | return false;
87 | }
88 |
89 | /**
90 | * Check if bag contains this element. The operator == is used to check for equality.
91 | */
92 | public boolean contains (E e) {
93 | for (int i = 0; size > i; i++) {
94 | if (e == data[i]) {
95 | return true;
96 | }
97 | }
98 | return false;
99 | }
100 |
101 | /**
102 | * @return the element at the specified position in Bag.
103 | */
104 | public E get (int index) {
105 | return data[index];
106 | }
107 |
108 | /**
109 | * @return the number of elements in this bag.
110 | */
111 | public int size () {
112 | return size;
113 | }
114 |
115 | /**
116 | * @return the number of elements the bag can hold without growing.
117 | */
118 | public int getCapacity () {
119 | return data.length;
120 | }
121 |
122 | /**
123 | * @param index
124 | * @return whether or not the index is within the bounds of the collection
125 | */
126 | public boolean isIndexWithinBounds (int index) {
127 | return index < getCapacity();
128 | }
129 |
130 | /**
131 | * @return true if this list contains no elements
132 | */
133 | public boolean isEmpty () {
134 | return size == 0;
135 | }
136 |
137 | /**
138 | * Adds the specified element to the end of this bag. if needed also increases the capacity of the bag.
139 | */
140 | public void add (E e) {
141 | // is size greater than capacity increase capacity
142 | if (size == data.length) {
143 | grow();
144 | }
145 |
146 | data[size++] = e;
147 | }
148 |
149 | /**
150 | * Set element at specified index in the bag.
151 | */
152 | public void set (int index, E e) {
153 | if (index >= data.length) {
154 | grow(index * 2);
155 | }
156 | size = Math.max(size, index + 1);
157 | data[index] = e;
158 | }
159 |
160 | /**
161 | * Removes all of the elements from this bag. The bag will be empty after this call returns.
162 | */
163 | public void clear () {
164 | // null all elements so gc can clean up
165 | for (int i = 0; i < size; i++) {
166 | data[i] = null;
167 | }
168 |
169 | size = 0;
170 | }
171 |
172 | private void grow () {
173 | int newCapacity = (data.length * 3) / 2 + 1;
174 | grow(newCapacity);
175 | }
176 |
177 | @SuppressWarnings("unchecked")
178 | private void grow (int newCapacity) {
179 | E[] oldData = data;
180 | data = (E[])new Object[newCapacity];
181 | System.arraycopy(oldData, 0, data, 0, oldData.length);
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/EntityManagerTests.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 |
7 | import com.badlogic.ashley.utils.ImmutableArray;
8 | import com.badlogic.gdx.utils.Array;
9 |
10 | public class EntityManagerTests {
11 |
12 | private static class EntityListenerMock implements EntityListener {
13 |
14 | public int addedCount = 0;
15 | public int removedCount = 0;
16 |
17 | @Override
18 | public void entityAdded (Entity entity) {
19 | ++addedCount;
20 | assertNotNull(entity);
21 | }
22 |
23 | @Override
24 | public void entityRemoved (Entity entity) {
25 | ++removedCount;
26 | assertNotNull(entity);
27 | }
28 | }
29 |
30 | @Test
31 | public void addAndRemoveEntity () {
32 | EntityListenerMock listener = new EntityListenerMock();
33 | EntityManager manager = new EntityManager(listener);
34 |
35 | Entity entity1 = new Entity();
36 | manager.addEntity(entity1);
37 |
38 | assertEquals(1, listener.addedCount);
39 | Entity entity2 = new Entity();
40 | manager.addEntity(entity2);
41 |
42 | assertEquals(2, listener.addedCount);
43 |
44 | manager.removeAllEntities();
45 |
46 | assertEquals(2, listener.removedCount);
47 | }
48 |
49 | @Test
50 | public void getEntities () {
51 | int numEntities = 10;
52 |
53 | EntityListenerMock listener = new EntityListenerMock();
54 | EntityManager manager = new EntityManager(listener);
55 |
56 | Array entities = new Array();
57 |
58 | for (int i = 0; i < numEntities; ++i) {
59 | Entity entity = new Entity();
60 | entities.add(entity);
61 | manager.addEntity(entity);
62 | }
63 |
64 | ImmutableArray engineEntities = manager.getEntities();
65 |
66 | assertEquals(entities.size, engineEntities.size());
67 |
68 | for (int i = 0; i < numEntities; ++i) {
69 | assertEquals(entities.get(i), engineEntities.get(i));
70 | }
71 |
72 | manager.removeAllEntities();
73 |
74 | assertEquals(0, engineEntities.size());
75 | }
76 |
77 | @Test(expected=IllegalArgumentException.class)
78 | public void addEntityTwice1 () {
79 | EntityListenerMock listener = new EntityListenerMock();
80 | EntityManager manager = new EntityManager(listener);
81 | Entity entity = new Entity();
82 | manager.addEntity(entity);
83 | manager.addEntity(entity);
84 | }
85 |
86 | @Test(expected=IllegalArgumentException.class)
87 | public void addEntityTwice2() {
88 | EntityListenerMock listener = new EntityListenerMock();
89 | EntityManager manager = new EntityManager(listener);
90 | Entity entity = new Entity();
91 | manager.addEntity(entity, false);
92 | manager.addEntity(entity, false);
93 | }
94 |
95 | @Test(expected=IllegalArgumentException.class)
96 | public void addEntityTwiceDelayed() {
97 | EntityListenerMock listener = new EntityListenerMock();
98 | EntityManager manager = new EntityManager(listener);
99 |
100 | Entity entity = new Entity();
101 | manager.addEntity(entity, true);
102 | manager.addEntity(entity, true);
103 | manager.processPendingOperations();
104 | }
105 |
106 | @Test
107 | public void delayedOperationsOrder() {
108 | EntityListenerMock listener = new EntityListenerMock();
109 | EntityManager manager = new EntityManager(listener);
110 |
111 | Entity entityA = new Entity();
112 | Entity entityB = new Entity();
113 |
114 | boolean delayed = true;
115 | manager.addEntity(entityA);
116 | manager.addEntity(entityB);
117 |
118 | assertEquals(2, manager.getEntities().size());
119 |
120 | Entity entityC = new Entity();
121 | Entity entityD = new Entity();
122 | manager.removeAllEntities(delayed);
123 | manager.addEntity(entityC, delayed);
124 | manager.addEntity(entityD, delayed);
125 | manager.processPendingOperations();
126 |
127 | assertEquals(2, manager.getEntities().size());
128 | assertNotEquals(-1, manager.getEntities().indexOf(entityC, true));
129 | assertNotEquals(-1, manager.getEntities().indexOf(entityD, true));
130 | }
131 |
132 | @Test
133 | public void removeAndAddEntityDelayed() {
134 | EntityListenerMock listener = new EntityListenerMock();
135 | EntityManager manager = new EntityManager(listener);
136 |
137 | Entity entity = new Entity();
138 | manager.addEntity(entity, false); // immediate
139 | assertEquals(1, manager.getEntities().size());
140 |
141 | manager.removeEntity(entity, true); // delayed
142 | assertEquals(1, manager.getEntities().size());
143 |
144 | manager.addEntity(entity, true); // delayed
145 | assertEquals(1, manager.getEntities().size());
146 |
147 | manager.processPendingOperations();
148 | assertEquals(1, manager.getEntities().size());
149 | }
150 |
151 | @Test
152 | public void removeAllAndAddEntityDelayed() {
153 | EntityListenerMock listener = new EntityListenerMock();
154 | EntityManager manager = new EntityManager(listener);
155 |
156 | Entity entity = new Entity();
157 | manager.addEntity(entity, false); // immediate
158 | assertEquals(1, manager.getEntities().size());
159 |
160 | manager.removeAllEntities(true); // delayed
161 | assertEquals(1, manager.getEntities().size());
162 |
163 | manager.addEntity(entity, true); // delayed
164 | assertEquals(1, manager.getEntities().size());
165 |
166 | manager.processPendingOperations();
167 | assertEquals(1, manager.getEntities().size());
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/FamilyManager.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import com.badlogic.ashley.utils.ImmutableArray;
4 | import com.badlogic.gdx.utils.Array;
5 | import com.badlogic.gdx.utils.Bits;
6 | import com.badlogic.gdx.utils.ObjectMap;
7 | import com.badlogic.gdx.utils.Pool;
8 | import com.badlogic.gdx.utils.SnapshotArray;
9 |
10 | class FamilyManager {
11 | ImmutableArray entities;
12 | private ObjectMap> families = new ObjectMap>();
13 | private ObjectMap> immutableFamilies = new ObjectMap>();
14 | private SnapshotArray entityListeners = new SnapshotArray(true, 16);
15 | private ObjectMap entityListenerMasks = new ObjectMap();
16 | private BitsPool bitsPool = new BitsPool();
17 | private boolean notifying = false;
18 |
19 | public FamilyManager(ImmutableArray entities) {
20 | this.entities = entities;
21 | }
22 |
23 | public ImmutableArray getEntitiesFor(Family family) {
24 | return registerFamily(family);
25 | }
26 |
27 | public boolean notifying() {
28 | return notifying;
29 | }
30 |
31 | public void addEntityListener (Family family, int priority, EntityListener listener) {
32 | registerFamily(family);
33 |
34 | int insertionIndex = 0;
35 | while (insertionIndex < entityListeners.size) {
36 | if (entityListeners.get(insertionIndex).priority <= priority) {
37 | insertionIndex++;
38 | } else {
39 | break;
40 | }
41 | }
42 |
43 | // Shift up bitmasks by one step
44 | for (Bits mask : entityListenerMasks.values()) {
45 | for (int k = mask.length(); k > insertionIndex; k--) {
46 | if (mask.get(k - 1)) {
47 | mask.set(k);
48 | } else {
49 | mask.clear(k);
50 | }
51 | }
52 | mask.clear(insertionIndex);
53 | }
54 |
55 | entityListenerMasks.get(family).set(insertionIndex);
56 |
57 | EntityListenerData entityListenerData = new EntityListenerData();
58 | entityListenerData.listener = listener;
59 | entityListenerData.priority = priority;
60 | entityListeners.insert(insertionIndex, entityListenerData);
61 | }
62 |
63 | public void removeEntityListener (EntityListener listener) {
64 | for (int i = 0; i < entityListeners.size; i++) {
65 | EntityListenerData entityListenerData = entityListeners.get(i);
66 | if (entityListenerData.listener == listener) {
67 | // Shift down bitmasks by one step
68 | for (Bits mask : entityListenerMasks.values()) {
69 | for (int k = i, n = mask.length(); k < n; k++) {
70 | if (mask.get(k + 1)) {
71 | mask.set(k);
72 | } else {
73 | mask.clear(k);
74 | }
75 | }
76 | }
77 |
78 | entityListeners.removeIndex(i--);
79 | }
80 | }
81 | }
82 |
83 | public void updateFamilyMembership (Entity entity) {
84 | // Find families that the entity was added to/removed from, and fill
85 | // the bitmasks with corresponding listener bits.
86 | Bits addListenerBits = bitsPool.obtain();
87 | Bits removeListenerBits = bitsPool.obtain();
88 |
89 | for (Family family : entityListenerMasks.keys()) {
90 | final int familyIndex = family.getIndex();
91 | final Bits entityFamilyBits = entity.getFamilyBits();
92 |
93 | boolean belongsToFamily = entityFamilyBits.get(familyIndex);
94 | boolean matches = family.matches(entity) && !entity.removing;
95 |
96 | if (belongsToFamily != matches) {
97 | final Bits listenersMask = entityListenerMasks.get(family);
98 | final Array familyEntities = families.get(family);
99 | if (matches) {
100 | addListenerBits.or(listenersMask);
101 | familyEntities.add(entity);
102 | entityFamilyBits.set(familyIndex);
103 | } else {
104 | removeListenerBits.or(listenersMask);
105 | familyEntities.removeValue(entity, true);
106 | entityFamilyBits.clear(familyIndex);
107 | }
108 | }
109 | }
110 |
111 | // Notify listeners; set bits match indices of listeners
112 | notifying = true;
113 | Object[] items = entityListeners.begin();
114 |
115 | try {
116 | for (int i = removeListenerBits.nextSetBit(0); i >= 0; i = removeListenerBits.nextSetBit(i + 1)) {
117 | ((EntityListenerData)items[i]).listener.entityRemoved(entity);
118 | }
119 |
120 | for (int i = addListenerBits.nextSetBit(0); i >= 0; i = addListenerBits.nextSetBit(i + 1)) {
121 | ((EntityListenerData)items[i]).listener.entityAdded(entity);
122 | }
123 | }
124 | finally {
125 | addListenerBits.clear();
126 | removeListenerBits.clear();
127 | bitsPool.free(addListenerBits);
128 | bitsPool.free(removeListenerBits);
129 | entityListeners.end();
130 | notifying = false;
131 | }
132 | }
133 |
134 | private ImmutableArray registerFamily(Family family) {
135 | ImmutableArray entitiesInFamily = immutableFamilies.get(family);
136 |
137 | if (entitiesInFamily == null) {
138 | Array familyEntities = new Array(false, 16);
139 | entitiesInFamily = new ImmutableArray(familyEntities);
140 | families.put(family, familyEntities);
141 | immutableFamilies.put(family, entitiesInFamily);
142 | entityListenerMasks.put(family, new Bits());
143 |
144 | for (Entity entity : entities){
145 | updateFamilyMembership(entity);
146 | }
147 | }
148 |
149 | return entitiesInFamily;
150 | }
151 |
152 | private static class EntityListenerData {
153 | public EntityListener listener;
154 | public int priority;
155 | }
156 |
157 | private static class BitsPool extends Pool {
158 | @Override
159 | protected Bits newObject () {
160 | return new Bits();
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/SystemManagerTests.java:
--------------------------------------------------------------------------------
1 | package com.badlogic.ashley.core;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import org.junit.Test;
6 |
7 | import com.badlogic.ashley.core.SystemManager.SystemListener;
8 | import com.badlogic.ashley.utils.ImmutableArray;
9 | import com.badlogic.gdx.utils.Array;
10 |
11 | public class SystemManagerTests {
12 |
13 | private static class SystemListenerSpy implements SystemListener {
14 | public int addedCount = 0;
15 | public int removedCount = 0;
16 |
17 | @Override
18 | public void systemAdded (EntitySystem system) {
19 | system.addedToEngine(null);
20 | ++addedCount;
21 | }
22 |
23 | @Override
24 | public void systemRemoved (EntitySystem system) {
25 | system.removedFromEngine(null);
26 | removedCount++;
27 | }
28 | }
29 |
30 | private static class EntitySystemMock extends EntitySystem {
31 | public int addedCalls = 0;
32 | public int removedCalls = 0;
33 |
34 | private Array updates;
35 |
36 | public EntitySystemMock () {
37 | super();
38 | }
39 |
40 | public EntitySystemMock (Array updates) {
41 | super();
42 |
43 | this.updates = updates;
44 | }
45 |
46 | @Override
47 | public void update (float deltaTime) {
48 | if (updates != null) {
49 | updates.add(priority);
50 | }
51 | }
52 |
53 | @Override
54 | public void addedToEngine (Engine engine) {
55 | ++addedCalls;
56 | }
57 |
58 | @Override
59 | public void removedFromEngine (Engine engine) {
60 | ++removedCalls;
61 | }
62 | }
63 |
64 | private static class EntitySystemMockA extends EntitySystemMock {
65 |
66 | public EntitySystemMockA () {
67 | super();
68 | }
69 |
70 | public EntitySystemMockA (Array updates) {
71 | super(updates);
72 | }
73 | }
74 |
75 | private static class EntitySystemMockB extends EntitySystemMock {
76 |
77 | public EntitySystemMockB () {
78 | super();
79 | }
80 |
81 | public EntitySystemMockB (Array updates) {
82 | super(updates);
83 | }
84 | }
85 |
86 | @Test
87 | public void addAndRemoveSystem () {
88 | EntitySystemMockA systemA = new EntitySystemMockA();
89 | EntitySystemMockB systemB = new EntitySystemMockB();
90 |
91 | SystemListenerSpy systemSpy = new SystemListenerSpy();
92 | SystemManager manager = new SystemManager(systemSpy);
93 |
94 | assertNull(manager.getSystem(EntitySystemMockA.class));
95 | assertNull(manager.getSystem(EntitySystemMockB.class));
96 |
97 | manager.addSystem(systemA);
98 | manager.addSystem(systemB);
99 |
100 | assertNotNull(manager.getSystem(EntitySystemMockA.class));
101 | assertNotNull(manager.getSystem(EntitySystemMockB.class));
102 | assertEquals(1, systemA.addedCalls);
103 | assertEquals(1, systemB.addedCalls);
104 |
105 | manager.removeSystem(systemA);
106 | manager.removeSystem(systemB);
107 |
108 | assertNull(manager.getSystem(EntitySystemMockA.class));
109 | assertNull(manager.getSystem(EntitySystemMockB.class));
110 | assertEquals(1, systemA.removedCalls);
111 | assertEquals(1, systemB.removedCalls);
112 |
113 | manager.addSystem(systemA);
114 | manager.addSystem(systemB);
115 | manager.removeAllSystems();
116 |
117 | assertNull(manager.getSystem(EntitySystemMockA.class));
118 | assertNull(manager.getSystem(EntitySystemMockB.class));
119 | assertEquals(2, systemA.removedCalls);
120 | assertEquals(2, systemB.removedCalls);
121 | }
122 |
123 | @Test
124 | public void getSystems () {
125 | SystemListenerSpy systemSpy = new SystemListenerSpy();
126 | SystemManager manager = new SystemManager(systemSpy);
127 | EntitySystemMockA systemA = new EntitySystemMockA();
128 | EntitySystemMockB systemB = new EntitySystemMockB();
129 |
130 | assertEquals(0, manager.getSystems().size());
131 |
132 | manager.addSystem(systemA);
133 | manager.addSystem(systemB);
134 |
135 | assertEquals(2, manager.getSystems().size());
136 | assertEquals(2, systemSpy.addedCount);
137 |
138 | manager.removeSystem(systemA);
139 | manager.removeSystem(systemB);
140 |
141 | assertEquals(0, manager.getSystems().size());
142 | assertEquals(2, systemSpy.addedCount);
143 | assertEquals(2, systemSpy.removedCount);
144 | }
145 |
146 | @Test
147 | public void addTwoSystemsOfSameClass () {
148 | SystemListenerSpy systemSpy = new SystemListenerSpy();
149 | SystemManager manager = new SystemManager(systemSpy);
150 | EntitySystemMockA system1 = new EntitySystemMockA();
151 | EntitySystemMockA system2 = new EntitySystemMockA();
152 |
153 | assertEquals(0, manager.getSystems().size());
154 |
155 | manager.addSystem(system1);
156 |
157 | assertEquals(1, manager.getSystems().size());
158 | assertEquals(system1, manager.getSystem(EntitySystemMockA.class));
159 | assertEquals(1, systemSpy.addedCount);
160 |
161 | manager.addSystem(system2);
162 |
163 | assertEquals(1, manager.getSystems().size());
164 | assertEquals(system2, manager.getSystem(EntitySystemMockA.class));
165 | assertEquals(2, systemSpy.addedCount);
166 | assertEquals(1, systemSpy.removedCount);
167 | }
168 |
169 | @Test
170 | public void systemUpdateOrder () {
171 | Array updates = new Array();
172 |
173 | SystemListenerSpy systemSpy = new SystemListenerSpy();
174 | SystemManager manager = new SystemManager(systemSpy);
175 | EntitySystemMock system1 = new EntitySystemMockA(updates);
176 | EntitySystemMock system2 = new EntitySystemMockB(updates);
177 |
178 | system1.priority = 2;
179 | system2.priority = 1;
180 |
181 | manager.addSystem(system1);
182 | manager.addSystem(system2);
183 |
184 | ImmutableArray systems = manager.getSystems();
185 | assertEquals(system2, systems.get(0));
186 | assertEquals(system1, systems.get(1));
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/systems/SortedIteratingSystem.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import com.badlogic.ashley.core.Engine;
20 | import com.badlogic.ashley.core.Entity;
21 | import com.badlogic.ashley.core.EntityListener;
22 | import com.badlogic.ashley.core.EntitySystem;
23 | import com.badlogic.ashley.core.Family;
24 | import com.badlogic.ashley.utils.ImmutableArray;
25 | import com.badlogic.gdx.utils.Array;
26 | import java.util.Comparator;
27 |
28 | /**
29 | * A simple EntitySystem that processes each entity of a given family in the order specified by a comparator and calls
30 | * processEntity() for each entity every time the EntitySystem is updated. This is really just a convenience class as rendering
31 | * systems tend to iterate over a list of entities in a sorted manner. Adding entities will cause the entity list to be resorted.
32 | * Call forceSort() if you changed your sorting criteria.
33 | * @author Santo Pfingsten
34 | */
35 | public abstract class SortedIteratingSystem extends EntitySystem implements EntityListener {
36 | private Family family;
37 | private Array sortedEntities;
38 | private final ImmutableArray entities;
39 | private boolean shouldSort;
40 | private Comparator comparator;
41 |
42 | /**
43 | * Instantiates a system that will iterate over the entities described by the Family.
44 | * @param family The family of entities iterated over in this System
45 | * @param comparator The comparator to sort the entities
46 | */
47 | public SortedIteratingSystem (Family family, Comparator comparator) {
48 | this(family, comparator, 0);
49 | }
50 |
51 | /**
52 | * Instantiates a system that will iterate over the entities described by the Family, with a specific priority.
53 | * @param family The family of entities iterated over in this System
54 | * @param comparator The comparator to sort the entities
55 | * @param priority The priority to execute this system with (lower means higher priority)
56 | */
57 | public SortedIteratingSystem (Family family, Comparator comparator, int priority) {
58 | super(priority);
59 |
60 | this.family = family;
61 | sortedEntities = new Array(false, 16);
62 | entities = new ImmutableArray(sortedEntities);
63 | this.comparator = comparator;
64 | }
65 |
66 | /**
67 | * Call this if the sorting criteria have changed. The actual sorting will be delayed until the entities are processed.
68 | */
69 | public void forceSort () {
70 | shouldSort = true;
71 | }
72 |
73 | private void sort () {
74 | if (shouldSort) {
75 | sortedEntities.sort(comparator);
76 | shouldSort = false;
77 | }
78 | }
79 |
80 | @Override
81 | public void addedToEngine (Engine engine) {
82 | ImmutableArray newEntities = engine.getEntitiesFor(family);
83 | sortedEntities.clear();
84 | if (newEntities.size() > 0) {
85 | for (int i = 0; i < newEntities.size(); ++i) {
86 | sortedEntities.add(newEntities.get(i));
87 | }
88 | sortedEntities.sort(comparator);
89 | }
90 | shouldSort = false;
91 | engine.addEntityListener(family, this);
92 | }
93 |
94 | @Override
95 | public void removedFromEngine (Engine engine) {
96 | engine.removeEntityListener(this);
97 | sortedEntities.clear();
98 | shouldSort = false;
99 | }
100 |
101 | @Override
102 | public void entityAdded (Entity entity) {
103 | sortedEntities.add(entity);
104 | shouldSort = true;
105 | }
106 |
107 | @Override
108 | public void entityRemoved (Entity entity) {
109 | sortedEntities.removeValue(entity, true);
110 | shouldSort = true;
111 | }
112 |
113 | @Override
114 | public void update (float deltaTime) {
115 | sort();
116 | startProcessing();
117 | for (int i = 0; i < sortedEntities.size; ++i) {
118 | processEntity(sortedEntities.get(i), deltaTime);
119 | }
120 | endProcessing();
121 | }
122 |
123 | /**
124 | * @return set of entities processed by the system
125 | */
126 | public ImmutableArray getEntities () {
127 | sort();
128 | return entities;
129 | }
130 |
131 | /**
132 | * @return the Family used when the system was created
133 | */
134 | public Family getFamily () {
135 | return family;
136 | }
137 |
138 | /**
139 | * This method is called on every entity on every update call of the EntitySystem. Override this to implement your system's
140 | * specific processing.
141 | * @param entity The current Entity being processed
142 | * @param deltaTime The delta time between the last and current frame
143 | */
144 | protected abstract void processEntity (Entity entity, float deltaTime);
145 |
146 | /**
147 | * This method is called once on every update call of the EntitySystem, before entity processing begins. Override this method to
148 | * implement your specific startup conditions.
149 | */
150 | public void startProcessing() {}
151 |
152 | /**
153 | * This method is called once on every update call of the EntitySystem after entity processing is complete. Override this method to
154 | * implement your specific end conditions.
155 | */
156 | public void endProcessing() {}
157 | }
158 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/Family.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | import com.badlogic.gdx.utils.Bits;
20 | import com.badlogic.gdx.utils.ObjectMap;
21 |
22 | /**
23 | * Represents a group of {@link Component}s. It is used to describe what {@link Entity} objects an {@link EntitySystem} should
24 | * process. Example: {@code Family.all(PositionComponent.class, VelocityComponent.class).get()} Families can't be instantiated
25 | * directly but must be accessed via a builder ( start with {@code Family.all()}, {@code Family.one()} or {@code Family.exclude()}
26 | * ), this is to avoid duplicate families that describe the same components.
27 | * @author Stefan Bachmann
28 | */
29 | public class Family {
30 | private static ObjectMap families = new ObjectMap();
31 | private static int familyIndex = 0;
32 | private static final Builder builder = new Builder();
33 | private static final Bits zeroBits = new Bits();
34 |
35 | private final Bits all;
36 | private final Bits one;
37 | private final Bits exclude;
38 | private final int index;
39 |
40 | /** Private constructor, use static method Family.getFamilyFor() */
41 | private Family (Bits all, Bits any, Bits exclude) {
42 | this.all = all;
43 | this.one = any;
44 | this.exclude = exclude;
45 | this.index = familyIndex++;
46 | }
47 |
48 | /** @return This family's unique index */
49 | public int getIndex () {
50 | return this.index;
51 | }
52 |
53 | /** @return Whether the entity matches the family requirements or not */
54 | public boolean matches (Entity entity) {
55 | Bits entityComponentBits = entity.getComponentBits();
56 |
57 | if (!entityComponentBits.containsAll(all)) {
58 | return false;
59 | }
60 |
61 | if (!one.isEmpty() && !one.intersects(entityComponentBits)) {
62 | return false;
63 | }
64 |
65 | if (!exclude.isEmpty() && exclude.intersects(entityComponentBits)) {
66 | return false;
67 | }
68 |
69 | return true;
70 | }
71 |
72 | /**
73 | * @param componentTypes entities will have to contain all of the specified components.
74 | * @return A Builder singleton instance to get a family
75 | */
76 | @SafeVarargs
77 | public static final Builder all (Class extends Component>... componentTypes) {
78 | return builder.reset().all(componentTypes);
79 | }
80 |
81 | /**
82 | * @param componentTypes entities will have to contain at least one of the specified components.
83 | * @return A Builder singleton instance to get a family
84 | */
85 | @SafeVarargs
86 | public static final Builder one (Class extends Component>... componentTypes) {
87 | return builder.reset().one(componentTypes);
88 | }
89 |
90 | /**
91 | * @param componentTypes entities cannot contain any of the specified components.
92 | * @return A Builder singleton instance to get a family
93 | */
94 | @SafeVarargs
95 | public static final Builder exclude (Class extends Component>... componentTypes) {
96 | return builder.reset().exclude(componentTypes);
97 | }
98 |
99 | public static class Builder {
100 | private Bits all = zeroBits;
101 | private Bits one = zeroBits;
102 | private Bits exclude = zeroBits;
103 |
104 | Builder() {
105 |
106 | }
107 |
108 | /**
109 | * Resets the builder instance
110 | * @return A Builder singleton instance to get a family
111 | */
112 | public Builder reset () {
113 | all = zeroBits;
114 | one = zeroBits;
115 | exclude = zeroBits;
116 | return this;
117 | }
118 |
119 | /**
120 | * @param componentTypes entities will have to contain all of the specified components.
121 | * @return A Builder singleton instance to get a family
122 | */
123 | @SafeVarargs
124 | public final Builder all (Class extends Component>... componentTypes) {
125 | all = ComponentType.getBitsFor(componentTypes);
126 | return this;
127 | }
128 |
129 | /**
130 | * @param componentTypes entities will have to contain at least one of the specified components.
131 | * @return A Builder singleton instance to get a family
132 | */
133 | @SafeVarargs
134 | public final Builder one (Class extends Component>... componentTypes) {
135 | one = ComponentType.getBitsFor(componentTypes);
136 | return this;
137 | }
138 |
139 | /**
140 | * @param componentTypes entities cannot contain any of the specified components.
141 | * @return A Builder singleton instance to get a family
142 | */
143 | @SafeVarargs
144 | public final Builder exclude (Class extends Component>... componentTypes) {
145 | exclude = ComponentType.getBitsFor(componentTypes);
146 | return this;
147 | }
148 |
149 | /** @return A family for the configured component types */
150 | public Family get () {
151 | String hash = getFamilyHash(all, one, exclude);
152 | Family family = families.get(hash, null);
153 | if (family == null) {
154 | family = new Family(all, one, exclude);
155 | families.put(hash, family);
156 | }
157 | return family;
158 | }
159 | }
160 |
161 | @Override
162 | public int hashCode () {
163 | return index;
164 | }
165 |
166 | @Override
167 | public boolean equals (Object obj) {
168 | return this == obj;
169 | }
170 |
171 | private static String getFamilyHash (Bits all, Bits one, Bits exclude) {
172 | StringBuilder stringBuilder = new StringBuilder();
173 | if (!all.isEmpty()) {
174 | stringBuilder.append("{all:").append(getBitsString(all)).append("}");
175 | }
176 | if (!one.isEmpty()) {
177 | stringBuilder.append("{one:").append(getBitsString(one)).append("}");
178 | }
179 | if (!exclude.isEmpty()) {
180 | stringBuilder.append("{exclude:").append(getBitsString(exclude)).append("}");
181 | }
182 | return stringBuilder.toString();
183 | }
184 |
185 | private static String getBitsString (Bits bits) {
186 | StringBuilder stringBuilder = new StringBuilder();
187 |
188 | int numBits = bits.length();
189 | for (int i = 0; i < numBits; ++i) {
190 | stringBuilder.append(bits.get(i) ? "1" : "0");
191 | }
192 |
193 | return stringBuilder.toString();
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/PooledEngine.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | import com.badlogic.gdx.utils.Array;
20 | import com.badlogic.gdx.utils.ObjectMap;
21 | import com.badlogic.gdx.utils.Pool;
22 | import com.badlogic.gdx.utils.Pool.Poolable;
23 | import com.badlogic.gdx.utils.ReflectionPool;
24 |
25 | /**
26 | * Supports {@link Entity} and {@link Component} pooling. This improves performance in environments where creating/deleting
27 | * entities is frequent as it greatly reduces memory allocation.
28 | *
29 | * - Create entities using {@link #createEntity()}
30 | * - Create components using {@link #createComponent(Class)}
31 | * - Components should implement the {@link Poolable} interface when in need to reset its state upon removal
32 | *
33 | * @author David Saltares
34 | */
35 | @SuppressWarnings({"rawtypes", "unchecked"})
36 | public class PooledEngine extends Engine {
37 |
38 | private EntityPool entityPool;
39 | private ComponentPools componentPools;
40 |
41 | /**
42 | * Creates a new PooledEngine with a maximum of 100 entities and 100 components of each type. Use
43 | * {@link #PooledEngine(int, int, int, int)} to configure the entity and component pools.
44 | */
45 | public PooledEngine () {
46 | this(10, 100, 10, 100);
47 | }
48 |
49 | /**
50 | * Creates new PooledEngine with the specified pools size configurations.
51 | * @param entityPoolInitialSize initial number of pre-allocated entities.
52 | * @param entityPoolMaxSize maximum number of pooled entities.
53 | * @param componentPoolInitialSize initial size for each component type pool.
54 | * @param componentPoolMaxSize maximum size for each component type pool.
55 | */
56 | public PooledEngine (int entityPoolInitialSize, int entityPoolMaxSize, int componentPoolInitialSize, int componentPoolMaxSize) {
57 | super();
58 |
59 | entityPool = new EntityPool(entityPoolInitialSize, entityPoolMaxSize);
60 | componentPools = new ComponentPools(componentPoolInitialSize, componentPoolMaxSize);
61 | }
62 |
63 | /** @return Clean {@link Entity} from the Engine pool. In order to add it to the {@link Engine}, use {@link #addEntity(Entity)}. @{@link Override {@link Engine#createEntity()}} */
64 | @Override
65 | public Entity createEntity () {
66 | return entityPool.obtain();
67 | }
68 |
69 | /**
70 | * Retrieves a new {@link Component} from the {@link Engine} pool. It will be placed back in the pool whenever it's removed
71 | * from an {@link Entity} or the {@link Entity} itself it's removed.
72 | * Overrides the default implementation of Engine (creating a new Object)
73 | */
74 | @Override
75 | public T createComponent (Class componentType) {
76 | return componentPools.obtain(componentType);
77 | }
78 |
79 | /**
80 | * Removes all free entities and components from their pools. Although this will likely result in garbage collection, it will
81 | * free up memory.
82 | */
83 | public void clearPools () {
84 | entityPool.clear();
85 | componentPools.clear();
86 | }
87 |
88 | @Override
89 | protected void removeEntityInternal (Entity entity) {
90 | super.removeEntityInternal(entity);
91 |
92 | if (entity instanceof PooledEntity) {
93 | entityPool.free((PooledEntity)entity);
94 | }
95 | }
96 |
97 | private class PooledEntity extends Entity implements Poolable {
98 | @Override
99 | Component removeInternal(Class extends Component> componentClass) {
100 | Component removed = super.removeInternal(componentClass);
101 | if (removed != null) {
102 | componentPools.free(removed);
103 | }
104 |
105 | return removed;
106 | }
107 |
108 | @Override
109 | public void reset () {
110 | removeAll();
111 | flags = 0;
112 | componentAdded.removeAllListeners();
113 | componentRemoved.removeAllListeners();
114 | scheduledForRemoval = false;
115 | removing = false;
116 | }
117 | }
118 |
119 | private class EntityPool extends Pool {
120 |
121 | public EntityPool (int initialSize, int maxSize) {
122 | super(initialSize, maxSize);
123 | }
124 |
125 | @Override
126 | protected PooledEntity newObject () {
127 | return new PooledEntity();
128 | }
129 |
130 | /**
131 | * Forwarding this call ensures {@link Poolable} {@link Component} instances are returned to their respective
132 | * {@link ComponentPools}s even if the {@link EntityPool} is full.
133 | */
134 | @Override
135 | protected void discard(PooledEntity pooledEntity) {
136 | pooledEntity.reset();
137 | }
138 | }
139 |
140 | private class ComponentPools {
141 | private ObjectMap, ReflectionPool> pools;
142 | private int initialSize;
143 | private int maxSize;
144 |
145 | public ComponentPools (int initialSize, int maxSize) {
146 | this.pools = new ObjectMap, ReflectionPool>();
147 | this.initialSize = initialSize;
148 | this.maxSize = maxSize;
149 | }
150 |
151 | public T obtain (Class type) {
152 | ReflectionPool pool = pools.get(type);
153 |
154 | if (pool == null) {
155 | pool = new ReflectionPool(type, initialSize, maxSize);
156 | pools.put(type, pool);
157 | }
158 |
159 | return (T)pool.obtain();
160 | }
161 |
162 | public void free (Object object) {
163 | if (object == null) {
164 | throw new IllegalArgumentException("object cannot be null.");
165 | }
166 |
167 | ReflectionPool pool = pools.get(object.getClass());
168 |
169 | if (pool == null) {
170 | return; // Ignore freeing an object that was never retained.
171 | }
172 |
173 | pool.free(object);
174 | }
175 |
176 | public void freeAll (Array objects) {
177 | if (objects == null) throw new IllegalArgumentException("objects cannot be null.");
178 |
179 | for (int i = 0, n = objects.size; i < n; i++) {
180 | Object object = objects.get(i);
181 | if (object == null) continue;
182 | free(object);
183 | }
184 | }
185 |
186 | public void clear () {
187 | for (Pool pool : pools.values()) {
188 | pool.clear();
189 | }
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/EntityTests.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | import static org.junit.Assert.*;
20 |
21 | import java.util.HashSet;
22 | import java.util.Set;
23 |
24 | import org.junit.Test;
25 |
26 | import com.badlogic.ashley.signals.Listener;
27 | import com.badlogic.ashley.signals.Signal;
28 | import com.badlogic.gdx.utils.Array;
29 | import com.badlogic.gdx.utils.Bits;
30 |
31 | public class EntityTests {
32 |
33 | private static class ComponentA implements Component {
34 | }
35 |
36 | private static class ComponentB implements Component {
37 | }
38 |
39 | private static class EntityListenerMock implements Listener {
40 |
41 | public int counter = 0;
42 |
43 | @Override
44 | public void receive (Signal signal, Entity object) {
45 | ++counter;
46 |
47 | assertNotNull(signal);
48 | assertNotNull(object);
49 | }
50 | }
51 |
52 | private ComponentMapper am = ComponentMapper.getFor(ComponentA.class);
53 | private ComponentMapper bm = ComponentMapper.getFor(ComponentB.class);
54 |
55 | @Test
56 | public void addAndReturnComponent(){
57 | Entity entity = new Entity();
58 | ComponentA componentA = new ComponentA();
59 | ComponentB componentB = new ComponentB();
60 |
61 | assertEquals(componentA, entity.addAndReturn(componentA));
62 | assertEquals(componentB, entity.addAndReturn(componentB));
63 |
64 | assertEquals(2, entity.getComponents().size());
65 | }
66 |
67 | @Test
68 | public void addAndReturnComponentGeneric () {
69 | Entity entity = new Entity();
70 | ComponentA componentA = entity.addAndReturn(new ComponentA());
71 | }
72 |
73 | @Test
74 | public void noComponents () {
75 | Entity entity = new Entity();
76 |
77 | assertEquals(0, entity.getComponents().size());
78 | assertTrue(entity.getComponentBits().isEmpty());
79 | assertNull(am.get(entity));
80 | assertNull(bm.get(entity));
81 | assertFalse(am.has(entity));
82 | assertFalse(bm.has(entity));
83 | }
84 |
85 | @Test
86 | public void addAndRemoveComponent () {
87 | Entity entity = new Entity();
88 |
89 | entity.add(new ComponentA());
90 |
91 | assertEquals(1, entity.getComponents().size());
92 |
93 | Bits componentBits = entity.getComponentBits();
94 | int componentAIndex = ComponentType.getIndexFor(ComponentA.class);
95 |
96 | for (int i = 0; i < componentBits.length(); ++i) {
97 | assertEquals(i == componentAIndex, componentBits.get(i));
98 | }
99 |
100 | assertNotNull(am.get(entity));
101 | assertNull(bm.get(entity));
102 | assertTrue(am.has(entity));
103 | assertFalse(bm.has(entity));
104 |
105 | entity.remove(ComponentA.class);
106 |
107 | assertEquals(0, entity.getComponents().size());
108 |
109 | for (int i = 0; i < componentBits.length(); ++i) {
110 | assertFalse(componentBits.get(i));
111 | }
112 |
113 | assertNull(am.get(entity));
114 | assertNull(bm.get(entity));
115 | assertFalse(am.has(entity));
116 | assertFalse(bm.has(entity));
117 | }
118 |
119 | @Test
120 | public void removeUnexistingComponent () throws Exception {
121 | // ensure remove unexisting component work with
122 | // new component type at default bag limits (64)
123 | Entity entity = new Entity();
124 |
125 | ComponentClassFactory cl = new ComponentClassFactory();
126 |
127 | for(int i=0 ; i<65 ; i++){
128 | Class extends Component> type = cl.createComponentType("Component" + i);
129 | entity.remove(type);
130 | entity.add(type.newInstance());
131 | }
132 | }
133 |
134 | @Test
135 | public void addAndRemoveAllComponents () {
136 | Entity entity = new Entity();
137 |
138 | entity.add(new ComponentA());
139 | entity.add(new ComponentB());
140 |
141 | assertEquals(2, entity.getComponents().size());
142 |
143 | Bits componentBits = entity.getComponentBits();
144 | int componentAIndex = ComponentType.getIndexFor(ComponentA.class);
145 | int componentBIndex = ComponentType.getIndexFor(ComponentB.class);
146 |
147 | for (int i = 0; i < componentBits.length(); ++i) {
148 | assertEquals(i == componentAIndex || i == componentBIndex, componentBits.get(i));
149 | }
150 |
151 | assertNotNull(am.get(entity));
152 | assertNotNull(bm.get(entity));
153 | assertTrue(am.has(entity));
154 | assertTrue(bm.has(entity));
155 |
156 | entity.removeAll();
157 |
158 | assertEquals(0, entity.getComponents().size());
159 |
160 | for (int i = 0; i < componentBits.length(); ++i) {
161 | assertFalse(componentBits.get(i));
162 | }
163 |
164 | assertNull(am.get(entity));
165 | assertNull(bm.get(entity));
166 | assertFalse(am.has(entity));
167 | assertFalse(bm.has(entity));
168 | }
169 |
170 | @Test
171 | public void addSameComponent () {
172 | Entity entity = new Entity();
173 |
174 | ComponentA a1 = new ComponentA();
175 | ComponentA a2 = new ComponentA();
176 |
177 | entity.add(a1);
178 | entity.add(a2);
179 |
180 | assertEquals(1, entity.getComponents().size());
181 | assertTrue(am.has(entity));
182 | assertNotEquals(a1, am.get(entity));
183 | assertEquals(a2, am.get(entity));
184 | }
185 |
186 | @Test
187 | public void componentListener () {
188 | EntityListenerMock addedListener = new EntityListenerMock();
189 | EntityListenerMock removedListener = new EntityListenerMock();
190 |
191 | Entity entity = new Entity();
192 | entity.componentAdded.add(addedListener);
193 | entity.componentRemoved.add(removedListener);
194 |
195 | assertEquals(0, addedListener.counter);
196 | assertEquals(0, removedListener.counter);
197 |
198 | entity.add(new ComponentA());
199 |
200 | assertEquals(1, addedListener.counter);
201 | assertEquals(0, removedListener.counter);
202 |
203 | entity.remove(ComponentA.class);
204 |
205 | assertEquals(1, addedListener.counter);
206 | assertEquals(1, removedListener.counter);
207 |
208 | entity.add(new ComponentB());
209 |
210 | assertEquals(2, addedListener.counter);
211 |
212 | entity.remove(ComponentB.class);
213 |
214 | assertEquals(2, removedListener.counter);
215 | }
216 |
217 | @Test
218 | public void getComponentByClass () {
219 | ComponentA compA = new ComponentA();
220 | ComponentB compB = new ComponentB();
221 |
222 | Entity entity = new Entity();
223 | entity.add(compA).add(compB);
224 |
225 | ComponentA retA = entity.getComponent(ComponentA.class);
226 | ComponentB retB = entity.getComponent(ComponentB.class);
227 |
228 | assertNotNull(retA);
229 | assertNotNull(retB);
230 |
231 | assertTrue(retA == compA);
232 | assertTrue(retB == compB);
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/core/EntityListenerTests.java:
--------------------------------------------------------------------------------
1 |
2 | package com.badlogic.ashley.core;
3 |
4 | import static org.mockito.Mockito.*;
5 |
6 | import org.junit.Test;
7 | import org.mockito.InOrder;
8 |
9 | public class EntityListenerTests {
10 |
11 | @Test
12 | public void addEntityListenerFamilyRemove () {
13 | final Engine engine = new Engine();
14 |
15 | Entity e = new Entity();
16 | e.add(new PositionComponent());
17 | engine.addEntity(e);
18 |
19 | @SuppressWarnings("unchecked")
20 | Family family = Family.all(PositionComponent.class).get();
21 | engine.addEntityListener(family, new EntityListener() {
22 |
23 | public void entityRemoved (Entity entity) {
24 | engine.addEntity(new Entity());
25 | }
26 |
27 | public void entityAdded (Entity entity) {
28 |
29 | }
30 | });
31 |
32 | engine.removeEntity(e);
33 | }
34 |
35 | @Test
36 | public void addEntityListenerFamilyAdd () {
37 | final Engine engine = new Engine();
38 |
39 | Entity e = new Entity();
40 | e.add(new PositionComponent());
41 |
42 | @SuppressWarnings("unchecked")
43 | Family family = Family.all(PositionComponent.class).get();
44 | engine.addEntityListener(family, new EntityListener() {
45 |
46 | public void entityRemoved (Entity entity) {
47 |
48 | }
49 |
50 | public void entityAdded (Entity entity) {
51 | engine.addEntity(new Entity());
52 | }
53 | });
54 |
55 | engine.addEntity(e);
56 | }
57 |
58 | @Test
59 | public void addEntityListenerNoFamilyRemove () {
60 | final Engine engine = new Engine();
61 |
62 | Entity e = new Entity();
63 | e.add(new PositionComponent());
64 | engine.addEntity(e);
65 |
66 | @SuppressWarnings("unchecked")
67 | final Family family = Family.all(PositionComponent.class).get();
68 | engine.addEntityListener(new EntityListener() {
69 |
70 | public void entityRemoved (Entity entity) {
71 | if (family.matches(entity)) engine.addEntity(new Entity());
72 | }
73 |
74 | public void entityAdded (Entity entity) {
75 |
76 | }
77 | });
78 |
79 | engine.removeEntity(e);
80 | }
81 |
82 | @Test
83 | public void addEntityListenerNoFamilyAdd () {
84 | final Engine engine = new Engine();
85 |
86 | Entity e = new Entity();
87 | e.add(new PositionComponent());
88 |
89 | @SuppressWarnings("unchecked")
90 | final Family family = Family.all(PositionComponent.class).get();
91 | engine.addEntityListener(new EntityListener() {
92 |
93 | public void entityRemoved (Entity entity) {
94 |
95 | }
96 |
97 | public void entityAdded (Entity entity) {
98 | if (family.matches(entity)) engine.addEntity(new Entity());
99 | }
100 | });
101 |
102 | engine.addEntity(e);
103 | }
104 |
105 | public class PositionComponent implements Component {
106 | }
107 |
108 | @Test
109 | public void entityListenerPriority () {
110 | EntityListener a = mock(EntityListener.class);
111 | EntityListener b = mock(EntityListener.class);
112 | EntityListener c = mock(EntityListener.class);
113 | InOrder inOrder = inOrder(a, b, c);
114 |
115 | Entity entity = new Entity();
116 | Engine engine = new Engine();
117 | engine.addEntityListener(-3, b);
118 | engine.addEntityListener(c);
119 | engine.addEntityListener(-4, a);
120 | inOrder.verifyNoMoreInteractions();
121 |
122 | engine.addEntity(entity);
123 | inOrder.verify(a).entityAdded(entity);
124 | inOrder.verify(b).entityAdded(entity);
125 | inOrder.verify(c).entityAdded(entity);
126 | inOrder.verifyNoMoreInteractions();
127 |
128 | engine.removeEntity(entity);
129 | inOrder.verify(a).entityRemoved(entity);
130 | inOrder.verify(b).entityRemoved(entity);
131 | inOrder.verify(c).entityRemoved(entity);
132 | inOrder.verifyNoMoreInteractions();
133 |
134 | engine.removeEntityListener(b);
135 | inOrder.verifyNoMoreInteractions();
136 |
137 | engine.addEntity(entity);
138 | inOrder.verify(a).entityAdded(entity);
139 | inOrder.verify(c).entityAdded(entity);
140 | inOrder.verifyNoMoreInteractions();
141 |
142 | engine.addEntityListener(4, b);
143 | inOrder.verifyNoMoreInteractions();
144 |
145 | engine.removeEntity(entity);
146 | inOrder.verify(a).entityRemoved(entity);
147 | inOrder.verify(c).entityRemoved(entity);
148 | inOrder.verify(b).entityRemoved(entity);
149 | inOrder.verifyNoMoreInteractions();
150 | }
151 |
152 | private static class ComponentA implements Component {
153 | }
154 |
155 | private static class ComponentB implements Component {
156 | }
157 |
158 | @Test
159 | public void familyListenerPriority () {
160 | EntityListener a = mock(EntityListener.class);
161 | EntityListener b = mock(EntityListener.class);
162 | InOrder inOrder = inOrder(a, b);
163 |
164 | Engine engine = new Engine();
165 | engine.addEntityListener(Family.all(ComponentB.class).get(), -2, b);
166 | engine.addEntityListener(Family.all(ComponentA.class).get(), -3, a);
167 | inOrder.verifyNoMoreInteractions();
168 |
169 | Entity entity = new Entity();
170 | entity.add(new ComponentA());
171 | entity.add(new ComponentB());
172 |
173 | engine.addEntity(entity);
174 | inOrder.verify(a).entityAdded(entity);
175 | inOrder.verify(b).entityAdded(entity);
176 | inOrder.verifyNoMoreInteractions();
177 |
178 | entity.remove(ComponentB.class);
179 | inOrder.verify(b).entityRemoved(entity);
180 | inOrder.verifyNoMoreInteractions();
181 |
182 | entity.remove(ComponentA.class);
183 | inOrder.verify(a).entityRemoved(entity);
184 | inOrder.verifyNoMoreInteractions();
185 |
186 | entity.add(new ComponentA());
187 | inOrder.verify(a).entityAdded(entity);
188 | inOrder.verifyNoMoreInteractions();
189 |
190 | entity.add(new ComponentB());
191 | inOrder.verify(b).entityAdded(entity);
192 | inOrder.verifyNoMoreInteractions();
193 | }
194 |
195 | private interface ComponentRecorder {
196 | void addingComponentA();
197 |
198 | void removingComponentA();
199 |
200 | void addingComponentB();
201 |
202 | void removingComponentB();
203 | }
204 |
205 | @Test
206 | public void componentHandlingInListeners() {
207 | final Engine engine = new Engine();
208 |
209 | final ComponentRecorder recorder = mock(ComponentRecorder.class);
210 |
211 | engine.addEntityListener(new EntityListener() {
212 | @Override
213 | public void entityAdded(Entity entity) {
214 | recorder.addingComponentA();
215 | entity.add(new ComponentA());
216 | }
217 |
218 | @Override
219 | public void entityRemoved(Entity entity) {
220 | recorder.removingComponentA();
221 | entity.remove(ComponentA.class);
222 | }
223 | });
224 |
225 | engine.addEntityListener(new EntityListener() {
226 | @Override
227 | public void entityAdded(Entity entity) {
228 | recorder.addingComponentB();
229 | entity.add(new ComponentB());
230 | }
231 |
232 | @Override
233 | public void entityRemoved(Entity entity) {
234 | recorder.removingComponentB();
235 | entity.remove(ComponentB.class);
236 | }
237 | });
238 |
239 | engine.update(0);
240 | Entity e = new Entity();
241 | engine.addEntity(e);
242 | engine.update(0);
243 | engine.removeEntity(e);
244 | engine.update(0);
245 |
246 | verify(recorder).addingComponentA();
247 | verify(recorder).removingComponentA();
248 | verify(recorder).addingComponentB();
249 | verify(recorder).removingComponentB();
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/ashley/tests/com/badlogic/ashley/systems/IteratingSystemTest.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.systems;
18 |
19 | import org.junit.Test;
20 |
21 | import com.badlogic.ashley.core.Component;
22 | import com.badlogic.ashley.core.ComponentMapper;
23 | import com.badlogic.ashley.core.Engine;
24 | import com.badlogic.ashley.core.Entity;
25 | import com.badlogic.ashley.core.Family;
26 | import com.badlogic.ashley.systems.IteratingSystem;
27 | import com.badlogic.ashley.utils.ImmutableArray;
28 |
29 | import static org.junit.Assert.*;
30 |
31 | public class IteratingSystemTest {
32 | private static final float deltaTime = 0.16f;
33 |
34 | private static class ComponentA implements Component {
35 | }
36 |
37 | private static class ComponentB implements Component {
38 | }
39 |
40 | private static class ComponentC implements Component {
41 | }
42 |
43 | private static class IteratingSystemMock extends IteratingSystem {
44 | public int numUpdates;
45 | public int numStartProcessing;
46 | public int numEndProcessing;
47 |
48 | public IteratingSystemMock (Family family) {
49 | super(family);
50 | }
51 |
52 | @Override
53 | public void startProcessing() {
54 | ++numStartProcessing;
55 | }
56 |
57 | @Override
58 | public void processEntity (Entity entity, float deltaTime) {
59 | ++numUpdates;
60 | }
61 |
62 | @Override
63 | public void endProcessing() {
64 | ++numEndProcessing;
65 | }
66 | }
67 |
68 | private static class SpyComponent implements Component {
69 | public int updates = 0;
70 | }
71 |
72 | private static class IndexComponent implements Component {
73 | public int index = 0;
74 | }
75 |
76 | private static class IteratingComponentRemovalSystem extends IteratingSystem {
77 |
78 | private ComponentMapper sm;
79 | private ComponentMapper im;
80 |
81 | public IteratingComponentRemovalSystem () {
82 | super(Family.all(SpyComponent.class, IndexComponent.class).get());
83 |
84 | sm = ComponentMapper.getFor(SpyComponent.class);
85 | im = ComponentMapper.getFor(IndexComponent.class);
86 | }
87 |
88 | @Override
89 | public void processEntity (Entity entity, float deltaTime) {
90 | int index = im.get(entity).index;
91 | if (index % 2 == 0) {
92 | entity.remove(SpyComponent.class);
93 | entity.remove(IndexComponent.class);
94 | } else {
95 | sm.get(entity).updates++;
96 | }
97 | }
98 |
99 | }
100 |
101 | private static class IteratingRemovalSystem extends IteratingSystem {
102 | private ComponentMapper sm;
103 | private ComponentMapper im;
104 |
105 | public IteratingRemovalSystem () {
106 | super(Family.all(SpyComponent.class, IndexComponent.class).get());
107 |
108 | sm = ComponentMapper.getFor(SpyComponent.class);
109 | im = ComponentMapper.getFor(IndexComponent.class);
110 | }
111 |
112 | @Override
113 | public void addedToEngine (Engine engine) {
114 | super.addedToEngine(engine);
115 | }
116 |
117 | @Override
118 | public void processEntity (Entity entity, float deltaTime) {
119 | int index = im.get(entity).index;
120 | if (index % 2 == 0) {
121 | getEngine().removeEntity(entity);
122 | } else {
123 | sm.get(entity).updates++;
124 | }
125 | }
126 |
127 | }
128 |
129 | @Test
130 | @SuppressWarnings("unchecked")
131 | public void shouldIterateEntitiesWithCorrectFamily () {
132 | final Engine engine = new Engine();
133 |
134 | final Family family = Family.all(ComponentA.class, ComponentB.class).get();
135 | final IteratingSystemMock system = new IteratingSystemMock(family);
136 | final Entity e = new Entity();
137 |
138 | engine.addSystem(system);
139 | engine.addEntity(e);
140 |
141 | // When entity has ComponentA
142 | e.add(new ComponentA());
143 | engine.update(deltaTime);
144 |
145 | assertEquals(0, system.numUpdates);
146 |
147 | // When entity has ComponentA and ComponentB
148 | system.numUpdates = 0;
149 | e.add(new ComponentB());
150 | engine.update(deltaTime);
151 |
152 | assertEquals(1, system.numUpdates);
153 |
154 | // When entity has ComponentA, ComponentB and ComponentC
155 | system.numUpdates = 0;
156 | e.add(new ComponentC());
157 | engine.update(deltaTime);
158 |
159 | assertEquals(1, system.numUpdates);
160 |
161 | // When entity has ComponentB and ComponentC
162 | system.numUpdates = 0;
163 | e.remove(ComponentA.class);
164 | e.add(new ComponentC());
165 | engine.update(deltaTime);
166 |
167 | assertEquals(0, system.numUpdates);
168 | }
169 |
170 | @Test
171 | public void entityRemovalWhileIterating () {
172 | Engine engine = new Engine();
173 | ImmutableArray entities = engine.getEntitiesFor(Family.all(SpyComponent.class, IndexComponent.class).get());
174 | ComponentMapper sm = ComponentMapper.getFor(SpyComponent.class);
175 |
176 | engine.addSystem(new IteratingRemovalSystem());
177 |
178 | final int numEntities = 10;
179 |
180 | for (int i = 0; i < numEntities; ++i) {
181 | Entity e = new Entity();
182 | e.add(new SpyComponent());
183 |
184 | IndexComponent in = new IndexComponent();
185 | in.index = i + 1;
186 |
187 | e.add(in);
188 |
189 | engine.addEntity(e);
190 | }
191 |
192 | engine.update(deltaTime);
193 |
194 | assertEquals(numEntities / 2, entities.size());
195 |
196 | for (int i = 0; i < entities.size(); ++i) {
197 | Entity e = entities.get(i);
198 |
199 | assertEquals(1, sm.get(e).updates);
200 | }
201 | }
202 |
203 | @Test
204 | public void componentRemovalWhileIterating () {
205 | Engine engine = new Engine();
206 | ImmutableArray entities = engine.getEntitiesFor(Family.all(SpyComponent.class, IndexComponent.class).get());
207 | ComponentMapper sm = ComponentMapper.getFor(SpyComponent.class);
208 |
209 | engine.addSystem(new IteratingComponentRemovalSystem());
210 |
211 | final int numEntities = 10;
212 |
213 | for (int i = 0; i < numEntities; ++i) {
214 | Entity e = new Entity();
215 | e.add(new SpyComponent());
216 |
217 | IndexComponent in = new IndexComponent();
218 | in.index = i + 1;
219 |
220 | e.add(in);
221 |
222 | engine.addEntity(e);
223 | }
224 |
225 | engine.update(deltaTime);
226 |
227 | assertEquals(numEntities / 2, entities.size());
228 |
229 | for (int i = 0; i < entities.size(); ++i) {
230 | Entity e = entities.get(i);
231 |
232 | assertEquals(1, sm.get(e).updates);
233 | }
234 | }
235 |
236 | @Test
237 | public void processingUtilityFunctions() {
238 | final Engine engine = new Engine();
239 |
240 | final IteratingSystemMock system = new IteratingSystemMock(Family.all().get());
241 |
242 | engine.addSystem(system);
243 |
244 | engine.update(deltaTime);
245 | assertEquals(1, system.numStartProcessing);
246 | assertEquals(1, system.numEndProcessing);
247 |
248 | engine.update(deltaTime);
249 | assertEquals(2, system.numStartProcessing);
250 | assertEquals(2, system.numEndProcessing);
251 | }
252 |
253 | }
254 |
--------------------------------------------------------------------------------
/ashley/src/com/badlogic/ashley/core/Entity.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.badlogic.ashley.core;
18 |
19 | import com.badlogic.ashley.signals.Signal;
20 | import com.badlogic.ashley.utils.Bag;
21 | import com.badlogic.ashley.utils.ImmutableArray;
22 | import com.badlogic.gdx.utils.Array;
23 | import com.badlogic.gdx.utils.Bits;
24 |
25 | /**
26 | * Simple containers of {@link Component}s that give them "data". The component's data is then processed by {@link EntitySystem}s.
27 | * @author Stefan Bachmann
28 | */
29 | public class Entity {
30 | /** A flag that can be used to bit mask this entity. Up to the user to manage. */
31 | public int flags;
32 | /** Will dispatch an event when a component is added. */
33 | public final Signal componentAdded;
34 | /** Will dispatch an event when a component is removed. */
35 | public final Signal componentRemoved;
36 |
37 | boolean scheduledForRemoval;
38 | boolean removing;
39 | ComponentOperationHandler componentOperationHandler;
40 |
41 | private Bag components;
42 | private Array componentsArray;
43 | private ImmutableArray immutableComponentsArray;
44 | private Bits componentBits;
45 | private Bits familyBits;
46 |
47 | /** Creates an empty Entity. */
48 | public Entity () {
49 | components = new Bag();
50 | componentsArray = new Array(false, 16);
51 | immutableComponentsArray = new ImmutableArray(componentsArray);
52 | componentBits = new Bits();
53 | familyBits = new Bits();
54 | flags = 0;
55 |
56 | componentAdded = new Signal();
57 | componentRemoved = new Signal();
58 | }
59 |
60 | /**
61 | * Adds a {@link Component} to this Entity. If a {@link Component} of the same type already exists, it'll be replaced.
62 | * @return The Entity for easy chaining
63 | */
64 | public Entity add (Component component) {
65 | if (addInternal(component)) {
66 | if (componentOperationHandler != null) {
67 | componentOperationHandler.add(this);
68 | }
69 | else {
70 | notifyComponentAdded();
71 | }
72 | }
73 |
74 | return this;
75 | }
76 |
77 | /**
78 | * Adds a {@link Component} to this Entity. If a {@link Component} of the same type already exists, it'll be replaced.
79 | * @return The Component for direct component manipulation (e.g. PooledComponent)
80 | */
81 | public T addAndReturn(T component) {
82 | add(component);
83 | return component;
84 | }
85 |
86 | /**
87 | * Removes the {@link Component} of the specified type. Since there is only ever one component of one type, we don't need an
88 | * instance reference.
89 | * @return The removed {@link Component}, or null if the Entity did not contain such a component.
90 | */
91 | public T remove (Class componentClass) {
92 | ComponentType componentType = ComponentType.getFor(componentClass);
93 | int componentTypeIndex = componentType.getIndex();
94 |
95 | if(components.isIndexWithinBounds(componentTypeIndex)){
96 | Component removeComponent = components.get(componentTypeIndex);
97 |
98 | if (removeComponent != null && removeInternal(componentClass) != null) {
99 | if (componentOperationHandler != null) {
100 | componentOperationHandler.remove(this);
101 | }
102 | else {
103 | notifyComponentRemoved();
104 | }
105 | }
106 |
107 | return (T) removeComponent;
108 | }
109 |
110 | return null;
111 | }
112 |
113 | /** Removes all the {@link Component}'s from the Entity. */
114 | public void removeAll () {
115 | while (componentsArray.size > 0) {
116 | remove(componentsArray.get(0).getClass());
117 | }
118 | }
119 |
120 | /** @return immutable collection with all the Entity {@link Component}s. */
121 | public ImmutableArray getComponents () {
122 | return immutableComponentsArray;
123 | }
124 |
125 | /**
126 | * Retrieve a component from this {@link Entity} by class. Note: the preferred way of retrieving {@link Component}s is
127 | * using {@link ComponentMapper}s. This method is provided for convenience; using a ComponentMapper provides O(1) access to
128 | * components while this method provides only O(logn).
129 | * @param componentClass the class of the component to be retrieved.
130 | * @return the instance of the specified {@link Component} attached to this {@link Entity}, or null if no such
131 | * {@link Component} exists.
132 | */
133 | public T getComponent (Class componentClass) {
134 | return getComponent(ComponentType.getFor(componentClass));
135 | }
136 |
137 | /**
138 | * Internal use.
139 | * @return The {@link Component} object for the specified class, null if the Entity does not have any components for that class.
140 | */
141 | @SuppressWarnings("unchecked")
142 | T getComponent (ComponentType componentType) {
143 | int componentTypeIndex = componentType.getIndex();
144 |
145 | if (componentTypeIndex < components.getCapacity()) {
146 | return (T)components.get(componentType.getIndex());
147 | } else {
148 | return null;
149 | }
150 | }
151 |
152 | /**
153 | * @return Whether or not the Entity has a {@link Component} for the specified class.
154 | */
155 | boolean hasComponent (ComponentType componentType) {
156 | return componentBits.get(componentType.getIndex());
157 | }
158 |
159 | /**
160 | * @return This Entity's component bits, describing all the {@link Component}s it contains.
161 | */
162 | Bits getComponentBits () {
163 | return componentBits;
164 | }
165 |
166 | /** @return This Entity's {@link Family} bits, describing all the {@link EntitySystem}s it currently is being processed by. */
167 | Bits getFamilyBits () {
168 | return familyBits;
169 | }
170 |
171 | /**
172 | * @param component
173 | * @return whether or not the component was added.
174 | */
175 | boolean addInternal (Component component) {
176 | Class extends Component> componentClass = component.getClass();
177 | Component oldComponent = getComponent(componentClass);
178 |
179 | if (component == oldComponent) {
180 | return false;
181 | }
182 |
183 | if (oldComponent != null) {
184 | removeInternal(componentClass);
185 | }
186 |
187 | int componentTypeIndex = ComponentType.getIndexFor(componentClass);
188 | components.set(componentTypeIndex, component);
189 | componentsArray.add(component);
190 | componentBits.set(componentTypeIndex);
191 |
192 | return true;
193 | }
194 |
195 | /**
196 | * @param componentClass
197 | * @return the component if the specified class was found and removed. Otherwise, null
198 | */
199 | Component removeInternal (Class extends Component> componentClass) {
200 | ComponentType componentType = ComponentType.getFor(componentClass);
201 | int componentTypeIndex = componentType.getIndex();
202 | Component removeComponent = components.get(componentTypeIndex);
203 |
204 | if (removeComponent != null) {
205 | components.set(componentTypeIndex, null);
206 | componentsArray.removeValue(removeComponent, true);
207 | componentBits.clear(componentTypeIndex);
208 |
209 | return removeComponent;
210 | }
211 |
212 | return null;
213 | }
214 |
215 | void notifyComponentAdded() {
216 | componentAdded.dispatch(this);
217 | }
218 |
219 | void notifyComponentRemoved() {
220 | componentRemoved.dispatch(this);
221 | }
222 |
223 | /** @return true if the entity is scheduled to be removed */
224 | public boolean isScheduledForRemoval () {
225 | return scheduledForRemoval;
226 | }
227 |
228 | /** @return true if the entity is being removed */
229 | public boolean isRemoving() {
230 | return removing;
231 | }
232 | }
233 |
--------------------------------------------------------------------------------