【问题标题】:Java Turtle Animation IssueJava Turtle 动画问题
【发布时间】:2016-11-29 12:50:05
【问题描述】:

我正在尝试制作一个动画,当您输入以下内容时,两个矩形将出现并从框架中消失:c with Turtle Graphics。但我遇到的问题是我不明白如何将海龟图形合并到循环中。为此,我必须使用 do-while 循环。我还假设我制作的矩形在屏幕上水平移动。我有大致的想法,但我不知道如何使用带有循环的海龟图形。当我尝试在这里设置时,我的代码不是最有序的。

/**
* Write a description of class Animation here.
* 
* @author (author)
* @version 
*/

import java.util.Scanner;
import java.awt.*;
class Animation
{      
//set conditions for turtle to start drawing
public void prepareTurtleToDraw(Turtle myrtle, Color color, int x, int y)
{
   myrtle.hide();
   myrtle.penUp();               //pick up the pen to avoid leaving a trail when moving the turtle
   myrtle.setColor(color);       //set myrtle's color
   myrtle.moveTo(x, y);          //move to coordinates
   myrtle.penDown();             //put the pen down to start drawing
}//end of prepareTurtleToDraw method

//draw a line
public void drawLine(Turtle myrtle, int x1, int y1, int x2, int y2)//, int width)
{
    myrtle.moveTo(x1, y1);      //moves to this coordinate first
    myrtle.moveTo(x2, y2);      //then moves to this coordinate
    //myrtle.setPenWidth(width);  //this adjusts the size of the lines
}//end of drawLine method   

public static void pressC()
{
    String userInput = "";                                  //declare and initialize a String variable
    char key = ' ';                                         //declare and initialize a char variable
    Scanner in = new Scanner(System.in);                    //construct a Scanner object

    System.out.println("Please press the c key to watch the animation.");
    //do-while loop to wait for the user to enter the letter c
    do  
    {
        userInput = in.next();                                  //accept one token from the keyboard
        in.nextLine();                                          //flush the buffer
        key = userInput.charAt(0);                              //picks off the first character from the userInput String variable

    }
    while(key != 'c');                                      //do-while condition statement 

    System.out.println("Thank you. You may continue");

 }//end of main method
}
public class AnimationTester
{
public static void main(String[] args)
{
    //Picture pictureObj = new Picture("");        //create a Picture object for the maze background image, has name and etc.
    World worldObj = new World();                            //create a World object to draw in
    //worldObj.setPicture(pictureObj);                         //set the maze background image in the World object
    Turtle lertle = new Turtle(300, 150, worldObj);             //create a Turtle object to do the drawing
    Animation turt = new Animation();

    Turtle dyrtle = new Turtle(150, 150, worldObj);    

    turt.prepareTurtleToDraw(lertle, Color.BLACK, 250, 150);
    turt.drawLine(lertle, 250, 150, 400, 150);
    turt.drawLine(lertle, 400, 150, 400, 250);
    turt.drawLine(lertle, 400, 250, 250, 250);
    turt.drawLine(lertle, 250, 250, 250, 150);

    turt.prepareTurtleToDraw(dyrtle, Color.RED, 150, 150);
    turt.drawLine(dyrtle, 150, 150, 260, 75);
    turt.drawLine(dyrtle, 260, 75, 335, 150);
    turt.drawLine(dyrtle, 335, 150, 225, 225);
    turt.drawLine(dyrtle, 225, 225, 150, 150);


    System.out.println(worldObj);
}    
}    

