package com.fdangelo.circleworld.universeview; import java.util.ArrayList; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.Batch; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.utils.Disposable; import com.fdangelo.circleworld.universeengine.IUniverseListener; import com.fdangelo.circleworld.universeengine.Thing; import com.fdangelo.circleworld.universeengine.ThingPosition; import com.fdangelo.circleworld.universeengine.ThingType; import com.fdangelo.circleworld.universeengine.Universe; import com.fdangelo.circleworld.universeengine.objects.Avatar; import com.fdangelo.circleworld.universeengine.objects.Ship; import com.fdangelo.circleworld.universeengine.objects.UniverseObject; import com.fdangelo.circleworld.universeengine.tilemap.Planet; import com.fdangelo.circleworld.universeengine.tilemap.PlanetType; import com.fdangelo.circleworld.universeengine.tilemap.PlanetTypes; import com.fdangelo.circleworld.universeengine.tilemap.TilemapCircle; import com.fdangelo.circleworld.universeengine.utils.UEProfiler; import com.fdangelo.circleworld.universeview.objects.AvatarView; import com.fdangelo.circleworld.universeview.objects.ShipView; import com.fdangelo.circleworld.universeview.objects.UniverseObjectView; import com.fdangelo.circleworld.universeview.tilemap.PlanetView; public final class UniverseView extends Actor implements IUniverseListener, Disposable { static private final int LAYER_COUNT = 3; static private final int LAYER_BACKGROUND = 0; static private final int LAYER_PLANETS = 1; static private final int LAYER_FOREGROUND = 2; static public final int MAX_ACTIVE_PLANET_VIEWS = 5; private final UniverseViewFactory universeFactory = new UniverseViewFactory(); private final PlanetView[] planetViews = new PlanetView[Universe.MAX_THINGS]; private final ArrayList<PlanetView> activePlanetViews = new ArrayList<PlanetView>(32); private final ArrayList<UniverseObjectView> tilemapObjectViews = new ArrayList<UniverseObjectView>(32); private AvatarView avatarView; private ShipView shipView; private Universe universe; private final OrthographicCamera camera; private final PlanetType[] planetTypes; private final Stage[] layers; public final Universe getUniverse() { return universe; } public final OrthographicCamera getCamera() { return camera; } public final AvatarView getAvatarView() { return avatarView; } public final ShipView getShipView() { return shipView; } public UniverseView() { camera = new OrthographicCamera(); layers = new Stage[LAYER_COUNT]; for (int i = 0; i < layers.length; i++) { layers[i] = new Stage(); layers[i].setCamera(camera); layers[i].setViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); } planetTypes = PlanetTypes.getPlanetTypes(); layers[LAYER_BACKGROUND].addActor(this); } public final void init(final int seed) { createUniverse(seed); updateMesh(true); } private final void createUniverse(final int seed) { universe = new Universe(); universe.init(seed, this); } public final PlanetView getPlanetView(final TilemapCircle tilemapCircle) { if (tilemapCircle instanceof Planet) { return getPlanetView(((Planet) tilemapCircle).getThingIndex()); } return null; } public final boolean existsPlanetView(final TilemapCircle tilemapCircle) { if (tilemapCircle instanceof Planet) { return planetViews[((Planet) tilemapCircle).getThingIndex()] != null; } return false; } public final PlanetView getPlanetView(final short thingIndex) { if (planetViews[thingIndex] != null) { return planetViews[thingIndex]; } if (activePlanetViews.size() >= MAX_ACTIVE_PLANET_VIEWS) { universe.returnPlanet(activePlanetViews.get(0).getPlanet()); } final Planet planet = universe.getPlanet(thingIndex); if (planet == null) { return null; } final PlanetView planetView = universeFactory.getPlanet(planet.getHeight()); planetView.initPlanet(planet, this); activePlanetViews.add(planetView); layers[LAYER_PLANETS].addActor(planetView); planetViews[thingIndex] = planetView; // Debug.Log(planetViews.Count); return planetView; } @Override public void onPlanetReturned(final Planet planet) { planetViews[planet.getThingIndex()] = null; for (int i = 0; i < activePlanetViews.size(); i++) { if (activePlanetViews.get(i).getPlanet() == planet) { final PlanetView planetView = activePlanetViews.get(i); // remove from stage planetView.remove(); universeFactory.returnPlanet(planetView); activePlanetViews.remove(i); break; } } } @Override public void onUniverseObjectAdded(final UniverseObject universeObject) { if (universeObject instanceof Avatar) { avatarView = universeFactory.getAvatar(); avatarView.init(universeObject, this); tilemapObjectViews.add(avatarView); layers[LAYER_FOREGROUND].addActor(avatarView); } else if (universeObject instanceof Ship) { shipView = universeFactory.getShip(); shipView.init(universeObject, this); tilemapObjectViews.add(shipView); layers[LAYER_FOREGROUND].addActor(shipView); } } // / <summary> // / Called by GameLogic // / </summary> public final void updateUniverse(final float deltaTime) { universe.updateUniverse(deltaTime); if (isVisible()) { UEProfiler.BeginSample("UniverseView.UpdateMesh"); updateMesh(false); UEProfiler.EndSample(); } } @Override public void draw(final Batch batch, final float parentAlpha) { final Thing[] things = universe.getThings(); final ThingPosition[] thingsPositions = universe.getThingsPositions(); final short[] thingsToRender = universe.getThingsToRender(); final short thingsToRenderAmount = universe.getThingsToRenderAmount(); for (int i = 0; i < thingsToRenderAmount; i++) { final short thingIndex = thingsToRender[i]; if (planetViews[thingIndex] != null) { continue; } final ThingPosition position = thingsPositions[thingIndex]; final Thing thing = things[thingIndex]; PlanetType planetType; if (thing.type == ThingType.Sun) { planetType = planetTypes[Math.abs(thing.seed % 2) + 4]; // suns! } else { planetType = planetTypes[Math.abs(thing.seed % 4)]; // planets! } batch.draw(planetType.planetSprite, position.x - position.radius, position.y - position.radius, position.radius * 2.0f, position.radius * 2.0f); } } private final void updateMesh(final boolean firstTime) { /* * Thing[] things = universe.getThings(); ThingPosition[] * thingsPositions = universe.getThingsPositions(); short[] * thingsToRender = universe.getThingsToRender(); short * thingsToRenderAmount = universe.getThingsToRenderAmount(); int * vertexCount = thingsToRenderAmount * 4; int triangleCount = * thingsToRenderAmount * 6; Vector3[] vertices = * DataPools.poolVector3.GetArray(vertexCount); int vertexOffset = 0; * //Update all positions for (int i = 0; i < thingsToRenderAmount; i++) * { ushort thingIndex = thingsToRender[i]; ThingPosition position = * thingsPositions[thingIndex]; vertices[vertexOffset + 0].x = * position.x - position.radius; vertices[vertexOffset + 0].y = * position.y - position.radius; vertices[vertexOffset + 1].x = * position.x - position.radius; vertices[vertexOffset + 1].y = * position.y + position.radius; vertices[vertexOffset + 2].x = * position.x + position.radius; vertices[vertexOffset + 2].y = * position.y + position.radius; vertices[vertexOffset + 3].x = * position.x + position.radius; vertices[vertexOffset + 3].y = * position.y - position.radius; vertexOffset += 4; } //Don't draw * preview of active planets (except the first time that everything is * draw) if (!firstTime) { for (int i = 0; i < activePlanetViews.Count; * i++) { ushort thingIndex = activePlanetViews[i].Planet.ThingIndex; * int thingsToRenderIndex = System.Array.BinarySearch(thingsToRender, * 0, thingsToRenderAmount, thingIndex); if (thingsToRenderIndex >= 0) { * vertexOffset = thingsToRenderIndex * 4; vertices[vertexOffset + 0].x * = 0; vertices[vertexOffset + 0].y = 0; vertices[vertexOffset + 1].x = * 0; vertices[vertexOffset + 1].y = 0; vertices[vertexOffset + 2].x = * 0; vertices[vertexOffset + 2].y = 0; vertices[vertexOffset + 3].x = * 0; vertices[vertexOffset + 3].y = 0; } } } if (firstTime) { //Update * triangles and uvs only the first time that the mesh is updated int * triangleOffset = 0; vertexOffset = 0; int[] triangles = * DataPools.poolInt.GetArray(triangleCount); Vector2[] uvs = * DataPools.poolVector2.GetArray(vertexCount); for (ushort i = 0; i < * thingsToRenderAmount; i++) { Thing thing = things[thingsToRender[i]]; * PlanetType planetType; if (thing.type == (ushort) ThingType.Sun) * planetType = planetTypes[Mathf.Abs(thing.seed % 2) + 4]; //suns! else * planetType = planetTypes[Mathf.Abs(thing.seed % 4)]; //planets! Rect * planetUV = planetType.planetSprite.UV; uvs[vertexOffset + 0] = new * Vector2(planetUV.xMin, planetUV.yMax); uvs[vertexOffset + 1] = new * Vector2(planetUV.xMax, planetUV.yMax); uvs[vertexOffset + 2] = new * Vector2(planetUV.xMax, planetUV.yMin); uvs[vertexOffset + 3] = new * Vector2(planetUV.xMin, planetUV.yMin); triangles[triangleOffset + 0] * = vertexOffset + 0; triangles[triangleOffset + 1] = vertexOffset + 1; * triangles[triangleOffset + 2] = vertexOffset + 2; * triangles[triangleOffset + 3] = vertexOffset + 2; * triangles[triangleOffset + 4] = vertexOffset + 3; * triangles[triangleOffset + 5] = vertexOffset + 0; triangleOffset += * 6; vertexOffset += 4; } mesh1.vertices = vertices; mesh2.vertices = * vertices; mesh1.triangles = triangles; mesh1.uv = uvs; mesh1.bounds = * new Bounds(Vector3.zero, new Vector3(ushort.MaxValue * 2, * ushort.MaxValue * 2, 0.0f)); mesh2.triangles = triangles; mesh2.uv = * uvs; mesh2.bounds = new Bounds(Vector3.zero, new * Vector3(ushort.MaxValue * 2, ushort.MaxValue * 2, 0.0f)); * mesh1.Optimize(); mesh2.Optimize(); * DataPools.poolInt.ReturnArray(triangles); * DataPools.poolVector2.ReturnArray(uvs); } if ((frameCount % 2) == 0) * { mesh1.vertices = vertices; meshFilter.sharedMesh = mesh1; } else { * mesh2.vertices = vertices; meshFilter.sharedMesh = mesh2; } * DataPools.poolVector3.ReturnArray(vertices); frameCount++; */ } public final void updateLayers(final float deltaTime) { for (int i = 0; i < layers.length; i++) { layers[i].act(deltaTime); } for (int i = 0; i < layers.length; i++) { layers[i].draw(); } } @Override public void dispose() { for (int i = 0; i < layers.length; i++) { layers[i].dispose(); } } public final void resize(final int width, final int height) { for (int i = 0; i < layers.length; i++) { layers[i].setViewport(width, height); } } }