简体   繁体   中英

Java applet shows white screen despite running code to display the menu

I have an applet for a small game me and a friend are working on for our computer science class. We are attempting to make a menu that opens at the start of the applet, then after 1 second displays a class selection screen. However, after the one second, the screen just turns white, but outputs the print statement assigned to signal the class selection screen has loaded, I am unsure of why this is happening and would like to solve this.

I have tried putting the code to show the class selection screen in another thread so nothing else will be holding it back when it runs, however, this has changed nothing. I have also made sure the conditions to show the screen are true, and to show it every .2 seconds, yet nothing seems to work. I tried to make the code run in the constructor for the character, and it is supposed to run once, it runs once, but the problem with it running once is that it immediately exits the menu and goes to the next phase of the game for no reason.

import java.awt.*;
import java.applet.*;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import java.util.*;

public class FinalProjectTest extends Applet implements KeyListener, Runnable, MouseListener
{
   int xCoord = 50;
   int yCoord = 600;
   int moveScale = 20;
   int xSize = 20;
   int ySize = 20;

   int leftWall = 0;
   int rightWall = 1000;
   int topWall = 0;
   int bottomWall = 650;
   public volatile Graphics graphics;
   boolean isInMenu = false;
   boolean firstRun = true;
   boolean drawMap = true;

   int hostileAmount = 1000;

   Character P1;

   @Override
   public void init()
   {
      addKeyListener(this);
      addMouseListener( this );
   }

   public void Looper(Graphics g)
   {
      drawPlayer(g);

      // Enemy 1
      HostileObject enemy = new HostileObject(100, 250);
      enemy.CreateHostile(g);
   }

   public void paint(Graphics g)
   {
      if (firstRun)
      {
         firstRun = false;
         isInMenu = true;
         System.out.println("Character Created");
         P1 = new Character(g);
      }
      if (!isInMenu && !firstRun)
      {
         System.out.println("Game has begun!");
         Map1 firstMap = new Map1(g);
         Looper(g);
      }
   }

   public void drawPlayer(Graphics g)
   {
      g.setColor(Util.black);
      g.fillRect(xCoord - xSize, yCoord - ySize, xSize, ySize);
   }

   public void MovePlayer(int x, int y)
   {
      if (CheckPosition(xCoord + x, yCoord + y))
      {
         xCoord += x;
         yCoord += y;
      }
   }

   public boolean CheckPosition(int x, int y)
   {
      if (WallCheck1(x,y) && WallCheck2(x,y) && CheckBorders(x, y))
      {
         return true;
      }
      else
         return false;
   }

   public boolean CheckBorders(int x, int y)
   {
      if (y + ySize <= bottomWall && y - ySize >= topWall && x - xSize >= leftWall && x + xSize <= rightWall)
      {
         return true;
      }
      else
         return false; 
   }

   public boolean WallCheck1(int x, int y)
   {
      if ((y - ySize >= Map1.wall1y1 || y + ySize <= Map1.wall1y2 + 20) || x - xSize >= Map1.wall1x2)
      {
         return true;
      }
      else
         return false; 
   }
   public boolean WallCheck2(int x, int y)
   {
      if ((y - ySize >= Map1.wall2y1 || y + ySize <= Map1.wall2y2 + 20) || x - xSize <= Map1.wall2x2)
      {
         return true;
      }
      else
         return false;
   }

   boolean keyIsHeld;
   char moveChar;

   public void keyReleased( KeyEvent e )
   {
      keyIsHeld = false;
      moveChar = ' ';
   }
   public void keyTyped( KeyEvent e ) { }

   public void keyPressed( KeyEvent a )
   {
      char c = a.getKeyChar();
      if ( c == 'w' )
      {
         moveChar = 'w';
         keyIsHeld = true;
      }
      else if ( c == 'a')
      {
         moveChar = 'a';
         keyIsHeld = true;
      }
      else if ( c == 's')
      {
         moveChar = 's';
         keyIsHeld = true;
      }
      else if ( c == 'd')
      {
         moveChar = 'd';
         keyIsHeld = true;
      }
   }

   public void mouseClicked(MouseEvent e)
   {
      int x = e.getX();
      int y = e.getY();
      if (isInMenu && P1.ClassID == 0)
      {
         if (x < 500 && y > 100 && y < 375)
         {
            P1.ClassID = 1;
            isInMenu = false;
            System.out.println(P1.Pseudo + " has chosen class: Warrior!");
         }
         if (x < 500 && y >= 375)
         {
            P1.ClassID = 3;
            isInMenu = false;
            System.out.println(P1.Pseudo + " has chosen class: UO3!");
         }
         if (x >= 500 && y > 100 && y < 375)
         {
            P1.ClassID = 2;
            isInMenu = false;
            System.out.println(P1.Pseudo + " has chosen class: Thief!");
         }
         if (x >= 500 && y >= 375)
         {
            P1.ClassID = 4;
            isInMenu = false;
            System.out.println(P1.Pseudo + " has chosen class: Mage!");
         }
         repaint();
      }
   }
   public void mouseEntered(MouseEvent e){}
   public void mouseExited(MouseEvent e) {}
   public void mousePressed(MouseEvent e) {}
   public void mouseReleased(MouseEvent e) {}
   public boolean mouseDown(Event e, int x, int y){return true;}

