前二篇记录了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小游戏框架搭建完毕!以后我们要做的就是考虑游戏的逻辑,用面向对象编程的思想来做游戏。我已经搞定一个小游戏,下篇笔记重点推出。