I know that everyone keeps saying JME is not very good for 2d games, but by God, I’m going to try to do this.
Now the major issue I’m having as of this moment is getting the pipes to draw on the screen properly and rotating when I click on them. Anybody willing to give some insight? Please and thank you.
By the way, this is a conversion from an example in one of my textbooks.
Main.java
/**
-
@author draygera
*/
import com.jme3.app.SimpleApplication;
import com.jme3.font.Rectangle;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.math.Vector2f;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import java.util.ArrayList;
public class Main extends SimpleApplication implements ActionListener {
// declare variables
Texture2D playingPieces;
Texture2D backgroundScreen;
Texture2D titleScreen;
Picture empty;
Picture piece;
Picture background;
Picture title;
//
GameBoard gameBoard;
//
Vector2f gameBoardDisplayOrigin = new Vector2f(70, 89);
//
int playerScore = 0;
//
enum GameStates {
TitleScreen, Playing
};
GameStates gameState = GameStates.TitleScreen;
//
Rectangle EmptyPiece = new Rectangle(1, 247, 40, 40);
//
static final float MinTimeSinceLastInput = 0.25f;
float timeSinceLastInput = 0.0f;
/**
* @param args
*/
public static void main(String[] args) {
AppSettings settings = new AppSettings(true);
settings.setFullscreen(false);
settings.setResolution(800, 600);
settings.setTitle("Flood Control");
Main app = new Main();
app.setSettings(settings);
app.setShowSettings(false);
app.setDisplayFps(false);
app.setDisplayStatView(false);
app.start();
}
@Override
public void simpleInitApp() {
initKeys();
flyCam.setEnabled(false);
gameBoard = new GameBoard();
playingPieces = (Texture2D) assetManager.loadTexture("Textures/Tile_Sheet.png");
backgroundScreen = (Texture2D) assetManager.loadTexture("Textures/Background.png");
titleScreen = (Texture2D) assetManager.loadTexture("Textures/TitleScreen.png");
piece = new Picture("Piece");
background = new Picture("Background");
title = new Picture("Title");
empty = new Picture("Empty");
piece.setTexture(assetManager, playingPieces, false);
background.setTexture(assetManager, backgroundScreen, false);
title.setTexture(assetManager, titleScreen, false);
empty.setTexture(assetManager, playingPieces, false);
}
@Override
public void simpleUpdate(float tpf) {
draw();
}
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if (gameState.equals(GameStates.TitleScreen)) {
if ((name.equals("Start")) && isPressed) {
gameBoard.ClearBoard();
gameBoard.GenerateNewPieces(false);
playerScore = 0;
gameState = GameStates.Playing;
}
}
if (gameState.equals(GameStates.Playing)) {
timeSinceLastInput += tpf;
if (timeSinceLastInput >= MinTimeSinceLastInput) {
int x = ((mouseInput.AXIS_X - (int) gameBoardDisplayOrigin.x) / GamePiece.PieceWidth);
int y = ((mouseInput.AXIS_Y - (int) gameBoardDisplayOrigin.y) / GamePiece.PieceHeight);
if ((x >= 0) && (x < GamePiece.PieceWidth) && (y >= 0) && (y < GamePiece.PieceHeight)) {
if ((name.equals("Left") && isPressed)) {
gameBoard.RotatePiece(x, y, false);
timeSinceLastInput = 0.0f;
}
if ((name.equals("Right")) && isPressed) {
gameBoard.RotatePiece(x, y, true);
timeSinceLastInput = 0.0f;
}
}
}
gameBoard.ResetWater();
for (int y = 0; y < GameBoard.GameBoardHeight; y++) {
CheckScoringChain(gameBoard.GetWaterChain(y));
}
gameBoard.GenerateNewPieces(true);
}
}
private void initKeys() {
//keyInput.initialize();
//mouseInput.initialize();
inputManager.addMapping("Start", new KeyTrigger(keyInput.KEY_SPACE));
inputManager.addMapping("Left", new MouseButtonTrigger(mouseInput.BUTTON_LEFT));
inputManager.addMapping("Right", new MouseButtonTrigger(mouseInput.BUTTON_RIGHT));
inputManager.addListener(this, new String[]{"Start"});
inputManager.addListener(this, new String[]{"Left", "Right"});
}
private void draw() {
if (gameState == GameStates.TitleScreen) {
title.setPosition(0, 0);
title.setWidth(settings.getWidth());
title.setHeight(settings.getHeight());
guiNode.attachChild(title);
}
if (gameState == GameStates.Playing) {
background.setPosition(0, 0);
background.setWidth(settings.getWidth());
background.setHeight(settings.getHeight());
guiNode.attachChild(background);
for (int x = 0; x < GameBoard.GameBoardWidth; x++) {
for (int y = 0; y < GameBoard.GameBoardHeight; y++) {
int pixelX = (int) gameBoardDisplayOrigin.x + (x * GamePiece.PieceWidth);
int pixelY = (int) gameBoardDisplayOrigin.y + (y * GamePiece.PieceHeight);
empty.setPosition(pixelX, pixelY);
empty.setWidth(GamePiece.PieceWidth);
empty.setHeight(GamePiece.PieceHeight);
empty.setLocalScale(EmptyPiece.x, EmptyPiece.y, 0);
guiNode.attachChild(empty);
piece.setPosition(pixelX, pixelY);
piece.setWidth(GamePiece.PieceWidth);
piece.setHeight(GamePiece.PieceHeight);
piece.setLocalScale(gameBoard.GetSourceRect(x, y).x,
gameBoard.GetSourceRect(x, y).y, 0);
guiNode.attachChild(piece);
}
}
settings.setTitle(Integer.toString(playerScore));
}
}
private int DetermineScore(int SquareCount) {
return (int) ((Math.pow((SquareCount / 5), 2) + SquareCount) * 10);
}
private void CheckScoringChain(ArrayList<Vector2f> WaterChain) {
if (WaterChain.size() > 0) {
Vector2f LastPipe = WaterChain.get(WaterChain.size() - 1);
if (LastPipe.x == GameBoard.GameBoardWidth - 1) {
if (gameBoard.HasConnector((int) LastPipe.x, (int) LastPipe.y, "Right")) {
playerScore += DetermineScore(WaterChain.size());
for (Vector2f ScoringSquare : WaterChain) {
gameBoard.SetSquare((int) ScoringSquare.x, (int) ScoringSquare.y, "Empty");
}
}
}
}
}
}
GamePiece.java
import com.jme3.font.Rectangle;
import java.util.ArrayList;
/**
*
-
@author draygera
*/
public class GamePiece {public static String[] PieceTypes = {
"Left,Right",
"Top,Bottom",
"Left,Top",
"Top,Right",
"Right,Bottom",
"Bottom,Left",
"Empty"
};
//
public static final int PieceHeight = 40;
public static final int PieceWidth = 40;
//
public static final int MaxPlayablePieceIndex = 5;
public static final int EmptyPieceIndex = 6;
//
private final int textureOffsetX = 1;
private final int textureOffsetY = 1;
private final int texturePaddingX = 1;
private final int texturePaddingY = 1;
//
private String pieceType = "";
private String pieceSuffix = "";public GamePiece(String type, String suffix) {
pieceType = type;
pieceSuffix = suffix;
}public GamePiece(String type) {
this(type, "");
}public void SetPiece(String type, String suffix) {
pieceType = type;
pieceSuffix = suffix;
}public void SetPiece(String type) {
SetPiece(type, "");
}
//public void AddSuffix(String suffix) {
if (!pieceSuffix.contains(suffix)) {
pieceSuffix += suffix;
}
}public void RemoveSuffix(String suffix) {
pieceSuffix = pieceSuffix.replace(suffix, "");
}public void RotatePiece(boolean Clockwise) {
switch (pieceType) {
case "Left,Right":
pieceType = "Top,Bottom";
break;
case "Top,Bottom":
pieceType = "Left,Right";
break;
case "Left,Top":
if (Clockwise) {
pieceType = "Top,Right";
} else {
pieceType = "Bottom,Left";
}
break;
case "Top,Right":
if (Clockwise) {
pieceType = "Right,Bottom";
} else {
pieceType = "Left,Top";
}
break;
case "Right,Bottom":
if (Clockwise) {
pieceType = "Bottom,Left";
} else {
pieceType = "Top,Right";
}
break;
case "Bottom,Left":
if (Clockwise) {
pieceType = "Left,Top";
} else {
pieceType = "Right,Bottom";
}
break;
case "Empty":
break;
}
}public String[] GetOtherEnds(String startingEnd) {
ArrayList<String> opposites = new ArrayList<>();for (String end : pieceType.split(",")) { if (!end.equals(startingEnd)) { opposites.add(end); } } return opposites.toArray(new String[0]);
}
public boolean HasConnector(String direction) {
return pieceType.contains(direction);
}public Rectangle GetSourceRect() {
int x = textureOffsetX;
int y = textureOffsetY;if (pieceSuffix.contains("W")) { x += PieceWidth + texturePaddingX; } for (int i = 0; i < PieceTypes.length; i++) { y += i * (PieceHeight + texturePaddingY); } return new Rectangle(x, y, PieceWidth, PieceHeight);
}
public String PieceType() {
return pieceType;
}public String Suffix() {
return pieceSuffix;
}
}
GameBoard.java
import com.jme3.font.Rectangle;
import com.jme3.math.Vector2f;
import java.util.ArrayList;
import java.util.Random;
/**
*
-
@author draygera
*/
public class GameBoard {
// declare variablesRandom rand = new Random(0);
//
public static final int GameBoardWidth = 8;
public static final int GameBoardHeight = 10;
//
private GamePiece[][] boardSquares = new GamePiece[GameBoardWidth][GameBoardHeight];
//
private ArrayList<Vector2f> WaterTracker = new ArrayList<>();public GameBoard() {
ClearBoard();
}public void ClearBoard() {
for (int x = 0; x < GameBoardWidth; x++) {
for (int y = 0; y < GameBoardHeight; y++) {
boardSquares[x][y] = new GamePiece("Empty");
}
}
}public void RotatePiece(int x, int y, boolean cloackwise) {
boardSquares[x][y].RotatePiece(cloackwise);
}public Rectangle GetSourceRect(int x, int y) {
return boardSquares[x][y].GetSourceRect();
}public String GetSquare(int x, int y) {
return boardSquares[x][y].PieceType();
}public void SetSquare(int x, int y, String pieceName) {
boardSquares[x][y].SetPiece(pieceName);
}public boolean HasConnector(int x, int y, String direction) {
return boardSquares[x][y].HasConnector(direction);
}public void RandomPiece(int x, int y) {
boardSquares[x][y].SetPiece(GamePiece.PieceTypes[
rand.nextInt(GamePiece.MaxPlayablePieceIndex + 1)]);
}public void FillFromAbove(int x, int y) {
int rowLookup = y - 1;while (rowLookup >= 0) { if (!(GetSquare(x, rowLookup).equals("Empty"))) { SetSquare(x, y, GetSquare(x, rowLookup)); SetSquare(x, rowLookup, "Empty"); rowLookup -= 1; } rowLookup--; }
}
public void GenerateNewPieces(boolean dropSquares) {
if (dropSquares) {
for (int x = 0; x < GameBoard.GameBoardWidth; x++) {
for (int y = GameBoard.GameBoardHeight - 1; y >= 0; y–) {
if (GetSquare(x, y).equals("Empty")) {
FillFromAbove(x, y);
}
}
}for (int y = 0; y < GameBoard.GameBoardHeight; y++) { for (int x = 0; x < GameBoard.GameBoardWidth; x++) { if (GetSquare(x, y).equals("Empty")) { RandomPiece(x, y); } } } }
}
public void ResetWater() {
for (int y = 0; y < GameBoardHeight; y++) {
for (int x = 0; x < GameBoardWidth; x++) {
boardSquares[x][y].RemoveSuffix("W");
}
}
}public void FillPiece(int X, int Y) {
boardSquares[X][Y].AddSuffix("W");
}public void PropogateWater(int x, int y, String fromDirection) {
if ((y >= 0) && (y < GameBoardHeight)
&& (x >= 0) && (x < GameBoardWidth)) {
if (boardSquares[x][y].HasConnector(fromDirection)
&& !boardSquares[x][y].Suffix().contains("W")) {
FillPiece(x, y);
WaterTracker.add(new Vector2f(x, y));
for (String end : boardSquares[x][y].GetOtherEnds(fromDirection)) {
switch (end) {
case "Left":
PropogateWater(x - 1, y, "Right");
break;
case "Right":
PropogateWater(x + 1, y, "Left");
break;
case "Top":
PropogateWater(x, y - 1, "Bottom");
break;
case "Bottom":
PropogateWater(x, y + 1, "Top");
break;
}
}
}
}
}public ArrayList<Vector2f> GetWaterChain(int y) {
WaterTracker.clear();
PropogateWater(0, y, "Left");
return WaterTracker;
}
}