   public void run()
   {
      while (!isInMenu || !firstRun)
      {
         if (moveChar == 'w')
         {
            MovePlayer(0, -moveScale);
         }
         else if (moveChar == 'a')
         {
            MovePlayer(-moveScale, 0);
         }
         else if (moveChar == 's')
         {
            MovePlayer(0, moveScale);
         }
         else if (moveChar == 'd')
         {
            MovePlayer(moveScale, 0);
         }
         Util.wait(200);
         repaint();
      }
   } 

   Thread moveThread;
   Graphics g;
   boolean increaseDecrease = false;

   public void SetUpGraphics(Graphics graphics)
   {
      g = graphics;
   }

   public void start ()
   {
      if (moveThread == null)
      {
         moveThread = new Thread(this);
         moveThread.start();
      }
   }

}

class Map1 extends FinalProjectTest
{
   protected static int wall1x1 = 0;
   protected static int wall1y1 = 500;
   protected static int wall1x2 = 810;
   protected static int wall1y2 = 440;

   protected static int wall2x1 = 1000;
   protected static int wall2y1 = 200;
   protected static int wall2x2 = 190;
   protected static int wall2y2 = 140;
   public Map1(Graphics g)
   {
      Walls wall1 = new Walls(g, wall1x1, wall1y1, wall1x2, wall1y2);
      Walls wall2 = new Walls(g, wall2x1, wall2y1, wall2x2, wall2y2);
   }
}

class HostileObject
{
   private int startPosX, startPosY;
   private int xSize = 35;
   private int ySize = 35;
   public int health = 100;

   public HostileObject(int x, int y)
   {
      startPosX = x;
      startPosY = y;
   }

   public void CreateHostile(Graphics g)
   {
      g.setColor(Util.black);
      //Util.fillRect(g ,startPosX,startPosY,xSize,ySize);
   }
}

class Walls
{
   private static int wallCount = 2;

   public Walls(Graphics g, int x1, int y1, int x2, int y2)
   {
      Util.fillRect(g, x1, y1, x2, y2);
   }
}



class Character extends FinalProjectTest implements MouseListener, Runnable
{
   protected int ClassID = 0;
   protected int PlayerID = 0;
   protected int GP = 100;
   protected String Pseudo = "Muritor";
   protected boolean DebuggingMode = false;
   protected Graphics menuGraphics;
   Thread startMenuThread;

   public Character(Graphics g)
   {
      g.setColor(Util.black);
      Util.fillRect(g, 1, 1, 1000, 650);
      Util.drawButton(g, 1, 1, 1000, 100, "3 Floors", 2);
      Util.wait(1000);
      menuGraphics = g;
      startMenuThread = new Thread(this);
      startMenuThread.start();
   }

   public void run()
   {
      while (Thread.currentThread() == startMenuThread)
      {
         Util.fillRect(menuGraphics, 1, 1, 1000, 650);
         Util.drawButton(menuGraphics, 1, 1, 1000, 100, "Choose a Class", 2);
         Util.drawButton(menuGraphics, 1, 100, 500, 375, "Warrior", 1);
         Util.drawButton(menuGraphics, 501, 100, 1000, 375, "Thief", 1);
         Util.drawButton(menuGraphics, 1, 376, 500, 650, "UO3", 1);
         Util.drawButton(menuGraphics, 501, 376, 1000, 650, "Mage", 1);
         repaint();
         System.out.println("Menu loaded");
         Util.wait(200);
      }
   } 

   public static void ButtonSelection(Graphics g)
   {

   }
}



class Util
{
   static final Color black = Color.black;
   static final Color white = Color.white;

   public static void wait(int mil)
   {
      try
      {
         Thread.sleep((mil));
      }
      catch(InterruptedException ex)
      {
         Thread.currentThread().interrupt();
      }
   }

   public static void fillRect(Graphics g, int x1, int y1, int x2, int y2)
   {
      int widthPlaceholder = x2 - x1;
      int heightPlaceholder = y2 - y1;
      g.fillRect(x1,y1,widthPlaceholder,heightPlaceholder);
   }

