如何为我的 java 游戏创建开始屏幕?

How can I create a start screen for my java game?

我怎样才能使我的小程序进入起始页然后进入游戏?所以有一个开始按钮,一个退出按钮,当我点击开始时,游戏才开始。由于我是初学者,请尽可能简单地回答。谢谢 :)


Main.java

   import java.awt.Graphics;

   public class Main extends GameLoop {
/**
 * 
 */
    private static final long serialVersionUID = 1L;


     public void init(){
       setSize(960,540);
       Thread th = new Thread(this);
       th.start();
       offscreen = createImage(960,540);
       c = offscreen.getGraphics();
       addKeyListener(this);
   }
   public void paint(Graphics g)
   {
    c.clearRect(0,0,960,480);
    c.drawImage(background, 0, 0, this);
    c.drawImage(mario, x, y, 100, 100, this);
    c.drawImage(goomba, ax, ay, 30, 30, this);
    c.drawImage(foreground, 0, 0 , this ); 
    c.drawImage(pipes, 0, 0, this);
    c.drawImage(block1, 0,  0, this);
    c.drawImage(block2, 0,  0, this);
    c.drawImage(block3, 0,  0, this);
    c.drawImage(block4, 0,  0, this);
    c.drawImage(block5, 0,  0, this);
    c.drawImage(block6, 0,  0, this);
    c.drawImage(block7 , 0, 0, this);
    //c.drawImage(blocks, 0, 0, this);
    g.drawImage(offscreen, 0 , 0 ,this);

}
@Override
public void update(Graphics g){
    paint(g);
}

}


