Java之详解坦克大战游戏(二)

上一篇,我们已经画出了一辆坦克,但是我们的坦克不会动,本篇(看起来长实际内容不多的),我们就来实现如何让坦克移动,(最好再建一个包存放复制原来的java文件),因为我们是一步步更新的,一乱可能连原来的文件都改回不了…
首先我们要做的是事件监听和事件处理,给MyPanel类添加一个接口KeyListener,并实现方法

class MyPanel extends Panel implements KeyListener
{
//省略部分代码......
/*实现KeyListener接口的方法*/
    //键入某个键时调用此方法。 
    public void keyTyped(KeyEvent e) {


    }
    //释放某个键时调用此方法
    public void keyReleased(KeyEvent e) {


    }
//按下某个键时调用此方法: A代表向左,W代表向上,D代表向右,S代表向下
    public void keyPressed(KeyEvent e) {

        if(e.getKeyCode() == KeyEvent.VK_W)//向上
        {

        }
        else if(e.getKeyCode() == KeyEvent.VK_D)//向下
        {

        }
        else if(e.getKeyCode() == KeyEvent.VK_S)//向下
        {

        }
        else if(e.getKeyCode() == KeyEvent.VK_A)//向左
        {

        }
        //没有这行代码即使实现了移动操作页面也不会动的
        this.repaint();//调用repaint()函数,来重绘页面
    }
    }

!!!要实现监听,还要注册监听事件

public class TankGame2 extends JFrame{
    public TankGame2(){
        //...
        this.addKeyListener(mp);//注册监听事件
    }
}

其中 public void keyPressed(KeyEvent e){…}是我们主要操作的方法,下面四个if语句是添加上去的,用于判断是按了哪个键,按这个节奏,if语句里面是不是该填写坐标移动来实现坦克的移动呢(y–,x++,…),但是考虑到之后的修改问题,我们还是把移动这一方法封装起来(好处后面会提到)。在Tank类定义一个变量 int speed=1;作为坦克的速度,再回到Hero类添加移动的方法,由于 Hero继承Tank类,所以Hero类也能访问speed。

class Hero extends Tank
{
    public Hero(int x,int y)
    {
        super(x,y);
    }
    //坦克向上移动
    public void moveUp()
    {
        y-=speed;
    }
    //坦克向右移动
    public void moveRight()
    {
        x+=speed;
    }
    //坦克向下移动
    public void moveDown()
    {
        y+=speed;
    }
    //坦克向左移动
    public void moveLeft()
    {
        x-=speed;
    }
}

(如果是y++,x++那样的形式控制速度,那要修改速度就会显得很麻烦,连续改几个,而定义speed的话修改速度只需修改speed的数值。)接着再到刚才if语句那里添加移动方法

