尽管运行代码显示菜单,Java小程序仍显示白屏

时间:2019-04-20 00:14:39

标签: java multithreading applet

我有一个小游戏,我和一个朋友正在为我们的计算机科学课做工。我们试图使一个菜单在小程序的开头打开,然后在1秒钟后显示一个班级选择屏幕。但是,一秒钟后,屏幕只是变成白色,但输出分配的打印语句来指示已加载类选择屏幕,我不确定为什么会发生这种情况,并想解决这个问题。

我试图将代码显示在另一个线程中显示类选择屏幕,以便在运行时没有其他阻止它运行的操作,但是,这并没有改变。我还确保了显示屏幕的条件是正确的,并且每0.2秒显示一次,但似乎没有任何效果。我试图使代码在角色的构造函数中运行,并且应该运行一次,然后运行一次,但是运行一次的问题是它会立即退出菜单并转到游戏的下一个阶段没有理由。

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;
      }
   }
}

我希望它每隔0.2秒钟说一次“菜单已加载”,并以相同的速率刷新实际菜单屏幕,我收到消息,但是小程序窗口只是白色。

1 个答案:

答案 0 :(得分:1)

问题1

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

我不认识你,但是当我编译你的代码时,我得到了

  

注意:... / FinalProjectTest.java使用或覆盖不推荐使用的API。   注意:有关详细信息,请使用-Xlint:deprecation重新编译。

因此,如果启用了编译器标志,则会得到...

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

这应该引起警钟。

Applet已被弃用,不再受支持,并且认为已在最新版本的API中将其删除,这是一个非常重要的时间。

事实上,当我运行代码时,我得到:

  

警告:不建议使用Applet API和AppletViewer。

问题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);
    }
}

绘画应该描绘状态,而不是做出逻辑决定或改变状态,实际上,更令人担忧的是...

P1 = new Character(g);

您永远不应保留对自己没有创建的Graphics上下文的引用。 AWT / Swing中的绘制系统使用共享的上下文,因此所有组件都将使用相同的Graphics上下文,也不能保证在绘制周期之间上下文将是相同的。

这也突出表明您不了解绘画系统在AWT / Swing中的工作方式。

Performing Custom PaintingPainting in AWT and Swing开始,以获取有关绘画实际工作方式以及如何使用绘画的更多详细信息

问题♾

好的,因此,从此以后,其他所有事情都只会基于上述情况而变得复杂,例如,使糟糕的局面变得更糟……

    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);
        }
    }

这种“可能”似乎还可以,但是如果您了解绘画的方式,您就会知道调用repaint将触发并绘制传递,并导致paint被再次调用并...等待,等等...

class Character extends FinalProjectTest implements MouseListener, Runnable {

为什么CharacterFinalProjectTest扩展出来?它甚至没有被添加到任何可以绘画的容器中...哦,亲爱的...

答案...

重新开始。

不,认真地,放弃您所做的一切,然后重新开始。这次从阅读(和理解)开始...

  • “责任分离”的基本OO设计概念。而不是将所有逻辑组合到一个方法中,而是将程序各部分的职责划分为各自的类。菜单应该是一个单独的独立组件,游戏画布应该是它自己的独立组件,然后应该有一个“控制器”,它可以基于这些组件的反馈(通过observer pattern)来决定什么时候应该显示每个(以及如何显示)。
  • Model-View-Controller(渗入上一个评论)
  • Performing Custom PaintingPainting in AWT and Swing
  • How to Use Key Bindings,因为KeyListener在这里不是一个好选择
  • Concurrency in Swing,因为Swing与大多数GUI框架一样,不是线程的,而是单线程的,您应该知道如何处理它。
  • How to Make Frames (Main Windows),因为小程序已死
  • How to Use CardLayout,因为这将使您的生活更轻松
  • 使用JavaFX。至少您应该使用Swing,但如果可以,请使用JavaFX