Taking a 2D XNA project and converting it to JME

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. :slight_smile:



Main.java

Code:
package mygame;

/**

  • @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
Code:
package mygame;

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(&quot;,&quot;)) {
         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(&quot;W&quot;)) {
         x += PieceWidth + texturePaddingX;
     }
    
     for (int i = 0; i &lt; 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
Code:
package mygame;

import com.jme3.font.Rectangle;
import com.jme3.math.Vector2f;
import java.util.ArrayList;
import java.util.Random;

/**
*

  • @author draygera
    */
    public class GameBoard {
    // declare variables

    Random 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 &gt;= 0) {
         if (!(GetSquare(x, rowLookup).equals(&quot;Empty&quot;))) {
             SetSquare(x, y, GetSquare(x, rowLookup));
             SetSquare(x, rowLookup, &quot;Empty&quot;);
             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 &lt; GameBoard.GameBoardHeight; y++) {
             for (int x = 0; x &lt; GameBoard.GameBoardWidth; x++) {
                 if (GetSquare(x, y).equals(&quot;Empty&quot;)) {
                     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;
    }
    }

A picuture of what it look like and what it should look like would say more than 100 lines of code in this case i guess.

Might be easier for you to just try to get your code to work with MonoGame http://monogame.codeplex.com/



You will probably only have to deal with small changes instead of rewriting your whole engine in java. MonoGame supports linux, mac, ios, android (through MonoDroid). It is free and in a constant state of development.

I just wanted to say thanks, but I already know quite a bit about Monogame. It was originally Mono-XNA, then died and was brought back to life by part of the team that helped create Bastion. In all honesty, I was able to get it to work using another Java engine called Libgdx, a really fun and easy to use 2D engine. The goal was not to make a Linux or Mac port using XNA but to see if I could port the game into Java. :slight_smile:

1 Like