class MyPanel extends Panel implements KeyListener
{//省略部分代码......
public void keyPressed(KeyEvent e) {

        if(e.getKeyCode() == KeyEvent.VK_W)//向上
        {
            this.hero.moveUp();
        }
        else if(e.getKeyCode() == KeyEvent.VK_D)//向下
        {
            this.hero.moveRight();
        }
        else if(e.getKeyCode() == KeyEvent.VK_S)//向下
        {
            this.hero.moveDown();
        }
        else if(e.getKeyCode() == KeyEvent.VK_A)//向左
        {
            this.hero.moveLeft();
        }

这个时候,运行效果是这样的(页面被我放大来拍摄做gif的)
这里写图片描述这里写图片描述

我们看到它可以移动,但左右移动跟螃蟹走一样,所以下一步是做出它向下还是向左向右,绘出坦克整体向哪个方向的图。
在Tank类中定义坦克方向,并添加setter和getter方法

class Tank
{//省略部分代码......
    //坦克方向 
    //0表示上,1表示右,2表示下,3表示左
    int direct=0;

    public int getDerect() {
        return direct;
    }

    public void setDerect(int derect) {
        this.direct = derect;
    }
    //...
}

再往回添加添加代码和修改

public void keyPressed(KeyEvent e) {

        if(e.getKeyCode() == KeyEvent.VK_W)//向上
        {
            this.hero.setDirect(0);
            this.hero.moveUp();
        }
        else if(e.getKeyCode() == KeyEvent.VK_D)//向右
        {
            this.hero.setDirect(1);
            this.hero.moveRight();
        }
        else if(e.getKeyCode() == KeyEvent.VK_S)//向下
        {
            this.hero.setDirect(2);
            this.hero.moveDown();
        }
        else if(e.getKeyCode() == KeyEvent.VK_A)//向左
        {
            this.hero.setDirect(3);
            this.hero.moveLeft();
        }
        this.repaint();//调用repaint()函数,来重绘页面
    }

再修改代码(上篇我们初始化是0,方向向上),由于我们要改变方向,灵活一点就改为this.hero.direct

class MyPanel extends Panel implements KeyListener{
public void paint(Graphics g){
    //...
this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
    }
}

接下来看方向改变后坦克如何画
这里写图片描述
有两种方式,一种还是以最左边矩形左上角为参照点画,但是可能效果不是令人特别满意,转动的变化略大,而如果以圆形中间的点为参照点,转动起来就比较自然了,不过坐标要计算得更精确哦,可以试试..这里我们
还是以左上角的点为参照点画向右的坦克

//画出坦克的函数
public void drawTank(int x,int y,Graphics g,int direct,int type)
{//省略....
        case 0://....
        case 1://炮筒向右
            //画出上面矩形
            g.fill3DRect(x, y, 30, 5,false);
            //2.画出右边矩形
            g.fill3DRect(x, y+15, 30, 5,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 20, 10,false);
            //4.画出圆形
            g.fillOval(x+10, y+5, 10, 10);
            //5.画直线
            g.drawLine(x+15, y+10, x+30, y+10);
            break;
        case 2://炮筒向下
            //画出上面矩形
            g.fill3DRect(x, y, 5, 30,false);
            //2.画出右边矩形
            g.fill3DRect(x+15, y, 5, 30,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 10, 20,false);
            //4.画出圆形
            g.fillOval(x+5, y+10, 10, 10);
            //5.画直线
            g.drawLine(x+10, y+15, x+10, y+30);
            break;

        case 3://炮筒向左
            //画出上面矩形
            g.fill3DRect(x, y, 30, 5,false);
            //2.画出右边矩形
            g.fill3DRect(x, y+15, 30, 5,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 20, 10,false);
            //4.画出圆形
            g.fillOval(x+10, y+5, 10, 10);
            //5.画直线
            g.drawLine(x+15, y+10, x, y+10);
            break;
        }
    }

事实上画出向右的方向,向左的就容易画了,因为算对称,而上篇画了向上的坦克,画向下的只要改动直线就行了,改后效果如图这里写图片描述
最后为了更好的阅读代码,我们把Tank类和Hero类剪切到一个Members.java文件,分为两个文件,最后附上完整代码:
Members.java

package com.TankGame1;

//坦克类
class Tank
{
    //表示坦克的横坐标
    int x=0;
    //表示坦克的纵坐标
    int y=0;

    //坦克方向 
    //0表示上,1表示右,2表示下,3表示左
    int direct=0;

    public int getDirect() {
        return direct;
    }

    public void setDirect(int derect) {
        this.direct = derect;
    }

    //坦克速度
    int speed=1;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public Tank(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
}

    //我的坦克
class Hero extends Tank
{
    public Hero(int x,int y)
    {
        super(x,y);
    }
    //坦克向上移动
    public void moveUp()
    {
        y-=speed;
    }
    //坦克向右移动
    public void moveRight()
    {
        x+=speed;
    }
    //坦克向下移动
    public void moveDown()
    {
        y+=speed;
    }
    //坦克向左移动
    public void moveLeft()
    {
        x-=speed;
    }
}

TankGame2.java

package com.TankGame1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/*
 * */
public class TankGame2 extends JFrame
{
    MyPanel mp =null;
    public static void main(String[] args) 
    {
        TankGame2 tankgame1 = new TankGame2();
    }

