package com.gdxjam.systems; import java.util.Comparator; import com.badlogic.ashley.core.Engine; import com.badlogic.ashley.core.Entity; import com.badlogic.ashley.core.Family; import com.badlogic.ashley.systems.SortedIteratingSystem; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer; import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.utils.Disposable; import com.gdxjam.components.Components; import com.gdxjam.components.HealthComponent; import com.gdxjam.components.ParalaxComponent; import com.gdxjam.components.PhysicsComponent; import com.gdxjam.components.SpriteComponent; public class EntityRenderSystem extends SortedIteratingSystem implements Disposable { private static final String TAG = "[" + EntityRenderSystem.class.getSimpleName() + "]"; private static final int spriteRotationOffset = -0; private static final float healthBarHeight = 0.15f; private SpriteBatch batch; private ShapeRenderer shapeRenderer; private CameraSystem cameraSystem; private Box2DDebugRenderer renderer; private World world; public static boolean debug = true; private int currentLayer = -10; // Used for log / debug private static boolean cullFustrum = false; private static int drawnEntities = 0; public EntityRenderSystem() { super(Family.one(SpriteComponent.class).get(), new Comparator<Entity>() { @Override public int compare(Entity e1, Entity e2) { if (Components.PARALAX.has(e1) && Components.PARALAX.has(e2)) { ParalaxComponent p1 = Components.PARALAX.get(e1); ParalaxComponent p2 = Components.PARALAX.get(e2); return p1.layer < p2.layer ? 1 : 0; } else if (Components.PARALAX.has(e1) || Components.PARALAX.has(e2)) { return Components.PARALAX.has(e1) ? -1 : 1; } else { return 0; } } }); batch = new SpriteBatch(); shapeRenderer = new ShapeRenderer(); } @Override public void addedToEngine(Engine engine) { super.addedToEngine(engine); cameraSystem = engine.getSystem(CameraSystem.class); renderer = new Box2DDebugRenderer(); world = engine.getSystem(PhysicsSystem.class).getWorld(); } public void drawDebug() { if (renderer == null) { renderer = new Box2DDebugRenderer(); } renderer.render(world, cameraSystem.getCamera().combined); } @Override public void update(float deltaTime) { // Sets the drawn entities counter to 0 for logging purposes drawnEntities = 0; currentLayer = 0; batch.setProjectionMatrix(cameraSystem.getParalaxCamera(currentLayer).combined); batch.begin(); shapeRenderer.setProjectionMatrix(cameraSystem.getCamera().combined); shapeRenderer.begin(ShapeType.Filled); super.update(deltaTime); batch.end(); shapeRenderer.end(); drawDebug(); // Displays the amount of entities that are being drawn // Gdx.app.debug(TAG, "drawn entities: " + drawnEntities); } @Override protected void processEntity(Entity entity, float deltaTime) { Sprite sprite = Components.SPRITE.get(entity).getSprite(); OrthographicCamera camera; if (currentLayer >= 0) { camera = cameraSystem.getParalaxCamera(currentLayer); } else { camera = cameraSystem.getCamera(); batch.setProjectionMatrix(camera.combined); } // Only renderer if the sprite is in the fustrum of the camera if (cullFustrum && !camera.frustum.boundsInFrustum(sprite.getX(), sprite.getY(), 0.0f, sprite.getWidth() * 0.5f, sprite.getHeight() * 0.5f, 0.0f)) { return; } if (Components.PARALAX.has(entity)) { ParalaxComponent paralaxComp = Components.PARALAX.get(entity); if (currentLayer != paralaxComp.layer) { batch.setProjectionMatrix(cameraSystem.getParalaxCamera(paralaxComp.layer).combined); currentLayer = paralaxComp.layer; } } else { if (currentLayer != -1) { batch.setProjectionMatrix(cameraSystem.getCamera().combined); currentLayer = -1; } if (Components.PHYSICS.has(entity)) { PhysicsComponent physics = Components.PHYSICS.get(entity); Vector2 pos = physics.getBody().getPosition(); sprite.setCenter(pos.x, pos.y); sprite.setRotation((MathUtils.radiansToDegrees * physics.getBody().getAngle()) + spriteRotationOffset); } } sprite.draw(batch); // NOTE: If an entity has health but no sprite this will not get // drawn if (Components.HEALTH.has(entity)) { HealthComponent healthComp = Components.HEALTH.get(entity); if (healthComp.value < healthComp.max) { float percent = (float) healthComp.value / (float) healthComp.max; // shapeRenderer.begin(ShapeType.Filled); shapeRenderer.setColor(Color.RED); shapeRenderer.rect(sprite.getX(), sprite.getY() + sprite.getHeight(), sprite.getWidth(), healthBarHeight); shapeRenderer.setColor(Color.GREEN); shapeRenderer.rect(sprite.getX(), sprite.getY() + sprite.getHeight(), sprite.getWidth() * percent, healthBarHeight); // shapeRenderer.end(); } } } @Override public void dispose() { batch.dispose(); renderer.dispose(); shapeRenderer.dispose(); } }