简体   繁体   English

打印一个每秒更新一次的计时器,使其成为一个简单的游戏

[英]Printing a timer that updates every second into a simple game

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.Timer;

public class FinalFlappy implements ActionListener, MouseListener, 
KeyListener
{
public static FinalFlappy finalFlappy;
public final int WIDTH = 800, HEIGHT = 800;
public FinalFlappyRend renderer;
public Rectangle bee;
public ArrayList<Rectangle> rect_column;
public int push, yMotion, score;
public boolean gameOver, started;
public Random rand;

public FinalFlappy()
{
    JFrame jframe = new JFrame();
    Timer timer = new Timer(16, this);

    renderer = new FinalFlappyRend();
    rand = new Random();
    jframe.add(renderer);
    jframe.setTitle("Flappy Bee");
    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jframe.setSize(WIDTH, HEIGHT);
    jframe.addMouseListener(this);
    jframe.addKeyListener(this);
    jframe.setResizable(false);
    jframe.setVisible(true);
    bee = new Rectangle(WIDTH / 2 - 10, HEIGHT / 2 - 10, 40, 40);
    rect_column = new ArrayList<Rectangle>();
    addColumn(true);
    addColumn(true);
    addColumn(true);
    addColumn(true);
    timer.start();
}

public void addColumn(boolean start)
{
    int space = 300;
    int width = 60;
    int height = 50 + rand.nextInt(300);

    if (start)
    {
        rect_column.add(new Rectangle(WIDTH + width + rect_column.size() * 300, HEIGHT - height - 120, width, height));
        rect_column.add(new Rectangle(WIDTH + width + (rect_column.size() - 1) * 300, 0, width, HEIGHT - height - space));
    }
    else
    {
        rect_column.add(new Rectangle(rect_column.get(rect_column.size() - 1).x + 600, HEIGHT - height - 120, width, height));
        rect_column.add(new Rectangle(rect_column.get(rect_column.size() - 1).x, 0, width, HEIGHT - height - space));
    }
}
public void jump()
{
    if (gameOver)
    {
        bee = new Rectangle(WIDTH / 2 - 10, HEIGHT / 2 - 10, 40, 40);
        rect_column.clear();
        yMotion = 0;
        score = 0;
        addColumn(true);
        addColumn(true);
        addColumn(true);
        addColumn(true);
        gameOver = false;
    }
    if (!started)
    {
        started = true;
    }
    else if (!gameOver)
    {
        if (yMotion > 0)
        {
            yMotion = 0;
        }
        yMotion -= 10;
    }
}

@Override
public void actionPerformed(ActionEvent e)
{
    int speed = 10;
    push++;

    if (started)
    {
        for (int i = 0; i < rect_column.size(); i++)
        {
            Rectangle column = rect_column.get(i);

            column.x -= speed;
        }

        if (push % 2 == 0 && yMotion < 15)
        {
            yMotion += 2;
        }

        for (int i = 0; i < rect_column.size(); i++)
        {
            Rectangle column = rect_column.get(i);

            if (column.x + column.width < 0)
            {
                rect_column.remove(column);

                if (column.y == 0)
                {
                    addColumn(false);
                }
            }
        }
        bee.y += yMotion;

        for (Rectangle column : rect_column)
        {
            if (column.y == 0 && bee.x + bee.width / 2 > column.x + column.width / 2 - 10 && bee.x + bee.width / 2 < column.x + column.width / 2 + 10)
            {
                score++;
            }

            if (column.intersects(bee))
            {
                gameOver = true;

                if (bee.x <= column.x)
                {
                    bee.x = column.x - bee.width;

                }
                else
                {
                    if (column.y != 0)
                    {
                        bee.y = column.y - bee.height;
                    }
                    else if (bee.y < column.height)
                    {
                        bee.y = column.height;
                    }
                }
            }
        }

        if (bee.y > HEIGHT - 120 || bee.y < 0)
        {
            gameOver = true;
        }

        if (bee.y + yMotion >= HEIGHT - 120)
        {
            bee.y = HEIGHT - 120 - bee.height;
            gameOver = true;
        }
    }

    renderer.repaint();
}
public void paintColumn(Graphics g, Rectangle column)
{
    g.setColor(Color.green.darker());
    g.fillRect(column.x, column.y, column.width, column.height);
    g.fillRect(column.x-20, column.y+column.height-10, column.width+40, 10);
    g.fillRect(column.x-20, column.y-10, column.width+40, 10);

}

public void repaint(Graphics g)
{
    g.setColor(new Color(153,204,255));
    g.fillRect(0, 0, WIDTH, HEIGHT);
    g.setColor(new Color(255,255,255));
    g.fillOval(50, 50, 100, 100);
    g.setColor(Color.YELLOW);
    g.fillOval(600, 50, 100, 100);
    g.setColor(new Color(156,93,82));
    g.fillRect(0, HEIGHT - 120, WIDTH, 120);
    g.setColor(new Color(128,255,0));
    g.fillRect(0, HEIGHT - 120, WIDTH, 20);
    g.setColor(Color.YELLOW);
    g.fillRect(bee.x, bee.y, bee.width, bee.height);

    for (Rectangle column : rect_column)
    {
        paintColumn(g, column);
    }

    g.setColor(Color.white);
    g.setFont(new Font("Times New Roman", 1, 100));

    if (!started)
    {
        g.drawString("Push A to start", 100, HEIGHT / 2 - 50);
    }

    if (gameOver)
    {
        g.drawString("Game Over", 100, HEIGHT / 2 - 50);
        g.drawString("A to replay", 100, HEIGHT / 2 + 90);
    }
}

public static void main(String[] args)
{
    finalFlappy = new FinalFlappy();
}

@Override
public void mouseClicked(MouseEvent e)
{
    jump();
}

@Override
public void keyReleased(KeyEvent e)
{
    if (e.getKeyCode() == KeyEvent.VK_A)
    {
        jump();
    }
}

@Override
public void mousePressed(MouseEvent e)
{
}

@Override
public void mouseReleased(MouseEvent e)
{
}

@Override
public void mouseEntered(MouseEvent e)
{
}

@Override
public void mouseExited(MouseEvent e)
{
}

@Override
public void keyTyped(KeyEvent e)
{

}

@Override
public void keyPressed(KeyEvent e)
{

}

}

