package stray.blocks; import java.util.HashMap; import stray.LevelEditor.EditorGroup; import stray.Main; import stray.Settings; import stray.entity.Entity; import stray.util.AssetMap; import stray.util.MathHelper; import stray.util.Utils; import stray.world.World; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; public class Block { /** * * @param path * actual path; omit .png! */ public Block(String path) { this.path = path; } public static final int globalMagicNumber = Main.getRandom().nextInt(); protected boolean connectedTextures = false; protected boolean variants = false; protected String animationlink = null; protected int varianttypes = 4; protected int solidFaces = BlockFaces.NONE; protected boolean usingMissingTex = false; public EditorGroup levelEditorGroup = EditorGroup.NORMAL; public void tickUpdate(World world, int x, int y) { } public float getDragCoefficient(World world, int x, int y) { return 1; } public boolean isRenderedFront() { return false; } public Block solidify(int faces) { solidFaces = faces; return this; } public void onCollideLeftFace(World world, int x, int y, Entity e) { } public void onCollideRightFace(World world, int x, int y, Entity e) { } public void onCollideUpFace(World world, int x, int y, Entity e) { } public void onCollideDownFace(World world, int x, int y, Entity e) { } public int isSolid(World world, int x, int y) { return solidFaces; } public String getAnimation() { return animationlink; } public Block setAnimation(String animationlink) { this.animationlink = animationlink; return this; } public void dispose() { } public int getTickRate() { return 1; } /** * turns off connected textures too * * @return itself for chaining */ public Block hasVariants(int types) { variants = true; varianttypes = types; connectedTextures = false; return this; } public Block useConTextures() { connectedTextures = true; return this; } public Block setEditorGroup(EditorGroup i) { levelEditorGroup = i; return this; } public void addTextures(Main main) { if (path == null) return; if (animationlink != null) { // assumes animation is loaded already return; } if (!connectedTextures) { if (!Gdx.files.internal(path + ".png").exists() && !variants) { Main.logger.warn("WARNING: a block has no texture (" + path + ".png); using missing texture"); connectedTextures = false; variants = false; usingMissingTex = true; return; } } else { if (!Gdx.files.internal(path + "-full.png").exists() && !variants) { Main.logger.warn("WARNING: a block has no \"full\" texture (" + path + ".png); using missing texture"); connectedTextures = false; variants = false; usingMissingTex = true; return; } } if (!connectedTextures) { if (!variants) { main.manager.load(path + ".png", Texture.class); } else { for (int i = 0; i < varianttypes; i++) { main.manager.load(path + i + ".png", Texture.class); } } } else { main.manager.load(path + "-full.png", Texture.class); main.manager.load(path + "-corner.png", Texture.class); main.manager.load(path + "-edgehor.png", Texture.class); main.manager.load(path + "-edgever.png", Texture.class); } } public void postLoad(Main main) { sprites = new HashMap<String, String>(); if (animationlink != null) return; if (path == null) return; if (usingMissingTex) return; if (connectedTextures) { sprites.put("full", path + "-full.png"); sprites.put("corner", path + "-corner.png"); sprites.put("edgehor", path + "-edgehor.png"); sprites.put("edgever", path + "-edgever.png"); } else { if (!variants) { sprites.put("defaulttex", path + ".png"); } else { for (int i = 0; i < varianttypes; i++) { sprites.put("defaulttex" + i, path + i + ".png"); } } } } // protected void drawAt(Batch batch, Texture sprite, float f, float g) { // batch.draw(sprite, f, Main.convertY(g + World.tilesizey), // World.tilesizex, World.tilesizey); // } /** * only used for connected textures connected: full, corner, edgehor, * edgever */ protected HashMap<String, String> sprites; protected String path = ""; private int getVarFromTime() { int time = (MathHelper.getNthDigit(System.currentTimeMillis(), 1)) + (MathHelper.getNthDigit(System.currentTimeMillis(), 2) * 10) + (MathHelper.getNthDigit(System.currentTimeMillis(), 3) * 100) + (MathHelper.getNthDigit(System.currentTimeMillis(), 4) * 1000); // 10k return ((int) time / (10000 / varianttypes)); } // /** // * topleft origin! // * // * @param batch // * @param x // * @param y // */ // public void renderModel(World world, int x, int y) { // Batch batch = world.batch; // if (path == null) return; // if (usingMissingTex) { // batch.draw(world.main.manager.get(AssetMap.get("blockmissingtexture"), // Texture.class), // x, Main.convertY(y + World.tilesizey), World.tilesizex, World.tilesizey); // return; // } // // if (animationlink != null) { // batch.draw(world.main.animations.get(animationlink).getCurrentFrame(), x, // Main.convertY(y + World.tilesizey), World.tilesizex, World.tilesizey); // return; // } // // if (!connectedTextures) { // if (!variants) { // drawAt(batch, world.main.manager.get(sprites.get("defaulttex"), // Texture.class), x, // y); // } else { // drawAt(batch, world.main.manager.get(sprites.get("defaulttex" + // getVarFromTime()), // Texture.class), x, y); // } // } else { // drawAt(batch, world.main.manager.get(sprites.get("full"), Texture.class), // x, y); // } // } public static int variantNum(World world, int x, int y) { return variantNum(world.msTime, x, y); } public static int variantNum(long magic, int x, int y) { return ((int) ((magic + (x + 17) * (y + 53) * 214013L + 2531011L) >> 16) & 0x7fff); } public static int variantNum(int x, int y) { return variantNum(Block.globalMagicNumber, x, y); } // public void renderPlain(Main main, float camerax, float cameray, int x, // int y, int magic) { // if (animationlink != null) { // main.batch.draw(main.animations.get(animationlink).getCurrentFrame(), x // * World.tilesizex - camerax, y * World.tilesizey - cameray, // World.tilesizex, // World.tilesizey); // return; // } // // if (usingMissingTex) { // main.batch.draw(main.manager.get(AssetMap.get("blockmissingtexture"), // Texture.class), x // * World.tilesizex - camerax, y * World.tilesizey - cameray, // World.tilesizex, // World.tilesizey); // return; // } // // if (path == null) return; // // if (!connectedTextures) { // if (!variants) { // drawAt(main.batch, main.manager.get(sprites.get("defaulttex"), // Texture.class), x // * World.tilesizex - camerax, y * World.tilesizey - cameray); // } else { // drawAt(main.batch, main.manager.get(sprites.get("defaulttex" // + ((variantNum(magic, x, y)) & (varianttypes - 1))), Texture.class), x // * World.tilesizex - camerax, y * World.tilesizey - cameray); // } // } else { // drawAt(main.batch, main.manager.get(sprites.get("full"), Texture.class), // x // * World.tilesizex - camerax, y * World.tilesizey - cameray); // // } // } public void render(World world, int x, int y) { renderWithOffset(world, x, y, 0, 0); } public void renderWithOffset(World world, int x, int y, float offx, float offy) { if (usingMissingTex) { world.batch.draw( world.main.manager.get(AssetMap.get("blockmissingtexture"), Texture.class), x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); return; } if (animationlink != null) { world.batch.draw( world.main.animations.get(animationlink).getCurrentFrame(), x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); return; } if (path == null) return; if (!connectedTextures) { if (!variants) { world.batch.draw( world.main.manager.get(sprites.get("defaulttex"), Texture.class), x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else { world.batch.draw(world.main.manager.get(sprites.get("defaulttex" + ((variantNum(world, x, y)) & (varianttypes - 1))), Texture.class), x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } } else { drawConnectedTexture(world, x, y, offx, offy, world.main.manager.get(sprites.get("corner"), Texture.class), world.main.manager.get(sprites.get("full"), Texture.class), world.main.manager.get(sprites.get("edgever"), Texture.class), world.main.manager.get(sprites.get("edgehor"), Texture.class)); } } public void drawConnectedTexture(World world, int x, int y, float offx, float offy, Texture corner, Texture full, Texture ver, Texture hor) { boolean up, down, left, right; up = world.getBlock(x, y - 1) == this; down = world.getBlock(x, y + 1) == this; left = world.getBlock(x - 1, y) == this; right = world.getBlock(x + 1, y) == this; if (up && down && left && right) { if (world.getBlock(x + 1, y + 1) != this || world.getBlock(x + 1, y - 1) != this || world.getBlock(x - 1, y + 1) != this || world.getBlock(x - 1, y - 1) != this) { world.batch.draw( corner, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else world.batch.draw( full, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else if (up && down && (left == false || right == false)) { world.batch.draw( ver, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else if (left && right && (up == false || down == false)) { world.batch.draw( hor, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else { world.batch.draw( corner, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } } public void drawConnectedTexture(World world, int x, int y, float offx, float offy, TextureRegion corner, TextureRegion full, TextureRegion ver, TextureRegion hor) { boolean up, down, left, right; up = world.getBlock(x, y - 1) == this; down = world.getBlock(x, y + 1) == this; left = world.getBlock(x - 1, y) == this; right = world.getBlock(x + 1, y) == this; if (up && down && left && right) { if (world.getBlock(x + 1, y + 1) != this || world.getBlock(x + 1, y - 1) != this || world.getBlock(x - 1, y + 1) != this || world.getBlock(x - 1, y - 1) != this) { world.batch.draw( corner, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey)); } else world.batch.draw( full, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else if (up && down && (left == false || right == false)) { world.batch.draw( ver, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else if (left && right && (up == false || down == false)) { world.batch.draw( hor, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } else { world.batch.draw( corner, x * world.tilesizex - world.camera.camerax + offx, Main.convertY((y * world.tilesizey - world.camera.cameray) + World.tilesizey + offy)); } } // protected void drawAt(SpriteBatch batch, TextureRegion corner, float f, // float g) { // batch.draw(corner, f, Main.convertY(g + World.tilesizey), // World.tilesizex, World.tilesizey); // } public static boolean isEntityNear(World world, int x, int y, int rad, Class<?> cls) { for (int i = 0; i < world.entities.size; i++) { Entity e = world.entities.get(i); if (!(cls.isInstance(e))) continue; if (MathHelper.intersects(e.x, e.y, e.sizex, e.sizey, x - rad + 1, y - rad + 1, rad * 2 - 1, rad * 2 - 1)) return true; } return false; } public static Entity getNearestEntity(World world, int x, int y, int rad, Class<?> cls) { if (isEntityNear(world, x, y, rad, cls)) { for (int i = 0; i < world.entities.size; i++) { Entity e = world.entities.get(i); if (!(cls.isInstance(e))) continue; if (MathHelper.intersects(e.x, e.y, e.sizex, e.sizey, x - rad + 1, y - rad + 1, rad * 2 - 1, rad * 2 - 1)) return e; } } return null; } public static boolean entityIntersects(World world, double x, double y, Entity e) { return entityIntersects(world, x, y, e, 1, 1); } public static boolean entityIntersects(World world, double x, double y, Entity e, double sizex, double sizey) { if (e == null) return false; return MathHelper.intersects(x, y, sizex, sizey, e.x, e.y, e.sizex, e.sizey); } public static boolean isBlockVisible(float camx, float camy, int x, int y) { return MathHelper.intersects(x * World.tilesizex, y * World.tilesizey, World.tilesizex, World.tilesizey, camx, camy, Settings.DEFAULT_WIDTH, Gdx.graphics.getHeight()); } public static boolean playSound(int x, int y, float camx, float camy, Sound sound, float vol, float pitch, boolean mustbevisible) { if (!Block.isBlockVisible(camx, camy, x, y) && mustbevisible) return false; sound.play(vol * Settings.soundVolume, pitch, Utils.getSoundPan(x, camx)); return true; } public static boolean playSound(int x, int y, float camx, float camy, Sound sound, float vol, float pitch) { return playSound(x, y, camx, camy, sound, vol, pitch, true); } public static class BlockFaces { public static final int NONE = 0x0; public static final int ALL = 0xF; public static final int UP = 0x1; public static final int DOWN = 0x2; public static final int LEFT = 0x4; public static final int RIGHT = 0x8; } }