Java, Swing, Webswing, Oracle Cloud/Windows VM Instance

Github Repository,  






The Game


Description

In this game you are playing versus the computer in a battleship combat. Your objective is to sink the computer's fleet before it sinks yours.

Each fleet will have eight ships:

  • 3 patrols (two squares long)
  • 2 cruisers (three squares long)
  • 1 submarine (three squares long)
  • 1 battleship (four squares long)
  • 1 carrier (five squares long)

The Boards

When playing you will see two boards:

  • In the top left corner you will have the computer's board, that is the board the user aims at.
  • In the bottom right corner you will have your board, that is the board the computer aims at.

Launch an Attack

To attack, click on a square on your opponent's board. The squares can take the following values:

  • Light gray square: The position has not been attacked.
  • Dark gray square: RAPID FIRE mode only - the position has been selected for attack, but the shot has not yet been made.
  • Translucent square: The position has been attacked, but it was empty - no ship was found.
  • Explosion square: The position has been attacked, a ship in this position was hit, but the ship is still floating.
  • Red Flag square: The position has been attacked, and the ship located in this square has been sunk.

Tracking the game

You can track the progress of the game by viewing the ships inventory in the top right corner. The inventory shows the total number or ships floating with designated ship types.

The second way to track the game by reading the text in the bottom left component that will narrate the updates.


Menu

When clicking on Menu the player will be prompted with three options:

  • UNHIDE SHIPS: this will reveal all of the opponent's ships but will not terminate the game.
  • RESTART: this will take the user back to the main screen to choose the gaming mode.
  • QUIT: this will close the entire application



Preview of Extreme Modes





Gaming Modes

The game has five different modes that are explained below:

Standard Game

In this classic game mode, each player has one shot per turn. The user will make the first move.

Ships on the Run

In this extreme version of the classic game, the ships will move and recover from the shots if they hit but are not sunk within a designated number of turns (dependent on the size of the ship).

Bombs Away!

In this mode, the user has a specific quantity of bombs (3) that can be used at any point during the game. If a ship is hit by a bomb, it will immediately be sunk.

Rapid Fire

Rapid fire mode allows the user to choose multiple squares to hit in one turn, with the quantity of available shots equal to the number of ships that the opponent has remaining. The player will make the shots without knowing what impact they had until the end of the turn.

Lucky Shot

If you miss several shots in a row, computer assist will be enabled to help you to find a target. The likelihood of computer assist hitting a target increases proportionally to the number of misses in a row.





Team Members & Roles

Hanzhao Yu: Game Classes & JUnit Tests, Computer Algorithm Classes
Holland Delany: Game Classes & JUnit Tests, Computer Algorithm Classes, GUI & Resources, Remote Deployment
Jorge Corrales: Game Classes & JUnit Tests





Class Overview



  • Main


    The main method invokes the GUIFrame class, which starts the game.

  • GUIFrame


    The GUIFrame class creates the window and menu bar.

    The menu bar has the options RESTART, UNHIDE SHIPS, and QUIT.

    The GUIFrame class instantiates a GUIPanel.

  • GUIPanel


    The GUIPanel class paints the panel for current page (main page or game page).

    It also instantiates a GUIMainPage and defines methods to create, navigate between, and repaint pages.

  • GUIMainPage


    The GUIMainPage class draws the main (intro) page components. This includes creating the buttons on the main page which allow the user to select the game mode.

    This class has action listener methods to capture the user game mode selection and call the method to instantiate the corresponding BattleShip/BattleshipMode# and GUIGamePage classes.

  • GUIGamePage


    The GUIGamePage class draws the game page (second page) components. This includes the user board, computer board, fleet status panels, and action result panel.

    This class uses the GUIGrids class to instantiate the boards.

    The GUIGamePage class has methods to update the text of the panels after each move based on the status of the game.

    The GUIGamePage class also has a method to receive mouse events/ capture the selection when a user clicks on a board square, and then call the Battleship public void fireTarget(Coordinate coordinate) method on the square.

  • GUIGrids


    The GUIGrids class is used to display the game board.

    Each square displays an ImageIcon based on status of the square.

    Status options are defined in the Status class (see below).

  • Battleship


    This class defines the methods for a standard game. This includes methods to create a set of ships, create the user board and computer board, play a move/ fire at a target, and get the game status (to be used by the GUI).

    The Battleship public void fireTarget(Coordinate coordinate) method plays the user move, and then immediately calls the AI method to play the computer opponent move.

    This class instantiates objects from the following classes - Board, Ship, AI.

    All BattleShipMode# classes extend the Battleship class.

  • BattleshipMode1


    This class extends the Battleship class to incorporate "SHIPS ON THE RUN" gameplay.

    In the "SHIPS ON THE RUN" mode, the ships move & regenerate if they are not sunk in time.

    This class defines a private boolean shipFlee(Board board, Ship ship) method, and overrides the Battleship public void fireTarget(Coordinate coordinate) method to incorporate the shipFlee method.

  • BattleshipMode2


    This class extends the Battleship class to incorporate "BOMBS AWAY!" gameplay.

    In the "BOMBS AWAY!" mode, the ships can be sunk with one hit if a bomb is used.

    This class defines bomb methods and overrides the Battleship public void fireTarget(Coordinate coordinate) method to incorporate them.

  • BattleshipMode3


    This class extends the Battleship class to incorporate "RAPID FIRE" gameplay.

    In the "RAPID FIRE" mode, the user selects multiple squares to hit on each turn, where the number of squares the user selects corresponds to the number of enemy ships left.

    This class defines methods for tracking multiple user selected squares, and overrides the Battleship public void fireTarget(Coordinate coordinate) and public String[] getRoundInfo() methods.

  • BattleshipMode4


    This class extends the Battleship class to incorporate "LUCKY SHOT" gameplay.

    In the "LUCKY SHOT" mode, if the player misses several shots in a row, the game will try another shot in background that becomes gradually more likely to hit a target. If that background shot hits a ship, it replaces the player shot.

    This class overrides the Battleship public void fireTarget(Coordinate coordinate) method.

  • AI


    The AI class defines the methods required for the computer opponent to play a move/ fire at a target.

    This includes the public Set getFireCoordinates(Board currentBoard, int ammo) method to return the computer decision of where to fire in the current round.

    It also includes helper methods to identify possible targets (priority is given by how many possible ships could be located in a particular square) and find targets around damaged ships.

  • Board


    The Board class is used to create the board for both the player and computer.

    Ships are auto arranged on the board.

    This class also contains methods to get information about the status of the board (the state of the squares and Ships on the board).

  • Coordinate


    This class defines a global usable coordinate.

    The coordinate is immutable it is after created.

  • Status


    enum class defining the possible status of a square in the board. Status options include:

    WATER - square that has not been hit, contains water

    SHIPINTACT - square that has not been hit, contains ship

    SHIPHIT - section of a ship that has been hit, but the ship is still floating

    SHIPSUNK - section of a sunk ship

    MISS - square that has been hit, contains water

    SELECTED_WATER - user selected square, rapid fire game mode only

    SELECTED_SHIPINTACT - user selected square, rapid fire game mode only



  • Ship


    The Ship class is used to create the ships.

    Ships have a size(int), name(string), and direction(Direction) where it points to.

  • Direction


    enum class defining the cardinal directions.

  • Test Classes


    The companion test classes are used to test for method functionality, state changes, and boundary & invalid input handling.