import java.awt.Graphics;
import javax.swing.JPanel;

public class FinalFlappyRend extends JPanel
{
@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent(g);

    FinalFlappy.finalFlappy.repaint(g);
}

}

I am working on making a Flappy bird game and I am stuck on how to make and display a timer that updates every second onto the screen How do I make it start as the game starts and end as the game over pops up? 我正在制作《飞扬的飞鸟》游戏,并且坚持制作和显示每秒钟更新一次的计时器到屏幕上,如何在游戏开始时启动它,在游戏弹出时结束呢?

There are a few ways you might achieve what you're asking. 您可以通过几种方法来实现自己的要求。 The important thing to remember is, any solution is going to have a degree of drift, meaning that it's unlikely to absolutely accurate, the degree of drift will depend on a lot of factors, so just beware. 要记住的重要一点是,任何解决方案都将具有一定程度的漂移,这意味着它不可能绝对准确,漂移的程度取决于很多因素,所以请提防。

You could use a Swing Timer 您可以使用Swing Timer

It's among the safest means for updating the UI on a regular basis, it's also useful if your main loop is already based on a Swing Timer 这是用于定期更新UI的最安全的方法之一,如果您的主循环已经基于Swing Timer ,它也很有用。

See How to Use Swing Timers for more details 有关更多详细信息,请参见如何使用Swing计时器

You could... 你可以...

Maintain some kind of counter within in your main loop. 在主循环中维护某种计数器。 This assumes that you're using a separate thread (although you can do the same thing with a Swing Timer ) and are simply looping at some consistent rate 假设您使用的是单独的线程(尽管您可以使用Swing Timer做同样的事情),并且只是以一致的速率循环

long tick = System.nanoTime();
long lastUpdate = -1;
while (true) {
    long diff = System.nanoTime() - tick;
    long seconds = TimeUnit.SECONDS.convert(diff, TimeUnit.NANOSECONDS);
    if (seconds != lastUpdate) {
        lastUpdate = seconds;
        updateTimerLabel(seconds);
    }
    Thread.sleep(100);
}

This basically runs a while-loop , which calculates the difference between a given point in time ( tick ) and now, if it's a "second" difference, it then updates the UI (rather than constantly updating the UI with the same value) 这基本上运行一个while-loop ,该while-loop计算给定时间点( tick )和现在之间的差异,如果是“第二”差异,则将更新UI(而不是用相同的值不断更新UI)

The updateTimerLabel method basically updates the label with the specified time, but does so in a manner which is thread safe updateTimerLabel方法基本上以指定的时间更新标签,但是这样做是线程安全的

protected void updateTimerLabel(long seconds) {
    if (EventQueue.isDispatchThread()) {
        timerLabel.setText(Long.toString(seconds));
    } else {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                updateTimerLabel(seconds);
            }
        });
    }
}

To make and display a timer that updates every second, Put this code in your main class: 要制作并显示每秒更新的计时器,请将以下代码放入主类:

private Timer timer = new Timer();
private JLabel timeLabel = new JLabel(" ", JLabel.CENTER);

timer.schedule(new UpdateUITask(), 0, 1000);

private class UpdateUITask extends TimerTask {

    int nSeconds = 0;

    @Override
    public void run() {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                timeLabel.setText(String.valueOf(nSeconds++));
            }
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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