一.游戏窗体的建立。
一款游戏肯定是设立在一个基础的窗体上的,首先我们就需要一个能装下所有游戏组件的界面。
public class Gameui extends JFrame {
public void iniUI() {
//界面绘制
this.setTitle("游戏界面");
this.setSize(1000, 800);
this.setDefaultCloseOperation(3);
this.setLayout(new FlowLayout());
this.setVisible(true);
Graphics g = this.getGraphics();
}
@Override
public void paint(Graphics g) {
super.paint(g);
}
public static void main(String[] args) {
Gameui gu=new Gameui();
gu.iniUI();
}
}
二.创建一个所有角色的共有接口
package textgame;
import java.awt.*;
import java.util.ArrayList;
//所有角色共有接口的定义
public interface IRole {
//移动
public void move();
//自我重绘
public void paintself(Graphics G);
//碰撞检测
}
三.创建一个画布类,通过双缓冲的方法将所有元素画在画布上。
public class ThreadDraw extends Thread{
private ArrayList<IRole> ros;
private ArrayList<IRole> remove;
private Graphics g;
public int count=1;
public ThreadDraw (ArrayList<IRole> ros, Graphics g,ArrayList<IRole> remove){
this.ros=ros;
this.g=g;
this.remove=remove;
}
@Override
public void run() {
while (true){
BufferedImage bi=new BufferedImage(1000,800,BufferedImage.TYPE_INT_RGB );
Graphics gb= bi.getGraphics();
for(int i=0;i<this.ros.size();i++){
IRole ro= ros.get(i);
ro.move();
ro.paintself(gb);
}
ros.removeAll(remove);
g.drawImage(bi,0,0,1000,800,null);
count++;
System.out.println(" "+count);
try {
Thread.sleep(20);
}catch (Exception ef){}
}
}
四.创建一个公共队列来存放所有组件里的元素,利用生成消费者的模型,便于对所有要添加删除的元素进行处理。
ArrayList<IRole> ros=new ArrayList<IRole>();
ThreadDraw TD=new ThreadDraw(ros,g,remove);
TD.start();
playerObj plane= new playerObj(this,ros,player,enemy,bullet,remove);
ros.add(plane);
player.add(plane);
五.在此基础下添加所需要的组件如敌机,子弹,玩家。
以玩家为例:
public class tankObj implements IRole {
private int x = 500, y = 300, width, height;
private ArrayList<IRole> ros;
private ArrayList<tankObj> player;
private ArrayList<enemyObj> enemylist;
private ArrayList<bulletObj> bulletlist;
private ArrayList<IRole> removelist;
public double speed;
private ImageIcon tank = new ImageIcon("imgs/Playplane.png");
private Image im = tank.getImage();
public JFrame jf;
public tankObj(JFrame jf, ArrayList<IRole> ros, ArrayList<tankObj> player, ArrayList<enemyObj> enemy, ArrayList<bulletObj> bullet, ArrayList<IRole> remove) {
this.jf = jf;
this.ros = ros;
this.player = player;
this.bulletlist = bullet;
this.enemylist = enemy;
this.removelist = remove;
}
@Override
public void move() {
this.jf.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
}
});
}
@Override
public void paintself(Graphics g) {
g.drawImage(im, x, y, width = 50, height = 50, null);
for (enemyObj enemy : enemylist) {
if ((Math.abs(this.x - enemy.x) < enemy.widht|| Math.abs(enemy.x - this.x) < this.width) && (Math.abs(enemy.y - this.y) < this.height || Math.abs(this.y - enemy.y) < enemy.height) ) {
this.x=-1000;
this.y=-1000;
enemy.x=-1000;
enemy.y=-1000;
explore ep=new explore(this.x,this.y);
ep.paintself(g);
ros.add(ep);
removelist.add(ep);
removelist.add(this);
removelist.add(enemy);
}
}
}
}
因为角色是随鼠标移动所以移动方法里使用的是利用鼠标监听器获得鼠标拖动的位置x,y。再不断的将这个更新的x和y更新给队列,在画板上画出新位置的飞机。
同时在绘制自身的方法中可以通过对两种类队列中的元素位置信息进行判断是否发生了碰撞,再将发生碰撞的元素移除屏幕后再将该元素添加到removelist中好方便后续的删除,以减少内容占用。
六.爆炸效果的实现
通过创建一个image类型的静态数组将一连串的图片存入其中,再遍历数组绘制实现爆炸效果。
public class explorerObj extend IRole{
public int x,y;
public explorerObj (int x,inty){
this.x=x;
this.y=y;
}
static Image[] explodePic=new Image[12];
int explodeCount=0;
static{
for(int i=0;i<explodePic.length;i++){
explodePic[i]=Toolkit.getDefowltToolkit().getImage("image/explode/e"+(i+1)+"gif");
}
}
public void move(){
}
public void paintself(Graphics g) {
super.paintself(g);
if(explodeCount<16){
super.img=explodePic[eexplodeCount]
explodeCount++;
}
g.drawImage(explodePic[explodeCount], x, y, width = 50, height = 50, null);
}
}
再在碰撞位置创建爆炸对象再添加到爆炸集合当中再添加到移除队列中去。实现爆炸效果的实现。
7.添加敌方BOSS单位。
以一个BOSS为例:创建BOSS类与其他类创建类似,添加BOSS需要的图片,重写接口方法,这里需要注意的是,因为BOSS是需要游戏进行一段时候后才能出来,我是以页面的绘制次数为count
if(count==1000&&(!ros.countains(boss1))){
ros.add(boss1);
}
剩下的就是在BOSS类中去补充所需要的常规方法,例如碰撞检测,爆炸。
需要注意的是这里的BOSS的移动方式是在被消灭前一直在窗口内活动。
所以在重新move方法时需要注意
public void move(){
if(y<150){
y+=2}else{
x=-speed;
if(x>800||x<10){
speed=-speed;
}}
}