此文转载自:https://blog.csdn.net/pandas_dream/article/details/113086334

目录

  • 游戏规则
  • 主要实现方法
  • 游戏流程展示
    • 1. 开始游戏页面
    • 2. 加载中页面
    • 3. 选择地图页面
    • 4. 自定义昵称页面
    • 5. 运行页面
    • 死亡页面
  • 发展方向
  • (前面都不感兴趣,快进到)原码
    • 最后

首先灰常开森在2020年下半年这学期收获了很多知识,自己的意志也得到了锻炼,尤其是在verilog学习中 摸爬滚打 爬爬爬爬的无数个日日夜夜最令我难忘。
Java课大作业消息出来的时候我脑子一片空白,连Hello World都不会输出,让用Java写个小游戏,七八个星期以来老师上课给我们讲的内容我一点也没印象,莫名有种给你一盒擦炮去炸碉堡的感觉哦。
ddl最后那三天,着实难受>_<…。
往事不可追,寒假决定把自己一点点磨出来的东西传上来,供大家参考和指正,谢谢。

游戏规则

球球大作战时一款多玩家实时在线对抗策略类游戏。在这款游戏中,玩家操控一个具有一定初始体积的小球在地图中移动。为了使自己的小球的体积增大,玩家可以规划自己的路线并吃掉沿途上的“微粒”,“微粒”具有一个很小的体积,吃掉微粒后,小球可以增加相应的体积,随着体积不断变大,如果当玩家控制小球的体积在直径上明显大于另一名玩家的小球时,如果玩家成功地使自己的小球将对方小球的超过二分之一体积覆盖,那么判定成功吃掉对方的小球,玩家控制的小球体积随之增加,对方的小球被吃掉,需要恢复初始体积重新开始游戏。

主要实现方法

在编写项目前,首先对需要实现的功能进行分析,制作了如下的分析图。

项目中较为关键的是Ball类。

public class Ball {private double x;          //绘制横坐标private double y;            //绘制纵坐标private double d;            //直径private double real_x;      //中心横坐标private double real_y;       //中心纵坐标private double speed;        //速度private double degree;      //角度private double m;           //质量private String name;        //昵称private boolean alive;      //存活private Color owncolor;     //颜色private BufferedImage flag; //国家国旗public Ball(double x, double y, double d) {this.setX(x);this.setY(y);this.setD(d);this.setOwncolor(randomcolor());this.real_x = x + d / 2;this.real_y = y + d / 2;this.alive = true;}public Ball(double x, double y, double speed, double degree, double m) {this.setX(x);this.setY(y);this.speed = speed;this.degree = degree;this.m = m;FreshD();this.alive = true;}public Ball(double x, double y, double speed, double degree, double m, String name) {super();this.x = x;this.y = y;this.speed = speed;this.degree = degree;this.m = m;this.name = name;this.setOwncolor(randomcolor());FreshD();this.alive = true;}public BufferedImage getFlag() {return flag;}public void setFlag(BufferedImage flag) {this.flag = flag;}public boolean isAlive() {return alive;}public void setAlive(boolean alive) {this.alive = alive;}public double getSpeed() {return speed;}public void setSpeed(double speed) {this.speed = speed;}public double getDegree() {return degree;}public void setDegree(double degree) {this.degree = degree;}public double getM() {return m;}public void setM(double m) {this.m = m;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getX() {return x;}public void setX(double x) {this.x = x;}public double getY() {return y;}public void setY(double y) {this.y = y;}public double getD() {return d;}public void setD(double d) {this.d = d;}public double getReal_x() {return real_x;}public void setReal_x(double real_x) {this.real_x = real_x;}public double getReal_y() {return real_y;}public void setReal_y(double real_y) {this.real_y = real_y;}public Color getOwncolor() {return owncolor;}public void setOwncolor(Color owncolor) {this.owncolor = owncolor;}public void draw(Graphics g) {Color c = g.getColor();g.setColor(Color.cyan);g.fillOval((int) x, (int) y, (int) d, (int) d);g.setColor(c);}public void draw(Graphics g, int windowx, int windowy) { //绘制自身Color c = g.getColor();g.setColor(Color.cyan);g.fillOval((int) (x - windowx), (int) (y - windowy), (int) d, (int) d);g.setColor(c);}public void move() {                 //移动小球if (x > ballfight.Width || x < 0)degree = Math.PI - degree;if (y > ballfight.Height || y < 0)degree = -degree;while (degree < 0)degree += 2 * Math.PI;while (degree > 2 * Math.PI)degree -= 2 * Math.PI;if (speed > 0) {x += speed * Math.cos(degree);y += speed * Math.sin(degree);}}public void eat(Ball b) {             //吃掉别的Ball类m += b.m;FreshD();}public void FreshD() {                  //刷新小球中心位置d = 30 + Math.sqrt(m) * 4;real_x = x + d / 2;real_y = y + d / 2;}public Color randomcolor() {           Random rand = new Random();float r = rand.nextFloat();float s = rand.nextFloat();float t = rand.nextFloat();return (new Color(r, s, t));}
}

