您的位置:首页 > 编程语言 > Java开发

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

2016-07-21 11:55 639 查看
上一篇,我们已经画出了一辆坦克,但是我们的坦克不会动,本篇(看起来长实际内容不多的),我们就来实现如何让坦克移动,(最好再建一个包存放复制原来的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()函数,来重绘页面 }

}



本篇看来篇幅长了点,实则内容不多,旨在详细描述步骤,下节继续分解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 游戏 坦克大战