GameLoop.java

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class GameLoop extends Applet implements Runnable, KeyListener {

/**
 * 
 */
private static final long serialVersionUID = 1L;
public int x,y,ax,ay;
public Image offscreen;
public Graphics c;
public boolean jump,down,right,left;
public BufferedImage background, foreground, pipes, blocks, block1, block2,        block3, block4, block5, block6, block7,  walk2, walk3, walk4, walk5, walk6,   jumpR,jumpL, mario, goomba, deadMario, money, block;
public BufferedImage Bblock1, Bblock2, Bblock3;
public int wow;
public int wow2;
public double counter = 4;
public int MaxH, MidH, MinH, delta;




@Override
public void run() {
    x = 60;
    y = 440;
    ax = x +5;
    ay = 493;
    MinH = 440;


    try {
        background = ImageIO.read(new File("resources/background1.png"));
        foreground = ImageIO.read(new File("resources/foreground1.png"));
        blocks = ImageIO.read(new File("resources/blocks1.png"));
        pipes = ImageIO.read(new File("resources/pipes1.png"));
        walk2 = ImageIO.read(new File("resources/walk2.png"));
        walk3 = ImageIO.read(new File("resources/walk3.png"));
        walk4 = ImageIO.read(new File("resources/walk4.png"));
        walk5 = ImageIO.read(new File("resources/walk5.png"));
        walk6 = ImageIO.read(new File("resources/walk6.png"));
        jumpR = ImageIO.read(new File("resources/jumpR.png"));
        jumpL = ImageIO.read(new File("resources/jumpL.png"));
        goomba = ImageIO.read(new File("resources/goomba.gif"));
        deadMario = ImageIO.read(new File("resources/deadmario.png"));
        money = ImageIO.read(new File("resources/money.png"));
        block = ImageIO.read(new File("resources/Block.png"));
        block1 = ImageIO.read(new File("resources/block1.png"));
        block2 = ImageIO.read(new File("resources/block2.png"));
        block3 = ImageIO.read(new File("resources/block3.png"));
        block4 = ImageIO.read(new File("resources/block4.png"));
        block5 = ImageIO.read(new File("resources/block5.png"));
        block6 = ImageIO.read(new File("resources/blocks6.png"));
        block7 = ImageIO.read(new File("resources/block7.png"));
        Bblock1 = ImageIO.read(new File("resources/Bblock1.png"));
        Bblock2 = ImageIO.read(new File("resources/Bblock2.png"));
        Bblock3 = ImageIO.read(new File("resources/Bblock3.png"));
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    mario = walk2;
    while(true)
    {
        if (y <=440&& jump != true){
            y += 5;

        }
        if (y <=175){
            y = MinH;
        }

    if(ax != 475 && ax < 475){
        ax++;
    }
    if(ax >= 475 && ax != 60){
        ax = ax - 475;
        repaint();
    }
    if(x >= 468 && x <= 546){
        y=385;
    }
    if(x >= 736 && x <= 826){
        y=355;
    }

    if(x >= 160 && x <= 200 && y < 440 && y > 400){
        y = MinH;
            block1 = block; 

                }

    if(x >= 264 && x <= 338 && y < 440 && y > 400){
        y = MinH;
        block3 = Bblock1;
                }
    if(x >= 339 && x <=410 && y < 440 && y > 400){
        y = MinH;
        block5 = Bblock2;
                }

    if (block1 == block && y >=  440){
        c.drawImage(money, 210, 332,30,20, this);

    }
    if (block3 == Bblock1 && y >=  440){
        c.drawImage(money, 337, 332,30,30, this);

    }
    if (block5 == Bblock2 && y >=  440){
        c.drawImage(money, 395, 332,30,30, this);

    }




        wow++;
        wow2++;
        if(wow >= 20){
            wow = 0;
        }
        if(wow <= 5 && right == true){
            mario = walk2;
        }
        if(wow >= 5 && wow <=10 && right == true){
            mario = walk2;
        }
        if(wow <= 10 && wow >=5 && right == true){
            mario = walk5;
        }
        if(wow >= 10  && wow <=5 &&right == true){
            mario = walk2;
        }


        if(wow2 >= 20){
            wow2 = 0;
        }
        if(wow2 <= 5 && left == true){
            mario = walk3;
        }
        if(wow2 >= 5 && left == true){
            mario = walk6;
        }
        if(wow2 <= 10 && wow >=5 && left == true){
            mario = walk6;
        }
        if(wow2 >= 10  && wow <=5 && left == true){
            mario = walk3;
}   


    if(left == true){
        x-=2;

    }
    if(right == true){
        x+=2;

    }
    if(jump == true){
        counter += 0.1;
     y = y + (int) ((Math.sin(counter ) + Math.cos(counter))*15.5); 

    }
    if(counter == 7){
        counter = 4;
    }
    if(down == true){
        y+=2;

    }

if(y >= MinH ){
        y = MinH;
}

    System.out.println("(" + x + "," + y + ")");
    repaint();

    try {
        Thread.sleep(20);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }

}


@Override
public void keyTyped(KeyEvent e) {
// don't use

}


@Override
public void keyPressed(KeyEvent e) {
    if(e.getKeyCode() == 37 ){
        left = true;
        }
    if(e.getKeyCode() == 38){
        jump = true;
        mario = jumpR;
    }
    if(e.getKeyCode() == 39){
        right = true;
    }
    if(e.getKeyCode() == 40){
        down = true;
    }

}


@Override
public void keyReleased(KeyEvent e) {
    if(e.getKeyCode() == 37){
        left = false;   
        mario = walk3;
    }
    if(e.getKeyCode() == 38){
        jump = false;
        mario = walk2;
        counter = 4;


    }
    if(e.getKeyCode() == 39){
        right = false;
        mario = walk2;
    }
    if(e.getKeyCode() == 40){
        down = false;
        mario = walk2;
    }
}

}

你需要跟上状态。例如,您将有一个 START 状态和一个 运行 状态。如果游戏处于 START 状态,那么您将绘制开始屏幕,如果它处于 运行 状态,您将绘制游戏。稍后您可能会有暂停状态和 GAME_OVER 状态,因此您可以在那里显示不同的屏幕。

因此,要做到这一点,您需要一个像这样的 State 枚举:

public enum State
{
    START, RUNNING, PAUSE, GAME_OVER;
}

然后在您的 GameLoop 中 class 创建一个变量来保存当前状态。

private State state = State.START;

然后在您的绘制代码和任何其他必要的地方,您可以检查当前状态变量并绘制适当的屏幕。

public void run()
{
    switch(state)
    {
    case START:
        //DRAW THE START SCREEN
        break;
    case RUNNING:
        //DRAW THE GAME
        break;
    case PAUSE:
        //DRAW THE PAUSE SCREEN
        break;
    case GAME_OVER:
        //DRAW THE GAME OVER SCREEN
        break;
    default:
        throw new RuntimeException("Unknown state: " + state);
    }
}

一个更干净的解决方案是让屏幕 class 具有绘制方法。然后你的 GameLoop 只是查找与给定状态关联的屏幕并调用它的 draw 方法。通过这种方式,您的绘图代码可以整齐地隐藏在每个屏幕中,而不是全部集中在一个地方。随着屏幕数量的增加,您只需添加另一个屏幕实现即可。下面是一些代码来说明我的意思:

这是一个屏幕界面。每个州都有一个 Screen 实现。

public interface Screen
{
    void update();
    void draw();
    void handleInput();
}

这是一个 RunningScreen 的空例子。

public class RunningScreen implements Screen
{
    @Override
    public void update()
    {
        //UPDATE LOGIC, MOVE ENTITIES OR WHATEVER
    }

    @Override
    public void draw()
    {
        //DRAW THE RUNNING SCREEN
    }

    @Override
    public void handleInput()
    {
        //CHECK FOR USER INPUT AND UPDATE THE SCREEN STATE
    }

}

这是一个空白的 StartScreen 示例。

public class StartScreen implements Screen
{

    @Override
    public void update()
    {
        //UPDATE THE START SCREEN
    }

    @Override
    public void draw()
    {
        //DRAW THE START SCREEN
    }

    @Override
    public void handleInput()
    {
        //CHECK FOR INPUT, TRANSITION TO THE RUNNING SCREEN WHEN THE USER CLICKS START
    }

}

您的游戏循环查找已注册以处理当前状态的屏幕,然后调用适当的方法。

public class GameLoop
{
    private State state = State.START;
    private Map<State, Screen> screens = new HashMap<>();

    public void addScreen(State state, Screen screen)
    {
        screens.put(state, screen);
    }

    public void run()
    {
        Screen screen = screens.get(state);
        screen.handleInput();
        screen.update();
        screen.draw();
    }
}

那么您的 Main 可能看起来像这样。它创建一个新的 GameLoop 并为每个状态注册屏幕。

public class Main
{
    public static void main(String[] args)
    {
        GameLoop game = new GameLoop();
        game.addScreen(State.START, new StartScreen());
        game.addScreen(State.RUNNING, new RunningScreen());
        //Add other states here
        game.run();
    }
}

我希望这能给您一些关于如何实现您想要的功能的想法。