use of com.agorria.shootandmove.math.Rectangle 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.math.Rectangle in project ShootAndRun by IonAgorria.
the class GameUI method showText.
/**
* Shows text in UI
*/
void showText(String text) {
if (text != null) {
List<String> lines = Arrays.asList(Utilities.getTextLines(text));
if (slowTextElement == null) {
slowTextElement = new SlowTextElement(new Rectangle(aspect * 0.3f, 0.0f, aspect * 0.4f, 0.5f), lines, () -> showText(null), true, false);
slowTextElement.onOpen();
} else if (!text.equals(lastText)) {
slowTextElement.setLines(lines);
}
} else {
slowTextElement = null;
}
lastText = text;
}
use of com.agorria.shootandmove.math.Rectangle 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);
}
use of com.agorria.shootandmove.math.Rectangle in project ShootAndRun by IonAgorria.
the class WorldLoader method parseTileLayers.
/**
* Parses map tile layers
*
* @param map to use
*/
private void parseTileLayers(Element map, GameView view) {
// Iterate layers
Map<LayerType, String> layersMap = new HashMap<>();
NodeList layers = map.getElementsByTagName("layer");
for (int layerIndex = 0; layerIndex < layers.getLength(); layerIndex++) {
Element layer = (Element) layers.item(layerIndex);
// Check attributes of layer
if (Integer.parseInt(layer.getAttribute("width")) != width) {
throw new IllegalArgumentException("Layer width doesn't match with map width");
}
if (Integer.parseInt(layer.getAttribute("height")) != height) {
throw new IllegalArgumentException("Layer width doesn't match with map width");
}
String layerName = layer.getAttribute("name");
LayerType layerType;
try {
layerType = LayerType.valueOf(layerName);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Unknown tile layer: " + layerName);
}
// Parse layer data
NodeList layerDatas = layer.getElementsByTagName("data");
// Check if exact one layer data
if (layerDatas.getLength() != 1) {
throw new IllegalArgumentException("Only one layer data is supported, found: " + layerDatas.getLength());
}
Element layerData = (Element) layerDatas.item(0);
String layerEncoding = layerData.getAttribute("encoding");
if (!layerEncoding.equals("csv")) {
throw new IllegalArgumentException("Layer '" + layerName + "' not supported encoding " + layerEncoding);
}
layersMap.put(layerType, layerData.getTextContent());
}
// Create masks
groundMask = new boolean[width * height];
wallMask = new boolean[width * height];
// Parse the layers
parseTileLayer(LayerType.Ground, layersMap, view);
parseTileLayer(LayerType.Walls, layersMap, view);
parseTileLayer(LayerType.Ceil, layersMap, view);
// Generate collisions from wall mask in X axis
int i = 0;
for (int y = 0; y < height; y++) {
Integer start = null;
for (int x = 0; x < width; x++) {
boolean wall = wallMask[i];
boolean last = x + 1 == width;
// Mark start of wall
if (wall) {
if (start == null) {
start = x;
}
}
// Make rectangle if ends wall or the next position is on next line
if (!wall || last) {
if (start != null) {
int width = (last ? x + 1 : x) - start;
Rectangle rectangle = new Rectangle(start, y, width, 1);
collisions.add(rectangle);
start = null;
}
}
i++;
}
}
// Merge rectangles in Y axis
boolean changes = true;
while (changes) {
changes = false;
for (Iterator<Rectangle> iterator = collisions.iterator(); iterator.hasNext(); ) {
Rectangle current = iterator.next();
boolean merged = false;
for (Rectangle collision : collisions) {
if (current.x == collision.x && current.width == collision.width && // Check if current is under collision
current.y > collision.y && // Check if collision end match current start
collision.y + collision.height == current.y) {
collision.height += current.height;
merged = true;
break;
}
}
if (merged) {
changes = true;
iterator.remove();
}
}
}
}
Aggregations