From 68576490a57a5ab9ddd3f30f517eff50987cb5c8 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 30 Aug 2021 21:53:23 -0500 Subject: [PATCH 01/19] Start work on Pong game --- src/main/java/gregtech/api/gui/Widget.java | 6 + .../api/terminal/TerminalRegistry.java | 2 + .../api/util/TwoDimensionalRayTracer.java | 60 ++++++++ .../items/behaviors/ClipboardBehavior.java | 6 +- .../terminal/app/game/pong/PongApp.java | 128 ++++++++++++++++++ .../app/game/pong/widget/BallWidget.java | 44 ++++++ .../app/game/pong/widget/PaddleWidget.java | 43 ++++++ .../textures/gui/widget/pong_ball.png | Bin 0 -> 5334 bytes 8 files changed, 286 insertions(+), 3 deletions(-) create mode 100644 src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java create mode 100644 src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/pong_ball.png diff --git a/src/main/java/gregtech/api/gui/Widget.java b/src/main/java/gregtech/api/gui/Widget.java index 81d52b17ba0..bf9b6add33a 100644 --- a/src/main/java/gregtech/api/gui/Widget.java +++ b/src/main/java/gregtech/api/gui/Widget.java @@ -133,6 +133,12 @@ public Rectangle toRectangleBox() { return new Rectangle(pos.x, pos.y, size.width, size.height); } + public Rectangle toSelfRectangleBox() { + Position pos = getSelfPosition(); + Size size = getSize(); + return new Rectangle(pos.x, pos.y, size.width, size.height); + } + protected void recomputePosition() { this.position = this.parentPosition.add(selfPosition); onPositionUpdate(); diff --git a/src/main/java/gregtech/api/terminal/TerminalRegistry.java b/src/main/java/gregtech/api/terminal/TerminalRegistry.java index 21d83e7651e..cd8da533800 100644 --- a/src/main/java/gregtech/api/terminal/TerminalRegistry.java +++ b/src/main/java/gregtech/api/terminal/TerminalRegistry.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.terminal.app.*; import gregtech.common.terminal.app.ThemeSettingApp; +import gregtech.common.terminal.app.game.pong.PongApp; import gregtech.common.terminal.app.guide.ItemGuideApp; import gregtech.common.terminal.app.guide.MultiBlockGuideApp; import gregtech.common.terminal.app.guide.SimpleMachineGuideApp; @@ -25,6 +26,7 @@ public static void init() { registerApp(new GuideEditorApp(), true); registerApp(new ThemeSettingApp(), true); registerApp(new OreProspectorApp(), true); + registerApp(new PongApp(), true); if (GTValues.isModLoaded(GTValues.MODID_JEI)) { registerApp(new RecipeChartApp(), true); } diff --git a/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java b/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java new file mode 100644 index 00000000000..17dfec4068d --- /dev/null +++ b/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java @@ -0,0 +1,60 @@ +package gregtech.api.util; + +import org.lwjgl.util.vector.Vector2f; + +import static net.minecraft.util.math.MathHelper.clamp; + +// Huge thanks to https://noonat.github.io/intersect! +public class TwoDimensionalRayTracer { + public static class TwoDimensionalRayTraceResult { + public Vector2f pos = new Vector2f(); + public Vector2f delta = new Vector2f(); + public Vector2f normal = new Vector2f(); + public float time = -1; + } + + /** + * Detects the intersection between a segment and a box, if there is any. + * @param pos The original position of the point. + * @param delta The proposed new position of the point. + * @param boxSize The half-width and half-height of the box + * @return + */ + public static TwoDimensionalRayTraceResult intersectBoxSegment(Vector2f pos, Vector2f delta, Vector2f boxCenter, Vector2f boxSize) { + float scaleX = (float) (1.0 / delta.x); + float scaleY = (float) (1.0 / delta.y); + float signX = Math.signum(scaleX); + float signY = Math.signum(scaleY); + float nearTimeX = (boxCenter.x - signX * (boxSize.x) - pos.x) * scaleX; + float nearTimeY = (boxCenter.y - signY * (boxSize.y) - pos.y) * scaleY; + float farTimeX = (boxCenter.x + signX * (boxSize.x) - pos.x) * scaleX; + float farTimeY = (boxCenter.y + signY * (boxSize.y) - pos.y) * scaleY; + + if (nearTimeX > farTimeY || nearTimeY > farTimeX) { + return null; + } + + double nearTime = Math.max(nearTimeX, nearTimeY); + double farTime = Math.min(farTimeX, farTimeY); + + if (nearTime >= 1 || farTime <= 0) { + return null; + } + + TwoDimensionalRayTraceResult result = new TwoDimensionalRayTraceResult(); + + result.time = (float) clamp(nearTime, 0, 1); + if (nearTimeX > nearTimeY) { + result.normal.x = -signX; + result.normal.y = 0; + } else { + result.normal.x = 0; + result.normal.y = -signY; + } + result.delta.x = (float) ((1.0 - result.time) * -delta.x); + result.delta.y = (float) ((1.0 - result.time) * -delta.y); + result.pos.x = pos.x + delta.x * result.time; + result.pos.y = pos.y + delta.y * result.time; + return result; + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java index e30b3e990f1..ee176a9b496 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java @@ -63,7 +63,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); builder.image(18, 8, 130, 14, GuiTextures.CLIPBOARD_TEXT_BOX); - builder.widget(new SimpleTextWidget(20, 10, "", 0xFFFFFF, () -> getTitle(holder)).setCenter(false)); + builder.widget(new SimpleTextWidget(20, 10, "", 0xFFFFFF, () -> getTitle(holder), true).setCenter(false)); for (int i = 0; i < 8; i++) { @@ -71,7 +71,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl builder.widget(new ImageCycleButtonWidget(6, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_BUTTON, 4, () -> getButtonState(holder, finalI), (x) -> setButton(holder, finalI, x))); builder.image(22, 38 + 20 * i, 140, 12, GuiTextures.CLIPBOARD_TEXT_BOX); - builder.widget(new SimpleTextWidget(24, 40 + 20 * i, "", 0xFFFFFF, () -> getString(holder, finalI)).setCenter(false)); + builder.widget(new SimpleTextWidget(24, 40 + 20 * i, "", 0xFFFFFF, () -> getString(holder, finalI), true).setCenter(false)); } builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) @@ -79,7 +79,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) .setButtonTexture(GuiTextures.BUTTON_RIGHT).setShouldClientCallback(true)); builder.widget(new SimpleTextWidget(85, 208, "", 0xFFFFFF, - () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); + () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES, true)); return builder.build(holder, entityPlayer); } diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java new file mode 100644 index 00000000000..d1e4f3e45a8 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -0,0 +1,128 @@ +package gregtech.common.terminal.app.game.pong; + +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.gui.widgets.SimpleTextWidget; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.util.Position; +import gregtech.api.util.TwoDimensionalRayTracer; +import gregtech.common.terminal.app.game.pong.widget.BallWidget; +import gregtech.common.terminal.app.game.pong.widget.PaddleWidget; +import net.minecraft.nbt.NBTTagCompound; +import org.lwjgl.input.Keyboard; +import org.lwjgl.util.vector.Vector2f; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + + +public class PongApp extends AbstractApplication { + public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/pong/icon.png"); + + private BallWidget ball; + private int leftScore; + private int rightScore; + private List paddles = new ArrayList<>(); + private List solidObjects = new ArrayList<>(); + private int userInput = -1; + + public PongApp() { + super("pong", ICON); + } + + @Override + public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + PongApp app = new PongApp(); + if (isClient) { + app.setOs(os); + app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); + app.addWidget(new ImageWidget(333 / 2 - 4, 5, 6, 232 - 10, new ColorRectTexture(0xAAAAAAAA))); + app.setBall(new BallWidget(333 / 2 - 1, 232 / 2 - 1)); + app.addWidget(new SimpleTextWidget(50, 20, "", 0xAAAAAA, () -> String.valueOf(app.getScore(true)), true)); + app.addWidget(new SimpleTextWidget(283, 20, "", 0xAAAAAA, () -> String.valueOf(app.getScore(false)), true)); + app.initPaddles(); + } + return app; + } + + @Override + public boolean isClientSideApp() { + return true; + } + + public void setBall(BallWidget ball) { + this.ball = ball; + this.addWidget(ball); + } + + public void initPaddles() { + paddles.add(new PaddleWidget(20, 232 / 2 - 1, 4, 20, (PaddleWidget paddle) -> this.getUserInput())); + paddles.add(new PaddleWidget(313, 232 / 2 - 1, 4, 20, this::simplePaddleAI)); + paddles.forEach(this::addWidget); + this.solidObjects.add(new Rectangle(0, 0, 333, 20)); + this.solidObjects.add(new Rectangle(0, 212, 333, 20)); + } + + public void score(boolean side) { + if (side) { + leftScore++; + ball.theta = (float) (5 * Math.PI / 8); + } else { + rightScore++; + ball.theta = (float) (Math.PI / 8); + } + ball.setSelfPosition(new Position(333 / 2 - 1, 232 / 2 - 1)); + } + + @Override + public void updateScreen() { + super.updateScreen(); + if (Keyboard.isKeyDown(Keyboard.KEY_UP) ^ Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { + if(Keyboard.isKeyDown(Keyboard.KEY_UP)) + userInput = 1; + else + userInput = 0; + } else { + userInput = -1; + } + if (ball.getSelfPosition().getX() < 10) { + this.score(false); // Right side gains a point + } else if (ball.getSelfPosition().getX() > 323) { + this.score(true); // Left side gains a point + } else { + paddles.forEach((paddle) -> solidObjects.add(new Rectangle(paddle.toSelfRectangleBox()))); + for (Rectangle object : solidObjects) { + TwoDimensionalRayTracer.TwoDimensionalRayTraceResult result = TwoDimensionalRayTracer.intersectBoxSegment( + new Vector2f(ball.getSelfPosition().x + 4, ball.getSelfPosition().y + 4), + new Vector2f((float) (Math.cos(ball.theta) * 3), (float) (Math.sin(ball.theta) * 3)), + new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), + new Vector2f(4 + object.width / 2, 4 + object.height / 2)); + if (result != null) { + ball.theta = (float) (Math.acos(result.normal.x) * 2 - ball.theta + Math.PI + (Math.random() - 0.5) * 0.5); // Reflects with a slight angle modification. + } + } + solidObjects.remove(2); solidObjects.remove(2); + } + ball.addSelfPosition((Math.cos(ball.theta) * 6), (Math.sin(ball.theta) * 6)); + } + + public int simplePaddleAI(PaddleWidget paddle) { + if(ball.getSelfPosition().getY() < paddle.getSelfPosition().getY() - 5) + return 1; + else if (ball.getSelfPosition().getY() > paddle.getSelfPosition().getY() + 5) + return 0; + return -1; + } + + public int getScore(boolean side) { + return side ? leftScore : rightScore; + } + + public int getUserInput() { + return userInput; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java new file mode 100644 index 00000000000..0e71f5b821c --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java @@ -0,0 +1,44 @@ +package gregtech.common.terminal.app.game.pong.widget; + +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.util.Position; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.tuple.Pair; + +public class BallWidget extends ImageWidget { + public double theta; + private double xAccurate; + private double yAccurate; + + public BallWidget(int xPosition, int yPosition) { + super(xPosition, yPosition, 8, 8, new TextureArea(new ResourceLocation("gregtech:textures/gui/widget/pong_ball.png"), 0, 0, 8, 8)); + theta = (Math.PI / 2); + xAccurate = xPosition; + yAccurate = yPosition; + } + + @Override + public void setSelfPosition(Position selfPosition) { + super.setSelfPosition(selfPosition); + xAccurate = selfPosition.x; + yAccurate = selfPosition.y; + } + + @Override + public Position addSelfPosition(int addX, int addY) { + xAccurate += addX; + yAccurate += addY; + return super.addSelfPosition(addX, addY); + } + + public void addSelfPosition(double addX, double addY) { + xAccurate += addX; + yAccurate += addY; + this.setSelfPosition(new Position((int) xAccurate, (int) yAccurate)); + } + + public Pair getDoubleSelfPosition() { + return Pair.of(xAccurate, yAccurate); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java new file mode 100644 index 00000000000..fd8156820a4 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java @@ -0,0 +1,43 @@ +package gregtech.common.terminal.app.game.pong.widget; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.util.Position; + +import java.util.function.Function; + +public class PaddleWidget extends Widget { + Function controlSupplier; + private float speed; + + public PaddleWidget(int x, int y, int width, int height, Function controlSupplier) { + super(x, y, width, height); + this.controlSupplier = controlSupplier; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + drawSolidRect(this.toRectangleBox().x - this.toRectangleBox().width / 2, this.toRectangleBox().y - this.toRectangleBox().height / 2, this.toRectangleBox().width, this.toRectangleBox().height, 0xFFFFFFFF); + } + + @Override + public void updateScreen() { + super.updateScreen(); + if (this.getSelfPosition().getY() < 30) { + this.setSelfPosition(new Position(this.getSelfPosition().getX(), 30)); + } + if (this.getSelfPosition().getY() > 202) { + this.setSelfPosition(new Position(this.getSelfPosition().getX(), 202)); + } + this.addSelfPosition(0, (int) speed); + switch (controlSupplier.apply(this)) { + case 0: + speed += 2; + break; + case 1: + speed -= 2; + break; + } + speed /= 1.2; + } +} diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/pong_ball.png b/src/main/resources/assets/gregtech/textures/gui/widget/pong_ball.png new file mode 100644 index 0000000000000000000000000000000000000000..48f674370f6cfafabda92e1036eb4e1a2f44a7f5 GIT binary patch literal 5334 zcmeHLc~}$I79Rx^P#1jO*_v(N8){ZIHN%-s7szjN;Io^x)7 zIT2waIyryl3_(yQRY-6o_-oHyj_tr_@xy|t5Y+bZJkcfGtJtVKRR8cyv?g@@&;s_SCj(v1K|%fFuRXi@eAzcSRjcdb zy(Ujyd$?NmPrtt{u7Y0Xtf*QTn&qB9)yr!w?+QLG%;D+zm}3=pr*^2GT6*I}zm7w< zXCz1jnl;tPzhB9Et~lqKIxEd>QRdRwF71hZo*~LZqqY(gcu#T~{(hsXn|(v{va9){ zuh@P6Ro2jK|A6eT58K&il^q-XGBWIi{24a;*@-QszdV|GsR4c1xxux*(r^CeKD*a@ z_FMJ*(i#1r_215MOkcEZ@JjdEx%)OmMkwHPkA;oruV$Ps>TLH*VQ{`zr;DSji^?j> zhj@&=-p)&NT{~`vs$=0|-H&Ahlyb){k~-Ir=Z|LR)@(WE&A8v2l@}T@T23ISuKL!o4S6HB z4C^q!>tcOL_ESxpK>KRvxR7D6uIuX1${!XuCbJKUBN_(Jk-~8Fy$6eO>Pp>*gjdJn zrPsGS>U%KXq4Qjv7^Yb@Nb1x{AarydAx^HE1hFdT!evKl}RJv##9|YAiW?{jO`reJ&r3@i@J9^%}l3 z@$<3NHq(;t(pTIt)TG}^S=+m~bnW=YJ=OQpFWecnu2WCy=HUYwS?F!$g8kE<20fR1 z?;2IFOb9ET_gU`Jny6EI!dTP}3A4ZI;{^YhhRzG~O#b2KfUU9aYXf^uxIL?i>S|Y3 z+U-u^yqZ3Y%ca0C-;^()8}m^%|wqyiDuh=0&%6iyPm2 zoI}6^yYl15Rh7ywUrmgR?^0iu>|a}xerd1WEZz6Tx|8;W3Ax!}~0*aN&;xZpx5d*Wqz-3d@&yFKjKkU_qoct*Yo#zx^%2*`#RA;-<`5-C^Y7F!t-{%zV-)4 zF5Y|Z;k{vI`b`1V*l4$O8?zmL{o)@G0qD#vNP03&EEDX{2`pj|cvfCHxaWq2JlG0h6a9Fx>IgW9W=L2fkO)M4rG-jGc|)CH1w-iMk-@{8 zDZrB-FP>$Ma-q;{HVe#R0nNk-5t&RT6rn;C+LJMXTA_9?6uWw~xVwI`y{Jq!06a`KNVI*myQy837rjiD>pRH44Qi{pe zXNrmBhOBWX5jr6V%IewHW`s%|(PG2N7)R-iRtpYoizM(CoH2z-vSJ8aNG6eb5Qqsd zBdzc(rF*wQt=7ZM{2>tFu7$r9`mJ8pSgg9rgK0d4bE*pV<8krI2^yyex%E~=dSirG zD&_lnYkl|!$x#7v0R?!(Iv)|Dm7si`R_n`` zcuNt!R;-ioF{u>8#Zm;vylpAM846SamSh_hM@0ZC0+Z+@7^(w-_!4{xj!5}hEvDo9 zibaSwBK9RD7-Efv+Xs0-gvyVH3PkTlB9bsxM>Bd*UX+2L&8Bx#QIww4uox#B;v*J` z#HiQ@6(bS}YQq>qGA5Ab94jIcps3ZHz~#dMCkE1u(qnO?&}fLWPH-C|2g?D{VqA3q zX6raujXa1UF_vbcXgbM{$3+Wsl-8nx70u-$52bOdp%qLLT*WolTp$)Fv_2|?9|He@ zNfS?-4gVX@J7^0_0K=MTCNZ1|*CvoS`(d8DV#Kz=nsW%3u%(Y<{$zw zH;sV<4xE?5mIJdnOSnS%3xArk?=SQKs6RRRD1AT4^+~ReQsAS&pR((dTpy*tM}a?O z*Z)l}=XbB%qyc>IGlLiE``h!5fS2)h+L0rIp)*h;)Ma9)F9N`blQCqB34#RuxT}q2 zwSOuYY|pCH%J$bBJ=zM|R_|zE2!;l$f&-!)&y7E@xf29CLS;+JuN9sDrn_ftpqEf~ pChFv|)t^s#%sy}`oK}$1CT3#~mqk5<-2W>fl`<@NW8kD2zXSVH!d(CW literal 0 HcmV?d00001 From 42ccfe4b8f10ed45c26b4a618ff38bd05b67e6ac Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Fri, 3 Sep 2021 22:38:13 -0500 Subject: [PATCH 02/19] Improve opponent's AI a little --- src/main/java/gregtech/api/gui/Widget.java | 6 --- .../terminal/app/game/pong/PongApp.java | 40 +++++++++++++++---- .../app/game/pong/widget/PaddleWidget.java | 10 +++++ 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/main/java/gregtech/api/gui/Widget.java b/src/main/java/gregtech/api/gui/Widget.java index bf9b6add33a..81d52b17ba0 100644 --- a/src/main/java/gregtech/api/gui/Widget.java +++ b/src/main/java/gregtech/api/gui/Widget.java @@ -133,12 +133,6 @@ public Rectangle toRectangleBox() { return new Rectangle(pos.x, pos.y, size.width, size.height); } - public Rectangle toSelfRectangleBox() { - Position pos = getSelfPosition(); - Size size = getSize(); - return new Rectangle(pos.x, pos.y, size.width, size.height); - } - protected void recomputePosition() { this.position = this.parentPosition.add(selfPosition); onPositionUpdate(); diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index d1e4f3e45a8..aa0c188f908 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -29,6 +29,7 @@ public class PongApp extends AbstractApplication { private List paddles = new ArrayList<>(); private List solidObjects = new ArrayList<>(); private int userInput = -1; + private int timer = 0; public PongApp() { super("pong", ICON); @@ -63,8 +64,8 @@ public void initPaddles() { paddles.add(new PaddleWidget(20, 232 / 2 - 1, 4, 20, (PaddleWidget paddle) -> this.getUserInput())); paddles.add(new PaddleWidget(313, 232 / 2 - 1, 4, 20, this::simplePaddleAI)); paddles.forEach(this::addWidget); - this.solidObjects.add(new Rectangle(0, 0, 333, 20)); - this.solidObjects.add(new Rectangle(0, 212, 333, 20)); + this.solidObjects.add(new Rectangle(0, 0, 333, 10)); + this.solidObjects.add(new Rectangle(0, 222, 333, 10)); } public void score(boolean side) { @@ -81,6 +82,7 @@ public void score(boolean side) { @Override public void updateScreen() { super.updateScreen(); + timer++; if (Keyboard.isKeyDown(Keyboard.KEY_UP) ^ Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { if(Keyboard.isKeyDown(Keyboard.KEY_UP)) userInput = 1; @@ -97,12 +99,32 @@ public void updateScreen() { paddles.forEach((paddle) -> solidObjects.add(new Rectangle(paddle.toSelfRectangleBox()))); for (Rectangle object : solidObjects) { TwoDimensionalRayTracer.TwoDimensionalRayTraceResult result = TwoDimensionalRayTracer.intersectBoxSegment( - new Vector2f(ball.getSelfPosition().x + 4, ball.getSelfPosition().y + 4), - new Vector2f((float) (Math.cos(ball.theta) * 3), (float) (Math.sin(ball.theta) * 3)), + new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), + new Vector2f((float) (Math.cos(ball.theta) * 12), (float) (Math.sin(ball.theta) * 12)), new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), new Vector2f(4 + object.width / 2, 4 + object.height / 2)); - if (result != null) { - ball.theta = (float) (Math.acos(result.normal.x) * 2 - ball.theta + Math.PI + (Math.random() - 0.5) * 0.5); // Reflects with a slight angle modification. + int i = 0; + while (result != null) { + float angleMod = 0; + if(result.pos.y < object.getCenterY() - 2) { + angleMod -= Math.signum(result.normal.x) * 0.6; + } else if (result.pos.x > object.getCenterY() + 2) { + angleMod += Math.signum(result.normal.x) * 0.6; + } + ball.theta = (float) (Math.acos(result.normal.x) * 2 - ball.theta + Math.PI + angleMod) % (2 * Math.PI); // Reflects with a slight angle modification. + if(Math.abs((ball.theta % Math.PI)- Math.PI / 2) < 0.5) { + ball.theta += (Math.random() - 0.5) * 0.9; + } else { + ball.theta += (Math.random() - 0.5) * 0.3; + } + result = TwoDimensionalRayTracer.intersectBoxSegment( + new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), + new Vector2f((float) (Math.cos(ball.theta) * 12), (float) (Math.sin(ball.theta) * 12)), + new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), + new Vector2f(4 + object.width / 2, 4 + object.height / 2)); + i++; + if(i > 20) + break; // There's probably no way out of this, just go forwards. } } solidObjects.remove(2); solidObjects.remove(2); @@ -111,9 +133,11 @@ public void updateScreen() { } public int simplePaddleAI(PaddleWidget paddle) { - if(ball.getSelfPosition().getY() < paddle.getSelfPosition().getY() - 5) + if(this.timer % 3 == 0) + return -1; + if((ball.getSelfPosition().getY() + 2 * paddle.getSelfPosition().getY()) / 3 < paddle.getSelfPosition().getY()) return 1; - else if (ball.getSelfPosition().getY() > paddle.getSelfPosition().getY() + 5) + else if ((ball.getSelfPosition().getY() + 2 * paddle.getSelfPosition().getY()) / 3 > paddle.getSelfPosition().getY()) return 0; return -1; } diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java index fd8156820a4..3d8d836baf2 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java @@ -3,7 +3,11 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; import gregtech.api.util.Position; +import gregtech.api.util.Size; +import javafx.geometry.Pos; +import org.lwjgl.util.vector.Vector2f; +import java.awt.*; import java.util.function.Function; public class PaddleWidget extends Widget { @@ -40,4 +44,10 @@ public void updateScreen() { } speed /= 1.2; } + + public Rectangle toSelfRectangleBox() { + return new Rectangle(this.getSelfPosition().x - this.toRectangleBox().width / 2, this.getSelfPosition().y - this.toRectangleBox().height / 2, + this.toRectangleBox().width, this.toRectangleBox().height); + } + } From d360c704e13320b5bb3efa3a96f4065c4ae9f3ab Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 4 Sep 2021 10:17:11 -0500 Subject: [PATCH 03/19] Polish Pong App --- .../terminal/app/game/pong/PongApp.java | 2 +- .../app/game/pong/widget/BallWidget.java | 6 +++--- .../resources/assets/gregtech/lang/en_us.lang | 2 ++ .../textures/gui/terminal/pong/icon.png | Bin 0 -> 696 bytes .../textures/gui/widget/pong_ball.png | Bin 5334 -> 5700 bytes 5 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/pong/icon.png diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index aa0c188f908..71f5baec6f2 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -118,7 +118,7 @@ public void updateScreen() { ball.theta += (Math.random() - 0.5) * 0.3; } result = TwoDimensionalRayTracer.intersectBoxSegment( - new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), + ball.getPreciseSelfPosition(), new Vector2f((float) (Math.cos(ball.theta) * 12), (float) (Math.sin(ball.theta) * 12)), new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), new Vector2f(4 + object.width / 2, 4 + object.height / 2)); diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java index 0e71f5b821c..aa6157c8c6e 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java @@ -4,7 +4,7 @@ import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.util.Position; import net.minecraft.util.ResourceLocation; -import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.util.vector.Vector2f; public class BallWidget extends ImageWidget { public double theta; @@ -38,7 +38,7 @@ public void addSelfPosition(double addX, double addY) { this.setSelfPosition(new Position((int) xAccurate, (int) yAccurate)); } - public Pair getDoubleSelfPosition() { - return Pair.of(xAccurate, yAccurate); + public Vector2f getPreciseSelfPosition() { + return new Vector2f((float) xAccurate , (float) yAccurate); } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 1644a722e16..755540f1972 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -3852,6 +3852,8 @@ gregtech.terminal.app_name.theme_settings=Theme Settings gregtech.terminal.app_name.guide_editor=Guide Editor gregtech.terminal.app_name.recipe_chart=Recipe Chart gregtech.terminal.app_name.ore_prospector=Ore Prospector +gregtech.terminal.app_name.pong=Pong + texture.modify_gui_texture.missing=Missing Texture texture.url_texture.fail=Load Failed diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/pong/icon.png b/src/main/resources/assets/gregtech/textures/gui/terminal/pong/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5d2ec192db2d0f1e436353e9163b4b886b43d2 GIT binary patch literal 696 zcmV;p0!RIcP)EX>4Tx04R}tkv&MmKpe$i(@IrZ9NIy|AwzYtAS&W0RV;#q(pG5I!Q|2}XktiG zTpR`0f`cE6RRVO3`G1Pb8jYx?vHo6Hjki zI_G`jD62>c@j3CBK^G)`_CX>@2HM@dakSAh-}0001wNkloz4^BGA_(oJsG*6S zIS0&aSnxOi007{xxUU{Q8^en?)CW*YEwyyfkU|P+;RPpy@Y2FD#~gECaQ5=6@zTQD z@zTQgd2<2G3Y)9IYGL&ikQUZn0cX7etNsHIfwz|%ou9>=u++Rb2qV0iu(p5@MtHM; e5JngPzz!Dy^8-I+Aam>h0000*okRP^ef6 zNzHS~IijSJ3Res~9;L39Vp{D{t~q*?hkJq{67+KF=TrZZ({14BDn|OokhgPUdz>ig zwC_)bPDe6##2EC`P&o|=9}{#MsK>Ele=crskFf1Wf381{>gUl$<1%Hs9dpmWCqwkQ z!jCZTLK4xk@Ua1z9|}@2D636Sgwh&2T9$I|1OfRdPVvpI!aFM0h(3`&L6LmO0|bx3 z%y<8xob==1hZW*Co~7NMALJ&ti-#bu7?18@jQu!WO&KB0=b^5ntPvCu_9Sare?~QY z6k}Vppn5>|HX!e@#SOJlAx6XpCF)dZ(7yUc4O>jSv!Q2h05xSU#)X^208VLE8f>7~ z!HcB7!uwA#5#$2-w;x9+|4y3>wS+S9Ik-fj22>~$d3hKw|Hla5_z5 zAeeSy9dxt%L+*iFNa>%r@kK67bl*WPOmv@+d(Z6yYJGm&v?yT_n%8g!H43gDlqx%Z z@SXJaKK$*1m!X%Tm!X%Tm!X%Tm!bd0kPQ6sfPV_ZZ>iCv)X=I>s{jB1W`BBASaech zcOYkgaUW1V!iuiIcS4gF_A(b_Ug168 z0004nX+uL$Nkc;*aB^>EX)SDJ004NLeUUv#!$2IxU(-reS{&Lz#34gh{*&$LRx*qpp^2fP+I|v`pD+9`Ek$?(N?*?f!lMZI^PT4tqI4 z000nsv$O>M0wggqVl!hlVlpi?G+{X{G&wLZEn+h>WGyl_F*r9hW@R`zHaU~l2ayan zHaIabIW;mkGdDN0a|nw9lOGCPBr;+$WiU23Wi2vgIAkp}F*ai@VKXr~Eo3%gGGb*g zHZe0XWs{!@N)0(JFf>##Fgh?eIx;!4_6lAJ1ORZV%ad3XF>46~4+tHotaMud002r! zL_t&-(}j+)3cw%?1a_7 spF07*qoM6N<$g8hS{@&Et; delta 1287 zcmV+i1^D{JEY>L{iBL{Q4GJ0x0000DNk~Le00004000042nGNE0IBhwegFUh^N}SV ze^HJbAqNQ7_WU^+ zqSqC6gn1W|h?<2D2V}k}NJYm{vt(W(^poTz=hG7eX? zkHO4W`%+H&I{0CQ_|CGl%kqQVCCN}N3uW*CMw$FtdaFo0YU`Z3TH?_AZ8M! zOwpK)2yt}qsZiuBi8ml1RqpVTli;)%J5SqKW3=Y7@*&2Z1rUm3WI$7-g4Mi}4FVT` zEX>4Tx0C=2zkv&MmKpe$iQ^g_`2Rn#$$WWbH5EXHhDi*;)X)CnqU~=gf zG-;F011*1*sbU zyLAHipMfi_a34~V_`LAlSc@V3@|e?Gd40aF*GzX zF|*_divqJw3|0vQ@3)!Blc*IjO$ZwTE&|)Q2cQ4|04zyFK~xCWUBj^r03Zke!I#A4 xsMvoLDc(XVFFDjy&&;JBVDohF37~+Ubpckc77vmZF9rYr002ovPDHLkV1mQiRmA`R From c9ce6a97d527d918272c515810a091e36899da4d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 4 Sep 2021 13:22:26 -0500 Subject: [PATCH 04/19] Fix compilation errors :eyes: --- .../common/terminal/app/game/pong/widget/PaddleWidget.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java index 3d8d836baf2..f003bae96aa 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java @@ -3,10 +3,6 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; import gregtech.api.util.Position; -import gregtech.api.util.Size; -import javafx.geometry.Pos; -import org.lwjgl.util.vector.Vector2f; - import java.awt.*; import java.util.function.Function; From 9fdfc5833ae4842fd99dadf801b0c9a085203d79 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 4 Sep 2021 17:57:19 -0500 Subject: [PATCH 05/19] Use DStrand1's suggestions --- .../terminal/app/game/pong/PongApp.java | 42 +++++++++++-------- .../app/game/pong/widget/BallWidget.java | 2 +- .../app/game/pong/widget/PaddleWidget.java | 12 +++--- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index 71f5baec6f2..ec60c126849 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -71,11 +71,12 @@ public void initPaddles() { public void score(boolean side) { if (side) { leftScore++; - ball.theta = (float) (5 * Math.PI / 8); + ball.theta = (float) Math.PI; } else { rightScore++; - ball.theta = (float) (Math.PI / 8); + ball.theta = (float) 0; } + ball.theta += Math.random() * 0.2; ball.setSelfPosition(new Position(333 / 2 - 1, 232 / 2 - 1)); } @@ -97,14 +98,16 @@ public void updateScreen() { this.score(true); // Left side gains a point } else { paddles.forEach((paddle) -> solidObjects.add(new Rectangle(paddle.toSelfRectangleBox()))); + boolean interacted = false; for (Rectangle object : solidObjects) { TwoDimensionalRayTracer.TwoDimensionalRayTraceResult result = TwoDimensionalRayTracer.intersectBoxSegment( new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), - new Vector2f((float) (Math.cos(ball.theta) * 12), (float) (Math.sin(ball.theta) * 12)), + new Vector2f((float) (Math.cos(ball.theta) * 6), (float) (Math.sin(ball.theta) * 6)), new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), new Vector2f(4 + object.width / 2, 4 + object.height / 2)); - int i = 0; - while (result != null) { + if (result != null && !interacted) { + ball.addSelfPosition((Math.cos(ball.theta) * 6 * result.time), (Math.sin(ball.theta) * 6 * result.time)); + float angleMod = 0; if(result.pos.y < object.getCenterY() - 2) { angleMod -= Math.signum(result.normal.x) * 0.6; @@ -112,24 +115,27 @@ public void updateScreen() { angleMod += Math.signum(result.normal.x) * 0.6; } ball.theta = (float) (Math.acos(result.normal.x) * 2 - ball.theta + Math.PI + angleMod) % (2 * Math.PI); // Reflects with a slight angle modification. - if(Math.abs((ball.theta % Math.PI)- Math.PI / 2) < 0.5) { - ball.theta += (Math.random() - 0.5) * 0.9; - } else { - ball.theta += (Math.random() - 0.5) * 0.3; + + if(ball.theta > Math.PI / 2 - 0.5 && ball.theta < Math.PI / 2 + 0.5) { + if(ball.theta <= Math.PI / 2) + ball.theta = Math.PI / 2 - 0.51; + else + ball.theta = Math.PI / 2 + 0.51; + } + if(ball.theta > 3 * Math.PI / 2 - 0.5 && ball.theta < 3 * Math.PI / 2 + 0.5) { + if(ball.theta < 3 * Math.PI / 2) + ball.theta = 3 * Math.PI / 2 - 0.51; + else + ball.theta = 3 * Math.PI / 2 + 0.51; } - result = TwoDimensionalRayTracer.intersectBoxSegment( - ball.getPreciseSelfPosition(), - new Vector2f((float) (Math.cos(ball.theta) * 12), (float) (Math.sin(ball.theta) * 12)), - new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), - new Vector2f(4 + object.width / 2, 4 + object.height / 2)); - i++; - if(i > 20) - break; // There's probably no way out of this, just go forwards. + ball.addSelfPosition((Math.cos(ball.theta) * 8 * (1 - result.time)), (Math.sin(ball.theta) * 8 * (1 - result.time))); + interacted = true; } } + if(!interacted) + ball.addSelfPosition((Math.cos(ball.theta) * 6), (Math.sin(ball.theta) * 6)); solidObjects.remove(2); solidObjects.remove(2); } - ball.addSelfPosition((Math.cos(ball.theta) * 6), (Math.sin(ball.theta) * 6)); } public int simplePaddleAI(PaddleWidget paddle) { diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java index aa6157c8c6e..92784f7e810 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java @@ -13,7 +13,7 @@ public class BallWidget extends ImageWidget { public BallWidget(int xPosition, int yPosition) { super(xPosition, yPosition, 8, 8, new TextureArea(new ResourceLocation("gregtech:textures/gui/widget/pong_ball.png"), 0, 0, 8, 8)); - theta = (Math.PI / 2); + theta = (Math.random() > 0.5 ? Math.PI : Math.PI / 2) + Math.random() * 0.2; xAccurate = xPosition; yAccurate = yPosition; } diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java index f003bae96aa..a847117eec0 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/PaddleWidget.java @@ -8,7 +8,6 @@ public class PaddleWidget extends Widget { Function controlSupplier; - private float speed; public PaddleWidget(int x, int y, int width, int height, Function controlSupplier) { super(x, y, width, height); @@ -29,16 +28,19 @@ public void updateScreen() { if (this.getSelfPosition().getY() > 202) { this.setSelfPosition(new Position(this.getSelfPosition().getX(), 202)); } - this.addSelfPosition(0, (int) speed); + int speed; switch (controlSupplier.apply(this)) { case 0: - speed += 2; + speed = 6; break; case 1: - speed -= 2; + speed = -6; break; + default: + speed = 0; } - speed /= 1.2; + this.addSelfPosition(0, speed); + } public Rectangle toSelfRectangleBox() { From 65e33a60b3d5b688da0f224d1cf1b7bab0b4541d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 5 Sep 2021 20:57:12 -0500 Subject: [PATCH 06/19] Improve pong physics again --- .../api/util/TwoDimensionalRayTracer.java | 27 +++++- .../terminal/app/game/pong/PongApp.java | 83 ++++++++++--------- .../app/game/pong/widget/BallWidget.java | 2 +- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java b/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java index 17dfec4068d..e612779a001 100644 --- a/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java +++ b/src/main/java/gregtech/api/util/TwoDimensionalRayTracer.java @@ -2,6 +2,9 @@ import org.lwjgl.util.vector.Vector2f; +import java.awt.*; +import java.util.List; + import static net.minecraft.util.math.MathHelper.clamp; // Huge thanks to https://noonat.github.io/intersect! @@ -11,12 +14,14 @@ public static class TwoDimensionalRayTraceResult { public Vector2f delta = new Vector2f(); public Vector2f normal = new Vector2f(); public float time = -1; + public Rectangle collidedWith = new Rectangle(); } /** * Detects the intersection between a segment and a box, if there is any. - * @param pos The original position of the point. - * @param delta The proposed new position of the point. + * + * @param pos The original position of the point. + * @param delta The proposed new position of the point. * @param boxSize The half-width and half-height of the box * @return */ @@ -57,4 +62,22 @@ public static TwoDimensionalRayTraceResult intersectBoxSegment(Vector2f pos, Vec result.pos.y = pos.y + delta.y * result.time; return result; } + + public static TwoDimensionalRayTraceResult nearestBoxSegmentCollision(Vector2f pos, Vector2f delta, List boxes, Vector2f padding) { + TwoDimensionalRayTraceResult result = new TwoDimensionalRayTraceResult(); + result.time = 1; + result.pos.x = pos.x + delta.x; + result.pos.y = pos.y + delta.y; + for (Rectangle box : boxes) { + TwoDimensionalRayTraceResult sweep = intersectBoxSegment(pos, delta, + new Vector2f((float) box.getCenterX(), (float) box.getCenterY()), + new Vector2f((float) box.getWidth() / 2 + padding.x, (float) box.getHeight() / 2 + padding.y)); + if (sweep != null && sweep.time < result.time) { + result = sweep; + result.collidedWith = box; + } + } + return result; + } + } diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index ec60c126849..c78bdaabaa9 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -85,7 +85,7 @@ public void updateScreen() { super.updateScreen(); timer++; if (Keyboard.isKeyDown(Keyboard.KEY_UP) ^ Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { - if(Keyboard.isKeyDown(Keyboard.KEY_UP)) + if (Keyboard.isKeyDown(Keyboard.KEY_UP)) userInput = 1; else userInput = 0; @@ -98,50 +98,57 @@ public void updateScreen() { this.score(true); // Left side gains a point } else { paddles.forEach((paddle) -> solidObjects.add(new Rectangle(paddle.toSelfRectangleBox()))); - boolean interacted = false; - for (Rectangle object : solidObjects) { - TwoDimensionalRayTracer.TwoDimensionalRayTraceResult result = TwoDimensionalRayTracer.intersectBoxSegment( - new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), - new Vector2f((float) (Math.cos(ball.theta) * 6), (float) (Math.sin(ball.theta) * 6)), - new Vector2f((float) object.getCenterX(), (float) object.getCenterY()), - new Vector2f(4 + object.width / 2, 4 + object.height / 2)); - if (result != null && !interacted) { - ball.addSelfPosition((Math.cos(ball.theta) * 6 * result.time), (Math.sin(ball.theta) * 6 * result.time)); - - float angleMod = 0; - if(result.pos.y < object.getCenterY() - 2) { - angleMod -= Math.signum(result.normal.x) * 0.6; - } else if (result.pos.x > object.getCenterY() + 2) { - angleMod += Math.signum(result.normal.x) * 0.6; - } - ball.theta = (float) (Math.acos(result.normal.x) * 2 - ball.theta + Math.PI + angleMod) % (2 * Math.PI); // Reflects with a slight angle modification. - - if(ball.theta > Math.PI / 2 - 0.5 && ball.theta < Math.PI / 2 + 0.5) { - if(ball.theta <= Math.PI / 2) - ball.theta = Math.PI / 2 - 0.51; - else - ball.theta = Math.PI / 2 + 0.51; - } - if(ball.theta > 3 * Math.PI / 2 - 0.5 && ball.theta < 3 * Math.PI / 2 + 0.5) { - if(ball.theta < 3 * Math.PI / 2) - ball.theta = 3 * Math.PI / 2 - 0.51; - else - ball.theta = 3 * Math.PI / 2 + 0.51; - } - ball.addSelfPosition((Math.cos(ball.theta) * 8 * (1 - result.time)), (Math.sin(ball.theta) * 8 * (1 - result.time))); - interacted = true; + int timeLeft = 1; + + TwoDimensionalRayTracer.TwoDimensionalRayTraceResult result = TwoDimensionalRayTracer.nearestBoxSegmentCollision( + new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), + new Vector2f((float) (Math.cos(ball.theta) * 6), (float) (Math.sin(ball.theta) * 6)), + solidObjects, + new Vector2f(4, 4)); + while (result.time != 1 && timeLeft != 0) { + float angleMod = 0; + if (result.pos.y < result.collidedWith.getCenterY() - 2) { + angleMod -= Math.signum(result.normal.x) * 0.6; + } else if (result.pos.x > result.collidedWith.getCenterY() + 2) { + angleMod += Math.signum(result.normal.x) * 0.6; + } + ball.theta = (float) (Math.acos(result.normal.x) * 2 - ball.theta + Math.PI + angleMod) % (2 * Math.PI); // Reflects with a slight angle modification. + + if (ball.theta > Math.PI / 2 - 0.5 && ball.theta < Math.PI / 2 + 0.5) { + if (ball.theta <= Math.PI / 2) + ball.theta = Math.PI / 2 - 0.51; + else + ball.theta = Math.PI / 2 + 0.51; } + if (ball.theta > 3 * Math.PI / 2 - 0.5 && ball.theta < 3 * Math.PI / 2 + 0.5) { + if (ball.theta < 3 * Math.PI / 2) + ball.theta = 3 * Math.PI / 2 - 0.51; + else + ball.theta = 3 * Math.PI / 2 + 0.51; + } + timeLeft -= result.time * timeLeft; + result = TwoDimensionalRayTracer.nearestBoxSegmentCollision( + new Vector2f(ball.getSelfPosition().x, ball.getSelfPosition().y), + new Vector2f((float) (Math.cos(ball.theta) * 8 * timeLeft), (float) (Math.sin(ball.theta) * 8 * timeLeft)), + solidObjects, + new Vector2f(4, 4)); + // To prevent it getting permanently lodged into something. + ball.addSelfPosition((Math.cos(ball.theta) * 6 * (result.time + 0.1) * timeLeft), (Math.sin(ball.theta) * 6 * (result.time + 0.1) * timeLeft)); } - if(!interacted) - ball.addSelfPosition((Math.cos(ball.theta) * 6), (Math.sin(ball.theta) * 6)); - solidObjects.remove(2); solidObjects.remove(2); + ball.addSelfPosition((Math.cos(ball.theta) * 6 * timeLeft), (Math.sin(ball.theta) * 6 * timeLeft)); + solidObjects.remove(2); + solidObjects.remove(2); } + if (ball.getSelfPosition().getY() > 222) { + ball.setSelfPosition(new Position(ball.getSelfPosition().getX(), 211)); + } else if (ball.getSelfPosition().getY() < 10) + ball.setSelfPosition(new Position(ball.getSelfPosition().getX(), 21)); } public int simplePaddleAI(PaddleWidget paddle) { - if(this.timer % 3 == 0) + if (this.timer % 3 == 0) return -1; - if((ball.getSelfPosition().getY() + 2 * paddle.getSelfPosition().getY()) / 3 < paddle.getSelfPosition().getY()) + if ((ball.getSelfPosition().getY() + 2 * paddle.getSelfPosition().getY()) / 3 < paddle.getSelfPosition().getY()) return 1; else if ((ball.getSelfPosition().getY() + 2 * paddle.getSelfPosition().getY()) / 3 > paddle.getSelfPosition().getY()) return 0; diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java index 92784f7e810..c88ac834cb4 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java @@ -35,7 +35,7 @@ public Position addSelfPosition(int addX, int addY) { public void addSelfPosition(double addX, double addY) { xAccurate += addX; yAccurate += addY; - this.setSelfPosition(new Position((int) xAccurate, (int) yAccurate)); + super.setSelfPosition(new Position((int) xAccurate, (int) yAccurate)); } public Vector2f getPreciseSelfPosition() { From ef306eeea715583e9bbf89f82c41932759267df1 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 11 Sep 2021 13:53:21 -0500 Subject: [PATCH 07/19] Begin work on Theseus' Escape --- src/main/java/gregtech/api/gui/Widget.java | 29 ++-- .../api/terminal/TerminalRegistry.java | 2 + .../terminal/app/game/maze/MazeApp.java | 101 +++++++++++ .../app/game/maze/widget/MazeWidget.java | 161 ++++++++++++++++++ .../app/game/maze/widget/PlayerWidget.java | 29 ++++ .../resources/assets/gregtech/lang/en_us.lang | 2 + 6 files changed, 313 insertions(+), 11 deletions(-) create mode 100644 src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java diff --git a/src/main/java/gregtech/api/gui/Widget.java b/src/main/java/gregtech/api/gui/Widget.java index 81d52b17ba0..e7619085b99 100644 --- a/src/main/java/gregtech/api/gui/Widget.java +++ b/src/main/java/gregtech/api/gui/Widget.java @@ -1,7 +1,6 @@ package gregtech.api.gui; import com.google.common.base.Preconditions; -import gregtech.api.gui.resources.RenderUtil; import gregtech.api.gui.widgets.WidgetUIAccess; import gregtech.api.util.Position; import gregtech.api.util.Size; @@ -28,8 +27,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Supplier; + import org.lwjgl.opengl.GL11; /** @@ -47,6 +48,7 @@ public abstract class Widget { private transient Position position; private transient Size size; private transient boolean isVisible; + private transient BooleanSupplier visibilitySupplier; private transient boolean isActive; public Widget(Position selfPosition, Size size) { @@ -112,13 +114,18 @@ public final Size getSize() { } public boolean isVisible() { - return isVisible; + return visibilitySupplier != null ? visibilitySupplier.getAsBoolean() : isVisible; } public void setVisible(boolean visible) { isVisible = visible; } + public Widget setVisibilitySupplier(BooleanSupplier supplier) { + visibilitySupplier = supplier; + return this; + } + public boolean isActive() { return isActive; } @@ -145,7 +152,7 @@ protected void onSizeUpdate() { } public boolean isMouseOverElement(int mouseX, int mouseY, boolean correctPositionOnMouseWheelMoveEvent) { - mouseX = correctPositionOnMouseWheelMoveEvent ? mouseX + this.gui.getGuiLeft(): mouseX; + mouseX = correctPositionOnMouseWheelMoveEvent ? mouseX + this.gui.getGuiLeft() : mouseX; return isMouseOverElement(mouseX, mouseY); } @@ -426,13 +433,13 @@ public static void drawCircle(float x, float y, float r, int color, int segments } tessellator.draw(); GlStateManager.enableTexture2D(); - GlStateManager.color(1,1,1,1); + GlStateManager.color(1, 1, 1, 1); } @SideOnly(Side.CLIENT) public static void drawSector(float x, float y, float r, int color, int segments, int from, int to) { if (from > to || from < 0 || color == 0) return; - if(to > segments) to = segments; + if (to > segments) to = segments; Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferbuilder = tessellator.getBuffer(); GlStateManager.enableBlend(); @@ -447,7 +454,7 @@ public static void drawSector(float x, float y, float r, int color, int segments } tessellator.draw(); GlStateManager.enableTexture2D(); - GlStateManager.color(1,1,1,1); + GlStateManager.color(1, 1, 1, 1); } public static void drawTorus(float x, float y, float outer, float inner, int color, int segments, int from, int to) { @@ -459,13 +466,13 @@ public static void drawTorus(float x, float y, float outer, float inner, int col setColor(color); bufferbuilder.begin(GL11.GL_QUAD_STRIP, DefaultVertexFormats.POSITION); for (int i = from; i <= to; i++) { - float angle = ( i / (float)segments ) * 3.14159f * 2.0f; - bufferbuilder.pos( x + inner * Math.cos(-angle), y + inner * Math.sin(-angle), 0).endVertex(); - bufferbuilder.pos( x + outer * Math.cos(-angle), y + outer * Math.sin(-angle), 0).endVertex(); + float angle = (i / (float) segments) * 3.14159f * 2.0f; + bufferbuilder.pos(x + inner * Math.cos(-angle), y + inner * Math.sin(-angle), 0).endVertex(); + bufferbuilder.pos(x + outer * Math.cos(-angle), y + outer * Math.sin(-angle), 0).endVertex(); } tessellator.draw(); GlStateManager.enableTexture2D(); - GlStateManager.color(1,1,1,1); + GlStateManager.color(1, 1, 1, 1); } @SideOnly(Side.CLIENT) @@ -520,7 +527,7 @@ public static List genBezierPoints(Vec2f from, Vec2f to, boolean horizont c1 = new Vec2f(from.x, (from.y + to.y) / 2); c2 = new Vec2f(to.x, (from.y + to.y) / 2); } - Vec2f[] controlPoint = new Vec2f[]{from,c1,c2,to}; + Vec2f[] controlPoint = new Vec2f[]{from, c1, c2, to}; int n = controlPoint.length - 1; int i, r; List bezierPoints = new ArrayList<>(); diff --git a/src/main/java/gregtech/api/terminal/TerminalRegistry.java b/src/main/java/gregtech/api/terminal/TerminalRegistry.java index cd8da533800..b1e42cbeeb5 100644 --- a/src/main/java/gregtech/api/terminal/TerminalRegistry.java +++ b/src/main/java/gregtech/api/terminal/TerminalRegistry.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.terminal.app.*; import gregtech.common.terminal.app.ThemeSettingApp; +import gregtech.common.terminal.app.game.maze.MazeApp; import gregtech.common.terminal.app.game.pong.PongApp; import gregtech.common.terminal.app.guide.ItemGuideApp; import gregtech.common.terminal.app.guide.MultiBlockGuideApp; @@ -27,6 +28,7 @@ public static void init() { registerApp(new ThemeSettingApp(), true); registerApp(new OreProspectorApp(), true); registerApp(new PongApp(), true); + registerApp(new MazeApp(), true); if (GTValues.isModLoaded(GTValues.MODID_JEI)) { registerApp(new RecipeChartApp(), true); } diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java new file mode 100644 index 00000000000..db5429eb7f5 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -0,0 +1,101 @@ +package gregtech.common.terminal.app.game.maze; + +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.ClickButtonWidget; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.common.terminal.app.game.maze.widget.MazeWidget; +import gregtech.common.terminal.app.game.maze.widget.PlayerWidget; +import net.minecraft.nbt.NBTTagCompound; +import org.lwjgl.input.Keyboard; + +public class MazeApp extends AbstractApplication { + public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/maze/icon.png"); + private int gamestate = 0; + private PlayerWidget player; + private MazeWidget maze; + + public MazeApp() { + super("maze", ICON); + } + + @Override + public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + MazeApp app = new MazeApp(); + if (isClient) { + app.setOs(os); + app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); + // Gamestate 0: Title + app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", (clickData -> app.setGamestate(1))).setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 0)); + // Gamestate 1: Play + app.setMaze((MazeWidget) new MazeWidget().setVisibilitySupplier(() -> app.getGamestate() == 1)); + app.setPlayer((PlayerWidget) new PlayerWidget(5, 5, app).setVisibilitySupplier(() -> app.getGamestate() == 1)); + // Gamestate 2: Pause + } + return app; + } + + public void setPlayer(PlayerWidget player) { + this.player = player; + this.addWidget(player); + } + + public void setMaze(MazeWidget maze) { + this.maze = maze; + this.addWidget(maze); + } + + @Override + public boolean isClientSideApp() { + return true; + } + + @Override + public void updateScreen() { + super.updateScreen(); + if (gamestate == 1) { + if (Keyboard.isKeyDown(Keyboard.KEY_LEFT) ^ Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) { + if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) + attemptMovePlayer(0); // Left + else + attemptMovePlayer(1); // Right + } + if (Keyboard.isKeyDown(Keyboard.KEY_UP) ^ Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { + if (Keyboard.isKeyDown(Keyboard.KEY_UP)) + attemptMovePlayer(2); // Up + else + attemptMovePlayer(3); // Down + } + } + } + + public int getGamestate() { + return gamestate; + } + + public void setGamestate(int gamestate) { + this.gamestate = gamestate; + } + + public int getRenderX(int posX) { + return this.maze.getSelfPosition().x + posX * 10; + } + + public int getRenderY(int posY) { + return this.maze.getSelfPosition().y + posY * 10; + } + + private void attemptMovePlayer(int direction) { + if (direction == 0 && !maze.isThereWallAt(player.posX, player.posY, false)) { + player.move(-1, 0); + } else if (direction == 1 && !maze.isThereWallAt(player.posX + 1, player.posY, false)) { + player.move(1, 0); + } else if (direction == 2 && !maze.isThereWallAt(player.posX, player.posY, true)) { + player.move(0, -1); + } else if (direction == 3 && !maze.isThereWallAt(player.posX, player.posY + 1, true)) { + player.move(0, 1); + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java b/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java new file mode 100644 index 00000000000..b7cc2087b92 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java @@ -0,0 +1,161 @@ +package gregtech.common.terminal.app.game.maze.widget; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import net.minecraft.util.math.Vec2f; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MazeWidget extends Widget { + + boolean[][] topWalls = new boolean[11][11]; + boolean[][] leftWalls = new boolean[11][11]; + boolean[][] includedSpots = new boolean[11][11]; + + public MazeWidget() { + super(333 / 2 - 55, 232 / 2 - 55, 110, 110); + initMaze(); + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + // Draw outer lines + drawLines(createBorder(), 0xFFFFFFFF, 0xFFFFFFFF, 4); + // Draw inner lines + createInternalLines(); + } + + public List createBorder() { + List result = new ArrayList<>(); + result.add(new Vec2f(getPosition().x, getPosition().y)); + result.add(new Vec2f(this.getSize().width + getPosition().x, getPosition().y)); + result.add(new Vec2f(this.getSize().width + getPosition().x, this.getSize().height + getPosition().y)); + result.add(new Vec2f(getPosition().x, this.getSize().height + getPosition().y)); + result.add(new Vec2f(getPosition().x, getPosition().y)); // Do this again so it's a connected square + return result; + } + + public boolean isThereWallAt(int x, int y, boolean onTops) { + if (x > 10 || y > 10) + return true; + if (x < 0 || y < 0) + return true; + if ((x == 0 && !onTops) || (y == 0 && onTops)) + return true; + if (onTops) { + return topWalls[x][y]; + } else { + return leftWalls[x][y]; + } + } + + public void createInternalLines() { + for (int i = 0; i < 11; i++) { + for (int j = 0; j < 11; j++) { + List list = new ArrayList<>(); + if (j != 0 && isThereWallAt(i, j, true)) { + list.add(new Vec2f(getPosition().x + 10 * i, getPosition().y + 10 * j)); + list.add(new Vec2f(getPosition().x + 10 * (i + 1), getPosition().y + 10 * j)); + drawLines(list, 0xFFFFFFFF, 0xFFFFFFFF, 2); + list.clear(); + } + if (i != 0 && isThereWallAt(i, j, false)) { + list.add(new Vec2f(getPosition().x + 10 * i, getPosition().y + 10 * j)); + list.add(new Vec2f(getPosition().x + 10 * i, getPosition().y + 10 * (j + 1))); + drawLines(list, 0xFFFFFFFF, 0xFFFFFFFF, 2); + } + } + } + } + + public void initMaze() { + for (int i = 0; i < 11; i++) { // Fill array with walls so that they can be carved out + for (int j = 0; j < 11; j++) { + leftWalls[i][j] = true; + topWalls[i][j] = true; + } + } + + includedSpots[5][5] = true; // The center is where the player starts + // Improves maze randomization. + List positions = new ArrayList<>(); + for(int i = 0; i < 11 * 11; i++) { + positions.add(i); + } + Collections.shuffle(positions); + + for (int position : positions) { + if (!includedSpots[position / 11][position % 11]) { + createPath(position / 11, position % 11, new boolean[11][11]); + } + } + } + + // Wilson random walk maze generation + public boolean createPath(int x, int y, boolean[][] walkedPaths) { + if(walkedPaths[x][y]) { + return false; + } + if(includedSpots[x][y]) { + return true; + } + includedSpots[x][y] = true; + walkedPaths[x][y] = true; + // Find unoccupied directions + // Left 0 + List directions = new ArrayList<>(); + if (x != 0 && !walkedPaths[x - 1][y]) { + directions.add(0); + } + // Right 1 + if (x != 10 && !walkedPaths[x + 1][y]) { + directions.add(1); + } + // Up 2 + if (y != 0 && !walkedPaths[x][y - 1]) { + directions.add(2); + } + // Down 3 + if (y != 10 && !walkedPaths[x][y + 1]) { + directions.add(3); + } + Collections.shuffle(directions); + // Select one + while (directions.size() > 0) { + int direction = directions.get(directions.size() - 1); + // Use direction to create new coordinates + int newX = x; + int newY = y; + if (direction == 0) { + newX--; + } else if (direction == 1) { + newX++; + } else if (direction == 2) { + newY--; + } else if (direction == 3) { + newY++; + } + if (createPath(newX, newY, walkedPaths)) { + // Delete walls and return + if (direction == 0) { + leftWalls[x][y] = false; + } else if (direction == 1) { + leftWalls[x + 1][y] = false; + } else if (direction == 2) { + topWalls[x][y] = false; + } else if (direction == 3) { + topWalls[x][y + 1] = false; + } + return true; + } else { + directions.remove(directions.size() - 1); + } + } + // Reset current position + includedSpots[x][y] = false; + walkedPaths[x][y] = false; + return false; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java b/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java new file mode 100644 index 00000000000..56f0da710a3 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java @@ -0,0 +1,29 @@ +package gregtech.common.terminal.app.game.maze.widget; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.util.Position; +import gregtech.common.terminal.app.game.maze.MazeApp; + +public class PlayerWidget extends Widget { + private MazeApp app; + public int posX; + public int posY; + public PlayerWidget(int posX, int posY, MazeApp app) { + super(app.getRenderX(posX), app.getRenderY(posY), 10, 10); + this.app = app; + this.posX = posX; + this.posY = posY; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + this.setSelfPosition(new Position(app.getRenderX(posX), app.getRenderY(posY))); + drawSolidRect(this.getPosition().x, this.getPosition().y, 10, 10, 0xAAAAAAFF); + } + + public void move(int deltaX, int deltaY) { + this.posX += deltaX; + this.posY += deltaY; + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 755540f1972..269f1911aa8 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -3853,6 +3853,8 @@ gregtech.terminal.app_name.guide_editor=Guide Editor gregtech.terminal.app_name.recipe_chart=Recipe Chart gregtech.terminal.app_name.ore_prospector=Ore Prospector gregtech.terminal.app_name.pong=Pong +gregtech.terminal.app_name.maze=Theseus's Escape + texture.modify_gui_texture.missing=Missing Texture From 59f77bfbb34f8c6ff8a8886c86a9d6133a49c7ac Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 19 Sep 2021 15:42:24 -0500 Subject: [PATCH 08/19] Complete basic game loop for Theseus's Escape --- .../terminal/app/game/maze/MazeApp.java | 128 +++++++++++++++++- .../app/game/maze/widget/EnemyWidget.java | 18 +++ .../app/game/maze/widget/MazeWidget.java | 84 ++++++++---- .../app/game/maze/widget/PlayerWidget.java | 8 +- 4 files changed, 204 insertions(+), 34 deletions(-) create mode 100644 src/main/java/gregtech/common/terminal/app/game/maze/widget/EnemyWidget.java diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index db5429eb7f5..76a1983ccf3 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -1,21 +1,34 @@ package gregtech.common.terminal.app.game.maze; +import gregtech.api.gui.resources.ColorRectTexture; import gregtech.api.gui.resources.TextureArea; import gregtech.api.gui.widgets.ClickButtonWidget; import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.gui.widgets.SimpleTextWidget; import gregtech.api.terminal.app.AbstractApplication; import gregtech.api.terminal.os.TerminalOSWidget; import gregtech.api.terminal.os.TerminalTheme; +import gregtech.common.terminal.app.game.maze.widget.EnemyWidget; import gregtech.common.terminal.app.game.maze.widget.MazeWidget; import gregtech.common.terminal.app.game.maze.widget.PlayerWidget; import net.minecraft.nbt.NBTTagCompound; import org.lwjgl.input.Keyboard; +import java.util.ArrayList; +import java.util.List; + public class MazeApp extends AbstractApplication { public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/maze/icon.png"); private int gamestate = 0; private PlayerWidget player; + private EnemyWidget enemy; private MazeWidget maze; + private int timer = 0; + private int mazesSolved = 0; + private float speed = 25; + private int lastPlayerInput = -2; + public static int MAZE_SIZE = 9; + private List movementStore = new ArrayList<>(); public MazeApp() { super("maze", ICON); @@ -28,11 +41,31 @@ public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTT app.setOs(os); app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); // Gamestate 0: Title - app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", (clickData -> app.setGamestate(1))).setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 0)); + app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", + (clickData -> { + app.setGamestate(1); + app.resetGame(); + })) + .setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 0)); // Gamestate 1: Play - app.setMaze((MazeWidget) new MazeWidget().setVisibilitySupplier(() -> app.getGamestate() == 1)); - app.setPlayer((PlayerWidget) new PlayerWidget(5, 5, app).setVisibilitySupplier(() -> app.getGamestate() == 1)); + app.setMaze((MazeWidget) new MazeWidget().setVisibilitySupplier(() -> app.getGamestate() >= 1)); + app.setPlayer((PlayerWidget) new PlayerWidget(0, 0, app).setVisibilitySupplier(() -> app.getGamestate() >= 1)); + app.setEnemy((EnemyWidget) new EnemyWidget(-100, -100, app).setVisibilitySupplier(() -> app.getGamestate() >= 1)); // Gamestate 2: Pause + + // Gamestate 3: Death + app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0x99000000)).setVisibilitySupplier(() -> app.getGamestate() == 3)); + app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); + app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + app.getMazesSolved() + " mazes before losing.", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); + app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); + app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 + 10, 40, 20, "Retry", (clickData -> { + app.setGamestate(1); + app.setMazesSolved(0); + MAZE_SIZE = 9; + app.resetGame(); + })).setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 3)); + + } return app; } @@ -47,6 +80,11 @@ public void setMaze(MazeWidget maze) { this.addWidget(maze); } + public void setEnemy(EnemyWidget enemy) { + this.enemy = enemy; + this.addWidget(enemy); + } + @Override public boolean isClientSideApp() { return true; @@ -68,6 +106,15 @@ public void updateScreen() { else attemptMovePlayer(3); // Down } + timer++; + if (enemy.posX < 0 && timer % (speed * 8) < 1) { + enemy.setGridPosition(0, 0); + } else if (timer % speed < 1) { + moveEnemy(); + } + if (enemy.posX == player.posX && enemy.posY == player.posY) { + gamestate = 3; + } } } @@ -87,15 +134,90 @@ public int getRenderY(int posY) { return this.maze.getSelfPosition().y + posY * 10; } + public int getTimer() { + return timer; + } + private void attemptMovePlayer(int direction) { + if (timer < lastPlayerInput + 2) { + return; + } + lastPlayerInput = timer; + + // Did the player reach the end? + if (player.posX == MAZE_SIZE - 1 && player.posY == MAZE_SIZE - 1 && direction == 3) { + mazesSolved++; + if (mazesSolved % 4 == 0) { + MAZE_SIZE += 2; + } + resetGame(); + return; + } + if (direction == 0 && !maze.isThereWallAt(player.posX, player.posY, false)) { player.move(-1, 0); + if (movementStore.size() > 0 && movementStore.get(movementStore.size() - 1) == 1) { + movementStore.remove(movementStore.size() - 1); + } else { + movementStore.add(direction); + } } else if (direction == 1 && !maze.isThereWallAt(player.posX + 1, player.posY, false)) { player.move(1, 0); + if (movementStore.size() > 0 && movementStore.get(movementStore.size() - 1) == 0) { + movementStore.remove(movementStore.size() - 1); + } else { + movementStore.add(direction); + } } else if (direction == 2 && !maze.isThereWallAt(player.posX, player.posY, true)) { player.move(0, -1); + if (movementStore.size() > 0 && movementStore.get(movementStore.size() - 1) == 3) { + movementStore.remove(movementStore.size() - 1); + } else { + movementStore.add(direction); + } } else if (direction == 3 && !maze.isThereWallAt(player.posX, player.posY + 1, true)) { player.move(0, 1); + if (movementStore.size() > 0 && movementStore.get(movementStore.size() - 1) == 2) { + movementStore.remove(movementStore.size() - 1); + } else { + movementStore.add(direction); + } + } + } + + private void moveEnemy() { // Move enemy with the latest movements + if (enemy.posX < 0 || movementStore.isEmpty()) + return; + + int direction = movementStore.get(0); + if (direction == 0) { + enemy.move(-1, 0); + } else if (direction == 1) { + enemy.move(1, 0); + } else if (direction == 2) { + enemy.move(0, -1); + } else if (direction == 3) { + enemy.move(0, 1); } + movementStore.remove(0); + } + + private void resetGame() { + player.setGridPosition(0, 0); + maze.recalculateSize(); + maze.initMaze(); + movementStore.clear(); + timer = 0; + lastPlayerInput = -5; + speed *= 0.95; + enemy.setGridPosition(-100, -100); + } + + public int getMazesSolved() { + return mazesSolved; + } + + public void setMazesSolved(int mazesSolved) { + this.mazesSolved = mazesSolved; } } diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/widget/EnemyWidget.java b/src/main/java/gregtech/common/terminal/app/game/maze/widget/EnemyWidget.java new file mode 100644 index 00000000000..f3ec600aee8 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/maze/widget/EnemyWidget.java @@ -0,0 +1,18 @@ +package gregtech.common.terminal.app.game.maze.widget; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.util.Position; +import gregtech.common.terminal.app.game.maze.MazeApp; + +public class EnemyWidget extends PlayerWidget { + + public EnemyWidget(int posX, int posY, MazeApp app) { + super(posX, posY, app); + } + + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + this.setSelfPosition(new Position(app.getRenderX(posX), app.getRenderY(posY))); + drawSolidRect(this.getPosition().x, this.getPosition().y, 10, 10, 0xFFFFAAAA); + } + +} diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java b/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java index b7cc2087b92..edcb57664c9 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/widget/MazeWidget.java @@ -2,43 +2,59 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; +import gregtech.api.util.Position; +import gregtech.api.util.Size; import net.minecraft.util.math.Vec2f; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static gregtech.common.terminal.app.game.maze.MazeApp.MAZE_SIZE; + public class MazeWidget extends Widget { - boolean[][] topWalls = new boolean[11][11]; - boolean[][] leftWalls = new boolean[11][11]; - boolean[][] includedSpots = new boolean[11][11]; + boolean[][] topWalls = new boolean[MAZE_SIZE][MAZE_SIZE]; + boolean[][] leftWalls = new boolean[MAZE_SIZE][MAZE_SIZE]; + boolean[][] includedSpots; + private int squaresChecked; public MazeWidget() { - super(333 / 2 - 55, 232 / 2 - 55, 110, 110); + super(333 / 2 - (MAZE_SIZE * 5), 232 / 2 - (MAZE_SIZE * 5), MAZE_SIZE * 10, MAZE_SIZE * 10); initMaze(); } @Override public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { // Draw outer lines - drawLines(createBorder(), 0xFFFFFFFF, 0xFFFFFFFF, 4); + createBorder(); // Draw inner lines createInternalLines(); } - public List createBorder() { - List result = new ArrayList<>(); - result.add(new Vec2f(getPosition().x, getPosition().y)); - result.add(new Vec2f(this.getSize().width + getPosition().x, getPosition().y)); - result.add(new Vec2f(this.getSize().width + getPosition().x, this.getSize().height + getPosition().y)); - result.add(new Vec2f(getPosition().x, this.getSize().height + getPosition().y)); - result.add(new Vec2f(getPosition().x, getPosition().y)); // Do this again so it's a connected square - return result; + public void recalculateSize() { + this.setSelfPosition(new Position(333 / 2 - (MAZE_SIZE * 5), 232 / 2 - (MAZE_SIZE * 5))); + this.setSize(new Size(MAZE_SIZE * 10, MAZE_SIZE * 10)); + topWalls = new boolean[MAZE_SIZE][MAZE_SIZE]; + leftWalls = new boolean[MAZE_SIZE][MAZE_SIZE]; + + } + + public void createBorder() { + List lineBuffer = new ArrayList<>(); + lineBuffer.add(new Vec2f(getPosition().x + 10, getPosition().y)); + lineBuffer.add(new Vec2f(this.getSize().width + getPosition().x, getPosition().y)); + lineBuffer.add(new Vec2f(this.getSize().width + getPosition().x, this.getSize().height + getPosition().y + 2)); // Corrects for line width misalignment + drawLines(lineBuffer, 0xFFFFFFFF, 0xFFFFFFFF, 4); + lineBuffer.clear(); + lineBuffer.add(new Vec2f(this.getSize().width + getPosition().x - 10, this.getSize().height + getPosition().y)); + lineBuffer.add(new Vec2f(getPosition().x, this.getSize().height + getPosition().y)); + lineBuffer.add(new Vec2f(getPosition().x, getPosition().y - 2)); + drawLines(lineBuffer, 0xFFFFFFFF, 0xFFFFFFFF, 4); } public boolean isThereWallAt(int x, int y, boolean onTops) { - if (x > 10 || y > 10) + if (x >= MAZE_SIZE || y >= MAZE_SIZE) return true; if (x < 0 || y < 0) return true; @@ -52,8 +68,8 @@ public boolean isThereWallAt(int x, int y, boolean onTops) { } public void createInternalLines() { - for (int i = 0; i < 11; i++) { - for (int j = 0; j < 11; j++) { + for (int i = 0; i < MAZE_SIZE; i++) { + for (int j = 0; j < MAZE_SIZE; j++) { List list = new ArrayList<>(); if (j != 0 && isThereWallAt(i, j, true)) { list.add(new Vec2f(getPosition().x + 10 * i, getPosition().y + 10 * j)); @@ -71,37 +87,41 @@ public void createInternalLines() { } public void initMaze() { - for (int i = 0; i < 11; i++) { // Fill array with walls so that they can be carved out - for (int j = 0; j < 11; j++) { + includedSpots = new boolean[MAZE_SIZE][MAZE_SIZE]; + for (int i = 0; i < MAZE_SIZE; i++) { // Fill array with walls so that they can be carved out + for (int j = 0; j < MAZE_SIZE; j++) { leftWalls[i][j] = true; topWalls[i][j] = true; } } - includedSpots[5][5] = true; // The center is where the player starts + includedSpots[(int) (Math.random() * MAZE_SIZE)][(int) (Math.random() * MAZE_SIZE)] = true; // Can seed our particular maze // Improves maze randomization. List positions = new ArrayList<>(); - for(int i = 0; i < 11 * 11; i++) { + for(int i = 0; i < MAZE_SIZE * MAZE_SIZE; i++) { positions.add(i); } Collections.shuffle(positions); for (int position : positions) { - if (!includedSpots[position / 11][position % 11]) { - createPath(position / 11, position % 11, new boolean[11][11]); + if (!includedSpots[position / MAZE_SIZE][position % MAZE_SIZE]) { + do { + resetStuckCounter(); + } while (!this.createPath(position / MAZE_SIZE, position % MAZE_SIZE, new boolean[MAZE_SIZE][MAZE_SIZE])); } } } // Wilson random walk maze generation public boolean createPath(int x, int y, boolean[][] walkedPaths) { - if(walkedPaths[x][y]) { + squaresChecked++; + if(squaresChecked > 20000) // Probably stuck. return false; - } - if(includedSpots[x][y]) { + if(walkedPaths[x][y]) + return false; + if(this.includedSpots[x][y]) return true; - } - includedSpots[x][y] = true; + this.includedSpots[x][y] = true; walkedPaths[x][y] = true; // Find unoccupied directions // Left 0 @@ -110,7 +130,7 @@ public boolean createPath(int x, int y, boolean[][] walkedPaths) { directions.add(0); } // Right 1 - if (x != 10 && !walkedPaths[x + 1][y]) { + if (x != MAZE_SIZE - 1 && !walkedPaths[x + 1][y]) { directions.add(1); } // Up 2 @@ -118,7 +138,7 @@ public boolean createPath(int x, int y, boolean[][] walkedPaths) { directions.add(2); } // Down 3 - if (y != 10 && !walkedPaths[x][y + 1]) { + if (y != MAZE_SIZE - 1 && !walkedPaths[x][y + 1]) { directions.add(3); } Collections.shuffle(directions); @@ -154,8 +174,12 @@ public boolean createPath(int x, int y, boolean[][] walkedPaths) { } } // Reset current position - includedSpots[x][y] = false; + this.includedSpots[x][y] = false; walkedPaths[x][y] = false; return false; } + + public void resetStuckCounter() { + squaresChecked = 0; + } } diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java b/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java index 56f0da710a3..16dbea8b46b 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/widget/PlayerWidget.java @@ -6,7 +6,7 @@ import gregtech.common.terminal.app.game.maze.MazeApp; public class PlayerWidget extends Widget { - private MazeApp app; + protected MazeApp app; public int posX; public int posY; public PlayerWidget(int posX, int posY, MazeApp app) { @@ -26,4 +26,10 @@ public void move(int deltaX, int deltaY) { this.posX += deltaX; this.posY += deltaY; } + + + public void setGridPosition(int posX, int posY) { + this.posX = posX; + this.posY = posY; + } } From 502488f42d791aaa13736478e7cb0f4367977582 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 19 Sep 2021 15:57:50 -0500 Subject: [PATCH 09/19] Properly update speed variables --- .../java/gregtech/common/terminal/app/game/maze/MazeApp.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index 76a1983ccf3..1459c9cc924 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -62,6 +62,7 @@ public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTT app.setGamestate(1); app.setMazesSolved(0); MAZE_SIZE = 9; + speed = 25; app.resetGame(); })).setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 3)); @@ -147,8 +148,10 @@ private void attemptMovePlayer(int direction) { // Did the player reach the end? if (player.posX == MAZE_SIZE - 1 && player.posY == MAZE_SIZE - 1 && direction == 3) { mazesSolved++; + speed *= 0.95; if (mazesSolved % 4 == 0) { MAZE_SIZE += 2; + speed *= 1.07; } resetGame(); return; @@ -209,7 +212,6 @@ private void resetGame() { movementStore.clear(); timer = 0; lastPlayerInput = -5; - speed *= 0.95; enemy.setGridPosition(-100, -100); } From 0a17c7c27c7709883fa8e2e777dbf42ff3df55d4 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 20 Sep 2021 21:17:44 -0500 Subject: [PATCH 10/19] Make branch compilable --- .../gregtech/api/terminal/TerminalRegistry.java | 8 ++++++-- .../common/terminal/app/game/maze/MazeApp.java | 8 +++----- .../common/terminal/app/game/pong/PongApp.java | 4 ++-- .../resources/assets/gregtech/lang/en_us.lang | 2 ++ .../textures/gui/terminal/maze/icon.png | Bin 0 -> 669 bytes .../textures/gui/terminal/pong/icon.png | Bin 696 -> 724 bytes 6 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/maze/icon.png diff --git a/src/main/java/gregtech/api/terminal/TerminalRegistry.java b/src/main/java/gregtech/api/terminal/TerminalRegistry.java index 21b032ba0c4..646d20f6137 100644 --- a/src/main/java/gregtech/api/terminal/TerminalRegistry.java +++ b/src/main/java/gregtech/api/terminal/TerminalRegistry.java @@ -68,9 +68,13 @@ public static void init() { AppRegistryBuilder.create(new TutorialGuideApp()).defaultApp().build(); AppRegistryBuilder.create(new GuideEditorApp()).defaultApp().build(); AppRegistryBuilder.create(new ThemeSettingApp()).defaultApp().build(); - AppRegistryBuilder.create(new PongApp()).defaultApp().build(); - AppRegistryBuilder.create(new MazeApp()).defaultApp().build(); + AppRegistryBuilder.create(new PongApp()) + .battery(GTValues.LV, 75) + .build(); + AppRegistryBuilder.create(new MazeApp()) + .battery(GTValues.LV, 150) + .build(); AppRegistryBuilder.create(new OreProspectorApp()) .battery(GTValues.MV, 1000) .upgrade(MetaItems.COIN_DOGE.getStackForm(10)) diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index 1459c9cc924..24872d5876b 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -18,7 +18,6 @@ import java.util.List; public class MazeApp extends AbstractApplication { - public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/maze/icon.png"); private int gamestate = 0; private PlayerWidget player; private EnemyWidget enemy; @@ -31,11 +30,10 @@ public class MazeApp extends AbstractApplication { private List movementStore = new ArrayList<>(); public MazeApp() { - super("maze", ICON); + super("maze"); } - @Override - public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + public AbstractApplication createAppInstance(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { MazeApp app = new MazeApp(); if (isClient) { app.setOs(os); @@ -108,7 +106,7 @@ public void updateScreen() { attemptMovePlayer(3); // Down } timer++; - if (enemy.posX < 0 && timer % (speed * 8) < 1) { + if (enemy.posX < 0 && timer % (speed * MAZE_SIZE - 1) < 1) { enemy.setGridPosition(0, 0); } else if (timer % speed < 1) { moveEnemy(); diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index c78bdaabaa9..f3934dd6966 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -32,11 +32,11 @@ public class PongApp extends AbstractApplication { private int timer = 0; public PongApp() { - super("pong", ICON); + super("pong"); } @Override - public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + public AbstractApplication createAppInstance(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { PongApp app = new PongApp(); if (isClient) { app.setOs(os); diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 49dacf2c174..097c6150e1a 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -3972,6 +3972,8 @@ terminal.items.description=A guide book about items. terminal.machines.description=A guide book about gt machines. terminal.multiblocks.description=A guide book about multi-blocks. terminal.tutorials.description=Introduces all kinds of things, CT integration, tips, tutorials and more. +terminal.pong.description=A classic pong game, if you're really that bored of waiting for that tungstensteel. +terminal.maze.description=A GTOS exclusive game finding you racing through an endless labyrinth to survive the Minotaur! texture.modify_gui_texture.missing=Missing Texture texture.url_texture.fail=Load Failed diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/maze/icon.png b/src/main/resources/assets/gregtech/textures/gui/terminal/maze/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1d878d98e14f6921a18dba27ec30804f3107dc00 GIT binary patch literal 669 zcmV;O0%HA%P)Px%S4l)cR5(vfQ%z4AQ4~FQu+hOmg5^srainx3j@`Jai@LU(>OZyX#*{7!izY6Z znwqd^1fzh^CL+U7!@JG9?}=qG%)GpN?z!ijORSg~j6@;<{YC^Z^n+o31km$4LEk1Q zH3yhLik1F@pN`fEvB3jVLn&-2&5FV?yCDH-BrYKY&#nuNU;GUW-Pld zrjy7v0jRdK!(Z!lyv$`Wjb}(ElLkPKpqWT(ivu8vCRlM@j7B3I9=-=vt5t3`8^~sJ zrWt_SUJsk44TC|1+HMVvMgyLgf@r|Na5%!j!8?$b@?FN zuuI0-_# z-NxPB5L;UnluAW(yBz^27K<1Rhv@veLO!3x>*^aQr7#!_Om4(SW=x|9%Pa1}M(cr% zj^qZjIEL%48fV2QBApeHKVQtDchi@Gh0$7}|AM(uETBIaNCAm9I&-A0F$Zd{aNF;r zq-~rl3DI5<;9Ii^&s#;pNmxctp%w;)g7`^{{%sGw?_)BZO8WNq_wl7($69*LCh|F; zW)gYYrC|cIGGmB&PvZa%Ii|ZwwoSS4*B`ck82Nl2Kf;T}GF|?>#LWY^=4luoVQs1H{hGO3_AS{bwU2 z2oW3@=Ht!0$IKfD6tkw~hWfy=^GX$%@sW1Gt)|!*}(*pM2Vqc zuttU~dFd;IEq{tjT=pYX{O!I!CN4u<8BB4Ev5JN6`%!=JyIVIk&|gYwia_m?=e>17 z-8Os`Jn!?+^S+KC_y`wv*}qzZ;djvsWv%l7S~lVAvaA_9aJ~g?4>{e@eJLn2kV?Vp ziG0%>v|dBwLaDc(eU9%SAze*f!QMV}rzLx_%Dd|;dp7&?jNc!TZ*7-yrCNvoo&W#< z32;bRa{vG?BLDy{BLR4&KXw2B00v@9M??VB0QUe9UkxWgli2|~f2~PGK~!i%?bX2w zfFKYAQ0@P}r%v^2g)npwqShU^!g(IVJs7%EB@q!38CJ&ZwgZ-C8L$lFejv`>eDE6X zA?zY1%)`y4M+Cju2 zLv^wsD&iQ%_|Va_}5q_we!c zF3z*O&;2>VO3`G1Pb8jYx?vHo6HjkiI_G`jD62>c@j3CBK^G)`|rcxny!x!N@U>4XBVDKlmT~?$#_#PPj>-1km$h+aDu9 za2IGbZ2SAzwp%BF{~5T_I{u9&F!M=zqoc)+fPrn`;<}^Bd%)!mF!-cPhU7?onnI}r zyr0oG6@bVs(7)>T*51eI1CXPxmTrK9LtwN_*=ru}?j!B)?cX!){(b;$mvW^BsPl#Z z000JJOGiWi)ByJY5nl}_L6fin7?auoIDd~xL_t(&-tCq_3cw%?1S|M5J?VqJ`L^~V z2<@e)p^2S22h40(@HhYf0N}5(!w#v9CKfA z_VTOo(!$#D(!%$7a{o2$TTVf7V|7S>(?XT1We{sRwzx0f58pT(T8)Vw$dBPG0< mu(p5@MtHM;5JngPzz!Dy^8-I+Aam>h0000 Date: Tue, 21 Sep 2021 21:24:25 -0500 Subject: [PATCH 11/19] Add Pause Screen and More Labels --- .../terminal/app/game/maze/MazeApp.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index 24872d5876b..c31eb530040 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -4,6 +4,7 @@ import gregtech.api.gui.resources.TextureArea; import gregtech.api.gui.widgets.ClickButtonWidget; import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.gui.widgets.LabelWidget; import gregtech.api.gui.widgets.SimpleTextWidget; import gregtech.api.terminal.app.AbstractApplication; import gregtech.api.terminal.os.TerminalOSWidget; @@ -13,6 +14,7 @@ import gregtech.common.terminal.app.game.maze.widget.PlayerWidget; import net.minecraft.nbt.NBTTagCompound; import org.lwjgl.input.Keyboard; +import scala.swing.event.Key; import java.util.ArrayList; import java.util.List; @@ -28,6 +30,7 @@ public class MazeApp extends AbstractApplication { private int lastPlayerInput = -2; public static int MAZE_SIZE = 9; private List movementStore = new ArrayList<>(); + private boolean lastPausePress; public MazeApp() { super("maze"); @@ -39,6 +42,7 @@ public AbstractApplication createAppInstance(TerminalOSWidget os, boolean isClie app.setOs(os); app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); // Gamestate 0: Title + app.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Theseus's Escape", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> app.getGamestate() == 0)); app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", (clickData -> { app.setGamestate(1); @@ -50,9 +54,10 @@ public AbstractApplication createAppInstance(TerminalOSWidget os, boolean isClie app.setPlayer((PlayerWidget) new PlayerWidget(0, 0, app).setVisibilitySupplier(() -> app.getGamestate() >= 1)); app.setEnemy((EnemyWidget) new EnemyWidget(-100, -100, app).setVisibilitySupplier(() -> app.getGamestate() >= 1)); // Gamestate 2: Pause - + app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0xFF000000)).setVisibilitySupplier(() -> app.getGamestate() > 1)); + app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 50, 20, "Continue", (clickData) -> app.setGamestate(1)).setVisibilitySupplier(() -> app.getGamestate() == 2)); + app.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Game Paused", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> app.getGamestate() == 2)); // Gamestate 3: Death - app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0x99000000)).setVisibilitySupplier(() -> app.getGamestate() == 3)); app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + app.getMazesSolved() + " mazes before losing.", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); @@ -93,6 +98,10 @@ public boolean isClientSideApp() { public void updateScreen() { super.updateScreen(); if (gamestate == 1) { + if (Keyboard.isKeyDown(Keyboard.KEY_P)) { + gamestate = 2; + lastPausePress = true; + } if (Keyboard.isKeyDown(Keyboard.KEY_LEFT) ^ Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) { if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) attemptMovePlayer(0); // Left @@ -115,6 +124,12 @@ public void updateScreen() { gamestate = 3; } } + if (gamestate == 2) { + if(!Keyboard.isKeyDown(Keyboard.KEY_P)) + lastPausePress = false; + if(Keyboard.isKeyDown(Keyboard.KEY_P) && !lastPausePress) + gamestate = 1; + } } public int getGamestate() { From e0a928deae097e38f862046c25ce43f019cdb813 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Thu, 23 Sep 2021 17:48:18 -0500 Subject: [PATCH 12/19] Implement Kila's Suggestions --- .../terminal/app/game/maze/MazeApp.java | 49 +++++++++---------- .../terminal/app/game/pong/PongApp.java | 20 ++++---- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index c31eb530040..1bca81d590f 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -36,42 +36,39 @@ public MazeApp() { super("maze"); } - public AbstractApplication createAppInstance(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { - MazeApp app = new MazeApp(); + public AbstractApplication initApp() { if (isClient) { - app.setOs(os); - app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); + this.setOs(os); + this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); // Gamestate 0: Title - app.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Theseus's Escape", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> app.getGamestate() == 0)); - app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", + this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Theseus's Escape", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> this.getGamestate() == 0)); + this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", (clickData -> { - app.setGamestate(1); - app.resetGame(); + this.setGamestate(1); + this.resetGame(); })) - .setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 0)); + .setShouldClientCallback(true).setVisibilitySupplier(() -> this.getGamestate() == 0)); // Gamestate 1: Play - app.setMaze((MazeWidget) new MazeWidget().setVisibilitySupplier(() -> app.getGamestate() >= 1)); - app.setPlayer((PlayerWidget) new PlayerWidget(0, 0, app).setVisibilitySupplier(() -> app.getGamestate() >= 1)); - app.setEnemy((EnemyWidget) new EnemyWidget(-100, -100, app).setVisibilitySupplier(() -> app.getGamestate() >= 1)); + this.setMaze((MazeWidget) new MazeWidget().setVisibilitySupplier(() -> this.getGamestate() >= 1)); + this.setPlayer((PlayerWidget) new PlayerWidget(0, 0, this).setVisibilitySupplier(() -> this.getGamestate() >= 1)); + this.setEnemy((EnemyWidget) new EnemyWidget(-100, -100, this).setVisibilitySupplier(() -> this.getGamestate() >= 1)); // Gamestate 2: Pause - app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0xFF000000)).setVisibilitySupplier(() -> app.getGamestate() > 1)); - app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 50, 20, "Continue", (clickData) -> app.setGamestate(1)).setVisibilitySupplier(() -> app.getGamestate() == 2)); - app.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Game Paused", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> app.getGamestate() == 2)); + this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0xFF000000)).setVisibilitySupplier(() -> this.getGamestate() > 1)); + this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 50, 20, "Continue", (clickData) -> this.setGamestate(1)).setVisibilitySupplier(() -> this.getGamestate() == 2)); + this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Game Paused", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> this.getGamestate() == 2)); // Gamestate 3: Death - app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); - app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + app.getMazesSolved() + " mazes before losing.", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); - app.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true).setVisibilitySupplier(() -> app.getGamestate() == 3)); - app.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 + 10, 40, 20, "Retry", (clickData -> { - app.setGamestate(1); - app.setMazesSolved(0); + this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true).setVisibilitySupplier(() -> this.getGamestate() == 3)); + this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + this.getMazesSolved() + " mazes before losing.", true).setVisibilitySupplier(() -> this.getGamestate() == 3)); + this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true).setVisibilitySupplier(() -> this.getGamestate() == 3)); + this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 + 10, 40, 20, "Retry", (clickData -> { + this.setGamestate(1); + this.setMazesSolved(0); MAZE_SIZE = 9; speed = 25; - app.resetGame(); - })).setShouldClientCallback(true).setVisibilitySupplier(() -> app.getGamestate() == 3)); - - + this.resetGame(); + })).setShouldClientCallback(true).setVisibilitySupplier(() -> this.getGamestate() == 3)); } - return app; + return this; } public void setPlayer(PlayerWidget player) { diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index f3934dd6966..8659e7aac2c 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -36,18 +36,16 @@ public PongApp() { } @Override - public AbstractApplication createAppInstance(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { - PongApp app = new PongApp(); - if (isClient) { - app.setOs(os); - app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); - app.addWidget(new ImageWidget(333 / 2 - 4, 5, 6, 232 - 10, new ColorRectTexture(0xAAAAAAAA))); - app.setBall(new BallWidget(333 / 2 - 1, 232 / 2 - 1)); - app.addWidget(new SimpleTextWidget(50, 20, "", 0xAAAAAA, () -> String.valueOf(app.getScore(true)), true)); - app.addWidget(new SimpleTextWidget(283, 20, "", 0xAAAAAA, () -> String.valueOf(app.getScore(false)), true)); - app.initPaddles(); + public AbstractApplication initApp() { + if(isClient) { + this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); + this.addWidget(new ImageWidget(333 / 2 - 4, 5, 6, 232 - 10, new ColorRectTexture(0xAAAAAAAA))); + this.setBall(new BallWidget(333 / 2 - 1, 232 / 2 - 1)); + this.addWidget(new SimpleTextWidget(50, 20, "", 0xAAAAAA, () -> String.valueOf(this.getScore(true)), true)); + this.addWidget(new SimpleTextWidget(283, 20, "", 0xAAAAAA, () -> String.valueOf(this.getScore(false)), true)); + this.initPaddles(); } - return app; + return this; } @Override From d1d095d5647f2edefafd668bbea2d0d58958623d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 26 Sep 2021 15:46:54 -0500 Subject: [PATCH 13/19] Create Minesweeper Assets --- .../app/game/minesweeper/MinesweeperApp.java | 19 ++++ .../minesweeper/widget/MineMapWidget.java | 85 ++++++++++++++++++ .../textures/gui/terminal/minesweeper/1.png | Bin 0 -> 5712 bytes .../textures/gui/terminal/minesweeper/2.png | Bin 0 -> 5719 bytes .../textures/gui/terminal/minesweeper/3.png | Bin 0 -> 5748 bytes .../textures/gui/terminal/minesweeper/4.png | Bin 0 -> 5713 bytes .../textures/gui/terminal/minesweeper/5.png | Bin 0 -> 5730 bytes .../textures/gui/terminal/minesweeper/6.png | Bin 0 -> 5726 bytes .../textures/gui/terminal/minesweeper/7.png | Bin 0 -> 5683 bytes .../textures/gui/terminal/minesweeper/8.png | Bin 0 -> 5712 bytes .../gui/terminal/minesweeper/blank.png | Bin 0 -> 570 bytes .../gui/terminal/minesweeper/bomb.png | Bin 0 -> 5838 bytes .../gui/terminal/minesweeper/covered.png | Bin 0 -> 5699 bytes .../gui/terminal/minesweeper/flag.png | Bin 0 -> 5824 bytes 14 files changed, 104 insertions(+) create mode 100644 src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/1.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/2.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/3.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/5.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/7.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/8.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/blank.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/bomb.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/covered.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/flag.png diff --git a/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java b/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java new file mode 100644 index 00000000000..f7ab5e08058 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java @@ -0,0 +1,19 @@ +package gregtech.common.terminal.app.game.minesweeper; + +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.common.terminal.app.game.minesweeper.widget.MineMapWidget; + +public class MinesweeperApp extends AbstractApplication { + MineMapWidget mineField; + + public MinesweeperApp() { + super("minesweeper"); + } + + @Override + public AbstractApplication initApp() { + mineField = new MineMapWidget(20, 20, 30); + + return this; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java b/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java new file mode 100644 index 00000000000..bebfb5ec89b --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java @@ -0,0 +1,85 @@ +package gregtech.common.terminal.app.game.minesweeper.widget; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; + +public class MineMapWidget extends Widget { + + int mineCount; + int width; + int height; + boolean[][] mines; + boolean[][] flags; + boolean[][] checkedSpaces; + int[][] generatedNumbers; + + public MineMapWidget(int width, int height, int mineCount) { + super(333 / 2 - width * 8, 232 / 2 - height * 8, width * 16, height * 16); + this.width = width; + this.height = height; + mines = new boolean[width][height]; + generatedNumbers = new int[width][height]; + checkedSpaces = new boolean[width][height]; + flags = new boolean[width][height]; + + this.mineCount = mineCount; + } + + public void initMines(int startX, int startY) { + for(int minesPlaced = 0; minesPlaced < mineCount; minesPlaced++) { + int x = (int) (Math.random() * width); + int y = (int) (Math.random() * height); + + // The weird part to the right is making sure the player doesn't start on a numbered tile + while (!mines[x][y] && (startX < x + 2 && startX > x - 2) && (startY < y + 2 && startY > y - 2)) { + x = (int) (Math.random() * width); + y = (int) (Math.random() * height); + } + mines[x][y] = true; + + // Add to surrounding numbers for the mine + for(int i = -1; i < 2; i++) { + for (int j = -1; j < 2; j++) { + try { + generatedNumbers[x + i][y + j]++; + } catch (ArrayIndexOutOfBoundsException e) { + // Lol don't do anything this is expected + } + } + } + } + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + if (!checkedSpaces[i][j]) { + // Draw uncovered tile + } else if (!mines[i][j]) { + if (generatedNumbers[i][j] > 0) { + // Draw number + } else { + // Draw blank + } + } else { + // Draw mine + } + } + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + int gridX = mouseX / 16; + int gridY = mouseY / 16; + + if (button == 0 && !flags[gridX][gridY]) { + checkedSpaces[gridX][gridY] = true; + } else if (button == 1) { + flags[gridX][gridY] = !flags[gridX][gridY]; + } + + return false; + } +} diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/1.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d1739ff431f3ff835c252dcabfd391229ce359 GIT binary patch literal 5712 zcmeHLX;>528jcI1ETUL9LJ$jAU~%kVpj)tQNG2 zZ56EGR<~PR*jy-7K@eJ3YTehWs1&vCVr#AUOhAmcUVD9>+kf&rNoLNx-}`;%J@0pB zhTPcb39e2aP815oRT3E<2Y&mJpWfZUcm7f>mqO{$kS>!GaS997gd5eE4y6*aOeht# zVrmM-dUos7#I&0MF3(Q+AL*BG?L9xIZcD1hv|tW*NO11CRl6lo2g7<{iHYv?tfakDBh?RCGfi^{KgY zY2fhXu=>x(v>T(QkGOVF=6`RCmR4Gmz)c-dn71V=+>lt1>%V@p+v+I?D{pP|znED( zxzE_zWv#_SPUJ&Nltuei@93cyAB%0_Ef|rV@ttvC^5-YYgIf0=n1Af?^qoVIP$st@ zxBQX(w70UP{$4Lx_wM-{G5?kIE86!|{nonR#sSS?XsBY`uG+$i_}QKn@mB3By!r=Y z-agjY=5G(4S>5s&@^Sn0%Hi_!J~Pq_AXegI)A@Qnw z+|7xi>w;;a3w>8+H~&lJ1kb3Wm1SLRTpXw|)GRJDbqn_^@sC*A{bcp%?1dxuryWT$ zHb~!Vm^!S#t3#R6dwCCMw`!~~(6fL0vaDlrg%r!3dp$Fm8ywXYx`07PcbzUTzOm}rh{G%B)d@Fc zl)-g79f#~puI;IEcjN}FJ9HQ688Yo*=j*kbOt zt;nYyNEFLYvOIQUM(Eg$g>eUlMzA@Wq9do5KANZ zEXu2M&4OHdJYSLB-y^tERrJlZx+RWJol8Pb=P~n;Q_oz^EnnxcWSr`d`+a8Zgl;QO zMwetaE$AU<)+l$|MS<+b399Sga&0?8P1eG8JVk z6-CyM^V~l@en-HvzUurd`D+CU{RYnbGGI_$C>B`RmW=`6)$pZdSG{>jxWkDqcO?xKhoF*%n+-p$oSgGuY}xk{ z%O}o`7OIaq6ae)Yqu>oWaWe< zS4N&m8FA;=+qZ6CVsHI3lk&j;ykOrPY7K?rR)m2~T`r9hAVxhyp)x8_hE;C@?x0YF zAy$(DNkIv!64hV^5$#U(UK$lsiD*-Uq>$7UhHA0MbR3OOkCq|nDF|Oh3mNMqvQFr> z#0;2Ouiyzx{c?d`nGbp8FNJ_~UHq@0U+874#ipwu+=!%-NhRST8d4!HkajY$LHc1)(PRhHc?0L=XWu6~JzoUZFvmCWFRyfm|2? zm=2IuL3RgVwvB_?2*PkwK^SqF(Wn#A$l9nRrLC!`!p?RPL>UoVpbdPdMI&c?L9N6v51U^ghH)4WXm`y4w)wT@?6iA2sWk_Qh<4vZ2gm;q3~OY&CwzLV>nTyLeo zTY=xX>z!P0rNCQ(-?{7mCYRI8S8mh*p8G7|h5EDef0F-+?PH2eFjFWDAM(@9x*;SD z3_21Lso3#aACLF^`VXkkQNhqqLM$i3jC%5&iPHIOPPJf!mP$UzPo3L$FaSv<;p1ig zN0En*9-&l+QV4?9Z`w3q``p~Q;kDV5kNchKdE_Gen@hK0`I85vxo4hedD3lRFV2Jk u%~{ifmKBA6?5g!%*tj9$7?m#X)17kQt{Zbny?!1brbxum;oCx!v;PeNIblHn literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/2.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/2.png new file mode 100644 index 0000000000000000000000000000000000000000..11be18c5486b99589e7df66b8a59ad8a202dfdb9 GIT binary patch literal 5719 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/3.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/3.png new file mode 100644 index 0000000000000000000000000000000000000000..e66644946ca2e1c33948331ba3d97b347192a258 GIT binary patch literal 5748 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 MsR;1e;Te_oZ|XmBKmY&$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/6.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/6.png new file mode 100644 index 0000000000000000000000000000000000000000..9fcf0523d12978fe46bdeda38c067449b22eea4f GIT binary patch literal 5726 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/7.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/7.png new file mode 100644 index 0000000000000000000000000000000000000000..c0c3f740a9f984ac23eb8cf2ea6475ebedacc07c GIT binary patch literal 5683 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 Gq<;hAJz*38 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/8.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/8.png new file mode 100644 index 0000000000000000000000000000000000000000..38bf860d3412102c17ccc98c7e4df46d2426c249 GIT binary patch literal 5712 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/blank.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..6706f57bb614eafc39cb1442caeffafcdb5c5afd GIT binary patch literal 570 zcmV-A0>%A_P)EX>4Tx04R}tkv&MmKpe$iQ?)9U4rY+zkfAzR5EXHhDi*;)X)CnqU~=h)(4--0 zad8w}3l4rPRvlcNb#-tR1i=pwH#a9m7b)?7NufoI2gm(*ckglc4iFk;rdeI%fTmZ? zR6HhSb1PEd6@3UpL=QqTvy4P~Ap_6xbq^n3@1i`*``n*nK+RhW@JYn8%rL9O>%`NW zRfF?BvB*lYN_%a0@IUz7tyP$uaFc>Dp!>zPKSqGSF3_yo_V=-EH%|cnGjOH1{gnnV^GSNW ztwoN2&^B;!-PV*n;Bp5TdNO2Fb|gPdp-=$c&*+8FWQhbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b z03%66K~yNuWAyd)WgrExFfcHrr>7IIfr)`cFsflx!+>c30Br06KJ68JKmY&$07*qo IM6N<$g0Z0NjsO4v literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/bomb.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/bomb.png new file mode 100644 index 0000000000000000000000000000000000000000..11ee1f365805c9a3e2ea21de8dc1c197da811fab GIT binary patch literal 5838 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 J-5xMK^)Iw`rg#7V literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/covered.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/covered.png new file mode 100644 index 0000000000000000000000000000000000000000..2b2e5bc6ccca0e47a3305a341c8a2fa9b7ec07ae GIT binary patch literal 5699 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 I-^gYE0d@hQzyJUM literal 0 HcmV?d00001 From 454c484e369bc49b4fe5e0f5a9f3b459b95e30cb Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 27 Sep 2021 21:55:07 -0500 Subject: [PATCH 14/19] Complete basic Minesweeper game loop --- .../api/terminal/TerminalRegistry.java | 5 + .../app/game/minesweeper/MinesweeperApp.java | 19 +- .../minesweeper/widget/MineMapWidget.java | 170 ++++++++++++++---- .../app/game/pong/widget/BallWidget.java | 2 +- .../resources/assets/gregtech/lang/en_us.lang | 2 + 5 files changed, 157 insertions(+), 41 deletions(-) diff --git a/src/main/java/gregtech/api/terminal/TerminalRegistry.java b/src/main/java/gregtech/api/terminal/TerminalRegistry.java index 646d20f6137..d0c9a8d7f7f 100644 --- a/src/main/java/gregtech/api/terminal/TerminalRegistry.java +++ b/src/main/java/gregtech/api/terminal/TerminalRegistry.java @@ -11,6 +11,7 @@ import gregtech.common.items.MetaItems; import gregtech.common.terminal.app.ThemeSettingApp; import gregtech.common.terminal.app.game.maze.MazeApp; +import gregtech.common.terminal.app.game.minesweeper.MinesweeperApp; import gregtech.common.terminal.app.game.pong.PongApp; import gregtech.common.terminal.app.appstore.AppStoreApp; import gregtech.common.terminal.app.multiblockhelper.MultiBlockPreviewARApp; @@ -75,6 +76,10 @@ public static void init() { AppRegistryBuilder.create(new MazeApp()) .battery(GTValues.LV, 150) .build(); + AppRegistryBuilder.create(new MinesweeperApp()) + .battery(GTValues.LV, 150) + .build(); + AppRegistryBuilder.create(new OreProspectorApp()) .battery(GTValues.MV, 1000) .upgrade(MetaItems.COIN_DOGE.getStackForm(10)) diff --git a/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java b/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java index f7ab5e08058..62b9642005c 100644 --- a/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java @@ -1,10 +1,12 @@ package gregtech.common.terminal.app.game.minesweeper; +import gregtech.api.gui.widgets.SimpleTextWidget; import gregtech.api.terminal.app.AbstractApplication; import gregtech.common.terminal.app.game.minesweeper.widget.MineMapWidget; public class MinesweeperApp extends AbstractApplication { MineMapWidget mineField; + int timer; public MinesweeperApp() { super("minesweeper"); @@ -12,8 +14,21 @@ public MinesweeperApp() { @Override public AbstractApplication initApp() { - mineField = new MineMapWidget(20, 20, 30); - + mineField = new MineMapWidget(20, 14, 50); + this.addWidget(mineField); + //this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2, "", 0x00000000, () -> "")); return this; } + + @Override + public void updateScreen() { + super.updateScreen(); + if(mineField.hasWon() || mineField.hasLost()) { + mineField = new MineMapWidget(20, 14, 50); + } + } + + public String getFlagsPercentage() { + return "/" + mineField.mineCount; + } } diff --git a/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java b/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java index bebfb5ec89b..346cb0efa93 100644 --- a/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java @@ -2,16 +2,37 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.TextureArea; +import net.minecraft.util.ResourceLocation; public class MineMapWidget extends Widget { - int mineCount; - int width; - int height; - boolean[][] mines; - boolean[][] flags; - boolean[][] checkedSpaces; - int[][] generatedNumbers; + private static final TextureArea COVERED = new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/covered.png"), 0, 0, 1, 1); + private static final TextureArea FLAG = new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/flag.png"), 0, 0, 1, 1); + private static final TextureArea BOMB = new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/bomb.png"), 0, 0, 1, 1); + + private static final TextureArea[] NUMBERS = { + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/blank.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/1.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/2.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/3.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/4.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/5.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/6.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/7.png"), 0, 0, 1, 1), + new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/minesweeper/8.png"), 0, 0, 1, 1) + }; + + public int mineCount; + public int flagsPlaced; + private int width; + private int height; + private boolean isPrepared; + private boolean[][] mines; + private boolean[][] flags; + private boolean[][] checkedSpaces; + private int[][] generatedNumbers; + private boolean isLost = false; public MineMapWidget(int width, int height, int mineCount) { super(333 / 2 - width * 8, 232 / 2 - height * 8, width * 16, height * 16); @@ -26,28 +47,58 @@ public MineMapWidget(int width, int height, int mineCount) { } public void initMines(int startX, int startY) { - for(int minesPlaced = 0; minesPlaced < mineCount; minesPlaced++) { - int x = (int) (Math.random() * width); - int y = (int) (Math.random() * height); - - // The weird part to the right is making sure the player doesn't start on a numbered tile - while (!mines[x][y] && (startX < x + 2 && startX > x - 2) && (startY < y + 2 && startY > y - 2)) { - x = (int) (Math.random() * width); - y = (int) (Math.random() * height); + int minesPlaced = 0; + while (minesPlaced < mineCount) { + for (; minesPlaced < mineCount; minesPlaced++) { + placeMine(startX, startY); + } + + // Are there any sections that we can't figure out what's inside? + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + boolean isTrapped = true; + // The weird ternaries here are making sure to not cause overflows + for (int xMod = i == 0 ? 0 : -1; xMod < (i == width - 1 ? 1 : 2); xMod++) { + for (int yMod = j == 0 ? 0 : -1; yMod < (j == height - 1 ? 1 : 2); yMod++) { + isTrapped &= mines[i + xMod][j + yMod]; + } + } + if (isTrapped) { + // Yes, so just take out the middle + mines[i][j] = false; + minesPlaced--; + } + } } - mines[x][y] = true; - - // Add to surrounding numbers for the mine - for(int i = -1; i < 2; i++) { - for (int j = -1; j < 2; j++) { - try { - generatedNumbers[x + i][y + j]++; - } catch (ArrayIndexOutOfBoundsException e) { - // Lol don't do anything this is expected + } + + + // Add to surrounding numbers for the mine + // The weird ternaries here are making sure to not cause overflows + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + if(mines[x][y]) { + for (int xMod = x == 0 ? 0 : -1; xMod < (x == width - 1 ? 1 : 2); xMod++) { + for (int yMod = y == 0 ? 0 : -1; yMod < (y == height - 1 ? 1 : 2); yMod++) { + generatedNumbers[x + xMod][y + yMod]++; + } } } } } + isPrepared = true; + } + + private void placeMine(int startX, int startY) { + int x = (int) (Math.random() * width); + int y = (int) (Math.random() * height); + + // The weird part to the right is making sure the player doesn't start on a numbered tile + while (!mines[x][y] && (startX < x + 3 && startX > x - 3) && (startY < y + 3 && startY > y - 3)) { + x = (int) (Math.random() * width); + y = (int) (Math.random() * height); + } + mines[x][y] = true; } @Override @@ -55,31 +106,74 @@ public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRender for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (!checkedSpaces[i][j]) { - // Draw uncovered tile - } else if (!mines[i][j]) { - if (generatedNumbers[i][j] > 0) { - // Draw number - } else { - // Draw blank - } - } else { - // Draw mine - } + if (flags[i][j]) + FLAG.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); + else + COVERED.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); + } else if (!mines[i][j]) + NUMBERS[generatedNumbers[i][j]].draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); + else + BOMB.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); } } } @Override public boolean mouseClicked(int mouseX, int mouseY, int button) { - int gridX = mouseX / 16; - int gridY = mouseY / 16; + int gridX = (mouseX - getPosition().getX()) / 16; + int gridY = (mouseY - getPosition().getY()) / 16; + if (gridX >= width || gridY >= height) { + return false; + } + if (button == 0 && !flags[gridX][gridY]) { - checkedSpaces[gridX][gridY] = true; + if (!isPrepared) + initMines(gridX, gridY); + if (generatedNumbers[gridX][gridY] == 0) + uncoverSafeTiles(gridX, gridY); + else + checkedSpaces[gridX][gridY] = true; + if (mines[gridX][gridY]) + isLost = true; } else if (button == 1) { flags[gridX][gridY] = !flags[gridX][gridY]; + if (flags[gridX][gridY]) + flagsPlaced++; + else + flagsPlaced--; + } + + return true; + } + + private void uncoverSafeTiles(int x, int y) { + checkedSpaces[x][y] = true; + if(generatedNumbers[x][y] != 0) + return; + // Weird ternaries again for preventing ArrayIndexOutOfBounds exceptions + for (int xMod = x == 0 ? 0 : -1; xMod < (x == width - 1 ? 1 : 2); xMod++) { + for (int yMod = y == 0 ? 0 : -1; yMod < (y == height - 1 ? 1 : 2); yMod++) { + if (!checkedSpaces[x + xMod][y + yMod]) + uncoverSafeTiles(x + xMod, y + yMod); + } } + } - return false; + public boolean hasLost() { + return isLost; + } + + public boolean hasWon() { + if (!isPrepared || mines != flags) + return false; + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + if (checkedSpaces[i][j] == mines[i][j]) { // If there is an unchecked safe square, or an uncovered bomb... + return false; + } + } + } + return true; } } diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java index c88ac834cb4..b4e9b63e9e2 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/widget/BallWidget.java @@ -12,7 +12,7 @@ public class BallWidget extends ImageWidget { private double yAccurate; public BallWidget(int xPosition, int yPosition) { - super(xPosition, yPosition, 8, 8, new TextureArea(new ResourceLocation("gregtech:textures/gui/widget/pong_ball.png"), 0, 0, 8, 8)); + super(xPosition, yPosition, 8, 8, new TextureArea(new ResourceLocation("gregtech:textures/gui/widget/pong_ball.png"), 0, 0, 1, 1)); theta = (Math.random() > 0.5 ? Math.PI : Math.PI / 2) + Math.random() * 0.2; xAccurate = xPosition; yAccurate = yPosition; diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 097c6150e1a..a29d75007d3 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -3956,6 +3956,7 @@ gregtech.terminal.app_name.guide_editor=Guide Editor gregtech.terminal.app_name.recipe_chart=Recipe Chart gregtech.terminal.app_name.ore_prospector=Ore Prospector gregtech.terminal.app_name.pong=Pong +gregtech.terminal.app_name.minesweeper=Minesweeper gregtech.terminal.app_name.maze=Theseus's Escape @@ -3973,6 +3974,7 @@ terminal.machines.description=A guide book about gt machines. terminal.multiblocks.description=A guide book about multi-blocks. terminal.tutorials.description=Introduces all kinds of things, CT integration, tips, tutorials and more. terminal.pong.description=A classic pong game, if you're really that bored of waiting for that tungstensteel. +terminal.minesweeper.description=A classic minesweeper game, if you're in class. terminal.maze.description=A GTOS exclusive game finding you racing through an endless labyrinth to survive the Minotaur! texture.modify_gui_texture.missing=Missing Texture From a79cd38fb9507dfe287d5cfa247d30dc30db4ab2 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 2 Oct 2021 10:43:22 -0500 Subject: [PATCH 15/19] Prepare Minesweeper for testing --- .../api/gui/widgets/SimpleTextWidget.java | 2 +- .../api/util/interpolate/RGBInterpolator.java | 50 ++++++++++++++++ .../app/game/minesweeper/MinesweeperApp.java | 37 ++++++++++-- .../minesweeper/widget/MineMapWidget.java | 56 ++++++++++++++---- .../gui/terminal/minesweeper/icon.png | Bin 0 -> 6023 bytes 5 files changed, 128 insertions(+), 17 deletions(-) create mode 100644 src/main/java/gregtech/api/util/interpolate/RGBInterpolator.java create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/icon.png diff --git a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java index 49435bb121d..f6ca61c1188 100644 --- a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java @@ -105,7 +105,7 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { int height = fontRenderer.FONT_HEIGHT * texts.size(); for (int i = 0; i < texts.size(); i++) { String resultText = texts.get(i); - int width = fontRenderer.getStringWidth(resultText);; + int width = fontRenderer.getStringWidth(resultText); float x = pos.x - (isCentered ? width / 2f : 0); float y = pos.y - (isCentered ? height / 2f : 0) + i * fontRenderer.FONT_HEIGHT; fontRenderer.drawString(resultText, x, y, color, false); diff --git a/src/main/java/gregtech/api/util/interpolate/RGBInterpolator.java b/src/main/java/gregtech/api/util/interpolate/RGBInterpolator.java new file mode 100644 index 00000000000..d12a86c8dfc --- /dev/null +++ b/src/main/java/gregtech/api/util/interpolate/RGBInterpolator.java @@ -0,0 +1,50 @@ +package gregtech.api.util.interpolate; + +import gregtech.api.util.function.TriConsumer; +import net.minecraft.util.ITickable; + +public class RGBInterpolator implements ITickable { + private final int speed; + private float r = 255; + private float g = 0; + private float b = 0; + private final TriConsumer interpolate; + private final TriConsumer callback; + private boolean isOn = false; + + public RGBInterpolator(int speed, TriConsumer interpolate, TriConsumer callback) { + this.speed = speed; + this.interpolate = interpolate; + this.callback = callback; + } + + @Override + public void update() { + if (isOn) { + if (r == 255 && g < 255) { + b -= Math.min(speed, b); + g += Math.min(speed, 255 - g); + } else if (g == 255 && b < 255) { + r -= Math.min(speed, r); + b += Math.min(speed, 255 - b); + } else if (b == 255 && r < 255) { + g -= Math.min(speed, g); + r += Math.min(speed, 255 - r); + } + interpolate.accept(r / 255, g / 255, b / 255); + } + } + + public void stop() { + callback.accept(r, g, b); + isOn = false; + } + + public void start() { + isOn = true; + } + + public boolean isActivated() { + return isOn; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java b/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java index 62b9642005c..a5866a4a969 100644 --- a/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/minesweeper/MinesweeperApp.java @@ -5,8 +5,9 @@ import gregtech.common.terminal.app.game.minesweeper.widget.MineMapWidget; public class MinesweeperApp extends AbstractApplication { - MineMapWidget mineField; - int timer; + private MineMapWidget mineField; + private int timer; + private int resetCountdown = 100; public MinesweeperApp() { super("minesweeper"); @@ -14,9 +15,11 @@ public MinesweeperApp() { @Override public AbstractApplication initApp() { - mineField = new MineMapWidget(20, 14, 50); + mineField = new MineMapWidget(20, 12, 40); this.addWidget(mineField); - //this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2, "", 0x00000000, () -> "")); + this.addWidget(new SimpleTextWidget(333 / 6, 10, "", 0xFFCCCCCC, this::getFlagsPercentage, true)); + this.addWidget(new SimpleTextWidget(333 / 8 * 5, 10, "", 0xFFCCCCCC, this::getStatus, true)); + return this; } @@ -24,11 +27,33 @@ public AbstractApplication initApp() { public void updateScreen() { super.updateScreen(); if(mineField.hasWon() || mineField.hasLost()) { - mineField = new MineMapWidget(20, 14, 50); + if(mineField.hasWon()) { + mineField.notifyWon(); + } + resetCountdown--; + } else + timer++; + if (resetCountdown == 0) { + mineField.resetData(); + resetCountdown = 100; + timer = 0; } } public String getFlagsPercentage() { - return "/" + mineField.mineCount; + return mineField.flagsPlaced + "/" + mineField.mineCount; + } + + public String getStatus() { + return resetCountdown == 100 ? + (timer / 20) + " seconds elapsed" : // Normal + mineField.hasLost() ? + "You lost. Game will restart in " + resetCountdown / 20 + " seconds." : // Losing condition + "You won in " + (timer / 20) + " seconds! Game will restart in " + resetCountdown / 20; // Winning condition + } + + @Override + public boolean isClientSideApp() { + return true; } } diff --git a/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java b/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java index 346cb0efa93..ec3ad0f73fa 100644 --- a/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java +++ b/src/main/java/gregtech/common/terminal/app/game/minesweeper/widget/MineMapWidget.java @@ -3,6 +3,8 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; import gregtech.api.gui.resources.TextureArea; +import gregtech.api.util.interpolate.RGBInterpolator; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; public class MineMapWidget extends Widget { @@ -25,25 +27,41 @@ public class MineMapWidget extends Widget { public int mineCount; public int flagsPlaced; + private int width; private int height; + private boolean isPrepared; + private boolean[][] mines; private boolean[][] flags; private boolean[][] checkedSpaces; private int[][] generatedNumbers; - private boolean isLost = false; + + private boolean isLost; + private boolean isWon; + private int timer = 0; + private static final RGBInterpolator interpolator = new RGBInterpolator(5, + (r, g, b) -> GlStateManager.color(r.floatValue(), g.floatValue(), b.floatValue()), + (r, g, b) -> GlStateManager.color(0, 0, 0)); public MineMapWidget(int width, int height, int mineCount) { super(333 / 2 - width * 8, 232 / 2 - height * 8, width * 16, height * 16); this.width = width; this.height = height; + this.resetData(); + this.mineCount = mineCount; + } + + public void resetData() { mines = new boolean[width][height]; generatedNumbers = new int[width][height]; checkedSpaces = new boolean[width][height]; flags = new boolean[width][height]; - - this.mineCount = mineCount; + isLost = false; + isWon = false; + isPrepared = false; + flagsPlaced = 0; } public void initMines(int startX, int startY) { @@ -94,7 +112,7 @@ private void placeMine(int startX, int startY) { int y = (int) (Math.random() * height); // The weird part to the right is making sure the player doesn't start on a numbered tile - while (!mines[x][y] && (startX < x + 3 && startX > x - 3) && (startY < y + 3 && startY > y - 3)) { + while (mines[x][y] || ((startX < x + 3 && startX > x - 3) && (startY < y + 3 && startY > y - 3))) { x = (int) (Math.random() * width); y = (int) (Math.random() * height); } @@ -103,15 +121,25 @@ private void placeMine(int startX, int startY) { @Override public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + timer++; + if (isWon && !interpolator.isActivated()) { // Fancy colors :) + interpolator.start(); + } + if (!isWon && interpolator.isActivated()) { + interpolator.stop(); + } + interpolator.update(); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - if (!checkedSpaces[i][j]) { + if (isLost && mines[i][j]) // If the player lost, show where the mines are. + BOMB.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); + else if (!checkedSpaces[i][j]) { if (flags[i][j]) FLAG.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); else COVERED.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); } else if (!mines[i][j]) - NUMBERS[generatedNumbers[i][j]].draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); + NUMBERS[generatedNumbers[i][j]].draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); else BOMB.draw(i * 16 + getPosition().getX(), j * 16 + getPosition().getY(), 16, 16); } @@ -120,9 +148,13 @@ public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRender @Override public boolean mouseClicked(int mouseX, int mouseY, int button) { + if(isWon || isLost) { + return false; // Don't let them interact now... + } + int gridX = (mouseX - getPosition().getX()) / 16; int gridY = (mouseY - getPosition().getY()) / 16; - if (gridX >= width || gridY >= height) { + if (gridX >= width || gridY >= height || gridX < 0 || gridY < 0) { return false; } @@ -136,7 +168,7 @@ public boolean mouseClicked(int mouseX, int mouseY, int button) { checkedSpaces[gridX][gridY] = true; if (mines[gridX][gridY]) isLost = true; - } else if (button == 1) { + } else if (button == 1 && !checkedSpaces[gridX][gridY]) { flags[gridX][gridY] = !flags[gridX][gridY]; if (flags[gridX][gridY]) flagsPlaced++; @@ -165,15 +197,19 @@ public boolean hasLost() { } public boolean hasWon() { - if (!isPrepared || mines != flags) + if (!isPrepared) return false; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - if (checkedSpaces[i][j] == mines[i][j]) { // If there is an unchecked safe square, or an uncovered bomb... + if (mines[i][j] != flags[i][j] || checkedSpaces[i][j] == mines[i][j]) { // If there is an unchecked safe square, or an uncovered bomb... return false; } } } return true; } + + public void notifyWon() { + isWon = true; + } } diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/icon.png b/src/main/resources/assets/gregtech/textures/gui/terminal/minesweeper/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec035c5919eedfbaa31c5fd472981b4565bf617 GIT binary patch literal 6023 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 literal 0 HcmV?d00001 From c5f9e7b773017810c3ff6763cdb21a99ef3974b5 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 2 Oct 2021 21:46:21 -0500 Subject: [PATCH 16/19] Fix descriptions --- src/main/resources/assets/gregtech/lang/en_us.lang | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index a29d75007d3..c2a599159c4 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -821,7 +821,6 @@ metaitem.tool.screwdriver.name=%s Screwdriver metaitem.tool.screwdriver.tooltip=Adjusts Covers and Machines metaitem.tool.mortar.name=%s Mortar metaitem.tool.wire_cutter.name=%s Wire Cutter -metaitem.tool.scoop.name=%s Scoop metaitem.tool.branch_cutter.name=%s Branch Cutter metaitem.tool.universal_spade.name=%s Universal Spade metaitem.tool.knife.name=%s Knife @@ -1411,6 +1410,7 @@ material.pyrite=Pyrite material.pyrolusite=Pyrolusite material.pyrope=Pyrope material.rock_salt=Rock Salt +material.ruthenian_iridium=Ruthenian Iridium material.rubber=Rubber material.raw_rubber=Raw Rubber material.ruby=Ruby @@ -1699,7 +1699,6 @@ material.diamericium_titanium=Diamericium Titanium material.fluxed_electrum=Fluxed Electrum material.milk=Milk -material.honey=Honey material.cocoa=Cocoa material.wheat=Wheat material.meat=Mince Meat @@ -3506,7 +3505,6 @@ gregtech.advancement.ultimate_voltage.80_diamericium_titanium_coil.name=The Fina gregtech.advancement.ultimate_voltage.80_diamericium_titanium_coil.desc=Craft a Diamericium Titanium Heating Coil. -behaviour.scoop=Catches Butterflies on Leftclick behaviour.softhammer=Activates and Deactivates Machines behaviour.wrench=Rotates Blocks on Rightclick behaviour.boor.by=by %s @@ -3868,6 +3866,7 @@ gregtech.multiblock.preview.location.t_c=Top Center gregtech.multiblock.preview.primitive_pump.hatch=Only Pump Hatch, ULV Hatch, or LV Hatch allowed gregtech.multiblock.preview.location_end=Very End gregtech.multiblock.preview.distillation_multi_fluid=Quadruple/Nonuple Output Hatches not allowed +gregtech.multiblock.preview.clear_amount=Must have a clear %dx%dx%d space in front gregtech.multiblock.blast_furnace.max_temperature=Max Temperature: %sK gregtech.multiblock.multi_furnace.heating_coil_level=Heating Coil Level: %s From 4495167f1a532c70323a68af47c4aa9ad005d49b Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 3 Oct 2021 11:05:00 -0500 Subject: [PATCH 17/19] Github is stupid --- build.gradle.kts | 4 ---- build.properties | 1 - 2 files changed, 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a75ebbd1565..9efc23c8030 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,7 +43,6 @@ val mcFullVersion = "$mcVersion-${config["forge.version"]}" val shortVersion = mcVersion.substring(0, mcVersion.lastIndexOf(".")) val strippedVersion = shortVersion.replace(".", "") + "0" -val forestryVersion = config["forestry.version"] as String val chickenasmVersion = config["chickenasm.version"] as String val cclVersion = config["ccl.version"] as String val crafttweakerVersion = config["crafttweaker.version"] as String @@ -107,9 +106,6 @@ repositories { } dependencies { - "deobfProvided"("net.sengir.forestry:forestry_$mcVersion:$forestryVersion") { - isTransitive = false - } "deobfCompile"("codechicken:ChickenASM:$shortVersion-$chickenasmVersion") "deobfCompile"("codechicken-lib-1-8:CodeChickenLib-$mcVersion:$cclVersion:universal") "deobfCompile"("CraftTweaker2:CraftTweaker2-MC$strippedVersion-Main:$crafttweakerVersion") diff --git a/build.properties b/build.properties index 42f1bd85376..35e5a68c29a 100644 --- a/build.properties +++ b/build.properties @@ -2,7 +2,6 @@ minecraft.version=1.12.2 forge.version=14.23.5.2847 ccl.version=3.2.3.358 chickenasm.version=1.0.2.9 -forestry.version=5.8.2.387 jei.version=4.16.1.302 crafttweaker.version=1.12-4.1.20.655 top.version=1.4.28-17 From ca77160255081ad4298cfe6f5b4c98c4f25ef904 Mon Sep 17 00:00:00 2001 From: Yefancy Date: Mon, 4 Oct 2021 20:48:53 +0800 Subject: [PATCH 18/19] FSM --- src/main/java/gregtech/api/gui/Widget.java | 12 +-- .../terminal/app/game/maze/MazeApp.java | 91 ++++++++++++------- 2 files changed, 58 insertions(+), 45 deletions(-) diff --git a/src/main/java/gregtech/api/gui/Widget.java b/src/main/java/gregtech/api/gui/Widget.java index c488f27d343..d95afce09fd 100644 --- a/src/main/java/gregtech/api/gui/Widget.java +++ b/src/main/java/gregtech/api/gui/Widget.java @@ -28,11 +28,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.function.BooleanSupplier; import java.util.function.Consumer; -import java.util.function.Supplier; - -import org.lwjgl.opengl.GL11; /** * Widget is functional element of ModularUI @@ -49,7 +45,6 @@ public abstract class Widget { private transient Position position; private transient Size size; private transient boolean isVisible; - private transient BooleanSupplier visibilitySupplier; private transient boolean isActive; public Widget(Position selfPosition, Size size) { @@ -115,18 +110,13 @@ public final Size getSize() { } public boolean isVisible() { - return visibilitySupplier != null ? visibilitySupplier.getAsBoolean() : isVisible; + return isVisible; } public void setVisible(boolean visible) { isVisible = visible; } - public Widget setVisibilitySupplier(BooleanSupplier supplier) { - visibilitySupplier = supplier; - return this; - } - public boolean isActive() { return isActive; } diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index 1bca81d590f..6327830e283 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -1,26 +1,25 @@ package gregtech.common.terminal.app.game.maze; +import gregtech.api.gui.Widget; import gregtech.api.gui.resources.ColorRectTexture; -import gregtech.api.gui.resources.TextureArea; import gregtech.api.gui.widgets.ClickButtonWidget; import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.gui.widgets.LabelWidget; import gregtech.api.gui.widgets.SimpleTextWidget; import gregtech.api.terminal.app.AbstractApplication; -import gregtech.api.terminal.os.TerminalOSWidget; import gregtech.api.terminal.os.TerminalTheme; import gregtech.common.terminal.app.game.maze.widget.EnemyWidget; import gregtech.common.terminal.app.game.maze.widget.MazeWidget; import gregtech.common.terminal.app.game.maze.widget.PlayerWidget; -import net.minecraft.nbt.NBTTagCompound; import org.lwjgl.input.Keyboard; -import scala.swing.event.Key; import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; import java.util.List; public class MazeApp extends AbstractApplication { - private int gamestate = 0; + private int gameState = 0; private PlayerWidget player; private EnemyWidget enemy; private MazeWidget maze; @@ -29,61 +28,76 @@ public class MazeApp extends AbstractApplication { private float speed = 25; private int lastPlayerInput = -2; public static int MAZE_SIZE = 9; - private List movementStore = new ArrayList<>(); + private List movementStore; private boolean lastPausePress; + private List[] FSM; + public MazeApp() { super("maze"); } public AbstractApplication initApp() { if (isClient) { + movementStore = new ArrayList<>(); + FSM = new List[4]; + FSM[0] = new LinkedList<>(); + FSM[1] = new LinkedList<>(); + FSM[2] = new LinkedList<>(); + FSM[3] = new LinkedList<>(); this.setOs(os); this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); - // Gamestate 0: Title - this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Theseus's Escape", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> this.getGamestate() == 0)); + // enemy 0: Title + this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Theseus's Escape", 0xFFFFFFFF), 0); this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 30, 30, "Play", (clickData -> { - this.setGamestate(1); + this.setGameState(1); this.resetGame(); - })) - .setShouldClientCallback(true).setVisibilitySupplier(() -> this.getGamestate() == 0)); + })).setShouldClientCallback(true), 0); // Gamestate 1: Play - this.setMaze((MazeWidget) new MazeWidget().setVisibilitySupplier(() -> this.getGamestate() >= 1)); - this.setPlayer((PlayerWidget) new PlayerWidget(0, 0, this).setVisibilitySupplier(() -> this.getGamestate() >= 1)); - this.setEnemy((EnemyWidget) new EnemyWidget(-100, -100, this).setVisibilitySupplier(() -> this.getGamestate() >= 1)); + this.setMaze(new MazeWidget()); + this.setPlayer(new PlayerWidget(0, 0, this)); + this.setEnemy(new EnemyWidget(-100, -100, this)); // Gamestate 2: Pause - this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0xFF000000)).setVisibilitySupplier(() -> this.getGamestate() > 1)); - this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 50, 20, "Continue", (clickData) -> this.setGamestate(1)).setVisibilitySupplier(() -> this.getGamestate() == 2)); - this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Game Paused", 0xFFFFFFFF).setXCentered(true).setVisibilitySupplier(() -> this.getGamestate() == 2)); + this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0xFF000000)), 2, 3); + this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 50, 20, "Continue", (clickData) -> this.setGameState(1)).setShouldClientCallback(true), 2); + this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Game Paused", 0xFFFFFFFF).setXCentered(true), 2); // Gamestate 3: Death - this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true).setVisibilitySupplier(() -> this.getGamestate() == 3)); - this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + this.getMazesSolved() + " mazes before losing.", true).setVisibilitySupplier(() -> this.getGamestate() == 3)); - this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true).setVisibilitySupplier(() -> this.getGamestate() == 3)); + this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true), 3); + this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + this.getMazesSolved() + " mazes before losing.", true), 3); + this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true), 3); this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 + 10, 40, 20, "Retry", (clickData -> { - this.setGamestate(1); + this.setGameState(1); this.setMazesSolved(0); MAZE_SIZE = 9; speed = 25; this.resetGame(); - })).setShouldClientCallback(true).setVisibilitySupplier(() -> this.getGamestate() == 3)); + })).setShouldClientCallback(true), 3); } return this; } + public void addWidget(Widget widget, int... visibleStates) { + this.addWidget(widget); + for (int state : visibleStates) { + FSM[state].add(widget); + } + widget.setVisible(Arrays.stream(visibleStates).allMatch(state->state==gameState)); + } + public void setPlayer(PlayerWidget player) { this.player = player; - this.addWidget(player); + this.addWidget(player, 1, 2, 3); } public void setMaze(MazeWidget maze) { this.maze = maze; - this.addWidget(maze); + this.addWidget(maze, 1, 2, 3); } public void setEnemy(EnemyWidget enemy) { this.enemy = enemy; - this.addWidget(enemy); + this.addWidget(enemy, 1, 2, 3); } @Override @@ -94,9 +108,10 @@ public boolean isClientSideApp() { @Override public void updateScreen() { super.updateScreen(); - if (gamestate == 1) { + int lastState = gameState; + if (gameState == 1) { if (Keyboard.isKeyDown(Keyboard.KEY_P)) { - gamestate = 2; + gameState = 2; lastPausePress = true; } if (Keyboard.isKeyDown(Keyboard.KEY_LEFT) ^ Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) { @@ -118,23 +133,31 @@ public void updateScreen() { moveEnemy(); } if (enemy.posX == player.posX && enemy.posY == player.posY) { - gamestate = 3; + gameState = 3; } } - if (gamestate == 2) { + if (gameState == 2) { if(!Keyboard.isKeyDown(Keyboard.KEY_P)) lastPausePress = false; if(Keyboard.isKeyDown(Keyboard.KEY_P) && !lastPausePress) - gamestate = 1; + gameState = 1; + } + if (gameState != lastState) { + FSM[lastState].forEach(widget -> widget.setVisible(false)); + FSM[gameState].forEach(widget -> widget.setVisible(true)); } } - public int getGamestate() { - return gamestate; + public int getGameState() { + return gameState; } - public void setGamestate(int gamestate) { - this.gamestate = gamestate; + public void setGameState(int gameState) { + if (gameState != this.gameState) { + FSM[this.gameState].forEach(widget -> widget.setVisible(false)); + FSM[gameState].forEach(widget -> widget.setVisible(true)); + } + this.gameState = gameState; } public int getRenderX(int posX) { From 08a8df9c0b9666f4fa55ac067e8362fefef7eab7 Mon Sep 17 00:00:00 2001 From: Yefancy Date: Mon, 4 Oct 2021 20:53:09 +0800 Subject: [PATCH 19/19] remove unused field --- .../gregtech/common/terminal/app/game/maze/MazeApp.java | 6 +++--- .../gregtech/common/terminal/app/game/pong/PongApp.java | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java index 6327830e283..944cd6c527f 100644 --- a/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/maze/MazeApp.java @@ -54,15 +54,15 @@ public AbstractApplication initApp() { this.setGameState(1); this.resetGame(); })).setShouldClientCallback(true), 0); - // Gamestate 1: Play + // GameState 1: Play this.setMaze(new MazeWidget()); this.setPlayer(new PlayerWidget(0, 0, this)); this.setEnemy(new EnemyWidget(-100, -100, this)); - // Gamestate 2: Pause + // GameState 2: Pause this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, new ColorRectTexture(0xFF000000)), 2, 3); this.addWidget(new ClickButtonWidget(323 / 2 - 10, 222 / 2 - 10, 50, 20, "Continue", (clickData) -> this.setGameState(1)).setShouldClientCallback(true), 2); this.addWidget(new LabelWidget(333 / 2, 222 / 2 - 50, "Game Paused", 0xFFFFFFFF).setXCentered(true), 2); - // Gamestate 3: Death + // GameState 3: Death this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 40, "", 0xFFFFFFFF, () -> "Oh no! You were eaten by the Minotaur!", true), 3); this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 28, "", 0xFFFFFFFF, () -> "You got through " + this.getMazesSolved() + " mazes before losing.", true), 3); this.addWidget(new SimpleTextWidget(333 / 2, 232 / 2 - 16, "", 0xFFFFFFFF, () -> "Try again?", true), 3); diff --git a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java index 8659e7aac2c..92c635bb194 100644 --- a/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java +++ b/src/main/java/gregtech/common/terminal/app/game/pong/PongApp.java @@ -21,13 +21,12 @@ public class PongApp extends AbstractApplication { - public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/pong/icon.png"); private BallWidget ball; private int leftScore; private int rightScore; - private List paddles = new ArrayList<>(); - private List solidObjects = new ArrayList<>(); + private List paddles; + private List solidObjects; private int userInput = -1; private int timer = 0; @@ -38,6 +37,8 @@ public PongApp() { @Override public AbstractApplication initApp() { if(isClient) { + paddles = new ArrayList<>(); + solidObjects = new ArrayList<>(); this.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); this.addWidget(new ImageWidget(333 / 2 - 4, 5, 6, 232 - 10, new ColorRectTexture(0xAAAAAAAA))); this.setBall(new BallWidget(333 / 2 - 1, 232 / 2 - 1));