Accessing the game in the browser





Launching as a Web App



Don’t use Swing for a web app

Java  Swing  is said to be an old, deprecated technology which can only design desktop apps. Truthfully, for anyone who aims to make a web app, Swing is not a good choice. By nature, Swing has been designed to be run as a desktop application. To access it, you have to setup the JRE on any computer that needs to run it, and it is not supported by modern browsers.


But what if you MUST use Swing?

For many years Swing has been the  framework  of choice for many companies and individuals for creating rich applications. Significant time, money, and effort has already been invested in Swing application development, and many of these applications are essential to their creator’s operations. The Extreme Battleship project was already completed in Swing when I set out to deploy it as a web app.


Swing is not supported in the browser!

Nowadays, the Swing framework is becoming a limiting factor, because Swing applications are not able to be used in modern web browsers.

Oracle announced in January 2016 that Applets would be deprecated in Java SE 9, and the technology was removed in Java SE 11. Given that nearly all browser makers were already getting rid of plugin support, you can argue that Oracle really didn’t have any choice but drop the feature. Support for running Applets in browsers is only possible while browser vendors are committed to standards-based plugins.

The argument is that plugins have to connect deeply to the browser’s architecture, and this makes it too difficult to keep everything up to date and secure. In the case of the Java plugin, it was even more complex because of the need to use the JVM etc. to actually run the code. Keeping all of this software up to date was a task beyond most users. So plugins of all types, including Java, had to go.

With the Applet technology support being discontinued, it leaves very few options.


So, how am I running Extreme Battleship in the browser?

My goal was to display the Swing project in a browser like any Web app. My solution was to use  Webswing , which uses a Jetty server to load the JAR and expose it as HTML5 pages. I would recommend the process for others who want to extend the life of their legacy Swing application.


Webswing translates activity to browser actions

The Swing API is by design cross-platform, which means all interactions with platform dependent features happen through a well-defined minimal interface (java.awt.Toolkit).

Webswing defines a new platform implementation for "Web", which simply turns web browser to a virtual desktop and translates platform specific actions to browser actions in the best possible way.

There are two core actions that every platform has to provide for Swing:

  1. Display content on screen
  2. Generate user input events

Webswing displays the content in a browser using HTML Canvas and captures keyboard and mouse events in JavaScript to generate Swing input events.

The quick start is simple: download the latest version, extract files, run a script file, and open your browser, it works! Just move your jar in the Webswing folder (or a subfolder) and configure it as a new app in the admin console of the running server. A Docker image is also provided in order to run Webswing in a container, for example on a PaaS like OpenShift or Kubernetes. It is also possible to customize the HTML pages, get stats from the admin console, or integrate it with other systems like nginx, SSL certificates or load-balancers: the excellent documentation gives a lot of information for usage in production.



Webswing Interactions



Last step is remote deployment

In order to  host  the project, I decided to rent a VM on   Oracle Cloud Infrastructure,  specifically, a Windows Server 2019 Standard Image and VM.Standard.A1.Flex shape for performance and rendering consistency.

As a drawback, every new Webswing session launches a new instance of the app, so developers must set the server with appropriate memory / cpu settings and limit the concurrent sessions. To deal with this constraint, a login, with a limited number of concurrent users, gates the instance.

Now, you can  access  the Java Swing app from any browser, including on mobile devices!
*case sensitive* username=user, password=user




Let's work together!

Like my work? I'm happy to connect.