You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
607 lines
15 KiB
607 lines
15 KiB
package net.tortuga.gui.panels;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
import net.tortuga.fonts.Fonts;
|
|
import net.tortuga.gui.screens.ScreenGame;
|
|
import net.tortuga.gui.screens.ScreenMenuMain;
|
|
import net.tortuga.gui.widgets.ETheme;
|
|
import net.tortuga.gui.widgets.IWidgetFactory;
|
|
import net.tortuga.gui.widgets.Theme;
|
|
import net.tortuga.gui.widgets.Widget;
|
|
import net.tortuga.gui.widgets.composite.*;
|
|
import net.tortuga.gui.widgets.display.Text;
|
|
import net.tortuga.gui.widgets.input.Button;
|
|
import net.tortuga.gui.widgets.input.ButtonIcon;
|
|
import net.tortuga.gui.widgets.layout.FullWidthLayout;
|
|
import net.tortuga.gui.widgets.layout.LayoutH;
|
|
import net.tortuga.gui.widgets.layout.LayoutV;
|
|
import net.tortuga.gui.widgets.layout.frame.FrameBelt;
|
|
import net.tortuga.gui.widgets.layout.frame.FrameBottom;
|
|
import net.tortuga.gui.widgets.layout.frame.FrameTop;
|
|
import net.tortuga.level.LevelBundle;
|
|
import net.tortuga.level.program.GrainRegistry;
|
|
import net.tortuga.level.program.StoneRegistry;
|
|
import net.tortuga.level.program.tiles.ProgTileGrain;
|
|
import net.tortuga.level.program.tiles.ProgTileStone;
|
|
import net.tortuga.level.program.tiles.grains.GrainJumpLabel;
|
|
import net.tortuga.level.program.tiles.grains.GrainNumber;
|
|
import net.tortuga.level.program.tiles.grains.GrainVariable;
|
|
import net.tortuga.level.program.tiles.stones.StoneLabel;
|
|
import net.tortuga.textures.Tx;
|
|
import net.tortuga.util.Align;
|
|
|
|
import org.lwjgl.input.Keyboard;
|
|
import org.lwjgl.input.Mouse;
|
|
|
|
import com.porcupine.color.RGB;
|
|
import com.porcupine.coord.Coord;
|
|
import com.porcupine.math.Calc;
|
|
|
|
|
|
/**
|
|
* Game panel
|
|
*
|
|
* @author Ondřej Hruška (MightyPork)
|
|
*/
|
|
public class PanelGame extends PanelGui {
|
|
|
|
@SuppressWarnings("unused")
|
|
private static final int PG_INFO = 0, PG_PROG = 1, PG_MAP = 2;
|
|
|
|
private static final int id_BACK = 0, id_RUN = 1, id_PROGRAM = 2, id_TURTLE = 3;
|
|
|
|
private static final int SHOP_ROW = 12;
|
|
public static final int LOW_PANEL_SIZE = 60;
|
|
public static final int TOP_PANEL_SIZE = 60;
|
|
|
|
/** Game GUI page: 0 = info, 1 = program, 2 = turtle map */
|
|
private int page = PG_PROG;
|
|
|
|
private Button bnProg;
|
|
|
|
private Button bnTurtle;
|
|
|
|
private static BeltCellFactory beltCellFactory = new BeltCellFactory();
|
|
private List<Widget> beltCells = new ArrayList<Widget>();
|
|
|
|
private static LowerShopSlotFactory stoneShopSlotFactory = new LowerShopSlotFactory();
|
|
private List<Widget> stoneShopSlots = new ArrayList<Widget>();
|
|
|
|
private static LowerShopRowFactory lowerShopRowFactory = new LowerShopRowFactory();
|
|
private List<Widget> lowerShopRows = new ArrayList<Widget>();
|
|
|
|
private static UpperShopSlotFactory grainShopSlotFactory = new UpperShopSlotFactory();
|
|
private List<Widget> grainShopSlots = new ArrayList<Widget>();
|
|
|
|
private static UpperShopRowFactory upperShopRowFactory = new UpperShopRowFactory();
|
|
private List<Widget> upperShopRows = new ArrayList<Widget>();
|
|
|
|
// the whole programming layout
|
|
private LayoutV programmingLayout;
|
|
private LayoutV ingameLayout;
|
|
|
|
// lower shop box
|
|
private CompositeScrollBoxV lowerShopBox;
|
|
// upper shop box
|
|
private CompositeScrollBoxV upperShopBox;
|
|
|
|
// belt frame
|
|
private FrameBelt beltFrame;
|
|
|
|
// belt box
|
|
private CompositeScrollBoxH beltBox;
|
|
|
|
private FullWidthLayout beltLayout;
|
|
|
|
private DragDropServer dndServer;
|
|
|
|
private LevelBundle bundle;
|
|
|
|
/** Screen as ScreenGame */
|
|
private ScreenGame screenGame;
|
|
|
|
private static class BeltCellFactory implements IWidgetFactory {
|
|
|
|
@Override
|
|
public Widget getWidget()
|
|
{
|
|
return new PgmBeltCell();
|
|
}
|
|
|
|
|
|
public Widget getWidget(int i)
|
|
{
|
|
return new PgmBeltCell(i);
|
|
}
|
|
|
|
}
|
|
|
|
private static class LowerShopSlotFactory implements IWidgetFactory {
|
|
|
|
@Override
|
|
public Widget getWidget()
|
|
{
|
|
return new PgmShopSquare();
|
|
}
|
|
|
|
|
|
public Widget getWidget(ProgTileStone stone)
|
|
{
|
|
return new PgmShopSquare(stone);
|
|
}
|
|
}
|
|
|
|
private static class UpperShopSlotFactory implements IWidgetFactory {
|
|
|
|
@Override
|
|
public Widget getWidget()
|
|
{
|
|
return new PgmShopHexagon();
|
|
}
|
|
|
|
|
|
public Widget getWidget(ProgTileGrain stone)
|
|
{
|
|
return new PgmShopHexagon(stone);
|
|
}
|
|
}
|
|
|
|
private static class LowerShopRowFactory implements IWidgetFactory {
|
|
|
|
@Override
|
|
public LayoutH getWidget()
|
|
{
|
|
return getWidget(SHOP_ROW);
|
|
}
|
|
|
|
|
|
private LayoutH getWidget(int inRow)
|
|
{
|
|
LayoutH lh = new LayoutH();
|
|
for (int j = 0; j < inRow; j++) {
|
|
lh.add(stoneShopSlotFactory.getWidget());
|
|
}
|
|
|
|
return lh;
|
|
}
|
|
|
|
|
|
private LayoutH getWidget(List<Widget> childs)
|
|
{
|
|
LayoutH lh = new LayoutH();
|
|
|
|
for (Widget w : childs) {
|
|
lh.add(w);
|
|
}
|
|
|
|
return lh;
|
|
}
|
|
}
|
|
|
|
private static class UpperShopRowFactory implements IWidgetFactory {
|
|
|
|
@Override
|
|
public LayoutH getWidget()
|
|
{
|
|
return getWidget(SHOP_ROW);
|
|
}
|
|
|
|
|
|
private LayoutH getWidget(int inRow)
|
|
{
|
|
LayoutH lh = new LayoutH();
|
|
for (int j = 0; j < inRow; j++) {
|
|
lh.add(grainShopSlotFactory.getWidget());
|
|
}
|
|
|
|
return lh;
|
|
}
|
|
|
|
|
|
private LayoutH getWidget(List<Widget> childs)
|
|
{
|
|
LayoutH lh = new LayoutH();
|
|
|
|
for (Widget w : childs) {
|
|
lh.add(w);
|
|
}
|
|
|
|
return lh;
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public boolean hasBackgroundLayer()
|
|
{
|
|
return page == PG_PROG;
|
|
}
|
|
|
|
|
|
@Override
|
|
public RGB getBackgroundColor()
|
|
{
|
|
return new RGB(0, 0.5);
|
|
}
|
|
|
|
|
|
/**
|
|
* Game panel
|
|
*
|
|
* @param screen the screen
|
|
* @param bundle the level bundle
|
|
*/
|
|
public PanelGame(ScreenGame screen, LevelBundle bundle) {
|
|
super(screen);
|
|
this.bundle = bundle;
|
|
|
|
screen.setMap(bundle.getBuiltMap().copy());
|
|
|
|
this.screenGame = screen;
|
|
}
|
|
|
|
|
|
@Override
|
|
public void initGui()
|
|
{
|
|
FullWidthLayout fwl;
|
|
FrameTop ft;
|
|
FrameBottom fb;
|
|
LayoutH h;
|
|
|
|
// sort the tile lists
|
|
Collections.sort(bundle.progGrains);
|
|
Collections.sort(bundle.progStones);
|
|
|
|
int programLength = bundle.progLength;
|
|
int labels = bundle.progLabels;
|
|
int vars = bundle.progVars;
|
|
|
|
List<ProgTileGrain> grains = new ArrayList<ProgTileGrain>();
|
|
List<ProgTileStone> stones = new ArrayList<ProgTileStone>();
|
|
|
|
// GRAINS
|
|
|
|
// add labels (stones and grains in one cycle, to save time)
|
|
for (int i = 0; i < labels; i++) {
|
|
stones.add((ProgTileStone) new StoneLabel().setVariant(i));
|
|
grains.add((ProgTileGrain) new GrainJumpLabel().setVariant(i));
|
|
}
|
|
|
|
int grainNumberId = GrainRegistry.getGrainIndex(GrainNumber.class);
|
|
int grainLabelId = GrainRegistry.getGrainIndex(GrainJumpLabel.class);
|
|
int stoneLabelId = StoneRegistry.getStoneIndex(StoneLabel.class);
|
|
|
|
// add requested grains
|
|
for (int id : bundle.progGrains) {
|
|
if (id == grainNumberId || id == grainLabelId || id < 1000) continue;
|
|
grains.add(GrainRegistry.getGrain(id));
|
|
}
|
|
|
|
// if there are variables, make sure there's also a number grain
|
|
if (bundle.progVars > 0 || bundle.progStones.contains(grainNumberId)) {
|
|
grains.add(new GrainNumber());
|
|
}
|
|
|
|
// add variables
|
|
for (int i = 0; i < vars; i++) {
|
|
grains.add((ProgTileGrain) new GrainVariable().setVariant(i));
|
|
}
|
|
|
|
// STONES
|
|
|
|
// add the stones
|
|
for (int id : bundle.progStones) {
|
|
if (id == stoneLabelId || id > 1000) continue;
|
|
stones.add(StoneRegistry.getStone(id));
|
|
}
|
|
|
|
dndServer = new DragDropServer();
|
|
|
|
// build belt
|
|
for (int i = 0; i < programLength; i++) {
|
|
Widget widget = beltCellFactory.getWidget(i + 1);
|
|
beltCells.add(widget);
|
|
((PgmBeltCell) widget).setServer(dndServer);
|
|
}
|
|
|
|
// prepare shop cells
|
|
for (ProgTileStone stone : stones) {
|
|
Widget widget = stoneShopSlotFactory.getWidget(stone);
|
|
stoneShopSlots.add(widget);
|
|
((PgmShopBase) widget).setServer(dndServer);
|
|
}
|
|
|
|
for (ProgTileGrain grain : grains) {
|
|
Widget widget = grainShopSlotFactory.getWidget(grain);
|
|
grainShopSlots.add(widget);
|
|
((PgmShopBase) widget).setServer(dndServer);
|
|
}
|
|
|
|
if (stoneShopSlots.size() == 0) stoneShopSlots.add(stoneShopSlotFactory.getWidget());
|
|
if (grainShopSlots.size() == 0) grainShopSlots.add(grainShopSlotFactory.getWidget());
|
|
|
|
// put shop cells to shop
|
|
for (int i = 0; i < Math.ceil(stoneShopSlots.size() / ((double) SHOP_ROW)); i++) {
|
|
int begin = i * SHOP_ROW;
|
|
int end = (i + 1) * SHOP_ROW;
|
|
|
|
end = Calc.clampi(end, 0, stoneShopSlots.size());
|
|
|
|
List<Widget> row = stoneShopSlots.subList(begin, end);
|
|
|
|
while (row.size() < SHOP_ROW) {
|
|
Widget widget = stoneShopSlotFactory.getWidget();
|
|
row.add(widget);
|
|
((PgmShopBase) widget).setServer(dndServer);
|
|
}
|
|
|
|
lowerShopRows.add(lowerShopRowFactory.getWidget(row));
|
|
}
|
|
|
|
for (int i = 0; i < Math.ceil(grainShopSlots.size() / ((double) SHOP_ROW)); i++) {
|
|
int begin = i * SHOP_ROW;
|
|
int end = (i + 1) * SHOP_ROW;
|
|
|
|
end = Calc.clampi(end, 0, grainShopSlots.size());
|
|
|
|
List<Widget> row = grainShopSlots.subList(begin, end);
|
|
|
|
while (row.size() < SHOP_ROW) {
|
|
Widget widget = grainShopSlotFactory.getWidget();
|
|
row.add(widget);
|
|
((PgmShopBase) widget).setServer(dndServer);
|
|
}
|
|
|
|
upperShopRows.add(upperShopRowFactory.getWidget(row));
|
|
}
|
|
|
|
//@formatter:off
|
|
|
|
// top frame with title
|
|
Text title = Theme.mkTitle("Game Screen of Tortuga");
|
|
ft = new FrameTop(title, Align.CENTER, Align.CENTER);
|
|
ft.setMinHeight(TOP_PANEL_SIZE);
|
|
fwl = new FullWidthLayout(ft, Align.CENTER, Align.CENTER);
|
|
addGui(fwl, Align.CENTER, Align.TOP);
|
|
|
|
// left button
|
|
h = new LayoutH(Align.LEFT, Align.CENTER);
|
|
h.setMargins(10, 0, 0, 0).setMinHeight(TOP_PANEL_SIZE);
|
|
|
|
ButtonIcon bnQuit = new ButtonIcon(id_BACK, Tx.ICON_QUIT, new RGB(0x990000));
|
|
bnQuit.setTooltip("Leave Game", new RGB(0xcc0000));
|
|
h.add(bnQuit);
|
|
addGui(h, Align.LEFT, Align.TOP);
|
|
|
|
|
|
// right buttons
|
|
bnProg = new ButtonIcon(id_PROGRAM, Tx.ICON_CODE, new RGB(0xffff00));
|
|
bnProg.setTooltip("Program", new RGB(0xcccc00));
|
|
bnProg.setSelected(page == PG_PROG);
|
|
|
|
bnTurtle = new ButtonIcon(id_TURTLE, Tx.ICON_TURTLE, new RGB(0x00ff00));
|
|
bnTurtle.setTooltip("Level Map", new RGB(0x00cc00));
|
|
bnTurtle.setSelected(page == PG_MAP);
|
|
|
|
h = new LayoutH(Align.RIGHT, Align.CENTER);
|
|
h.setMargins(0, 0, 10, 0).setMinHeight(TOP_PANEL_SIZE);
|
|
h.add(bnProg);
|
|
h.add(bnTurtle);
|
|
|
|
addGui(h, Align.RIGHT, Align.TOP);
|
|
|
|
|
|
|
|
|
|
|
|
// center layout
|
|
programmingLayout = new LayoutV(Align.CENTER, Align.CENTER);
|
|
|
|
upperShopBox = new CompositeScrollBoxV(2, upperShopRowFactory, upperShopRows, Align.CENTER, Align.BOTTOM);
|
|
upperShopBox.setMarginsV(10, 0);
|
|
fwl = new FullWidthLayout(upperShopBox, Align.CENTER, Align.CENTER);
|
|
programmingLayout.add(fwl);
|
|
|
|
beltBox = new CompositeScrollBoxH(5, beltCellFactory, beltCells, Align.CENTER, Align.CENTER);
|
|
beltFrame = new FrameBelt(beltBox, Align.CENTER, Align.TOP);
|
|
beltFrame.padding.top += 7;
|
|
beltFrame.padding.bottom -= 3;
|
|
beltLayout = new FullWidthLayout(beltFrame, Align.CENTER, Align.CENTER);
|
|
beltLayout.setRenderIndex(1);
|
|
beltLayout.setMarginsV(10, 10);
|
|
programmingLayout.add(beltLayout);
|
|
|
|
lowerShopBox = new CompositeScrollBoxV(2, lowerShopRowFactory, lowerShopRows, Align.CENTER, Align.TOP);
|
|
fwl = new FullWidthLayout(lowerShopBox, Align.CENTER, Align.CENTER);
|
|
programmingLayout.add(fwl);
|
|
programmingLayout.add(dndServer);
|
|
addGui(programmingLayout, Align.CENTER, Align.CENTER).setRenderIndex(1);
|
|
|
|
|
|
// MAP
|
|
|
|
ingameLayout = new LayoutV(Align.CENTER, Align.CENTER);
|
|
|
|
addGui(ingameLayout, Align.CENTER, Align.CENTER);
|
|
|
|
// BOTTOM GUI
|
|
Button bn = new Button(id_RUN, "Go turtle, go!", Fonts.gui_title);
|
|
bn.setTheme(ETheme.BUTTON_LAUNCH);
|
|
fb = new FrameBottom(bn, Align.CENTER, Align.CENTER);
|
|
fb.setMinHeight(LOW_PANEL_SIZE);
|
|
fwl = new FullWidthLayout(fb, Align.CENTER, Align.CENTER);
|
|
addGui(fwl, Align.CENTER, Align.BOTTOM);
|
|
|
|
//@formatter:on
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onPostInit()
|
|
{
|
|
onWindowChanged(); // adapt belt to window
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onWindowChanged()
|
|
{
|
|
super.onWindowChanged();
|
|
|
|
adaptBeltSize();
|
|
adaptShopSizes();
|
|
|
|
updateWidgetPositions();
|
|
|
|
screenGame.correctMapOffset();
|
|
}
|
|
|
|
|
|
private void adaptBeltSize()
|
|
{
|
|
int width = (int) (app.getSize().x);
|
|
|
|
Widget b = beltCellFactory.getWidget();
|
|
b.calcChildSizes();
|
|
int one = b.getSize().xi() + b.getMargins().left;
|
|
|
|
int canFit = width / one;
|
|
|
|
beltBox.adaptForSize(canFit);
|
|
}
|
|
|
|
|
|
private void adaptShopSizes()
|
|
{
|
|
int height = (int) (app.getSize().y);
|
|
|
|
height -= LOW_PANEL_SIZE;
|
|
height -= TOP_PANEL_SIZE;
|
|
height -= beltLayout.getSize().y;
|
|
height -= beltLayout.getMargins().getVetical();
|
|
height -= lowerShopBox.getMargins().getVetical();
|
|
height -= upperShopBox.getMargins().getVetical();
|
|
height -= 8;
|
|
|
|
height /= 2;
|
|
|
|
Widget b = lowerShopRowFactory.getWidget();
|
|
b.calcChildSizes();
|
|
int one = b.getSize().yi() + b.getMargins().top;
|
|
|
|
int canFit = (int) Math.floor(height / one);
|
|
|
|
lowerShopBox.adaptForSize(canFit);
|
|
|
|
upperShopBox.adaptForSize(canFit);
|
|
}
|
|
|
|
|
|
@Override
|
|
public void actionPerformed(Widget widget)
|
|
{
|
|
switch (widget.id) {
|
|
case id_BACK:
|
|
app.replaceScreen(new ScreenMenuMain());
|
|
break;
|
|
|
|
case id_PROGRAM:
|
|
bnProg.setSelected(true);
|
|
bnTurtle.setSelected(false);
|
|
programmingLayout.setVisible(true);
|
|
page = PG_PROG;
|
|
break;
|
|
|
|
case id_TURTLE:
|
|
bnProg.setSelected(false);
|
|
bnTurtle.setSelected(true);
|
|
programmingLayout.setVisible(false);
|
|
page = PG_MAP;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private boolean dragging = false;
|
|
private Coord dragStartMapOffset = null;
|
|
private Coord dragStartMouse = null;
|
|
|
|
|
|
@Override
|
|
public void onMouseButton(int button, boolean down, int wheelDelta, Coord pos, Coord deltaPos)
|
|
{
|
|
super.onMouseButton(button, down, wheelDelta, pos, deltaPos);
|
|
|
|
if (page != 2) return;
|
|
|
|
Coord mouse = new Coord(Mouse.getX(), Mouse.getY());
|
|
Coord scrSize = app.getSize();
|
|
|
|
if (mouse.y < scrSize.y - TOP_PANEL_SIZE && mouse.y > LOW_PANEL_SIZE) {
|
|
if (button == 0 && down) {
|
|
dragging = true;
|
|
dragStartMapOffset = screenGame.mapOffset;
|
|
dragStartMouse = mouse;
|
|
}
|
|
}
|
|
|
|
if (button == 0 && !down) {
|
|
dragging = false;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
@Override
|
|
public void onKey(int key, char c, boolean down)
|
|
{
|
|
if (down && key == Keyboard.KEY_R) {
|
|
screenGame.setMap(bundle.getBuiltMap().copy());
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
public void handleStaticInputs()
|
|
{
|
|
super.handleStaticInputs();
|
|
|
|
if (screenGame.currentMap.isMovementFinished()) {
|
|
if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
|
|
screenGame.currentMap.getTurtleController().goForward();
|
|
|
|
} else if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
|
|
screenGame.currentMap.getTurtleController().goBackward();
|
|
|
|
} else if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
|
|
screenGame.currentMap.getTurtleController().turnLeft();
|
|
|
|
} else if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
|
|
screenGame.currentMap.getTurtleController().turnRight();
|
|
|
|
}
|
|
}
|
|
|
|
if (dragging) {
|
|
Coord mouse = new Coord(Mouse.getX(), Mouse.getY());
|
|
|
|
screenGame.mapOffset = dragStartMapOffset.add(dragStartMouse.vecTo(mouse));
|
|
|
|
Coord oldOffset = screenGame.mapOffset.copy();
|
|
|
|
screenGame.correctMapOffset();
|
|
|
|
if (!oldOffset.equals(screenGame.mapOffset)) {
|
|
dragStartMapOffset = screenGame.mapOffset.copy();
|
|
dragStartMouse = mouse.copy();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|