diff --git a/logs/game.log b/logs/game.log new file mode 100644 index 0000000..7244071 --- /dev/null +++ b/logs/game.log @@ -0,0 +1 @@ +22:26:25.948 [Music Thread ] WARN ru.windcorp.progressia.test.TestMusicPlayer > No music found diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Background.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Background.java new file mode 100644 index 0000000..a3312dd --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Background.java @@ -0,0 +1,28 @@ +package ru.windcorp.progressia.client.graphics.gui; + +import glm.mat._4.Mat4; +import glm.vec._3.Vec3; +import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.texture.Texture; + +public class Background extends GUILayer { + + protected Texture backgroundTexture; + + public Background(String name, Layout layout, Texture inTexture) { + super(name, layout); + + backgroundTexture = inTexture; + } + + @Override + protected void assemble(RenderTarget target) { + getRoot().setBounds(0, 0, getWidth(), getHeight()); + getRoot().invalidate(); + target.pushTransform(new Mat4(1).translate(new Vec3(0,0,500))); + target.drawTexture(0, 0, getWidth(), getHeight(), backgroundTexture); + target.popTransform(); + getRoot().assemble(target); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java index 5d42241..9ac0e9f 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Button.java @@ -23,6 +23,10 @@ import ru.windcorp.progressia.client.graphics.flat.RenderTarget; import ru.windcorp.progressia.client.graphics.font.Font; import ru.windcorp.progressia.client.graphics.Colors; +/** Class for a traditional button that gets clicked to activate + * + * @author opfromthestart + */ public class Button extends BasicButton { public Button(String name, String label, Font labelFont) { @@ -51,9 +55,7 @@ public class Button extends BasicButton { // Inside area - if (isPressed()) { - // Do nothing - } else { + if (!isPressed()) { Vec4 backgroundColor; if (isHovered() && isEnabled()) { backgroundColor = Colors.HOVER_BLUE; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/TextureComponent.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/TextureComponent.java new file mode 100644 index 0000000..0dc150e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/TextureComponent.java @@ -0,0 +1,23 @@ +package ru.windcorp.progressia.client.graphics.gui; + +import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.texture.Texture; + +public class TextureComponent extends Component { + + private final Texture texture; + + public TextureComponent(String name, Texture texture2) { + super(name); + + texture = texture2; + setPreferredSize(texture.getSprite().getWidth(),texture.getSprite().getHeight()); + } + + @Override + protected void assembleSelf(RenderTarget target) + { + target.drawTexture(getX(), getY(), getWidth(), getHeight(), texture); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java index d521914..860b7b6 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutAlign.java @@ -27,8 +27,8 @@ import ru.windcorp.progressia.client.graphics.gui.Layout; public class LayoutAlign implements Layout { - private final int margin; - private double alignX, alignY; + protected final int margin; + protected double alignX, alignY; public LayoutAlign(double alignX, double alignY, int margin) { this.alignX = alignX; @@ -72,7 +72,7 @@ public class LayoutAlign implements Layout { Vec2i result = new Vec2i(0, 0); c.getChildren().stream() - .map(child -> child.getPreferredSize()) + .map(Component::getPreferredSize) .forEach(size -> { result.x = max(size.x, result.x); result.y = max(size.y, result.y); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutEdges.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutEdges.java new file mode 100644 index 0000000..afc0ba4 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/layout/LayoutEdges.java @@ -0,0 +1,56 @@ +package ru.windcorp.progressia.client.graphics.gui.layout; + +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.gui.Component; +import ru.windcorp.progressia.client.graphics.gui.Layout; +import static java.lang.Math.max; +import static java.lang.Math.min; + +public class LayoutEdges implements Layout { + + private final int margin; + + public LayoutEdges(int margin) { + this.margin = margin; + } + + @Override + public void layout(Component c) { + for (int i=0;i<2;i++) + { + Component child = c.getChild(i); + + Vec2i size = child.getPreferredSize(); + + int cWidth = c.getWidth() - 2 * margin; + int cHeight = c.getHeight() - 2 * margin; + + size.x = min(size.x, cWidth); + size.y = min(size.y, cHeight); + + if (i==0) { + child.setBounds( + c.getX() + margin, + c.getY(), + size + ); + } else { + child.setBounds( + 1920 - size.x - margin, + c.getY(), + size + ); + } + + } + } + + @Override + public Vec2i calculatePreferredSize(Component c) { + Vec2i result = new Vec2i(1920,0); + c.getChildren().stream() + .map(Component::getPreferredSize) + .forEach(size -> result.y = max(Math.abs(size.y), result.y)); + return result; + } +} diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java index b25535c..87744e3 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/Region.java @@ -43,10 +43,8 @@ public class Region { private static final boolean RESET_CORRUPTED = true; - public int loadedChunks; - - private AtomicBoolean isUsing = new AtomicBoolean(false); - private AtomicBoolean isClosed = new AtomicBoolean(false); + private final AtomicBoolean isUsing = new AtomicBoolean(false); + private final AtomicBoolean isClosed = new AtomicBoolean(false); private final RegionFile file; @@ -60,6 +58,7 @@ public class Region { } catch (IOException e) { RegionWorldContainer.LOG.debug("Uh the file broke"); + RegionWorldContainer.LOG.debug(e.getLocalizedMessage()); if (RESET_CORRUPTED) { this.file.makeHeader(regionCoords); } @@ -132,7 +131,7 @@ public class Region { DecodingException { isUsing.set(true); - int dataOffset = 0; + int dataOffset; Vec3i pos = RegionWorldContainer.getInRegionCoords(chunkPos); if (hasOffset(pos)) { diff --git a/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java index 520d24e..a3fadce 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/io/region/RegionFile.java @@ -26,9 +26,9 @@ public class RegionFile { private static final int ID_HEADER_SIZE = 16; private static final byte[] HEADER_ID = {'P','R','O','G'}; - final byte endBytes[] = new byte[SECTOR_SIZE]; + final byte[] endBytes = new byte[SECTOR_SIZE]; - public static enum SectorType { + public enum SectorType { Ending(0), // Just an empty block Data(1), // has a byte counting up in position 1, and then PartitionLink(2), @@ -54,7 +54,7 @@ public class RegionFile { public void confirmHeaderHealth(ChunkMap offsets, Vec3i regionCoords) throws IOException { - Set used = new HashSet(); + Set used = new HashSet<>(); int maxUsed = 0; final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER; @@ -63,9 +63,10 @@ public class RegionFile { } - char prog; + byte prog; + file.seek(0); for (int i=0;i<4;i++) { - prog = file.readChar(); + prog = file.readByte(); if (prog != HEADER_ID[i]) { throw new IOException("File is not a .progressia_chunk file"); @@ -109,7 +110,7 @@ public class RegionFile { throw new IOException("A sector is used twice"); } - file.seek(HEADER_SIZE + SECTOR_SIZE * offset); + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * offset); byte type = file.readByte(); if (type == SectorType.Data.data) { @@ -131,25 +132,26 @@ public class RegionFile { } public void makeHeader(Vec3i regionCoords) throws IOException { + file.seek(0); + for (int i = 0; i < HEADER_SIZE; i++) { + file.write(0); + } file.seek(0); file.write(HEADER_ID); file.writeInt(regionCoords.x); file.writeInt(regionCoords.y); file.writeInt(regionCoords.z); - for (int i = 0; i < HEADER_SIZE; i++) { - file.write(0); - } } public void writeBuffer(byte[] buffer, int dataOffset, Vec3i pos) throws IOException { - file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset); int loc = 0; - byte tempBuffer[] = new byte[SECTOR_SIZE]; + byte[] tempBuffer = new byte[SECTOR_SIZE]; byte counter = 0; boolean isDone = false; while (!isDone) { - if (file.length() > HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)) { - file.seek(HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)); + if (file.length() > HEADER_SIZE + (long) SECTOR_SIZE * (dataOffset + 1)) { + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * (dataOffset + 1)); byte header = file.readByte(); if (header == SectorType.Data.data) { byte fileCounter = file.readByte(); @@ -157,7 +159,7 @@ public class RegionFile { // partition place { int newOffset = allocateEmptySector(); - file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset); file.write(2); file.writeInt(newOffset); dataOffset = newOffset; @@ -179,7 +181,7 @@ public class RegionFile { if (file.getFilePointer() < 256) LogManager.getLogger("Region") .debug("at {}, ({},{},{}), {}", file.getFilePointer(), pos.x, pos.y, pos.z, dataOffset); - file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset); dataOffset++; file.write(tempBuffer); } @@ -197,7 +199,7 @@ public class RegionFile { file.seek(definitionOffset); file.writeInt(dataOffset + 1); - file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE); + file.setLength(HEADER_SIZE + (long) dataOffset * SECTOR_SIZE); return dataOffset; } @@ -206,17 +208,17 @@ public class RegionFile { int dataOffset = (int) Math.ceil((double) (outputLen - HEADER_SIZE) / SECTOR_SIZE); - file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE); + file.setLength(HEADER_SIZE + (long) dataOffset * SECTOR_SIZE); return dataOffset; } public byte[] readBuffer(int dataOffset) throws IOException { - file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset); + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset); int bufferPos = 0; - byte buffer[] = new byte[SECTOR_SIZE * 16]; - byte tempBuffer[] = new byte[SECTOR_SIZE]; + byte[] buffer = new byte[SECTOR_SIZE * 16]; + byte[] tempBuffer = new byte[SECTOR_SIZE]; boolean reachedEnd = false; byte counter = 0; @@ -229,31 +231,24 @@ public class RegionFile { if (tempBuffer[0] == SectorType.Data.data) { if (tempBuffer[1] != counter) { throw new IOException( - "Sectors were read out of order\nExpected chunk number " + Byte.toString(counter) - + " but encountered number " + Byte.toString(tempBuffer[1]) + "Sectors were read out of order\nExpected chunk number " + counter + + " but encountered number " + tempBuffer[1] ); } counter++; if (buffer.length - bufferPos < SECTOR_SIZE - SECTOR_HEADER_SIZE - 1) { - byte newBuffer[] = new byte[buffer.length + SECTOR_SIZE * 16]; - for (int i = 0; i < buffer.length; i++) // TODO dedicated - // copy, java-y at - // least - { - newBuffer[i] = buffer[i]; - } + byte[] newBuffer = new byte[buffer.length + SECTOR_SIZE * 16]; + System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); buffer = newBuffer; } - for (int i = 0; i < SECTOR_SIZE - SECTOR_HEADER_SIZE - 1; i++) { - buffer[bufferPos + i] = tempBuffer[i + 2]; - } + System.arraycopy(tempBuffer, 2, buffer, bufferPos, SECTOR_SIZE - SECTOR_HEADER_SIZE - 1); bufferPos += SECTOR_SIZE - SECTOR_HEADER_SIZE - 1; } else if (tempBuffer[0] == SectorType.Ending.data) { reachedEnd = true; } else if (tempBuffer[0] == SectorType.PartitionLink.data) { ByteBuffer intBuffer = ByteBuffer.wrap(tempBuffer); int newOffset = intBuffer.getInt(1); - file.seek(HEADER_SIZE + SECTOR_SIZE * newOffset); + file.seek(HEADER_SIZE + (long) SECTOR_SIZE * newOffset); } else { throw new IOException("Invalid sector ID."); } diff --git a/src/main/java/ru/windcorp/progressia/test/CubeComponent.java b/src/main/java/ru/windcorp/progressia/test/CubeComponent.java new file mode 100644 index 0000000..bf535d0 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/CubeComponent.java @@ -0,0 +1,108 @@ +package ru.windcorp.progressia.test; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import glm.mat._4.Mat4; +import glm.vec._3.Vec3; +import glm.vec._4.Vec4; +import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.gui.Component; + +public class CubeComponent extends Component { + + private final Mat4[] transforms; + private final Vec4[] normals; + private final long startTime; + + private final double r3 = Math.sqrt(3+.01); + + private final int size; + + public CubeComponent(String name, int size) { + super(name); + this.size = size; + transforms = new Mat4[6]; + normals = new Vec4[6]; + setPreferredSize((int) Math.ceil(r3*size),(int) Math.ceil(r3*size)); + ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + executor.scheduleAtFixedRate(this::requestReassembly, 1, 60, TimeUnit.MILLISECONDS); + startTime = System.currentTimeMillis(); + } + + // Notes to me + // z axis is through the screen + // y is horizontal spin + // x is vertical spin + + + private void computeTransforms() + { + //Creates all of the sides + transforms[0] = new Mat4(1); + transforms[1] = new Mat4(1); + transforms[2] = new Mat4(1); + transforms[3] = new Mat4(1); + transforms[4] = new Mat4(1); + transforms[5] = new Mat4(1); + + //Gets time since creation(for rotation amount) + long time = System.currentTimeMillis()-startTime; + + //Initializes the way each face is facing + normals[0] = new Vec4(0,0,-1,0); + normals[1] = new Vec4(0,1,0,0); + normals[2] = new Vec4(1,0,0,0); + normals[3] = new Vec4(0,0,1,0); + normals[4] = new Vec4(0,-1,0,0); + normals[5] = new Vec4(-1,0,0,0); + + for (int i=0;i<6;i++) + { + //Rotates given side with the time one first, then ot get it on its off axis, then gets the image of each axis under the given rotation + //The rotate functions do change the transforms, but the multiplication does not + normals[i] = transforms[i].rotate((float) (time%(6000*6.28) )/ 6000, new Vec3(0,1,0)).rotate((float) 24, new Vec3(1,.5,0)).mul_(normals[i]); + } + double pi2 = Math.PI / 2; + + //Move and rotate the sides from the middle of the cube to the appropriate edges + transforms[0].translate(new Vec3(-size/2f,-size/2f,size/2f)); + transforms[1].translate(new Vec3(-size/2f,-size/2f,-size/2f)).rotate((float) pi2, new Vec3(1,0,0)); + transforms[2].translate(new Vec3(-size/2f,-size/2f,size/2f)).rotate((float) pi2, new Vec3(0,1,0)); + transforms[3].translate(new Vec3(-size/2f,-size/2f,-size/2f)); + transforms[4].translate(new Vec3(-size/2f,size/2f,-size/2f)).rotate((float) pi2, new Vec3(1,0,0)); + transforms[5].translate(new Vec3(size/2f,-size/2f,size/2f)).rotate((float) pi2, new Vec3(0,1,0)); + + for (int i=0;i<6;i++) // I have no clue why this is necessary, without it the sides of the cube mess up; may need to be changed if the title screen changes position. + { + transforms[i] = transforms[i].translate(new Vec3(0,0,17.5-3*(i<2 ? 1 : 0))); + } + + } + + @Override + protected void assembleSelf(RenderTarget target) + { + computeTransforms(); + + setPosition(750,780); + + target.pushTransform(new Mat4(1).translate(new Vec3(getX()+size*r3/2,getY()-size*r3/2,0))); //-size*r3/2 + + for (int b=0; b<6;b++) + { + target.pushTransform(transforms[b]); + + float dot = normals[b].dot(new Vec4(-1,0,0,0)); //Gets the "amount" the given side is pointing in the -x direction + + Vec4 color = new Vec4(.4+.3*dot, .4+.3*dot, .6+.4*dot,1.0); //More aligned means brighter color + + target.fill(0,0, size, size, color); + + target.popTransform(); + } + + target.popTransform(); + } +} diff --git a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java index 0011985..e777d4d 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java @@ -31,6 +31,8 @@ import ru.windcorp.progressia.client.localization.MutableStringLocalized; public class LayerAbout extends GUILayer { + public static String version = "pre-alpha 3"; + public LayerAbout() { super("LayerAbout", new LayoutAlign(1, 1, 5)); diff --git a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java index 365e437..25fdb5e 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerTitle.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerTitle.java @@ -1,16 +1,20 @@ package ru.windcorp.progressia.test; +import ru.windcorp.progressia.Progressia; import ru.windcorp.progressia.client.ClientState; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.font.Font; +import ru.windcorp.progressia.client.graphics.gui.Background; import ru.windcorp.progressia.client.graphics.gui.BasicButton; import ru.windcorp.progressia.client.graphics.gui.Button; -import ru.windcorp.progressia.client.graphics.gui.GUILayer; import ru.windcorp.progressia.client.graphics.gui.Group; import ru.windcorp.progressia.client.graphics.gui.Label; +import ru.windcorp.progressia.client.graphics.gui.TextureComponent; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutEdges; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; +import ru.windcorp.progressia.client.graphics.texture.SimpleTextures; import ru.windcorp.progressia.client.localization.MutableString; import ru.windcorp.progressia.client.localization.MutableStringLocalized; import ru.windcorp.progressia.common.util.crash.CrashReports; @@ -24,34 +28,55 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; -public class LayerTitle extends GUILayer { +public class LayerTitle extends Background { private final BasicButton resetButton; public LayerTitle(String name) { - super(name, new LayoutAlign(0.5f, 0.7f, 15)); + super(name, new LayoutAlign(0, 1f, 15), SimpleTextures.get("title/background")); Group content = new Group("Layer" + name + ".Group", new LayoutVertical(15)); + Group info = new Group("Layer"+name+".InfoGroup", new LayoutEdges(30)); + Group buttonContent = new Group("Layer" + name + ".ButtonGroup", new LayoutColumn(15, 320)); - MutableString title = new MutableStringLocalized("Layer" + name + ".Title"); - Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f); - content.addChild(new Label(name + ".Title", titleFont, title)); + Font titleFont = new Font().deriveBold().withColor(Colors.BLUE).withAlign(0.5f); + content.addChild(new TextureComponent(name + ".Title", SimpleTextures.get("title/progressia"))); + + info.addChild(new Label( + "About", + titleFont, + new MutableStringLocalized("LayerAbout.Title") + ) + ); + + info.addChild( + new Label( + "Version", + titleFont, + Progressia.getFullerVersion() + ) + ); + content.addChild(info); Font buttonFont = titleFont.deriveNotBold(); MutableString playText = new MutableStringLocalized("Layer" + name + ".Play"); - content.addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame)); + buttonContent.addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame)); MutableString resetText = new MutableStringLocalized("Layer" + name + ".Reset"); this.resetButton = new Button(name + ".Reset", new Label(name + ".Reset", buttonFont, resetText)).addAction(this::resetWorld); - content.addChild(resetButton); + buttonContent.addChild(resetButton); updateResetButton(); MutableString quitText = new MutableStringLocalized("Layer" + name + ".Quit"); - content.addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> { - System.exit(0); - })); + buttonContent.addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> System.exit(0))); + content.addChild(buttonContent); getRoot().addChild(content); + buttonContent.setPreferredSize(500, 1000); + + CubeComponent cube = new CubeComponent(name+".Cube",300); + + getRoot().addChild(cube); } private void updateResetButton() { diff --git a/src/main/java/ru/windcorp/progressia/test/LayoutColumn.java b/src/main/java/ru/windcorp/progressia/test/LayoutColumn.java new file mode 100644 index 0000000..604cf2e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/LayoutColumn.java @@ -0,0 +1,33 @@ +package ru.windcorp.progressia.test; + +import ru.windcorp.progressia.client.graphics.gui.Component; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; + +public class LayoutColumn extends LayoutVertical { + + protected int maxWidth; + private final int margin; + + public LayoutColumn(int gap, int maxWidth) + { + super(gap); + this.maxWidth = maxWidth; + margin = gap; + } + + @Override + public void layout(Component c) { + int x = c.getX() + margin, + y = c.getY() + c.getHeight(); + + synchronized (c.getChildren()) { + for (Component child : c.getChildren()) { + + int height = child.getPreferredSize().y; + y -= margin + height; + child.setBounds(x, y, maxWidth, height); + + } + } + } +} diff --git a/src/main/resources/assets/textures/title/background.png b/src/main/resources/assets/textures/title/background.png new file mode 100644 index 0000000..21b7d76 Binary files /dev/null and b/src/main/resources/assets/textures/title/background.png differ diff --git a/src/main/resources/assets/textures/title/progressia.png b/src/main/resources/assets/textures/title/progressia.png new file mode 100644 index 0000000..1506b13 Binary files /dev/null and b/src/main/resources/assets/textures/title/progressia.png differ