Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
3D Java Game Programming – Episode 17.5 Building a Java First-Person Shooter Episode 17.5 – Creating an Applet In this episode CHERNO discusses how to run our game in a web browser. Java can be created to run as an application or as an applet in a web browser. In order to run as an applet additional code will need to be added. Creating a new Class The new class MinefrontApplet.java shall be added to the project under the package com.mime.minefront. This class will extend the JApplet class located in javax.swing.JApplet (CHERNO uses the AWT Applet class but we opt for the Swing version). An applet gets set up and managed by a browser in an area defined in an html file. From the browser point of view an applet runs in its own thread. A key point to remember is that a Java applet does not have a main() method. An applet provides one or more methods to be invoked by the browser thread. The typical signature for a Java Applet is: public class MyWildApplet extends JApplet { : : } There are five key classes an applet implements to perform initialization, starting, stopping, destroying and painting. public void init() { : } The web browser first invokes the init() method as soon as the applet completes loading. We would place into this method the processing of initial parameters that may have been provided in the html file or the loading of images. You will also create any other objects that will be used to implement the functionality or logic of the applet. public void start() { : } The start() method is invoked after the init() method. This method can be invoked several times during an applet’s lifetime. If the applet was stopped (e.g. paused, user went to another web page, minimized the screen, etc.) then this is where you would put the code to start the applet up again. public void stop() { : 1 3D Java Game Programming – Episode 17.5 } The stop() method may be invoked by the browser when the user exits the html page the applet is running on, or you can have a “pause” button on the screen that will invoke stop(). By default, when the reader leaves a page, any threads the applet has started will continue to run. By implementing logic in the stop() method you can suspend execution of the thread in which the applet is running. public void destroy() { : } The destroy() method enables the applet to release resources and clean up. We usually don’t implement this method. The key method implemented by an applet is the paint(Graphics g) method: public void paint(Graphics g) { : } The method above is invoked each time to draw on the screen – it defines what the applet looks and does for the user. So here is a simple applet. Table 1 - SimpleApplet01 import javax.swing.JApplet; public class SimpleApplet01 extends JApplet { private static final long serialVersionUID = 1L; } 2 3D Java Game Programming – Episode 17.5 Figure 1 - Resutls of running SimpleApplet01.java As you can see from running in Eclipse the applet does come up and show an empty window frame when we have no code for the construction and definition of the window – this is because the contents in which the applet will run is set up and maintained by the browser. Here is a version where we implement the methods init() and paint() methods: Table 2 - SimpleApplet02.java import java.awt.Color; import java.awt.Graphics; import javax.swing.JApplet; public class SimpleApplet02 extends JApplet { private static final long serialVersionUID = 1L; private int width; private int height; @Override public void init() { setBackground(Color.YELLOW); setForeground(Color.RED); width = getWidth(); height = getHeight(); } @Override public void paint(Graphics g) { g.drawLine(0, 0, width / 2, height / 2); } 3 3D Java Game Programming – Episode 17.5 } Figure 2 - Results of running SimpleApplet02.java You don’t always need to add a paint() method within the applet class. In the next example we are going to create a helper class for our SimpleApplet03.java example. In this helper class we will do actual drawing to the component space. Table 3- MainDisplay.java import import import import import java.awt.Canvas; java.awt.Color; java.awt.Graphics; java.awt.Point; java.util.Random; public class MainDisplay extends Canvas implements Runnable { private static final long serialVersionUID = 1L; private boolean running = false; private Thread thread = null; private Color currentColor; private Point screenLocation = null; private Random rng = null; public MainDisplay() { rng = new Random(); screenLocation = new Point(); } public synchronized void start() { 4 3D Java Game Programming – Episode 17.5 if (running ) { return; } running = true; thread = new Thread(this); thread.start(); } public synchronized void stop() { if (!running) { return; } running = false; try { thread.join(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } } @Override public void run() { // just to do something ... let's update the color and location we plan on drawing to // on the screen while (running) { currentColor = new Color(rng.nextInt(256), rng.nextInt(256), rng.nextInt(256)); screenLocation.x = rng.nextInt(getWidth()); screenLocation.y = rng.nextInt(getHeight()); // sleep a bit try { Thread.sleep(500); } catch (InterruptedException ie) { // ignore } repaint(); } } public void paint(Graphics g) { g.setColor(currentColor); g.fillRect(screenLocation.x, screenLocation.y, 4, 4); } } The helper class above is similar in spirit to the Minefront Display.java class. It extends the java Canvas class and implements the Runnable interface. The java Canvas class is a component that 5 3D Java Game Programming – Episode 17.5 represents a blank rectangular area of the screen onto which the application can draw or from which the application can trap input events from the user. The paint() method must be overridden in order to perform custom graphics on the canvas screen. This auxiliary class merely sets a new color and position on the screen (in the portion that would be equivalent to our game loop) in two field properties: currentColor and screenLocation. The class constructor merely initializes the random number generator rng and the screenLocation Point. The start() method gets our independent thread (that runs the game loop) up and running (same as in Minefront). The stop() method will sent the running flag off and force the game loop (and therefore the thread) to stop. The game loop is represented in the while loop in the run() method. It does not do much of anything just update the current color and location we will draw a small rectangle on the screen. The run() method calls the repaint() method in order to get the new and updated rectangle drawn whenever the applet container invokes the paint() method for all the components defined in the applet. Table 4 - SimpleApplet03.java import javax.swing.JApplet; public class SimpleApplet03 extends JApplet { private static final long serialVersionUID = 1L; MainDisplay mySimpleDisplay = null; public void init() { mySimpleDisplay = new MainDisplay(); add(mySimpleDisplay); } public void start() { mySimpleDisplay.start(); } public void stop() { mySimpleDisplay.stop(); } } The class SimpleApplet03.java uses our auxiliary class to perform all the work. Our final version of SimpleApplet04.java uses a slightly different auxiliary class that matches in spirit (with respect to drawing) the episode’s Display.java class. 6 3D Java Game Programming – Episode 17.5 We don’t use the typical paint() method but follow the technique used in our episodes which is to have our game loop set up the next screen in the game loop and invoke a render() method to display the next screen. Table 5 - MainDisplay2.java import import import import import import java.awt.Canvas; java.awt.Color; java.awt.Graphics; java.awt.Point; java.awt.image.BufferStrategy; java.util.Random; public class MainDisplay2 extends Canvas implements Runnable { private static final long serialVersionUID = 1L; private boolean running = false; private Thread thread = null; private Color currentColor; private Point screenLocation = null; private Random rng = null; public MainDisplay2() { rng = new Random(); screenLocation = new Point(); } public synchronized void start() { if (running ) { return; } running = true; thread = new Thread(this); thread.start(); } public synchronized void stop() { if (!running) { return; } running = false; try { thread.join(); } catch (Exception e) { e.printStackTrace(); System.exit(0); } } @Override 7 3D Java Game Programming – Episode 17.5 public void run() { // just to do something ... let's update the color and location we plan on drawing to // on the screen while (running) { currentColor = new Color(rng.nextInt(256), rng.nextInt(256), rng.nextInt(256)); screenLocation.x = rng.nextInt(getWidth()); screenLocation.y = rng.nextInt(getHeight()); // sleep a bit try { Thread.sleep(500); } catch (InterruptedException ie) { // ignore } render(); } } private void render() { BufferStrategy bs = this.getBufferStrategy(); if (bs == null) { createBufferStrategy(3); return; } Graphics g = bs.getDrawGraphics(); // first set the background g.setColor(Color.black); g.fillRect(0, 0, getWidth(), getHeight()); // Draw the random rectangle g.setColor(currentColor); g.fillRect(screenLocation.x, screenLocation.y, 4, 4); g.dispose(); bs.show(); } } The differences between MainDisplay2.java and MainDisplay.java are highlighted above. The run() method now invokes the render() method rather than repaint(). The render() method implements a buffer strategy in order to draw in one internal buffer screen and switch screens completely in order to avoid tearing and flickering on the screen. The graphics object is obtained from the BufferStrategy object and used to draw our screen. The other difference is that here we set the background to black in order to match the initial background color of the back buffer. 8 3D Java Game Programming – Episode 17.5 In using these simple applets and helper classes we wanted to highlight how the new changes we are introducing work with the current game engine architecture we are using in these video episodes without cluttering them with the 3D aspects and input handling elements. This is how our new Applet class looks like: Table 6 - MinefrontApplet.java package com.mime.minefront; import java.awt.BorderLayout; import javax.swing.JApplet; public class MinefrontApplet extends JApplet { private static final long serialVersionUID = 1L; private Display display = new Display(); public void init() { setLayout(new BorderLayout()); add(display); } public void start() { display.start(); } public void stop() { display.stop(); } } That is it. If you run it (as an applet) you may see a small screen as shown below. 9 3D Java Game Programming – Episode 17.5 Figure 3 - Our application running as an applet In order get the window size to match in Eclipse to the application window size perform the following steps: Right-click on the MinefrontApplet.java file Select Run As | Run Configurations… Click on the (x) = Parameters tab Figure 4 - Setting Screen Size 10 3D Java Game Programming – Episode 17.5 Click on “Apply” Now “Run” Your applet will now run in a window that matches the window frame 800 x 600. What is synchronization all about? When of the changes we made in the Display.java class was to the methods start() and stop() was to add the keyword “synchronization” to both. Here they go: Exporting as Jar File The next step we want to do is generate a jar file for the Java Applet version in order to be able to run the game from an Internet html page. We do the following: Highlight the Minefront project File | Export Select Java folder – JAR file Figure 5 - Exporting an applet JAR file Click on Next> 11 3D Java Game Programming – Episode 17.5 Figure 6 - JAR file specification Select src and resources directory Enter and name and location for the applet JAR file Click on “Finish” The JAR file is NOT a runnable JAR file as we created in Episode 16.5. Creating HTML file to test our JAR file Open a text editor (e.g. notepad) and enter the following HTML code Table 7 - Minefront.html <!DOCTYPE html> <HTML> <HEAD> <TITLE>Minefront Applet</TITLE> </HEAD> 12 3D Java Game Programming – Episode 17.5 <BODY bgcolor="#222222"> <BR><P></P> <BR><P></P> <CENTER> <APPLET CODE="com.mime.minefront.MinefrontApplet" archive="MinefrontApplet.jar" width="800" height="600"> </APPLET> </CENTER> </BODY> </HTML> Save the file as “Minefront.html” in the same directory where you saved the JAR file created for the applet Open up with a browser Figure 7 - Applet running in Chrome web browser 13