   public static void drawButton(Graphics g, int x1, int y1, int x2, int y2, String title, int fontType)
   {
      g.setColor(Util.black);
      int widthPlaceholder = x2 - x1;
      int heightPlaceholder = y2 - y1;
      g.fillRect(x1,y1,widthPlaceholder,heightPlaceholder);
      g.setColor(Util.white);
      widthPlaceholder = x2 - x1;
      heightPlaceholder = y2 - y1;
      for (int k = 0; k < 3; k++)
      {
         g.drawRect(x1+k,y1+k,widthPlaceholder-k,heightPlaceholder-k);
      }
      switch(fontType)
      {
         case 1:
            Font characterCreateButton = new Font("SansSerif", Font.PLAIN, 75);
            g.setFont(characterCreateButton);
            g.drawString(title, x1+100, y1+100);
            break;
         case 2:
            Font characterCreateTitle = new Font("SansSerif", Font.BOLD, 100);
            g.setFont(characterCreateTitle);
            g.drawString(title, x1+25, y1+80);
            break;
         case 3:
            Font mainMenu = new Font("Arial", Font.ITALIC, 50);
            g.setFont(mainMenu);
            break;
      }
   }
}

I expect it to say "Menu Loaded" every .2 seconds and refresh the actual menu screen at the same rate, I get the message, but the applet window is just white.

Problem #1

public class FinalProjectTest extends Applet implements KeyListener, Runnable, MouseListener {

I don't know about you, but when I compile your code, I get

Note: .../FinalProjectTest.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details.

So, if I enable the compiler flag, I get...

Compiling 1 source file to .../build/classes
.../FinalProjectTest.java:18: warning: [deprecation] Applet in java.applet has been deprecated
public class FinalProjectTest extends Applet implements KeyListener, Runnable, MouseListener {
.../FinalProjectTest.java:179: warning: [deprecation] mouseDown(Event,int,int) in Component has been deprecated
    public boolean mouseDown(Event e, int x, int y) {
                   ^
.../FinalProjectTest.java:179: warning: [deprecation] Event in java.awt has been deprecated
    public boolean mouseDown(Event e, int x, int y) {
                             ^
3 warnings

This should be raising alarm bells.

Applets have been actively been deprecated and are simply no longer supported and believe have been removed in the latest versions of the API, seriously time to move on.

In fact, when I run the code, I get:

Warning: Applet API and AppletViewer are deprecated.

Problem #2

public void paint(Graphics g) {
    if (firstRun) {
        firstRun = false;
        isInMenu = true;
        System.out.println("Character Created");
        P1 = new Character(g);
    }
    if (!isInMenu && !firstRun) {
        System.out.println("Game has begun!");
        Map1 firstMap = new Map1(g);
        Looper(g);
    }
}

Painting should paint state, not make logical decisions or change the state, in fact, what's ever more worrying is...

P1 = new Character(g);

You should never maintain a reference to a Graphics context you did not create yourself. The painting system in AWT/Swing uses a shared context, so all components will use the same Graphics context, there's also no guarantee that the context will be the same between paint cycles.

This also highlights that you don't understand how the painting system works in AWT/Swing.

Start with Performing Custom Painting and Painting in AWT and Swing for more details about how painting actually works and how you should work with it

Problem ♾

Okay, so from there on in, every thing else is just compounding based on the above, make a bad situation infinitely worse, for example...

    public void run() {
        while (Thread.currentThread() == startMenuThread) {
            Util.fillRect(menuGraphics, 1, 1, 1000, 650);
            Util.drawButton(menuGraphics, 1, 1, 1000, 100, "Choose a Class", 2);
            Util.drawButton(menuGraphics, 1, 100, 500, 375, "Warrior", 1);
            Util.drawButton(menuGraphics, 501, 100, 1000, 375, "Thief", 1);
            Util.drawButton(menuGraphics, 1, 376, 500, 650, "UO3", 1);
            Util.drawButton(menuGraphics, 501, 376, 1000, 650, "Mage", 1);
            repaint();
            System.out.println("Menu loaded");
            Util.wait(200);
        }
    }

This "might" seem okay, but if you understood how the painting, you'd understand the calling repaint will trigger and paint pass and cause paint to be called again and ... wait, hang on...

class Character extends FinalProjectTest implements MouseListener, Runnable {

Why does Character extend from FinalProjectTest ?? It's not even added to any container which could paint it...oh dear ...

Answer...

Start again.

No, seriously, throw away what you've done and start again. This time start by reading (and understanding)...

  • Basic OO design concepts of "separation of responsibility". Rather then compounding all you logic into a single method, seperate the responsibility of each part of your program into their own class(es). The menu should be a single, stand alone component, the game canvas should be it's own, stand alone component, you should then have a "controller" which can, based on feedback from these components (via a observer pattern ) decide when each should be shown (and how).
  • Model-View-Controller (which bleeds into the previous comment)
  • Performing Custom Painting and Painting in AWT and Swing
  • How to Use Key Bindings because KeyListener is not a good choice here
  • Concurrency in Swing because Swing, like most GUI frameworks, is not thread and is single threaded and you should know how to handle it.
  • How to Make Frames (Main Windows) because Applets are dead
  • How to Use CardLayout as this will help make your lives easier
  • Use JavaFX. At the very least you should be using Swing, but if you can, use JavaFX

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM