Slick Forums

Discuss the Slick 2D Library
It is currently Wed May 22, 2013 4:30 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Tue Dec 28, 2010 10:23 pm 
Offline
Game Developer
User avatar

Joined: Tue Nov 21, 2006 4:46 am
Posts: 619
Location: Iceland
NOTE: This was a precursor project to the Artemis Entity System framework and is not related to it.

--------------------------------------------------

What I use for my games.

It's a container framework for your in-game entities, that are made up of components.

JAR: http://gamadu.com/artemis/old/artemis.jar
Source: http://gamadu.com/artemis/old/artemis-src.zip


Very raw right now, but very usable. I prefered simplicity over complexity, and that's what this system is, pure entity/component system, with rendering layering (16 hardcoded), etc.

The example is quite bad, but shows you how to create an example entity, set a rendering layer, initialize, and add to the manager.

The manager is the heart and brain of the whole thing, make sure you check out the public methods.

There aren't any components included, it's really up to you to provide them. Artemis is just a entity/component container. Although, sometime in the future I could provide generic components.

Any questions how do accomplish things, ask here. Component based systems require different thinking.

Currently missing: adding/removing component of an active entity.

Make sure to resolve component dependencies in initialize() of a component. Initialize should be called AFTER all components have been added to the entity. (this is not required, but preferred for performance reasons)

Use however you like.


Example of instantiating an entity:

Code:
Entity e = new Entity("heavyTank","Heavy Tank", "tanks");
e.setComponent(new Transform(100,100));

Bounds b = new Bounds(30); // radius
e.setComponent(b);

Sprite sprite = new Sprite("unit.png");
sprite.setLayer(5); // higher means rendered later
e.setComponent(sprite);

e.initialize();

EntityManager.getInstance().addEntity(e);


After adding all entities to the EntityManager, all you need to update and render the game world is this:

Code:
   @Override
   public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
      EntityManager.getInstance().update(container, game, delta);
   }

   @Override
   public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
      EntityManager.getInstance().render(container, game, g);
   }


Last edited by appel on Tue Mar 08, 2011 10:44 pm, edited 9 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 28, 2010 10:35 pm 
Offline
Game Developer
User avatar

Joined: Tue Nov 21, 2006 4:46 am
Posts: 619
Location: Iceland
Example components:

Code:
public class Transform extends AbstractComponent {
   private float x;
   private float y;
   private float rotation;
   
   public Transform() {
   }

   public Transform(float x, float y) {
      this();
      this.x = x;
      this.y = y;
   }
   
   public Transform(float x, float y, float rotation) {
      this(x,y);
      this.rotation = rotation;
   }

   @Override
   public Class<? extends Component> getFamilyId() {
      return Transform.class;
   }

   public void setX(float x) {
      this.x = x;
   }

   public float getX() {
      return x;
   }

   public void setY(float y) {
      this.y = y;
   }

   public float getY() {
      return y;
   }
   
   public void addRotation(float angle) {
      rotation = (rotation + angle) % 360;
   }

   public void setRotation(float rotation) {
      this.rotation = rotation;
   }

   public float getRotation() {
      return rotation;
   }
   
   public float getRotationAsRadians() {
      return (float)Math.toRadians(rotation);
   }
   
   public void setLocation(float x, float y) {
      this.x = x;
      this.y = y;
   }
   
}



Expire the entity after a period:

Code:
public class Expires extends AbstractComponent {
   private int lifetime;
   private Timer expiresTimer;

   public Expires(int lifetime) {
      this.lifetime = lifetime;
   }

   @Override
   public Class<? extends Component> getFamilyId() {
      return Expires.class;
   }

   @Override
   public void initialize(GameContainer container, StateBasedGame game) {
      expiresTimer = new Timer(lifetime, false) {
         @Override
         public void execute() {
            die();
         }
      };
   }

   @Override
   public void update(GameContainer container, StateBasedGame game, int delta) {
      expiresTimer.update(delta);
   }

   private void die() {
      EntityManager.getInstance().deleteEntity(owner);
   }

}




Code:
public class Particles extends AbstractComponent {

   private ParticleSystem ps;
   private Transform transform;

   public Particles(ParticleSystem particleSystem) {
      this.ps = particleSystem;
   }

   @Override
   public Class<? extends Component> getFamilyId() {
      return Particles.class;
   }

   @Override
   public void initialize(GameContainer container, StateBasedGame game) {
      transform = getComponent(Transform.class);
   }

   @Override
   public void update(GameContainer container, StateBasedGame game, int delta) {
      ps.update(delta);
   }

   @Override
   public void render(GameContainer container, StateBasedGame game, Graphics g) {
      ps.render(transform.getX(), transform.getY());
   }



Code:
public class Health extends AbstractComponent {
   private Transform transform;
   private int maximumHealth;
   private float currentHealth;
   private boolean destroyed;

   public Health(int maximumHealth) {
      this(maximumHealth,maximumHealth);
   }
   
   public Health(int currentHealth, int maximumHealth) {
      this.currentHealth = currentHealth;
      this.maximumHealth = maximumHealth;
   }
   
   @Override
   public Class<? extends Component> getFamilyId() {
      return Health.class;
   }

   @Override
   public void initialize(GameContainer container, StateBasedGame game) {
      transform = getComponent(Transform.class);
   }
   
   @Override
   public void update(GameContainer container, StateBasedGame game, int delta) {
      if(destroyed) {
         EntityManager.getInstance().deleteEntity(owner);
      }
   }

   @Override
   public void render(GameContainer container, StateBasedGame game, Graphics g) {
      float x = transform.getX();
      float y = transform.getY();
      
      
      float h = currentHealth/maximumHealth;
      
      
      g.drawString(String.valueOf(h) + "%", x, y);
   }

   public void addDamage(float damage) {
      setCurrentHealth(currentHealth-damage);
   }

   public int getMaximumHealth() {
      return maximumHealth;
   }

   public void setCurrentHealth(float currentHealth) {
      this.currentHealth = currentHealth;
      
      if(this.currentHealth > maximumHealth) {
         this.currentHealth = maximumHealth;
      } else if(this.currentHealth <= 0) {
         this.currentHealth = 0;
         destroyed = true;
      }
   }
   
   public void instantKill() {
      currentHealth = 0;
      destroyed = true;
   }

   public float getCurrentHealth() {
      return currentHealth;
   }
   
   public boolean isDestroyed() {
      return destroyed;
   }

   public void addHealth(float health) {
      currentHealth += health;
      if(currentHealth > maximumHealth)
         currentHealth = maximumHealth;
   }
   
   public boolean isAtFullHealth() {
      return currentHealth == maximumHealth;
   }

}


Up to you to create whatever you need for your game.

With this code you could create a "wisp" entity, that has a finite lifetime (lives only for 100 seconds), has health, and some particle system. All you need is to create some AI component to make it move randomly around.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 30, 2010 5:01 am 
Offline
Game Developer
User avatar

Joined: Tue Nov 21, 2006 4:46 am
Posts: 619
Location: Iceland
Here's a real example of how I create a laser tower (in my upcoming game). I simply have a EntityFactory which takes care of assembling the requested entity, e.g.:

Entity laserTowerEntity = EntityFactory.createEntity("laserTower");


Code:
               Entity e = new Entity("laserTower", "Laser", "towers");
               e.setComponent(new Transform());
               e.setComponent(new Bounds(laserConfig.getRadius()));
               e.setComponent(new EnergyConsumer(laserConfig.getEnergy()));
               e.setComponent(new ExpandableBuildArea(laserConfig.getBuildAreaRadius(), laserConfig.getRadius(), 0.01f));

               e.setComponent(new SpawnerBefore("construct"));
               
               Sellable sellable = new Sellable(laserConfig.getRefund(), fontRadiostars14px);
               sellable.setLayer(LAYER_OVERLAY);
               e.setComponent(sellable);
               
               Repair repair = new Repair();
               repair.setLayer(LAYER_OVERLAY);
               e.setComponent(repair);

               Targeter targeter = new Targeter(laserConfig.getStartRange(), laserConfig.getRange(), 500, false, "towers");
               targeter.setLayer(LAYER_OVERLAY);
               e.setComponent(targeter);

               {
                  Weapons weapons = new Weapons();

                  IntervalShootingWeaponController intervalShootingWeaponController = new IntervalShootingWeaponController();
                  intervalShootingWeaponController.setShootInterval(2000);

                  List<Shooter> shooters = new ArrayList<Shooter>();
                  shooters.add(new Shooter("laserProjectile", 16, 0));
                  intervalShootingWeaponController.setShooters(shooters);

                  List<WeaponController> weaponControllers = new ArrayList<WeaponController>();
                  weaponControllers.add(intervalShootingWeaponController);
                  weapons.setWeaponControllers(weaponControllers);
                  e.setComponent(weapons);
               }

               Selection selection = new Selection(highlightImage);
               selection.setLayer(LAYER_OVERLAY);
               e.setComponent(selection);

               NameHighlight nameHighlight = new NameHighlight(fontRadiostars14px);
               nameHighlight.setLayer(LAYER_OVERLAY);
               e.setComponent(nameHighlight);

               Health health = new Health(8000);
               health.setLayer(LAYER_OVERLAY);
               e.setComponent(health);

               TowerBaseSprite baseSprite = new TowerBaseSprite(laserBaseImage);
               baseSprite.setLayer(LAYER_FIELD_BOTTOM);
               e.setComponent(baseSprite);

               TowerSprite towerSprite = new TowerSprite(laserTurretImage);
               towerSprite.setLayer(LAYER_FIELD);
               e.setComponent(towerSprite);

               e.setComponent(new Rotator(0.05f));
               
               return e;


This could be data driven as well, e.g. in some XML or INI.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 02, 2011 11:18 am 
Offline

Joined: Wed Feb 02, 2011 12:21 am
Posts: 12
Hi appel,

This looks very interesting. I'm getting used to the Entity/Component design pattern and it feels very nice to me. I think I'll give this a try, thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 02, 2011 8:40 pm 
Offline
Game Developer
User avatar

Joined: Tue Nov 21, 2006 4:46 am
Posts: 619
Location: Iceland
CWolf wrote:
Hi appel,

This looks very interesting. I'm getting used to the Entity/Component design pattern and it feels very nice to me. I think I'll give this a try, thanks!


If you need more examples or have any questions how to do things, ask away. I've spent a great amount of time tinkering with this stuff so I can answer easily.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group