【问题讨论】:

    标签: java bluej turtle-graphics


    【解决方案1】:

    好吧,我似乎无法上传我为我的程序拍摄的照片,因为我没有足够的声誉。 谢谢!

    图 1. 按 C 之前

    图 2. 按 C 后


    我为您编写了这个小程序,它在 Java Swing 上运行以创建动画。我有三个矩形,两个 - 红色和蓝色 - 根据经过的秒数淡入和淡出,第三个在按 C 时出现和消失。

    我认为在处理动画时可能对您有帮助的是“game loop”。你可以在下面的 MainFrame.java 中找到我的实现。粗略地说,游戏循环控制动画的更新速度,以便程序在慢速和快速计算机上始终如一地运行。如果未实现游戏循环,则速度较快的计算机可能会比相对较慢的计算机更快地完成动画。

    这是一个完整的程序,只需编译三个.java文件并运行Main即可调出游戏界面。

    Main.java

    import java.lang.reflect.InvocationTargetException;
    
    import javax.swing.SwingUtilities;
    
    public class Main {
        public static void main(String[] args) {
            try {
                SwingUtilities.invokeAndWait(() -> {
    
                    MainFrame mf = MainFrame.getMainFrame();
                    new Thread(mf).start();
    
                });
            } catch (InvocationTargetException | InterruptedException e) {
                System.out.println("Could not create GUI");
            }
        }
    }
    


    MainFrame.java
    import java.awt.BorderLayout;
    
    import javax.swing.JFrame;
    
    class MainFrame extends JFrame implements Runnable {
    
        private static final long serialVersionUID = 1L;
        private DisplayPanel dp;
        private boolean isRunning;
        private double secondsPerFrame = 1.0 / 60.0;
        private static MainFrame mf;
    
        private MainFrame() {
            super("Title");
    
            dp = new DisplayPanel();
            add(dp, BorderLayout.CENTER); // Add display to the center
    
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            pack();
            setVisible(true);
        }
    
        /**
         * Static factory
         *
         * @return A singleton MainFrame
         */
        static MainFrame getMainFrame() {
            return mf == null ? mf = new MainFrame() : mf;
        }
    
        /**
         * Game loop
         */
        @Override
        public void run() {
            isRunning = true;
            int frames = 0;
            double frameCounter = 0;
    
            double lastTime = System.nanoTime() / 1000000000.0;
            double unprocessedTime = 0;
    
            while(isRunning) {
                boolean render = false;
                double startTime = System.nanoTime() / 1000000000.0;
                double passedTime = startTime - lastTime;
                lastTime = startTime;
                unprocessedTime += passedTime;
                frameCounter += passedTime;
    
                while(unprocessedTime > secondsPerFrame) {
                    render = true;
                    unprocessedTime -= secondsPerFrame;
    
                    // Update the state of the rectangles' brightness
                    dp.update(secondsPerFrame);
    
                    if(frameCounter >= 1.0) {
                        // Show fps count. Updates every second
                        dp.setFps(frames);
                        frames = 0;
                        frameCounter = 0;
                    }
                }
                if(render) {
    
                    // Render the rectangles
                    dp.render();
    
                    frames++;
                } else {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException ie) {}
                }
            }
        }
    }
    


    DisplayPanel.java
    import java.awt.Canvas;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.image.BufferStrategy;
    
    // Create a display within the window
    class DisplayPanel extends Canvas implements KeyListener {
    
        private static final long serialVersionUID = 2L;
        private Graphics2D g2; // Drawing tool
        private BufferStrategy strategy; // Drawing tool
        private FadingRectangle[] fadingRectangles; // Appears/disappears based on elapsed time
        private FadingRectangle userControlledRectangle; // Appears/disappears upon command by user
        private int fps; // Used to display the fps on screen
    
        DisplayPanel() {
            setPreferredSize(new Dimension(800, 600));
            addKeyListener(this);
            setFocusable(true);
    
            fadingRectangles = new FadingRectangle[2];
            fadingRectangles[0] = new FadingRectangle(150, 250, 100, 100);
            fadingRectangles[1] = new FadingRectangle(550, 250, 100, 100);
    
            userControlledRectangle = new FadingRectangle(350, 100, 100, 100);
        }
    
        /**
         * Updates the brightness of rectangles
         *
         * @param elapsedSeconds Seconds elapsed since the last call to this method
         */
        void update(double elapsedSeconds) {
            fadingRectangles[0].update(elapsedSeconds);
            fadingRectangles[1].update(elapsedSeconds);
        }
    
        /**
         * Draw everything
         */
        void render() {
            // Prepare drawing tools
            if (strategy == null || strategy.contentsLost()) {
                createBufferStrategy(2);
                strategy = getBufferStrategy();
                Graphics g = strategy.getDrawGraphics();
                this.g2 = (Graphics2D) g;
            }
    
            // Anti-aliasing
            this.g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
            // Clear screen by drawing background on top
            this.g2.setColor(Color.BLACK);
            this.g2.fillRect(0, 0, getWidth(), getHeight());
    
            // Draw the rectangles
            fadingRectangles[0].draw(new Color(255, 0, 0));
            fadingRectangles[1].draw(new Color(0, 0, 255));
            userControlledRectangle.draw(Color.WHITE);
    
            // Draw fps count on the upper left corner
            g2.setColor(Color.WHITE);
            g2.drawString("FPS: " + Integer.toString(fps), 10, 20);
    
            // Set the drawn lines visible
            if(!strategy.contentsLost())
                strategy.show();
        }
    
        /**
         * @param fps The fps to be drawn when render() is called
         */
        void setFps(int fps) {
            this.fps = fps;
        }
    
        /**
         * Used to draw rectangles in the display
         */
        private class FadingRectangle {
            private int x, y, width, height; // Location and size of the rectangle
            private double secondsPassed; // Arbitrary number that determines the brightness of blue
    
            private FadingRectangle(int x, int y, int width, int height) {
                this.x = x;
                this.y = y;
                this.width = width;
                this.height = height;
            }
    
            /**
             * Called by render()
             *
             * @param color The color of the rectangle to be drawn
             */
            private void draw(Color color) {
                // Determine color
                double fade = Math.abs(Math.sin(secondsPassed));
                int red = (int) (color.getRed() * fade);
                int green = (int) (color.getGreen() * fade);
                int blue = (int) (color.getBlue() * fade);
                g2.setColor(new Color(red, green, blue));
    
                // Draw the rectangle
                g2.drawRect(x, y, width, height);
            }
    
            private void update(double elapsedSeconds) {
                secondsPassed += elapsedSeconds;
            }
        }
    
        // A quick and dirty implementation. Should be fixed to make it clearer
        @Override
        public void keyReleased(KeyEvent e) {
            if(e.getKeyCode() == KeyEvent.VK_C) {
                userControlledRectangle.update(Math.PI / 2);
            }
        }
    
        @Override
        public void keyPressed(KeyEvent e) {}
    
        @Override
        public void keyTyped(KeyEvent e) {}
    }
    

    【讨论】:

    • 谢谢你,但问题是,我正在处理一项任务,我必须使用 Turtle Graphics。我正在和我的老师交谈,我对我的代码进行了一些更改和添加,但它仍然不是我需要的地方。我会尽快发布。感谢您的帮助。
    猜你喜欢
    • 2014-04-20
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 2011-08-07
    相关资源
    最近更新 更多