JAVA游戏编程学习笔记(三)Java 2D游戏底层绘图框架

前二篇记录了java如何绘制图形与动画,今天打算总结复习一下,把这些知识点集合起来,制作一个Java2D小游戏框架(暂且这么叫,好像挺牛逼似的!)。


Java AWT 下边提供一个 class 

Canvas

这是一个现成的画布,我们可以继承它来实现底层的绘制框架,为什么不直接继承JFrame?之前只是一些绘图测试,方便建立场景绘制图形,以后我们的游戏画布需要放到GUI容器里,所以继承一个类似panel的组件比较好些。


好了,底层的绘制框架实现起来很简单,代码如下:

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Image;

/**
 * 基于Java AWT Canvas 创建的游戏画布框架 用来绘制整个游戏的画布。
 *
 * @author J_sky
 * @version 1.0.0 2015-11-04
 */
public class MyGameCanvas extends Canvas {

    /**
     * 双缓冲的画布
     */
    Image iBuffer;
    /**
     * 双缓冲的画笔
     */
    Graphics gBuffer;

    /**
     * 构造器 初始化画板
     *
     */
    public MyGameCanvas() {
        new PaintThread().start();
    }

    /**
     * 定义一个重绘窗口的线程类,是一个内部类。 通过线程中的循环来控制动画的间隔时间。
     */
    class PaintThread extends Thread {

        @Override
        public void run() {
            while (true) {
                try {
                    repaint();//重绘画布
                    Thread.sleep(30);//间隔时间
                } catch (InterruptedException ex) {
                    System.out.println(ex);
                }
            }
        }

    }

    /**
     * 绘图方法,继承后可以重写这个方法来绘制场景及游戏元素,就可以不用。 我们制作游戏动画绘制场景主要是利用这个方法来实现。
     * 可以避免过于重写继承来的方法。也为后继加入双缓冲做准备。
     *
     * @param src
     */
    public void draw(Graphics g) {

    }

    /**
     * 重写这个方法并加入了双缓冲!
     *
     * @param g
     */
    @Override
    public void paint(Graphics g) {
        if (iBuffer == null) {
            iBuffer = createImage(this.getSize().width, this.getSize().height);
            gBuffer = iBuffer.getGraphics();
        }

        gBuffer.setColor(getBackground());
        gBuffer.fillRect(0, 0, this.getSize().width, this.getSize().height);
        draw(gBuffer);

        g.drawImage(iBuffer, 0, 0, this);
    }

    /**
     * 双缓冲重写
     *
     * @param g
     */
    @Override
    public void update(Graphics g) {

        paint(g);
    }

}


这段代码我已经实现了双缓冲,关于JAVA 双缓冲不明白的,可以百度了解一下,这里不再重复。我们只要记得draw()这方法,以后绘图都是在这里啦!


其实双缓冲JPane组件已经实现,那么我们继承JPane这个组件来实现框架试试,代码如下:

package mygameframe;

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

/**
 * 基于swing.JPanel创建的游戏画布框架 用来绘制整个游戏的画布。
 *
 * @author J_sky
 * @version 1.0.0 2015-11-06 [email protected]
 */
public class MyGameJpane extends JPanel {

    /**
     * 构造器 初始化画板
     *
     */
    public MyGameJpane() {
        new PaintThread().start();//启动线程刷新。
    }

    /**
     * 定义一个重绘窗口的线程类,是一个内部类。 通过线程中的循环来控制动画的间隔时间。
     */
    class PaintThread extends Thread {

        @Override
        public void run() {
            while (true) {
                try {
                    repaint();//重绘画布
                    Thread.sleep(30);//间隔时间
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }

    }

    /**
     * 绘图方法,继承后可以重写这个方法来绘制场景及游戏元素,就可以不用。 我们制作游戏动画绘制场景主要是利用这个方法来实现。
     * 可以避免过于重写继承来的方法。也为后继加入双缓冲做准备。
     *
     * @param src
     */
    public void draw(Graphics g) {

    }

    /**
     * JPanel 双缓冲绘图的方法是paintComponent() 我们重写实现绘图。
     *
     * @param g
     */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.\
        draw(g);
    }

    /**
     * 重写update()也是双缓冲的必须。
     *
     * @param g
     */
    @Override
    public void update(Graphics g) {
        super.update(g); //To change body of generated methods, choose Tools | Templates.
        paintComponent(g);//双缓冲绘制
    }

}

相对之前的框架代码量要少些,我们来测试一下:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import mygameframe.MyGameJpane;

/**
 * Java2D游戏框架测试
 *
 * @author J_sky
 * @version 1.0.0 2015-11-06 [email protected]
 */
public class GameTest03 extends MyGameJpane {

    int x = 50;
    int y = 50;
    int width = 100;
    int height = 100;
    //动画变化转折点
    boolean isW = true;
    boolean isH = true;

    /**
     * 重写这个绘图的方法来绘制场景中的元素
     *
     * @param g
     */

    @Override
    public void draw(Graphics g) {
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());//绘制游戏窗口背景
        g.setColor(Color.red);
        g.fillOval(x, y, width, height);
        move();
    }

    /**
     * 圆形的移动逻辑
     */
    private void move() {
        //圆形一直下落,知道屏幕底部,就回到顶部重新下落。
        if (y < this.getHeight()) {
            y++;
        } else {
            y = 0;
        }
        //缩小方形
        if (width > 1 && isW) {
            width--;
        } else {
            isW = false;
        }

        if (height > 1 && isW) {
            height--;
        } else {
            isH = false;
        }

        //放大方形
        if (width < 100 && !isW) {
            width++;
        } else {
            isW = true;
        }

        if (height < 100 && !isW) {
            height++;
        } else {
            isH = true;
        }

    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("游戏窗口!");
        frame.setVisible(true);
        frame.setDefaultCloseOperation(3);
        GameTest03 gc = new GameTest03();
        gc.setPreferredSize(new Dimension(400, 300));
        frame.add(gc);
        frame.pack();

    }

}

大家可以跑起来看看,至此,我们的Java2D小游戏框架搭建完毕!以后我们要做的就是考虑游戏的逻辑,用面向对象编程的思想来做游戏。我已经搞定一个小游戏,下篇笔记重点推出。

你可能感兴趣的:(JAVA游戏编程学习笔记(三)Java 2D游戏底层绘图框架)