    public TankGame2()
    {
        mp=new MyPanel();
        this.addKeyListener(mp);
        this.setVisible(true);
        this.setSize(400, 300);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(mp);
    }

}

//我的面板
class MyPanel extends Panel implements KeyListener
{
    //定义一个我的坦克
    Hero hero =null;

    public MyPanel()
    {
        hero =new Hero(100,100); //坦克的初始位置(10,10)
    }

    //重新paint
    public void paint(Graphics g)
    {
        super.paint(g);
        g.fillRect(0, 0, 1200, 900);  //填充使背景变为黑色   
        this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
    }

    //画出坦克的函数
    public void drawTank(int x,int y,Graphics g,int direct,int type)
    {
        switch(type)
        {
        case 0:
            g.setColor(Color.cyan);
            break;
        case 1:
            g.setColor(Color.yellow);
            break;
        }

        //判断方向
        switch(direct)
        {
        //向上
        case 0:
            //画出我的坦克(到时再封装成一个函数)
            //1.画出左边的矩形
            g.fill3DRect(x, y, 5, 30,false);
            //2.画出右边矩形
            g.fill3DRect(x+15, y, 5, 30,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 10, 20,false);
            //4.画出圆形
            g.fillOval(x+5, y+10, 10, 10);
            //5.画直线
            g.drawLine(x+10, y+15, x+10, y);
            break;
        case 1://炮筒向右
            //画出上面矩形
            g.fill3DRect(x, y, 30, 5,false);
            //2.画出右边矩形
            g.fill3DRect(x, y+15, 30, 5,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 20, 10,false);
            //4.画出圆形
            g.fillOval(x+10, y+5, 10, 10);
            //5.画直线
            g.drawLine(x+15, y+10, x+30, y+10);
            break;
        case 2://炮筒向下
            //画出上面矩形
            g.fill3DRect(x, y, 5, 30,false);
            //2.画出右边矩形
            g.fill3DRect(x+15, y, 5, 30,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 10, 20,false);
            //4.画出圆形
            g.fillOval(x+5, y+10, 10, 10);
            //5.画直线
            g.drawLine(x+10, y+15, x+10, y+30);
            break;

        case 3://炮筒向左
            //画出上面矩形
            g.fill3DRect(x, y, 30, 5,false);
            //2.画出右边矩形
            g.fill3DRect(x, y+15, 30, 5,false);
            //3.画出中间矩形
            g.fill3DRect(x+5, y+5, 20, 10,false);
            //4.画出圆形
            g.fillOval(x+10, y+5, 10, 10);
            //5.画直线
            g.drawLine(x+15, y+10, x, y+10);
            break;
        }

    }
/*实现KeyListener接口的方法*/
    //键入某个键时调用此方法。 
    public void keyTyped(KeyEvent e) {


    }
    //释放某个键时调用此方法
    public void keyReleased(KeyEvent e) {


    }
    //按下某个键时调用此方法: a代表向左,w代表向上,d代表向右,s代表向下
    public void keyPressed(KeyEvent e) {

        if(e.getKeyCode() == KeyEvent.VK_W)//向上
        {
            this.hero.setDirect(0);
            this.hero.moveUp();
        }
        else if(e.getKeyCode() == KeyEvent.VK_D)//向右
        {
            this.hero.setDirect(1);
            this.hero.moveRight();
        }
        else if(e.getKeyCode() == KeyEvent.VK_S)//向下
        {
            this.hero.setDirect(2);
            this.hero.moveDown();
        }
        else if(e.getKeyCode() == KeyEvent.VK_A)//向左
        {
            this.hero.setDirect(3);
            this.hero.moveLeft();
        }
        this.repaint();//调用repaint()函数,来重绘页面
    }




}


本篇看来篇幅长了点,实则内容不多,旨在详细描述步骤,下节继续分解

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值