JAVA零基础学习之路(三十)

飞机大战

简介和项目

通过游戏项目学习整个Java基础知识体系。比如:多线程用来实现动画效果、容器实现对于多发炮弹的存取和处理、常用类等等的应用。

大纲知识点要求

游戏项目基本功能开发AWT基本知识了解

ImagelO 加载图片掌握

多线程和内部类了解

双缓冲技术了解

飞机类设计键盘控制了解

八个方向自由控制了解

类的设计(复习面向对象)理解

炮弹类设计炮弹任意角度飞行了解

容器或数组存储炮弹了解

矩形碰撞检测了解

爆炸类设计利用数组实现系列图片轮播了解

主窗囗中实现爆炸对象展示了解

时间控制了解

字符串显示了解

游戏项目基本功能开发

AWT技术画出游戏主窗口

基本功能实现

AWT和Swing是Java中常见的GUI(图形用户界面)技术。仅限于画出最基本的窗口和图形加载,所以,大家无需在此花大量时间学习这两门技术。

本项目中,我们使用的是 AWT技术,它是Java中最老的GUI技术,非常简单。

建立Java项目,并建立类MyGameFrame。

import java.awt.*;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

public class MyGameFrame extends Frame {

    //初始化窗口

    public void launchFrame(){

        this.setTitle("飞机大战");

        this.setvisible(true);//窗口默认不可见。需要让他可见

        this.setSize(width: 500, height: 500);

        this.setLocation(x:300, y:300);

        //增加关闭窗口的动作

        this.addWindowListener(new WindowAdapter() {

            @Override

            public void windowClosing(WindowEvent e) {

                System.exit(status:0);

            }

        });

    }

    public static void main(String[] args) {

        MyGameFrame frame = new MyGameFrame();

        frame.LaunchFrame();

    }

}

图形和文本绘制

paint方法

1.如果要在窗口中画图或者显示什么内容,重写paint(Graphics g)方法。

2. paint()画出窗口及其内部内容。它会被系统自动调用。我们不需要去调用这个方法。

【例】paint方法介绍

@Override

public void paint(Graphics g) {

    //paint方法作用是:画出整个窗口及内部内容。被系统自动调用。

}

ImagelO实现图片加载技术

public class MyGameFrame extends Frame {

    Image bg = GameUtil.getImage(path:"images/bg.jpg");

    Image plane = GameUtil.getImage(path:"images/plane.png");

    //初始化窗口

    public void launchFrame(){...}

    @Override

    public void paint(Graphics g) {

        g.drawImage(bg, x:0, y:0, width:500, height:500, observer: null);

        g.drawImage(plane, x: 200, y:200, width: 30, height:30, observer: null);

    }

    public static void main(String[] args] {

        MyGameFrame frame = new MyGameFrame();

        frame.launchFrame();

    }

}

双缓冲技术解决闪烁问题

在实际开发中,绘制图形是非常复杂的,绘图可能需要几秒甚至更长时间,也经常发生闪烁现象,为了解决这个问题,我们通常使用“双缓冲技术”。

“双缓冲技术”的绘图过程如下:

1、在内存中创建与画布一致的缓冲区

2、在缓冲区画图

3、将缓冲区位图拷贝到当前画布上

4、释放内存缓冲区

双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。

我们只需将如下“双缓冲”实现代码,放入MyGrameFrame 类中,即可:

【例】添加双缓冲技术

private Image offScreenImage = null;

public void update(Graphics g) {

    if(offScreenlmage == null)

        offScreenlmage=this.createlmage(500,500);//这是游戏窗口的宽度和高度

    Graphics gOff = offScreenlmage.getGraphics();

    paint(gOff);

    g.drawlmage(offScreenlmage, 0, 0, null);

}

GameObject类设计

import java.awt.*;

//游戏物体的根类

public class GameObject {

    Image img;//对应的图片

    int x,y;//坐标

    int speed;//物体移动速度

    int width,height;//物体的宽度和高度

    //画自己

    public void drawMySelf(Graphics g){

        g.drawImage(img,x,y,width,height, observer: null);

    }

    //返回该物体对应的矩形

    public Rectangle getRec(){

        return new Rectangle(x,y,width,height);

    }

    public GameObject(){}

    public GameObject(Image img, int x, int y, int speed, int width, int height){

        this.img = img;

        this.x = x;

        this.y = y;

        this.speed = speed;

        this.width = width;

        this.height = height;

    }

    public Game0bject(Image img, int x, int y, int speed) {

        this(img,x,y);

        this.speed = speed;

    }

    public Game0bject(Image img, int x, int y) {

        this(img);

        this.x = x;

        this.y =y;

    }

    public GameObject(Image img) {

        this.img =img;

        if(this.img!=null){

            this.width = img.getWidth(observer:null);

            this.height = img.getHeight(observer:null);

        }

    }

}

设计飞机类

有了GameObject类,设计飞机类特别简单。

飞机是我们游戏中的主物体,需要由玩家直接控制,手段有:键盘、鼠标、触摸屏等等。无论是什么硬件,本质上都是玩家通过硬件改变游戏物体的坐标,从而实现多种多样的效果。

键盘控制原理

