use of com.agorria.shootandmove.graphics.DrawableBatch in project ShootAndRun by IonAgorria.
the class GameView method createBatch.
/**
* Creates batch for current drawables in queue, this clears queue.
*
* @param slot to set batch
* @param mode to use
* @param drawables to draw in the batch
* @param camera location when drawing
* @param rotation of camera when drawing
* @param color to set when drawing
* @return batch created
*/
public DrawableBatch createBatch(DrawableBatch.SLOT slot, DrawableBatch.MODE mode, List<Drawable> drawables, Vector3f camera, Vector3f rotation, Color color) {
// Vertices calculation
int vertexCount = 0;
for (Drawable drawable : drawables) {
vertexCount += drawable.getVertexCount();
}
// Create buffers
FloatBuffer positionBuffer = Utilities.getDirectByteBuffer(vertexCount * Constants.STRIDE_POSITION).asFloatBuffer();
FloatBuffer texCoordBuffer = Utilities.getDirectByteBuffer(vertexCount * Constants.STRIDE_TEXCOORD).asFloatBuffer();
// Fill buffers with each drawable
TextureAtlas.Atlas atlas = null;
int i = 0;
int indicesCount = 0;
List<short[]> indicesList = new ArrayList<>();
for (Drawable drawable : drawables) {
float[] positions = drawable.getVertexPositions();
positionBuffer.put(positions);
texCoordBuffer.put(drawable.getVertexTexCoords());
short[] indices = drawable.getVertexIndices(i);
indicesCount += indices.length;
indicesList.add(indices);
// Increment indices index
i += positions.length / Constants.FLOATS_PER_POSITION;
// Check atlas is the same
TextureAtlas.Atlas drawableAtlas = drawable.getAtlas();
if (atlas == null) {
atlas = drawableAtlas;
} else if (atlas != drawableAtlas) {
throw new RuntimeException("This batch uses " + atlas + " but drawable has " + drawableAtlas);
}
}
// Create indices buffer
ShortBuffer indicesBuffer = Utilities.getDirectByteBuffer(indicesCount * 2).asShortBuffer();
for (short[] indices : indicesList) {
indicesBuffer.put(indices);
}
// Reset positions for reading
positionBuffer.position(0);
texCoordBuffer.position(0);
indicesBuffer.position(0);
// Create and return batch
return new DrawableBatch(slot, mode, camera, rotation, new Color(color), atlas, positionBuffer, texCoordBuffer, indicesBuffer, indicesCount);
}
use of com.agorria.shootandmove.graphics.DrawableBatch in project ShootAndRun by IonAgorria.
the class GameUI method sizeChanged.
/**
* Called when size of view is changed
*
* @param width in pixes
* @param height in pixels
*/
public void sizeChanged(GameView view, int width, int height) {
Log.d(TAG, "sizeChanged " + width + "x" + height);
this.viewWidth = width == 0 ? 1 : width;
this.viewHeight = height == 0 ? 1 : height;
this.aspect = viewWidth / viewHeight;
// Create non scaled background and submit
TextureAtlas sprite128 = view.getTextureAtlas(TextureAtlas.Atlas.Sprite128);
List<Drawable> backgrounds = new ArrayList<>();
backgrounds.add(new DrawableRectangle(aspect / 2f - 1f, 0, 1f, 1f, sprite128.getRegion(0, 0).copy().flip(false, true)));
backgrounds.add(new DrawableRectangle(aspect / 2f, 0, 1f, 1f, sprite128.getRegion(0, 0)));
DrawableBatch batch = view.createBatchOrthographic(DrawableBatch.SLOT.Background, backgrounds, Color.WHITE);
view.submitBatch(batch);
// Generate menus
menuMap.put(MenuMain.class, new MenuMain(this, view));
menuMap.put(MenuHelp.class, new MenuHelp(this, view));
menuMap.put(MenuPlay.class, new MenuPlay(this, view));
menuMap.put(MenuIntro.class, new MenuIntro(this, view));
menuMap.put(MenuEnding.class, new MenuEnding(this, view));
menuMap.put(MenuCredits.class, new MenuCredits(this, view));
menuMap.put(MenuOptions.class, new MenuOptions(this, view));
// Generate control drawables
TextureAtlas atlas = view.getTextureAtlas(TextureAtlas.Atlas.Sprite32);
gameDrawables.clear();
float controlSize = CONTROLS_SIZE / 2;
// Joystick
joystickRectangle = new Rectangle(CONTROLS_PADDING, CONTROLS_PADDING, controlSize * 2, controlSize * 2);
gameDrawables.add(new DrawableRectangle(joystickRectangle, atlas.getRegion(14, 0)));
// Shoot
gameDrawables.add(new DrawableRectangle(aspect - controlSize - CONTROLS_PADDING, CONTROLS_PADDING + controlSize, controlSize, controlSize, atlas.getRegion(14, 1)));
// Prev
gameDrawables.add(new DrawableRectangle(aspect - controlSize * 2 - CONTROLS_PADDING, CONTROLS_PADDING, controlSize, controlSize, atlas.getRegion(15, 0)));
// Next
gameDrawables.add(new DrawableRectangle(aspect - controlSize - CONTROLS_PADDING, CONTROLS_PADDING, controlSize, controlSize, // Flip side
atlas.getRegion(15, 0).copy().flip(true, false)));
// Cross
gameDrawables.add(new DrawableRectangle(aspect / 2f - CROSS_SIZE / 2f, 0.5f - CROSS_SIZE / 2f, CROSS_SIZE, CROSS_SIZE, atlas.getRegion(8, 1)));
// Health
float playerSpace = aspect * PLAYER_SPACE;
float playerPadding = (1f - PLAYER_PADDING) - PLAYER_SIZE;
gameDrawables.add(new DrawableRectangle(aspect / 2 - playerSpace - PLAYER_SIZE, playerPadding, PLAYER_SIZE, PLAYER_SIZE, atlas.getRegion(4, 2).copy().setSizeCentered(20, 20)));
// Movement
movementDrawables = new Drawable[] { new DrawableRectangle(aspect - controlSize * 2 - CONTROLS_PADDING, CONTROLS_PADDING + controlSize, controlSize, controlSize, atlas.getRegion(15, 1)), new DrawableRectangle(aspect - controlSize * 2 - CONTROLS_PADDING, CONTROLS_PADDING + controlSize, controlSize, controlSize, atlas.getRegion(15, 2)) };
// Death drawables
deathDrawables = new Drawable[] { new DrawableRectangle(0, 0, aspect, 1f, atlas.getRegion(14, 2)), new DrawableRectangle(0, 0, aspect, 1f, atlas.getRegion(13, 2)), new DrawableRectangle(0, 0, aspect, 1f, atlas.getRegion(12, 2)) };
// Set flag
requireDraw = true;
}
use of com.agorria.shootandmove.graphics.DrawableBatch in project ShootAndRun by IonAgorria.
the class GameUI method draw.
/**
* Draws the UI if required
*
* @param view of game
* @param player instance
*/
void draw(GameView view, Player player) {
if (player != null) {
requireDraw |= player.hasChanged();
}
if (requireDraw) {
requireDraw = false;
List<Drawable> drawables = new ArrayList<>();
// Draw death overlay
if (player != null) {
int health = player.getCurrentHealth();
if (health <= 50)
drawables.add(deathDrawables[0]);
if (health <= 25)
drawables.add(deathDrawables[1]);
}
// Draw UI per state
Color color = null;
String text = null;
if (currentGameState == GameState.Menu) {
// Draw current menu
color = Color.WHITE;
Menu menu = menuMap.get(currentMenu);
if (menu != null) {
menu.draw(view, drawables);
}
} else if (currentGameState == GameState.Active) {
color = Color.GRAY_LIGHT_50;
drawables.addAll(gameDrawables);
// Movement mode
if (movementDrawables != null) {
drawables.add(movementDrawables[movementMode ? 1 : 0]);
}
// Add player stuff
if (player != null) {
Weapon weapon = player.getWeapon();
Drawable weaponDrawable = weapon.getDrawable();
float playerPadding = (1 - PLAYER_PADDING) - PLAYER_SIZE;
float middle = aspect / 2f;
// Draw player health
int health = player.getCurrentHealth();
view.drawText(drawables, middle, playerPadding, 0, PLAYER_SIZE, false, false, String.valueOf(health));
// Draw weapon
weaponDrawable.getPosition().set(middle - PLAYER_SIZE - PLAYER_SPACE, playerPadding - PLAYER_SIZE - PLAYER_SPACE, 0);
weaponDrawable.getSize().set(PLAYER_SIZE, PLAYER_SIZE, 0);
drawables.add(weaponDrawable);
// Draw weapon ammo
view.drawText(drawables, middle, playerPadding - PLAYER_SIZE - PLAYER_SPACE, 0, PLAYER_SIZE, false, false, String.valueOf(weapon.getShots()));
}
} else if (currentGameState == GameState.Lost) {
color = Color.RED;
drawables.add(deathDrawables[2]);
text = view.getText(R.string.lost);
} else if (currentGameState == GameState.Pause) {
color = Color.GRAY_LIGHT_50;
text = view.getText(R.string.paused);
}
// Add text
if (text != null) {
String[] lines = Utilities.getTextLines(text);
int textWidth = Utilities.getTextWidth(lines) + 2;
float charWidth = aspect / textWidth;
view.drawText(drawables, aspect / 2f, 0.5f, charWidth, 0, true, true, lines);
}
// Draw slow text if any
if (slowTextElement != null) {
slowTextElement.onDraw(view, drawables);
}
// Send drawables to batch if any
if (drawables.isEmpty()) {
view.clearBatches(DrawableBatch.SLOT.UI);
} else {
DrawableBatch batch = view.createBatchOrthographic(DrawableBatch.SLOT.UI, drawables, color);
view.submitBatch(batch);
}
}
if (vibrate) {
vibrate = false;
view.vibrate(Constants.VIBRATE_UI);
}
}
use of com.agorria.shootandmove.graphics.DrawableBatch in project ShootAndRun by IonAgorria.
the class World method load.
/**
* Loads level as current world
*
* @param level to load
* @param clear state
*/
void load(Integer level, boolean clear) {
// Store player relative data if any
float playerDirection = Constants.HALF_PI;
Vector3f playerPreviousPosition = null;
if (clear) {
playerPosition = null;
walked = 0;
}
if (!clear && player != null) {
playerDirection = player.getDirection();
playerPreviousPosition = player.getPreviousPosition().sub(player.getPosition(), new Vector3f());
}
// Reset stuff
cameraPosition = new Vector3f(0, 0, 0);
cameraRotation = new Vector3f(0, 0, 0);
batches.clear();
entities.clear();
entitiesNext.clear();
collisions.clear();
doors.clear();
player = null;
requestedLevel = null;
robots = 0;
// Use loader if none or different name
if (level == null) {
throw new RuntimeException("No level to load");
}
if (loader == null || !level.equals(loader.level)) {
loader = new WorldLoader(level, view);
}
// Load the world collisions
collisions.addAll(loader.collisions);
// Load world entities from spawns
entities.clear();
for (WorldLoader.EntitySpawn spawn : loader.entities) {
Vector3f position = new Vector3f(spawn.position);
Vector3f size = spawn.size == null ? null : new Vector3f(spawn.size);
switch(spawn.name) {
case "Player":
// Restore old player position
if (playerPosition != null) {
position.add(playerPosition);
}
player = new Player(this, position, playerDirection);
// Restore old previous position
if (playerPreviousPosition != null) {
player.getPosition().add(playerPreviousPosition, player.getPreviousPosition());
}
entities.add(player);
break;
case "Robot":
entities.add(new Robot(this, position, spawn.type));
robots++;
break;
case "Pistol":
entities.add(new Item(this, position, Item.ItemType.Pistol));
break;
case "Plasma":
entities.add(new Item(this, position, Item.ItemType.Plasma));
break;
case "Missile":
entities.add(new Item(this, position, Item.ItemType.Missile));
break;
case "Health":
entities.add(new Item(this, position, Item.ItemType.Health));
break;
case "Door":
Door door = new Door(this, position, size, spawn.type);
entities.add(door);
doors.add(door);
break;
case "LockedDoor":
LockedDoor lockedDoor = new LockedDoor(this, position, size, spawn.type);
entities.add(lockedDoor);
doors.add(lockedDoor);
break;
case "Warp":
entities.add(new Warp(this, position, spawn.type));
break;
default:
throw new IllegalArgumentException("Unknown object name");
}
}
// Update camera before batch
updateCamera();
// Create the batch, use depth as world has no transparency
DrawableBatch batch = view.createBatch(DrawableBatch.SLOT.World, DrawableBatch.MODE.PerspectiveDepth, loader.planes, cameraPosition, cameraRotation, Color.WHITE);
view.submitBatch(batch);
batches.add(batch);
}
use of com.agorria.shootandmove.graphics.DrawableBatch in project ShootAndRun by IonAgorria.
the class World method update.
/**
* Updates the world
*
* @param delta time since last update
*/
void update(float delta) {
// Update entities except player
List<Entity> entitiesCollision = new ArrayList<>();
for (Entity entity : entities) {
// This removes entity as is not added to next list
if (entity.isDestroyed()) {
removedEntity(entity);
continue;
}
// Update entity
entity.update(delta);
// Add to next
entitiesNext.add(entity);
if (entity.getCollision() != null) {
entitiesCollision.add(entity);
}
}
// Check if collides with world
for (Entity entity : entitiesCollision) {
for (Rectangle collision : collisions) {
if (!entity.ignoreCollisionWorld(collision) && entity.checkCollision(collision)) {
boolean unhandled = entity.handleCollisionWorld(collision);
if (unhandled) {
Vector2f vector = entity.resolveCollision(collision);
if (vector != null) {
entity.getPosition().add(vector.x, 0, vector.y);
entity.updateAfterPosition();
}
}
}
}
}
// Check if entities collide
for (Iterator<Entity> iterator = entitiesCollision.iterator(); iterator.hasNext(); ) {
Entity entity = iterator.next();
// Check other entities
for (Entity other : entitiesCollision) {
CollisionInterface otherCollision = other.getCollision();
if (entity != other && !(entity.ignoreCollisionEntity(other) || other.ignoreCollisionEntity(entity)) && entity.checkCollision(otherCollision)) {
boolean entityUnhandled = entity.handleCollisionEntity(other) && !other.ignoreCollisionResolution(entity);
boolean otherUnhandled = other.handleCollisionEntity(entity) && !entity.ignoreCollisionResolution(other);
if (entityUnhandled) {
Vector2f vector = entity.resolveCollision(otherCollision);
if (vector != null) {
if (otherUnhandled) {
// Handle both by distributing equally at opposing direction
vector.mul(0.5f);
other.getPosition().add(-vector.x, 0, -vector.y);
other.updateAfterPosition();
}
// Handle entity
entity.getPosition().add(vector.x, 0, vector.y);
entity.updateAfterPosition();
}
} else if (otherUnhandled) {
// Only handle other
Vector2f vector = other.resolveCollision(entity.getCollision());
if (vector != null) {
other.getPosition().add(vector.x, 0, vector.y);
other.updateAfterPosition();
}
}
}
}
// Remove entity as we have checked it
iterator.remove();
}
// Remove entities that are destroyed and get drawables
List<Drawable> entitiesDrawable = new ArrayList<>();
for (Iterator<Entity> iterator = entitiesNext.iterator(); iterator.hasNext(); ) {
Entity entity = iterator.next();
if (entity.isDestroyed()) {
// Remove entity
removedEntity(entity);
iterator.remove();
} else {
// Add to draw
Drawable drawable = entity.getDrawable();
if (drawable != null) {
entitiesDrawable.add(drawable);
}
}
}
// Set the current entities from next
entities.clear();
entities = entitiesNext;
entitiesNext = new ArrayList<>();
// Update camera
if (player != null && !player.isDestroyed()) {
updateCamera();
}
// Submit batch to draw entities
DrawableBatch batch = view.createBatch(DrawableBatch.SLOT.Entities, DrawableBatch.MODE.PerspectiveDepthBlend, entitiesDrawable, cameraPosition, cameraRotation, Color.WHITE);
view.submitBatch(batch);
}
Aggregations