Player(玩家)类继承Ball类,但是需要重写draw()方法、move()方法,并添加spore()方法和my_spore_move()方法,具体如下。

public void move(double mx, double my) {       //移动的边界处理和普通Ball不同double dis = Math.sqrt((mx - screenx) * (mx - screenx) + (my - screeny) * (my - screeny));double Degree;Degree = Math.acos((mx - screenx) / dis);if (my - screeny < 0) {Degree = -Degree;}setDegree(Degree);if (dis > 2) {if (getSpeed() > 0) {if ((getX() + getSpeed() * Math.cos(getDegree()) < 0|| getX() + getSpeed() * Math.cos(getDegree()) > ballfight.Width)&& (getY() + getSpeed() * Math.sin(getDegree()) < 0|| getY() + getSpeed() * Math.sin(getDegree()) > ballfight.Height)) {} else if (getX() + getSpeed() * Math.cos(getDegree()) < 0|| getX() + getSpeed() * Math.cos(getDegree()) > ballfight.Width) {setY(getY() + getSpeed() * Math.sin(getDegree()));FreshD();} else if (getY() + getSpeed() * Math.sin(getDegree()) < 0|| getY() + getSpeed() * Math.sin(getDegree()) > ballfight.Height) {setX(getX() + getSpeed() * Math.cos(getDegree()));FreshD();} else {setX(getX() + getSpeed() * Math.cos(getDegree()));setY(getY() + getSpeed() * Math.sin(getDegree()));FreshD();}}}}public double getsize(double weight) {return 10 + Math.sqrt(weight) * 4;}public void spore(double speed) {        //吐出孢子System.out.println(getM());if (resttime < ballfight.timeperspore / ballfight.breaktime)resttime++;else {resttime = 0;if (getM() > 2 * ballfight.sporeweight) {double rx, ry;Spore s = new Spore(getReal_x() + getD() * 0.5 * Math.cos(getDegree()) - 0.5 * getsize(ballfight.sporeweight),getReal_y() + getD() * 0.5 * Math.sin(getDegree()) - 0.5 * getsize(ballfight.sporeweight),speed, this.getDegree(), ballfight.sporeweight);s.FreshD();spores.add(s);rx = getReal_x();ry = getReal_y();double weight = getM();weight -= s.getM();setM(weight);FreshD();setX(rx - getD() * 0.5);setY(ry - getD() * 0.5);FreshD();}}}public void my_spore_move() {      //所有已吐出孢子运动for (int i = 0; i < spores.size(); i++) {Spore s = spores.get(i);if (s.isAlive()) {s.move();s.FreshD();}}}

完成基本的类的编写,下面是页面以及线程的编写。
主类ballfight继承JPanel,在主类的实例化方法中初始化JFrame作为游戏页面的框架。

public class ballfight extends JPanel
public ballfight(String name) {LoadImgs();setBackground(Color.black);InitialImages();frame = new JFrame(name);frame.setVisible(true);frame.setResizable(false);frame.add(this);frame.setBackground(Color.black);frame.setBounds(this.X, this.Y, ballfight.windowWidth, ballfight.windowHeight);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

接下来为frame添加KeyListener键盘监听。

keylistener= new KeyListener() {/**************/@Overridepublic void keyTyped(KeyEvent e) {// TODO Auto-generated method stub/*********/}@Overridepublic void keyReleased(KeyEvent e) {// TODO Auto-generated method stub/*********/}@Overridepublic void keyPressed(KeyEvent e) {// TODO Auto-generated method stub/*********/}};
frame.addKeyListener(keylistener);

为ballfight类中的实例化对象添加了MouseMotionListener和MouseListener监听,用来获取用户在面板上的鼠标移动和鼠标点击。

game.mouse_adapter = new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {// TODO Auto-generated method stub}@Overridepublic void mousePressed(MouseEvent e) {// TODO Auto-generated method stub/*********/}};game.addMouseListener(mouse_adapter);game.addMouseMotionListener(new MouseMotionListener() {@Overridepublic void mouseMoved(MouseEvent e) {// TODO Auto-generated method stubmx = e.getX();my = e.getY();}@Overridepublic void mouseDragged(MouseEvent e) {// TODO Auto-generated method stub}});

在游戏进行中需要在地图中随机生成微粒,通过Runnable接口定义一个ParticleMaker类,将这个线程加入到主类中即可实现随机生成的任务。

public class ParticleMaker implements Runnable {@Overridepublic void run() {// TODO Auto-generated method stubwhile (player.isAlive()) {synchronized (this) {for (int i = 0; i < particlepertime; i++) {MakeParticle();}}try {Thread.sleep(particletime);} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}}}

为了增强游戏的趣味性,添加了和用户体重相关的排行榜功能。通过定义一个ranking类,实现对场上所有存活玩家和敌人的体重排序并生成一个实时更新的排行榜,供玩家参考自己的体重在当前场上的排名情况。

public class ranking {Ball[] M = new Ball[10000];Color Gold = new Color(255, 215, 0);Color Silver = new Color(192, 192, 192);Color Copper = new Color(244, 164, 96);Color MediumOrchid = new Color(186, 85, 211);Color Lavender = new Color(230, 230, 250);Color CornflowerBlue = new Color(100, 149, 237);public Ball[] getM() {return M;}public void setM(Ball[] m) {M = m;}public ranking() {int j = 0;for (int i = 0; i < enemy.size(); i++) {Enemy e = enemy.get(i);if (e != null && e.isAlive()) {M[j] = e;j++;}}M[j] = player;for (int i = 0; i < ranknum; i++) {int x = i;for (int ii = i + 1; ii <= j; ii++) {if (M[ii].getM() > M[x].getM()) {x = ii;}}Ball y = M[i];M[i] = M[x];M[x] = y;}}public void UpdateRankingList() {int j = 0;for (int i = 0; i < enemy.size(); i++) {Enemy e = enemy.get(i);if (e != null && e.isAlive()) {M[j] = e;j++;}}M[j] = player;for (int i = 0; i < ranknum; i++) {int x = i;for (int ii = i + 1; ii <= j; ii++) {if (M[ii].getM() > M[x].getM()) {x = ii;}}Ball y = M[i];M[i] = M[x];M[x] = y;}}public void DrawRankingList(Graphics g) {UpdateRankingList();g.setColor(MediumOrchid);g.setFont(new Font("Comic Sans MS", Font.LAYOUT_LEFT_TO_RIGHT, 21));g.drawString("---Ranking---", windowWidth - 200, 20);g.setFont(new Font("楷体", Font.LAYOUT_LEFT_TO_RIGHT, 18));g.drawString("排名", windowWidth - 200, 45);g.drawString("昵称", windowWidth - 140, 45);g.drawString("地区", windowWidth - 90, 45);g.setColor(Gold);g.setFont(new Font("黑体", Font.LAYOUT_LEFT_TO_RIGHT, 20));g.drawString(1 + ": ", windowWidth - 200, 70 + fontlineheight * 0);g.setColor(Color.white);g.drawString(M[0].getName(), windowWidth - 160, 70 + fontlineheight * 0);g.drawImage(M[0].getFlag(), windowWidth - 85, 55 + fontlineheight * 0, 27, 18, null);g.setColor(Silver);g.setFont(new Font("黑体", Font.LAYOUT_LEFT_TO_RIGHT, 20));g.drawString(2 + ": ", windowWidth - 200, 70 + fontlineheight * 1);g.setColor(Color.white);g.drawString(M[1].getName(), windowWidth - 160, 70 + fontlineheight * 1);g.drawImage(M[1].getFlag(), windowWidth - 85, 55 + fontlineheight * 1, 27, 18, null);g.setColor(Copper);g.setFont(new Font("黑体", Font.LAYOUT_LEFT_TO_RIGHT, 20));g.drawString(3 + ": ", windowWidth - 200, 70 + fontlineheight * 2);g.setColor(Color.white);g.drawString(M[2].getName(), windowWidth - 160, 70 + fontlineheight * 2);g.drawImage(M[2].getFlag(), windowWidth - 85, 55 + fontlineheight * 2, 27, 18, null);for (int i = 3; i < ranknum; i++) {g.setColor(CornflowerBlue);g.setFont(new Font("黑体", Font.LAYOUT_LEFT_TO_RIGHT, 20));g.drawString(i + 1 + ": ", windowWidth - 200, 70 + fontlineheight * i);g.setColor(Color.white);g.drawString(M[i].getName(), windowWidth - 160, 70 + fontlineheight * i);g.drawImage(M[i].getFlag(), windowWidth - 85, 55 + fontlineheight * i, 27, 18, null);}}}

游戏流程展示

1. 开始游戏页面

2. 加载中页面

3. 选择地图页面

4. 自定义昵称页面

5. 运行页面

死亡页面

发展方向

这次项目学习收获很大,在初期因为空指针错误耽误了很长时间去琢磨Java中的ArrayList和List及其方法,但是当问题经过广泛地排查得到解决后对知识的理解也更进一步。这个项目现在虽然能够较流畅地运行,但是其发展空间仍然巨大。正如前面在分析图中介绍的,我希望能够为所有的敌人类分阶段地设计编写一种智能的算法,让程序控制的小球能够在某种情境下以超过玩家的速度发育,可能要用到贪心算法、最短路径等理论。在真正的手机端游戏中,小球可以分裂成两个、四个甚至更多,因为本项目未实现玩家视野大小的动态调整,所以很遗憾没能实现分裂功能。这些都为以后这个项目的继续发展提供了可能。

(前面都不感兴趣,快进到)原码

链接:https://pan.baidu.com/s/1oLecTmwYWkvFDwVWu9KFYQ
提取码:y0v1

最后

我是第一次用Java写游戏,所以如果有错误和愚蠢的地方请大家指出,也请同样小白的同学对我的代码不要依赖可能有错555 ,欢迎大家在评论区交流学习!\\^ _ ^//!

《Java小游戏》:球球大作战相关推荐

  1. JAVA小游戏推球球

    图形化界面的简单应用 先看效果 java小游戏推球球 代码如下 import javax.swing.*; import java.awt.*; import java.awt.event.*;pub ...

  2. Java窗体小游戏开发飞机大作战Java小游戏开发源码

    Java窗体小游戏开发飞机大作战Java小游戏开发源码

  3. egret开发HTML5小游戏-《猫猫大作战》(一)

    ps:本文适用于和我一样刚刚入门egret的同学们,大佬看到这里可以忙别的去了. 之前用egret引擎设计了一款双人设计小游戏-<疯狂大乱斗>,算是初步了解了引擎的使用,这次打算开发一款基 ...

  4. 【C/C++小游戏】2048 大作战!(基于Easyx图形窗口实现)

    目录 目录 目录 写在前面 游戏简介 Easyx 图形库 编写游戏 预编译代码 第一步:初始化棋盘 第二步:绘制棋盘 第三步:用户操作 第四步:封装函数 完整代码 效果展示 写在前面 大家好!本人是一 ...

  5. python:小游戏“贪吃蛇大作战“!

    代码: import pygame import sys import random from pygame.locals import * class Snake(object): #制作背景和蛇. ...

  6. Java小程序之球球大作战(基于Java线程实现)

    Java小程序之球球大作战(基于Java线程实现) 一.游戏基本功能: 1.自己的小球可以随着鼠标的移动而改变坐标: 2.敌方小球不断的在界面中移动 3.当检测到敌方小球相互碰撞时,小球会弹开 4.当 ...

  7. c++游戏代码坦克大作战_一红一蓝多种模式的双人小游戏:红蓝大作战

    作者有话说:上次推荐的森林冰火人很多小伙伴后台找我要链接,或者搜索不到:首先声明下森林冰火人.同桌大作战都不是辣椒人游戏工作室研发的,小编也是微信小游戏双人栏目下搜索到的,如果想要玩双人小游戏的可以打 ...

  8. 各种经典java小游戏_Java是这个世界上最好的语言!

    为什么? 请看TIOBE最新发布的编程语言排行榜: TIOBE开发语言排行榜每月更新一次,其结果可以用来检阅开发者的编程技能能否跟上趋势,或是否有必要作出战略改变,以及什么编程语言是应该及时掌握的. ...

  9. hihoCoder 1114 小Hi小Ho的惊天大作战:扫雷·一 最详细的解题报告

    题目来源:小Hi小Ho的惊天大作战:扫雷·一 解题思路:因为只要确定了第一个是否有地雷就可以推算出后面是否有地雷(要么为0,要么为1,如果不是这两个值就说明这个方案行不通),如果两种可能中有一种成功, ...

  10. 【Java】寒假答辩作品:Java小游戏

    文章目录 java入门小游戏[test] 游戏界面 前言 (可直接跳到程序介绍) 前期入门小项目 前期收获 后期自创关卡 熄灯问题拓展 新游戏拓展 实现切换关卡切换音乐 后续 java入门小游戏[te ...

最新文章

  1. JavaScript验证时间格式
  2. ML之SR:Softmax回归(Softmax Regression)的简介、使用方法、案例应用之详细攻略
  3. iservice封装有哪些方法_5w大功率led白光灯珠参数,5w大功率led灯珠有哪些?
  4. 将一个实体转换成 Url 参数的形式 ?a=ab=b
  5. 搜集的一些有意思的牛人博客地址
  6. windows下python 自动截图功能
  7. varchar长度可以任意设置吗_户内金属软管长度可以超过2m吗?
  8. javaweb框架和其他知识点总结
  9. 怎么理解java面向对象
  10. 微波雷达感应模块,智能洗衣机雷达技术方案,自动感应开门应用
  11. 计算机网络部分英文缩写汇总
  12. 微信公众号(订阅号)如何开通付费功能?
  13. 科海故事博览杂志科海故事博览杂志社科海故事博览编辑部2022年第15期目录
  14. CSS基础常识问答(二)
  15. vant 验证手机号_Vue 正则表达式验证邮箱和手机号码
  16. 华为交换机如何批量清除接口配置信息
  17. 解析二分查找时间复杂度
  18. 《思维力:高效的系统思维》读书笔记05 - 快速提升你的沟通表达能力
  19. Echarts 用图形纹理来填充颜色(color - pattern)
  20. PAC学习框架-泛化误差

热门文章

  1. ubuntu下火狐浏览器更新版本
  2. PTA平台 · PAT(Basic Level) Practice(中文) 题目集
  3. 支付宝网页服务器出错500,YunCart电商网站支付宝接口出现500错误
  4. 使用vue实现超级课程表的功能【附完整源码】
  5. cubase立体声_Cubase 小贴士:混响评比
  6. 如何在蒲公英免费分发托管自己的应用?
  7. 数据库服务器账号不能登录问题
  8. UWB 技术为 AVP 赋能
  9. python给图片加动态特效_用Python给图片加上抖音效果
  10. 阿里云OSS获取STS临时访问凭证