主要功能:
1.w,a,s,d八个方向移动,j射击
2.默认会右有5个敌机,敌机会有一个随机方向,并一直按着这个方向移动,碰到边界会发生反弹
3.每个飞机只能发5个子弹,只有玩家的子弹才能对敌机造成伤害。
4.用ArrayList存放子弹,repaint的时候遍历重绘
5.用ConcurrentHashMap存放飞机,用HaskMap的话,当遍历的时候如果改变HaskMap的元素的话就会有一个Concurrent异常,而ConcurrentHashMap会自己检查变化。
OSC@GIT地址:http://git.oschina.net/A_yes/PlaneGame
遇到的问题:
plane类:
问题:在按键触发时执行,但是飞机的移动不顺滑即按住一个方向它会顿一下才继续向前。
解决方法:给飞机类加个Runnable接口,用线程来处理飞机移动,给4个方向boolean标志。
完整代码:
package com.ztc.plane;
import javax.swing.*;
import java.awt.*;
/**
* Created by ztc on 15-11-29.
*/
public class Plane implements Runnable{
//坐标
double x,y;
double speed;
Image img;
//移动方向,存活状态
boolean up,down,left,right,alive;
//发射子弹数
int bulletSum;
String name;
public void setUp(boolean up) {
this.up = up;
}
public void setDown(boolean down) {
this.down = down;
}
public void setLeft(boolean left) {
this.left = left;
}
public void setRight(boolean right) {
this.right = right;
}
public Plane(){}
public void setAlive(boolean alive) {
this.alive = alive;
}
public Plane(String path,double x,double y,double speed,String name){
this.x=x;
this.y=y;
this.speed=speed;
this.alive=true;
this.name=name;
img=Util.getImage(path);
}
public void draw(Graphics g){
g.drawImage(img,(int)x,(int)y,null);
}
public void move(boolean up,boolean down,boolean left,boolean right){
if(up&&y-speed>0)
y-=speed;
if(down&&y+speed<Constant.GrameHeight-new ImageIcon(img).getIconHeight())
y+=speed;
if(left&&x-speed>0)
x-=speed;
if(right&&x+speed<Constant.GrameWidht-new ImageIcon(img).getIconWidth())
x+=speed;
}
public Rectangle getRect(){
return new Rectangle((int)x,(int)y,new ImageIcon(img).getIconWidth(),new ImageIcon(img).getIconHeight());
}
public void boom(Graphics g) {
for (int i = 3; i > 0; i--) {
g.drawImage(Util.getImage("assets/boom0" + i + ".png"), (int) x, (int) y, null);
}
}
public int getBulletSum() {
return bulletSum;
}
public void setBulletSum(int bulletSum) {
this.bulletSum = bulletSum;
}
public Bullet shot(){
Bullet bullet=null;
if(alive&&bulletSum<Constant.BulletSum) {
bullet = new Bullet("assets/bullet02.png", (int) x - 7 + new ImageIcon(img).getIconWidth() / 2, (int) y-15, Constant.BulletSpeed, 0.5,name);
new Thread(bullet).start();
bulletSum++;
}
return bullet;
}
@Override
public void run() {
while(true){
move(up,down,left,right);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Enemy类:
Enemy类继承Plane类,所以它的移动只要重写run函数。
随机角度:double o=new Random().nextDouble()*Math.PI*2;
问题:遇到边界后镜面反弹;
解决方法:以随机出来的方向与垂直向下的方向的夹角为要计算的角度,显然若碰到垂直的边则o= Math.PI*2-o碰到水平方向则o=Math.PI-o;
完整代码:
package com.ztc.plane;
import javax.swing.*;
import java.util.Random;
/**
* Created by ztc on 15-11-30.下午1:22
*/
public class Enemy extends Plane{
//轨迹
String track;
double o=new Random().nextDouble()*Math.PI*2;
public Enemy(){}
public Enemy(String path,double x,double y,double speed,String name,String track){
super(path,x,y,speed,name);
this.track=track;
}
//随机方向,遇边镜面反射
public void myTrack(){
x-=speed*Math.sin(o);
y-=speed*Math.cos(o);
if(x<0||x>Constant.GrameWidht-new ImageIcon(img).getIconWidth()){
o= Math.PI*2-o;
}
if(y<0||y>Constant.GrameHeight-new ImageIcon(img).getIconHeight()-100){
o=Math.PI-o;
}
}
public void run(){
while(true){
myTrack();
if(alive&&bulletSum<Constant.BulletSum) {
Bullet bullet = new Bullet("assets/bullet01.png", (int) x - 7 + new ImageIcon(img).getIconWidth() / 2, (int) y + new ImageIcon(img).getIconHeight(), Constant.BulletSpeed, 0,name);
new Thread(bullet).start();
Util.bullets.add(bullet);
bulletSum++;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Bullet类:
问题:刚开始时把移动写了一个方法在repaint的时候调用,速度很怪异
解决:加Runnable借口,移动写在run里
package com.ztc.plane;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
* Created by ztc on 15-11-29.下午12:35
*/
public class Bullet implements Runnable{
//坐标
double x=200,y=200;
double speed;
Image img;
//方向(0,1)
double direct;
double o=new Random().nextDouble()*Math.PI*2;
boolean alive;
String owner;
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
public Bullet(){
}
public Bullet(String path,double x,double y,double speed,double direct,String owner){
this.x=x;
this.y=y;
this.speed=speed;
this.direct=direct;
this.alive=true;
this.owner=owner;
img=Util.getImage(path);
}
public void draw(Graphics g){
g.drawImage(img,(int)x,(int)y,null);
}
public String getOwner() {
return owner;
}
//随机方向,遇边镜面反射
public void drawRandom(Graphics g){
g.drawImage(img,(int)x,(int)y,null);
x-=speed*Math.sin(o);
y-=speed*Math.cos(o);
if(x<0||x>Constant.GrameWidht){
o=Math.PI*2-o;
}
if(y<0||y>Constant.GrameHeight){
o=Math.PI-o;
}
}
public Rectangle getRect(){
return new Rectangle((int)x,(int)y,new ImageIcon(img).getIconWidth(),new ImageIcon(img).getIconHeight());
}
@Override
public void run() {
while(true){
x+=speed*Math.sin(direct*Math.PI*2);
y+=speed*Math.cos(direct*Math.PI*2);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(y<0||x<0||y>Constant.GrameHeight||x>Constant.GrameWidht) {
alive=false;
break;
}
}
}
}