飞机对战
联机版思路1正在报错中…,就不上传了
联机版思路1:同步画面,2个玩家可以一起玩游戏,每两个客户机进行联机,如果连接服务器的客户机的数量为奇数,则最后一个连接服务器的客户端需要等待下一个客户端的连接才能开始游戏 每两个客户端进行实体类的坐标利用服务器中转信息进行同步,但是会有延迟,好像不可行…
联机版思路2:向服务器发送玩家的最高分数,进行排名存储,然后发送给客户端对所有玩家进行排名;数据库可以实现数据持久化;
游戏规则:
参考于: https://blog.csdn.net/qq_50459047/article/details/118472562
操作: 可以操作两个飞机,分别是飞机1、飞机2,当两个飞机血量都为零游戏结束; 飞机1操作:wsad控制上下左右,空格发射子弹 飞机2操作:鼠标控制飞机移动,按压鼠标发射子弹 敌机子弹打死后随机掉落金钱20,50,100;
联机思路1后:可以把每一组(2个客户机)看作一个整体,进行按照金钱总数的游戏排名;这一组的两个客户机的飞机1、2的金钱分数可以进行比较,判断谁赢了;多了画面同步,可两人一起玩,并且判断两人的输赢
联机版思路2后:对所有玩家进行一个排名,并使客户端的游戏在结束后可查看其所有人的排名 缺点:游戏在玩的时候还是单人游戏,只是最终可以看到其他人玩的分数;
以下为单机版
以下为联机版思路2
飞机对战单机版
implements Serializable 进行对象序列化原因:联机时可能要用到 Fly:定义的通用类减少代码的重复编写,关键是坐标x,y;在之后的实体类中都继承Fly
package flyevery;
import java.awt.image.BufferedImage;
import java.io.Serializable;
public class Fly implements Serializable {
public BufferedImage img ;
public int x;
public int y;
public int w;
public int h;
}
GetIMG:读取图片,获得图片,利用BufferedImage
mport java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
public class GetIMG implements Serializable {
public static BufferedImage getImg(String path)
{
try {
BufferedImage img = ImageIO.read(new FileInputStream(path));
return img;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
MainPlane1:飞机1,创建时出现在定义的初始位置处,有四个方法moveUp、moveDown、moveLeft、moveRight,进行坐标上下左右的改变,在之后根据事件监听而调用
package flyplane;
import img.GetIMG;
public class MainPlane1 extends flyevery.Fly{
private int blood;
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
public MainPlane1(){
img = GetIMG.getImg("src/main/java/img/飞机1.png");
w = img.getWidth();
h = img.getHeight();
x = 175;
y = 650 - h;
blood = 5;
}
public void moveUp(){
if(y >= 50) y -= 50;
}
public void moveDown(){
if(y <= 530) y += 50;
}
public void moveLeft(){
if(x >= 25) x -= 50;
}
public void moveRight(){
if(x <= 335) x += 50;
}
}
DeputyPlane2:飞机2,创建时出现在定义的初始位置处,有方法moveToMouse,进行坐标的改变,在之后根据事件监听而调用
package flyplane;
import img.GetIMG;
public class DeputyPlane2 extends flyevery.Fly{
private int blood;
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
public DeputyPlane2(){
img = GetIMG.getImg("src/main/java/img/飞机2.png");
w = img.getWidth();
h = img.getHeight();
x = 300;
y = 550 - h;
blood = 5;
}
public void moveToMouse(int mx, int my){
x = mx - w/2;
y = my - h/2;
}
}
EnemyPlane:敌机,有速度,血量,但不能进行攻击。被子弹击中后,血量减少一滴,和我方飞机相撞后直接死亡且对应我机血量减少一滴;方法有move坐标改变,hitBy判断是否和我机相撞,shootBy判读是否被子弹击中
package flyplane;
import img.GetIMG;
import flyevery.Fly;
import java.util.Random;
public class EnemyPlane extends flyevery.Fly{
private int speed;
public int blood;
public EnemyPlane(){
int index = new Random().nextInt(6) + 1;
img = GetIMG.getImg("src/main/java/img/敌机"+index+".png");
w = img.getWidth();
h = img.getHeight();
x = new Random().nextInt(480 - w);
y = -h;
blood = index * 2;
speed = new Random().nextInt(15)+10;
}
public void move() {
y += speed;
}
public boolean hitBy(MainPlane1 he) {
boolean hitH = x <= he.x + he.w && x >= he.x - w && y <= he.y + he.h && y >= he.y-h;
return hitH;
}
public boolean hitBy(DeputyPlane2 he) {
boolean hitH = x <= he.x + he.w && x >= he.x - w && y <= he.y + he.h && y >= he.y-h;
return hitH;
}
public boolean shootBy(Fly b) {
boolean hit = x <= b.x + b.w && x >= b.x - w && y <= b.y + b.h && y >= b.y - h;
return hit;
}
}
BulletPlane1:飞机1发射的子弹,初始位置即飞机1的前方,有方法move坐标的改变;空格发射
package flyothers;
java
import img.GetIMG;
public class BulletPlane1 extends flyevery.Fly{
public BulletPlane1(int plane1x, int plane1y)
{
img = GetIMG.getImg("src/main/java/img/子弹1.png");
w = img.getWidth();
h = img.getHeight();
x = plane1x + 5;
y = plane1y + 5;
}
public void move(){
y -= 9;
}
}
BulletPlane2:飞机2的子弹,初始位置即飞机2的前方,有方法move坐标的改变,鼠标按压发射
package flyothers;
import img.GetIMG;
public class BulletPlane2 extends flyevery.Fly{
public BulletPlane2(int plane2x, int plane2y)
{
img = GetIMG.getImg("src/main/java/img/子弹2.png");
w = img.getWidth();
h = img.getHeight();
x = plane2x + 5;
y = plane2y + 5;
}
public void move(){
y -= 9;
}
}
Money:金钱掉落,当敌机被子弹打死后会掉落子弹。有20、50、100随机掉落,有方法move坐标改变,catchBy判断是否捡取
package flyothers;
import flyplane.DeputyPlane2;
import flyplane.MainPlane1;
import img.GetIMG;
import java.util.Random;
public class Money extends flyevery.Fly{
private int money;
public int getMoney() {
return money;
}
public Money(int enemyplanex, int enemyplaney){
int []a ={20,50,100};
int index = new Random().nextInt(3);
money = a[index];
index++;
img = GetIMG.getImg("src/main/java/img/金钱"+index+".jpg");
w = img.getWidth();
h = img.getHeight();
x = enemyplanex;
y = enemyplaney;
}
public void move(){
y += new Random().nextInt(5) + 2;
x += new Random().nextInt(50) - 25;
}
public boolean catchBy(MainPlane1 plane1) {
boolean catchMoney = x <= plane1.x + plane1.w && x >= plane1.x - w && y <= plane1.y + plane1.h && y >= plane1.y - h;
return catchMoney;
}
public boolean catchBy(DeputyPlane2 plane2) {
boolean catchMoney = x <= plane2.x + plane2.w && x >= plane2.x - w && y <= plane2.y + plane2.h && y >= plane2.y - h;
return catchMoney;
}
}
GamePanel:游戏面板,核心;在构造函数时,进行事件监听,键盘的按压、释放,鼠标的按压释放,根据方法myPlane进行对应的移动或攻击;paint进行可视化,画图操作;enemyPlaneEnter敌机入场;enemyPlaneMove敌机移动;plane1Shoot飞机1发射子弹;lane2Shoot飞机2发射子弹;bulletPlane1sMove飞机1发射的子弹移动;bulletPlane2sMove飞机2发射的子弹移动;attack敌机是否被子弹攻击打中;shootPlane 判断每一个子弹是否命中敌机;moneyMoveCatch金钱掉落是否被捡取;最终以一个线程运行;
package gamePlay;
import img.GetIMG;
import flyevery.Fly;
import flyothers.BulletPlane1;
import flyothers.BulletPlane2;
import flyothers.Money;
import flyplane.DeputyPlane2;
import flyplane.EnemyPlane;
import flyplane.MainPlane1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class GamePanel extends JPanel implements Serializable {
private int moneyCnt = 0;
private int enemyCnt = 0;
public int moneyCnt1 = 0;
public int enemyCnt1 = 0;
public int moneyCnt2 = 0;
public int enemyCnt2 = 0;
boolean GameOver;
boolean plane1Over;
boolean plane2Over;
protected int xx, yy;
boolean[] mouse = {false};
boolean[] keywords = {false, false, false, false, false};
public int getMoneyCnt() {
return moneyCnt;
}
public int getEnemyCnt() {
return enemyCnt;
}
public int getXx() {
return xx;
}
public void setXx(int xx) {
this.xx = xx;
}
public int getYy() {
return yy;
}
public void setYy(int yy) {
this.yy = yy;
}
BufferedImage background;
public MainPlane1 plane1 = new MainPlane1();
public DeputyPlane2 plane2 = new DeputyPlane2();
public List<EnemyPlane> enemyPlanes = new ArrayList<EnemyPlane>();
public List<BulletPlane1> bulletPlane1s = new ArrayList<BulletPlane1>();
public List<BulletPlane2> bulletPlane2s = new ArrayList<BulletPlane2>();
public List<Money> money = new ArrayList<Money>();
private void init(){
plane1 = new MainPlane1();
plane2 = new DeputyPlane2();
GameOver = false;
plane1Over = false;
plane2Over = false;
int moneyCnt = 0;
int enemyCnt = 0;
int moneyCnt1 = 0;
int enemyCnt1 = 0;
int moneyCnt2 = 0;
int enemyCnt2 = 0;
enemyPlanes.clear();
bulletPlane1s.clear();
bulletPlane2s.clear();
money.clear();
repaint();
}
public GamePanel(JFrame frame){
setBackground(Color.black);
int index = new Random().nextInt(3) + 1;
background = GetIMG.getImg("src/main/java/img/background"+index+".png");
KeyAdapter kd = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(GameOver && keyCode == KeyEvent.VK_ENTER) init();
else if (!GameOver && ! plane1Over){
if (keyCode == KeyEvent.VK_W) keywords[0] = true;
else if (keyCode == KeyEvent.VK_S) keywords[1] = true;
else if (keyCode == KeyEvent.VK_A) keywords[2] = true;
else if (keyCode == KeyEvent.VK_D) keywords[3] = true;
else if (keyCode == KeyEvent.VK_SPACE) keywords[4] = true;
}
}
@Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_W) keywords[0] = false;
else if (keyCode == KeyEvent.VK_S) keywords[1] = false;
else if (keyCode == KeyEvent.VK_A) keywords[2] = false;
else if (keyCode == KeyEvent.VK_D) keywords[3] = false;
else if (keyCode == KeyEvent.VK_SPACE) keywords[4] = false;
}
};
frame.addKeyListener(kd);
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
xx = e.getX();
yy = e.getY();
}
@Override
public void mouseMoved(MouseEvent e) {
xx = e.getX();
yy = e.getY();
}
@Override
public void mousePressed(MouseEvent e) {
mouse[0] = true;
}
@Override
public void mouseReleased(MouseEvent e) {
mouse[0] = false;
}
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1);
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(background, 0, 0, null);
g.drawImage(background, 480, 0, null);
if (!plane1Over)
g.drawImage(plane1.img, plane1.x, plane1.y, plane1.w, plane1.h, null);
if (!plane2Over)
g.drawImage(plane2.img, plane2.x, plane2.y, plane2.w, plane2.h, null);
for (int i = 0; i < enemyPlanes.size(); i++) {
EnemyPlane enemyplane = enemyPlanes.get(i);
g.drawImage(enemyplane.img, enemyplane.x, enemyplane.y, enemyplane.w, enemyplane.h, null);
}
for (int i = 0; i < bulletPlane1s.size(); i++){
BulletPlane1 bulletPlane1 = bulletPlane1s.get(i);
g.drawImage(bulletPlane1.img, bulletPlane1.x, bulletPlane1.y, bulletPlane1.w, bulletPlane1.h, null);
}
for (int i = 0; i < bulletPlane2s.size(); i++){
BulletPlane2 bulletPlane2 = bulletPlane2s.get(i);
g.drawImage(bulletPlane2.img, bulletPlane2.x, bulletPlane2.y, bulletPlane2.w, bulletPlane2.h, null);
}
for (int i = 0; i < money.size(); i++){
Money money1 = money.get(i);
g.drawImage(money1.img, money1.x, money1.y, money1.w, money1.h, null);
}
for (int i = 0; i < plane1.getBlood(); i++){
g.drawImage(plane1.img,300+i*35,5,30,30,null);
}
for (int i = 0; i < plane2.getBlood(); i++){
g.drawImage(plane2.img,300+i*35,30,30,30,null);
}
g.setColor(Color.white);
g.setFont(new Font("楷体",Font.BOLD,15));
g.drawString("金钱:"+moneyCnt,13,30);
g.drawString("击杀数:"+enemyCnt,13,45);
g.drawString("飞机1金钱:"+moneyCnt1,13,60);
g.drawString("飞机1击杀数:"+enemyCnt1,13,75);
g.drawString("飞机2金钱:"+moneyCnt2,13,90);
g.drawString("飞机2击杀数:"+enemyCnt2,13,105);
g.setColor(Color.red);
g.setFont(new Font("楷体",Font.BOLD,15));
g.drawString("飞机1血量:",250,25);
g.drawString("飞机2血量:",250,50);
if(GameOver) {
g.setColor(Color.WHITE);
g.setFont(new Font("黑体", Font.BOLD, 40));
g.drawString("游戏结束 Game Over!!", 105, 300);
g.setColor(Color.BLACK);
g.setFont(new Font("楷体",Font.BOLD,20));
g.drawString("enter再次开始游戏",100,350);
}
}
protected void myPlane(){
if (!plane2Over){
plane2.moveToMouse(xx, yy);
plane2.x = xx;
plane2.y = yy;
}
if (mouse[0]) plane2Shoot();
if (keywords[0]) plane1.moveUp();
if (keywords[1]) plane1.moveDown();
if (keywords[2]) plane1.moveLeft();
if (keywords[3]) plane1.moveRight();
if (keywords[4]) plane1Shoot();
repaint();
}
int t = 0;
protected void enemyPlaneEnter(){
t++;
if (t >= 12){
EnemyPlane enemyPlane = new EnemyPlane();
enemyPlanes.add(enemyPlane);
t = 0;
}
}
protected void enemyPlaneMove(){
for (int i = 0; i < enemyPlanes.size(); i++){
EnemyPlane enemyPlane = enemyPlanes.get(i);
enemyPlane.move();
}
}
int bulletPlane1Num = 0;
protected void plane1Shoot(){
bulletPlane1Num ++;
if (bulletPlane1Num > 2){
BulletPlane1 bulletPlane1 = new BulletPlane1(plane1.x, plane1.y);
BulletPlane1 bulletPlane12 = new BulletPlane1(plane1.x + 40, plane1.y);
BulletPlane1 bulletPlane13 = new BulletPlane1(plane1.x + 80, plane1.y);
bulletPlane1s.add(bulletPlane1);
bulletPlane1s.add(bulletPlane12);
bulletPlane1s.add(bulletPlane13);
bulletPlane1Num = 0;
}
}
int bulletPlane2Num = 0;
protected void plane2Shoot(){
bulletPlane2Num ++;
if (bulletPlane2Num > 1){
BulletPlane2 bulletPlane2 = new BulletPlane2(plane2.x, plane2.y);
BulletPlane2 bulletPlane22 = new BulletPlane2(plane2.x + 36, plane2.y);
bulletPlane2s.add(bulletPlane2);
bulletPlane2s.add(bulletPlane22);
bulletPlane2Num = 0;
}
}
protected void bulletPlane1sMove(){
for(int i = 0; i < bulletPlane1s.size(); i++){
BulletPlane1 bulletPlane1 = bulletPlane1s.get(i);
bulletPlane1.move();
}
}
protected void bulletPlane2sMove(){
for(int i = 0; i < bulletPlane2s.size(); i++){
BulletPlane2 bulletPlane2 = bulletPlane2s.get(i);
bulletPlane2.move();
}
}
protected void attack(Fly bullet){
if (!(bullet instanceof BulletPlane1) && !(bullet instanceof BulletPlane2)) return;
for (int i = 0; i < enemyPlanes.size(); i++){
EnemyPlane enemyPlane = enemyPlanes.get(i);
if (enemyPlane.shootBy(bullet)) {
enemyPlane.blood--;
if (enemyPlane.blood <= 0){
if (bullet instanceof BulletPlane1) enemyCnt1++;
else enemyCnt2++;
int x = enemyPlane.x;
int y = enemyPlane.y;
enemyPlanes.remove(enemyPlane);
enemyCnt++;
money.add(new Money(x, y));
}
if (bullet instanceof BulletPlane1) bulletPlane1s.remove(bullet);
else bulletPlane2s.remove(bullet);
}
}
}
protected void shootPlane(){
for (int i = 0; i < bulletPlane1s.size(); i++){
BulletPlane1 bulletPlane1 = bulletPlane1s.get(i);
attack(bulletPlane1);
}
for (int i = 0; i < bulletPlane2s.size(); i++){
BulletPlane2 bulletPlane2 = bulletPlane2s.get(i);
attack(bulletPlane2);
}
}
protected void moneyMoveCatch(){
for (int i = 0; i < money.size(); i++){
Money m = money.get(i);
m.move();
if (m.catchBy(plane1)){
m.move();
moneyCnt += m.getMoney();
moneyCnt1 += m.getMoney();
money.remove(m);
}
else if (m.catchBy(plane2)){
m.move();
moneyCnt += m.getMoney();
moneyCnt2 += m.getMoney();
money.remove(m);
}
}
}
protected void hit(){
for (int i = 0; i < enemyPlanes.size(); i++){
EnemyPlane enemyPlane = enemyPlanes.get(i);
if (!plane1Over && enemyPlane.hitBy(plane1)){
enemyPlanes.remove(enemyPlane);
plane1.setBlood(plane1.getBlood()-1);
enemyCnt++;
enemyCnt1++;
if (plane1.getBlood() <= 0) plane1Over = true;
}
else if (!plane2Over && enemyPlane.hitBy(plane2)){
enemyPlanes.remove(enemyPlane);
plane2.setBlood(plane2.getBlood()-1);
enemyCnt++;
enemyCnt2++;
if (plane2.getBlood() <= 0) plane2Over = true;
}
if (plane1Over && plane2Over) GameOver = true;
}
}
public void start(){
Runnable r = ()->{
while (true) {
try {
if (!GameOver) {
myPlane();
enemyPlaneEnter();
enemyPlaneMove();
bulletPlane1sMove();
bulletPlane2sMove();
shootPlane();
moneyMoveCatch();
hit();
}
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
repaint();
}
};
new Thread(r).start();
}
}
游戏的窗体(固定的模式) Java中的窗体类:JFrame 自定义窗体步骤: 1、写一个类,继承JFrame 2、写一个构造方法,初始化窗体的属性 属性对应特点,方法对应行为
package gamePlay;
import javax.swing.*;
import java.awt.*;
import java.io.Serializable;
public class GameFrame extends JFrame implements Serializable{
private static final long serialVersionUID = 1;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public GameFrame(){
setTitle("飞机对战");
setSize(500,740);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
GameFrame frame = new GameFrame();
GamePanel panel =new GamePanel(frame);
panel.start();
frame.add(panel);
frame.setVisible(true);
}
}
|