键盘和程序交互时,每次按下键、松开键都会触发相应的键盘事件,事件的信息都封装到了KeyEvent 对象中。

为了识别按下的键是哪个键,系统对键盘所有按键做了编号,每个按键都对应相应的数字。比如:回车键对应数字10,空格键对应数字32等。这些编号,我们都可以通过KeyEvent对象来查询,KeyEvent.VKENTER实际就是存储了数字10。

增加操控功能

我们为飞机类增加了4个方向,用来控制飞机的移动。同时,为了后续需求,也增加了live变量,它表示飞机是“活的”还是“死的”,“活的”我们就画出飞机,“死的”就不画飞机了。

【例】Plane类:增加操控功能

package com.bjsxt.plane;

import java.awt.Graphics;

import java.awt.Image;

import java.awt.event.KeyEvent;

public class Plane extends GameObject {

    boolean left, up, right, down;

    boolean live = true;

    //按下上下左右键,则改变方向值。

    //比如:按下上键,则e.getKeyCode()的值就是VK_UP,那么置:up=true;

    public void addDirection(KeyEvent e) {

        switch (e.getKeyCode()) {

        case KeyEvent.VK LEFT:

            left = true;

            break;

        case KeyEvent.VK UP:

            up = true;

            break;

        case KeyEvent.VK RIGHT:

            right = true;

            break;

        case KeyEvent.VK DOWN:

            down = true;

            break;

        default:

            break;

        }

    }

    @Override

    public void drawMySelf(Graphics g) {

        super.drawMySelf(g);

        //根据方向,计算飞机新的坐标

        if(left){

            x -= speed;

        }

        if(right){

            ×+=speed;

        }

        if(up){

            y -= speed;

        }

        if(down){

            y += speed;

        }

    }

}

炮弹类设计

通过炮弹类的设计,我们可以更深入面向对象编程以及数组的知识。同时,可能还需要读者稍微回忆一下初中数学曾学过的三角函数,这样更能理解炮弹飞行路径的计算原理。当然,如果忘记这些知识了也没关系,毕竟在实际开发中很少涉及数学原理性的内容。

炮弹类我们用实心的黄色椭圆实现,不再加载新的图片。当然,大家可以自行找一些炮弹图片亦可。

我们的逻辑是在窗口固定位置(200,200)处生成炮弹,炮弹方向是随机的,并且遇到边界会反弹。

【例】Shell类

package com.bjsxt.plane;

import java.awt.Color;

import java.awt.Graphics;

public class Shell extends GameObject {

    double degree;

    public Shell(){

        degree = Math.random()*Math.P*2;

        ×=200;

        y=200;

        width = 10;

        height = 10;

        speed = 3;

        //炮弹沿着任意角度飞行

        × += speed*Math.cos(degree);

        y += speed*Math.sin(degree);

        //如下代码,用来实现碰到边界,炮弹反弹回来(原理和打台球游戏一样)

        if(y>Constant.GAME HEIGHT-height|ly<30){

            degree = -degree;

        }

        if(x<O||x>Constant.GAME_ WIDTH-width){

            degree = Math.P/-degree;

        }

        //返回给外部,变回以前的颜色

        g.setColor(c);

    }

}

炮弹任意角度飞行路径

炮弹沿着任意角度飞行,核心代码就两行:

× += speed*Math.cos(degree);

y += speed*Math.sin(degree);

这里实际用到了初中学的三角函数,通过cos/sin将任意角度分解到×轴、Y轴,从而可以精确的直到x、y坐标的变化情况。

碰撞检测技术

游戏中,碰撞是遇到最频繁的技术。当然,很多游戏引擎内部已经做了碰撞检测处理,我们只需调用即可。

矩形检测原理

游戏中,多个元素是否碰到一起,实际上,通常是用“矩形检测”原理实现的。我们在前面提到,游戏中所有的物体都可以抽象成“矩形”,我们只需判断两个矩形是否相交即可。对于一些复杂的多边形、不规则物体,实际上是将他分解成多个矩形,继续进行矩形检测。

Java的APl中,为我们提供了Rectangle类来表示矩形相关信息,并且提供了intersects()方法,直接判断矩形是否相交。

我们的游戏逻辑是:“飞机碰到炮弹,则死亡”。也就是说,我们需要检测:“飞机和所有的炮弹是否碰撞”。如果有50个炮弹对象,则进行50次比对检测即可。我们修改MyGameFrame类的paint()方法

【例】MyGameFrame类:增加碰撞检测

public void paint(Graphics g){

    g.drawlmage(bglmg, 0, 0null);

    plane.drawMySelf(g);//画出飞机本身

    //画出容器中所有的炮弹

    for(int i=0;i<shellList.size();i+ +){

        Shell b ==shellList.get(i);

        b.draw(g);//飞机和所有炮弹对象进行矩形检测

        boolean peng = b.getRect().intersects(plane.getRect()

        if(peng){

            plane.live = false;//飞机死掉,画面不显示

        }

    }

}

分享一个全面学习JAVA的视频教程

以上就是小编为大家整理的关于JAVA的知识。

后续持续更新,还望诸君多多学习,早日上岸!

需要学习具体教程的可以关注私信我哦!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容