Java课程设计--大鱼吃小鱼
- 前言
- 1、创建FishFrame.java
- 2、创建FishPanel.java
- 3. 创建一个DataImg.java来统一加载图片
- 3.1 将图片保存在一个包下面如图:
- 4.创建鱼的类
- 4.1 鱼的父类Fish.java
- 4.2 其他鱼(都是相似的)
- 4.3 自己的鱼
- 5.结语
前言
游戏整体框架来着B站:这是链接:Java实战训练营 在我的课设中改进了让鱼有游动特效,以及增添了鼠标监听事件等等游戏优化
游戏效果:
1、创建FishFrame.java
package FishGame;
import javax.swing.*;
import java.awt.event.*;
/*
* 步骤:
* 1.先创建窗体对象
* 2.背景的绘制
* 3.键盘的监听事件
* 1.实现接口
* 2.添加监听的事件
* 4.将己方鱼放上去
* 5.让小鱼移动
* 6.敌方的🐟(先创建集合把鱼装起来,获取每个对象,画图)
* 7.吃鱼
* 8.被吃
* 9.增加了鼠标事件
* */
public class FishFrame extends JFrame{
public FishFrame(String username){
setTitle("大鱼吃小鱼:欢迎你 "+username);
FishPanel fishPanel=new FishPanel(username);
add(fishPanel);
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
fishPanel.move(e.getPoint());
}
});
addKeyListener(new MyFishKeyListener(){
@Override
public void keyPressed(KeyEvent e) {
int vk=e.getKeyCode();
fishPanel.move(vk);
}
});
fishPanel.action();//启动线程
setBounds(100,20,1440,900);
setVisible(true);
setResizable(false);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
addKeyListener(new MyFishKeyListener());
}
public static void main(String[] args){
new FishFrame("用户");
}
}
class MyFishKeyListener implements KeyListener{
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
2、创建FishPanel.java
里面的hit()鱼碰撞事件可以改进
package FishGame;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.TimerTask;
import java.util.Timer;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
public class FishPanel extends JPanel{
标识状态0开始,1运行,2暂停,3是结束
public int state = START;
public static final int START=0;
public static final int RUNNING =1;
public static final int PAUSE =2;
public static final int GAMEOVER =3;
Image bkImg = DataImg.background;
Image start =DataImg.start;
int score=0;//经验得分
ArrayList<Fish> fishes = new ArrayList<Fish>();//装其他🐟的集合
int fish_1=0,fish_2=1,fish_3=1,fish_4=1,fish_5=1;
boolean lock=true;
Point p;
myFish fish;
String username;
public FishPanel(String username){
this.username=username;
fish=new myFish();
}
@Override
public void paint(Graphics g) {
super.paint(g);
//绘制游戏背景界面
switch(state) {
case START: g.drawImage(start, 0, 0, 1440, 900, null);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.setColor(Color.WHITE);
g.drawString("按下空格开始",600,600);
score=0;//再次初始化
break;
case RUNNING:
//背景绘制
drawBackGround(g);
//绘制己方的小鱼
drawMyFish(g);
//绘制其他的小鱼
drawFishes(g);
//设置字体颜色
g.setColor(Color.white);
Font f = new Font("黑体",Font.BOLD,20);//加粗
g.setFont(f); //传进去
g.drawString("当前得分:"+score, 15, 20);//在x=15,y=20显示分数
g.drawString("战斗力:"+fish.zhanli, 200, 20);
break;//一样
case PAUSE:
drawBackGround(g);
drawMyFish(g);
drawFishes(g);
g.setColor(Color.white);
Font fff = new Font("黑体",Font.BOLD,50);
g.setFont(fff);
g.drawString("按下空格继续游戏",500 ,450);
break;
case GAMEOVER:
drawBackGround(g);
drawMyFish(g);
drawFishes(g);
g.drawString("当前得分:"+score, 15, 20);
g.setColor(Color.white);
Font ff = new Font("黑体",Font.BOLD,50);
g.setFont(ff);
g.drawString("游戏 结束",600 ,450);
break;
}
}
/*定时器、
1.生成其他鱼
2.移动*/
public void action(){//多线程,timer内部实现
Timer timer=new Timer();
timer.schedule(new TimerTask() {//定时器任务
@Override
public void run() {
if(state==1) {
createFish();//1.创建其他鱼2.不断的改变其他鱼的位置:
hitFish();//3.吃鱼
if(lock)move(p);
outOfBounds();//4.当鱼跑出圈外,我们要删除集合中的鱼;
repaint(); //重画
}
}
},20,10);//20延迟执行,10每隔10ms执行run里面的内容一次
}
//产生鱼
private void createFish() {
if((fish_1++%200)==0) {//每隔10ms自加一次
fishes.add(new Fish_1());
}
if((fish_2++%300)==0) {
fishes.add(new Fish_2());
fishes.add(new Fish_2_1());
}
if((fish_3++%400)==0) {
fishes.add(new Fish_3());
}
if((fish_4++%600)==0) {
fishes.add(new Fish_4());
}
if((fish_5++%1500)==0) {
fishes.add(new Fish_5());
}
}
private void hitFish() {
for(int i=0;i<fishes.size();i++) {
if(hit(fishes.get(i))) {
if(fish.zhanli>=fishes.get(i).zhanli) {
switch(fishes.get(i).zhanli) {
case 1:
score++;
break;
case 2:
score+=2;
break;
case 3:
score+=3;
break;
case 4:
score+=4;
break;
}
fishes.remove(i);//根据分数加战力
if(score>=10 && score<40)
fish.zhanli=2;
if(score>=40 && score<80)
fish.zhanli=3;
if(score>=80)
fish.zhanli=4;
}else {
state=3;//运行结束
}
}
}
}
private void outOfBounds() {
for(int i=0;i<fishes.size();i++) {
if(fishes.get(i).isMoveLeft) {
if(fishes.get(i).x+fishes.get(i).length<=0) {
fishes.remove(i);
}
} else
if(fishes.get(i).x>=1440) {
fishes.remove(i);
}
}
}
//中心点在鱼的xy范围内,检测碰撞
public boolean hit(Fish fishs) {
int x=(fish.x1+fish.x)/2,y=(fish.y+fish.y1)/2;
int x1 = fish.x1,y1 = fish.y1;
int x2 = fish.x,y2 = fish.y;
if(((x>=fishs.x)&&(x<=fishs.x+fishs.length))||((x1>=fishs.x)&&(x1<=fishs.x+fishs.length))||((x2>=fishs.x)&&(x2<=fishs.x+fishs.length)) ){
if(((y>=fishs.y)&&(y<=fishs.y+fishs.height))||((y1>=fishs.y)&&(y1<=fishs.y+fishs.height))||((y2>=fishs.y)&&(y2<=fishs.y+fishs.height))) {
return true;//产生碰撞
}
}
return false;
}
public void move(int keycode) {//键盘事件移动鱼
switch(keycode) {
case KeyEvent.VK_RIGHT:
fish.moveRight();
break;
case KeyEvent.VK_LEFT:
fish.moveLeft();
break;
case KeyEvent.VK_UP:
fish.fishMoveUp();
break;
case KeyEvent.VK_DOWN:
fish.fishMoveDown();
break;
case KeyEvent.VK_ESCAPE:
if (state==RUNNING)state=GAMEOVER;
break;
case KeyEvent.VK_SPACE:
if(state == 0) {
state=RUNNING;
}else if(state==1){
state=PAUSE;
}else if(state==2){
state=RUNNING;
}
else if(state==3) {
state=START;
fish=new myFish();
fishes = new ArrayList<Fish>();
}
break;
}
repaint();
}
public void move(Point point){
p=point;
lock=true;//产生鼠标事件
if(p.x>(fish.x1+fish.x)/2 && p.y>=(fish.y1+fish.y)/2){fish.moveDownAndRight();}
else if(p.x>(fish.x1+fish.x)/2 && p.y<=(fish.y1+fish.y)/2){fish.moveUpAndRight();}
else if(p.x<(fish.x1+fish.x)/2 && p.y>=(fish.y1+fish.y)/2){fish.moveDownAndLeft();}
else if(p.x<(fish.x1+fish.x)/2 && p.y<=(fish.y1+fish.y)/2){ fish.moveUpAndLeft();}
else{lock=false;}
}
//画其他鱼
private void drawFishes(Graphics g) {
// TODO Auto-generated method stub
for(int i=0;i<fishes.size();i++) {
fishes.get(i).draw(g);
}
}
//画自己的鱼
private void drawMyFish(Graphics g) {
// TODO Auto-generated method stub
fish.draw(g);
}
private void drawBackGround(Graphics g) {
// TODO Auto-generated method stub
g.drawImage(bkImg, 0, 0, 1440, 900, 0, 0, 1920, 1080, null);
}
}
3. 创建一个DataImg.java来统一加载图片
注:游戏鱼的图片要采用游戏素材半透明的图片,截图会有框。
package FishGame;
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class DataImg {
public static URL start_path = DataImg.class.getResource("Img/begin_picture.jpg");
public static URL fish08_path = DataImg.class.getResource("Img/fish08.png");
public static URL fish12_path = DataImg.class.getResource("Img/fish12.png");
public static URL fish03_path = DataImg.class.getResource("Img/fish03.png");
public static URL fish17_path = DataImg.class.getResource("Img/fish17.png");
public static URL background_path = DataImg.class.getResource("Img/background2.jpeg");
public static URL fish06_path = DataImg.class.getResource("Img/fish06.png");
public static URL lantern_path = DataImg.class.getResource("Img/fish.png");
public static Image start = new ImageIcon(start_path).getImage();
public static Image fish08 = new ImageIcon(fish08_path).getImage();
public static Image fish12 = new ImageIcon(fish12_path).getImage();
public static Image fish03 = new ImageIcon(fish03_path).getImage();
public static Image fish17 = new ImageIcon(fish17_path).getImage();
public static Image background = new ImageIcon(background_path).getImage();
public static Image fish06 = new ImageIcon(fish06_path).getImage();
public static Image lantern = new ImageIcon(lantern_path).getImage();
}
3.1 将图片保存在一个包下面如图:
4.创建鱼的类
4.1 鱼的父类Fish.java
package FishGame;
import java.awt.Graphics;
import java.awt.Image;
//父类的鱼
public class Fish {
int length,height;//鱼的宽高
int x,y;//初始位置
boolean isMoveLeft=true;//鱼的初始方向
//原图片的坐标左上角和右下角(裁剪)
int sx1,sy1;
int sx2,sy2;
int step;
int zhanli;
Image img;//鱼的图片
//绘制
public void draw(Graphics g) {};
}
4.2 其他鱼(都是相似的)
package FishGame;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_1 extends Fish{
int xx;
int change=0;
public Fish_1() {
action();
step=2;
xx=(int)(Math.random()*2);//0或者1
switch(xx) {//出场位置
case 0:
isMoveLeft=false;
x=-68;
break;
case 1:
isMoveLeft=true;
x=1440;
break;
}
y=(int)(Math.random()*900);//垂直位置
length= 68;
height= 55;
zhanli=1;
//界面坐标
img = DataImg.fish08;
}
public void draw(Graphics g){
if(isMoveLeft) {//左移
sy1=height*change;;
sx1=0;
sy2=height+height*change;
sx2=length;
g.drawImage(img, x=x-4, y, x+length, y+height, sx1, sy1, sx2,sy2, null);//可以控制鱼的速度
}
else {//右移
sx2=0;
sy2=height*change;;
sx1=length;
sy1=height+height*change;
g.drawImage(img, x=x+4, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
每条鱼里都有单独的时间线程,每0.5秒切换一次鱼的图片,达到游动动态效果
package FishGame;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_2_1 extends Fish{
int xx;
int change=0;
public Fish_2_1() {
step=3;
action();
xx=(int)(Math.random()*2);
switch(xx) {
case 0:
isMoveLeft=false;
x=-96;
break;
case 1:
isMoveLeft=true;
x=1440;
break;
}
y=(int)(Math.random()*900);
length= 90;
height= 29;
zhanli=2;
//界面坐标
img = DataImg.fish06;
}
public void draw(Graphics g){
if(isMoveLeft) {//左移
sy1=height*change;;
sx1=0;
sy2=height+height*change;
sx2=length;
g.drawImage(img, x=x-3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
else {//右移
sx2=0;
sy2=height*change;;
sx1=length;
sy1=height+height*change;
g.drawImage(img, x=x+3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
package FishGame;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_2 extends Fish{
int xx;
int change=0;
public Fish_2() {
step=3;
action();
xx=(int)(Math.random()*2);
switch(xx) {
case 0:
isMoveLeft=false;
x=-96;
break;
case 1:
isMoveLeft=true;
x=1440;
break;
}
y=(int)(Math.random()*900);
length= 96;
height= 29;
zhanli=2;
//界面坐标
img = DataImg.fish12;
}
public void draw(Graphics g){
if(isMoveLeft) {//左移
sy1=height*change;;
sx1=0;
sy2=height+height*change;
sx2=length;
g.drawImage(img, x=x-3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
else {//右移
sx2=0;
sy2=height*change;;
sx1=length;
sy1=height+height*change;
g.drawImage(img, x=x+3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
package FishGame;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_3 extends Fish{
int xx;
int change=0;
public Fish_3() {
step=3;
action();
xx=(int)(Math.random()*2);
switch(xx) {
case 0:
isMoveLeft=false;
x=-96;
break;
case 1:
isMoveLeft=true;
x=1440;
break;
}
y=(int)(Math.random()*900);
length= 110;
height=60;
zhanli=3;
//界面坐标
img = DataImg.lantern;
}
public void draw(Graphics g){
if(isMoveLeft) {//左移
sy1=336+height*change;;
sx1=330;
sy2=336+height+height*change;
sx2=336+length;
g.drawImage(img, x=x-3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
else {//右移
sx2=330;
sy2=336+height*change;;
sx1=330+length;
sy1=336+height+height*change;
g.drawImage(img, x=x+3, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
package FishGame;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_4 extends FishGame.Fish {
int xx;
int change=0;
public Fish_4() {
step=4;
action();
xx=(int)(Math.random()*2);
switch(xx) {
case 0:
isMoveLeft=false;
x=-310;
break;
case 1:
isMoveLeft=true;
x=1440;
break;
}
y=(int)(Math.random()*900);
length= 310;
height= 104;
zhanli=3;
//界面坐标
img = DataImg.fish03;
}
public void draw(Graphics g){
if(isMoveLeft) {//左移
sy1=height*change;;
sx1=0;
sy2=height+height*change;
sx2=length;
g.drawImage(img, x=x-2, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
else {//右移
sx2=0;
sy2=height*change;;
sx1=length;
sy1=height+height*change;
g.drawImage(img, x=x+2, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
package FishGame;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
public class Fish_5 extends Fish {
int xx;
int change=0;
public Fish_5() {
step=2;
action();
xx=(int)(Math.random()*2);
switch(xx) {
case 0:
isMoveLeft=false;
x=-380;
break;
case 1:
isMoveLeft=true;
x=1440;
break;
}
y=(int)(Math.random()*900);
length= 380;
height= 210;
zhanli=4;
//界面坐标
img = DataImg.fish17;
}
public void draw(Graphics g){
if(isMoveLeft) {//左移
sy1=height*change;;
sx1=0;
sy2=height+height*change;
sx2=length;
g.drawImage(img, x--, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
else {//右移
sx2=0;
sy2=height*change;;
sx1=length;
sy1=height+height*change;
g.drawImage(img, x++, y, x+length, y+height, sx1, sy1, sx2,sy2, null);
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
4.3 自己的鱼
package FishGame;
import java.util.TimerTask;
import java.util.Timer;
import java.awt.*;
public class myFish extends Fish{
int x1,y1;//
int change=0;
public myFish() {
action();
length= 68;//鱼的大小
height= 55;
zhanli=1;
//初始鱼界面坐标
x=100;
y=450;
//初始坐标加上长宽后就确定了鱼图片的位置
x1=x+68;
y1=y+55;
step=2;
}
//鱼的转向
public void draw(Graphics g){
super.draw(g);
changeFishSize(zhanli);
if(isMoveLeft) {
sy1=height*change;
sx1=0;
sy2=height+height*change;
sx2=length;
}else {
sy2=height*change;
sx2=0;
sy1=height+height*change;
sx1=length;
}
Image img = selectImage(zhanli);
//画图前4个坐标确定鱼显示位置,后4个对鱼进行剪裁
g.drawImage(img, x, y, x1, y1, sx1, sy1, sx2,sy2, null);
}
private void changeFishSize(int level) {
if(level<2){ }
else if(level==2){
length=96;
height=29;
step=3;
x1=x+96;
y1=y+29;
}
else if(level==3){
length=310;
height=106;
step=4;
x1=x+310;
y1=y+104;
}
else {
length=375;
height=205;
step=2;
x1=x+380;
y1=y+210;
}
}
public void moveRight() {
isMoveLeft=false;
if(x<=1350) {//符合移动规范
x+=10;
x1+=10;
}//水平移动y不变;
}
public void moveLeft() {
isMoveLeft=true;
if(x>=10) {
x-=10;
x1-=10;
}//水平移动y不变;
}
//上下移动不关其他事
public void fishMoveUp() {
if(y>=0) {
y-=10;
y1-=10;
}
}
public void fishMoveDown() {
if(y<=800) {
y+=10;
y1+=10;
}
}
public void moveUpAndRight() {
isMoveLeft=false;
y-=1;
x+=1;
x1=x+68;
y1=y+55;
}
public void moveUpAndLeft() {
isMoveLeft=true;
y-=1;
x-=1;
x1=x+68;
y1=y+55;
}
public void moveDownAndRight() {
isMoveLeft=false;
y+=1;
x+=1;
x1=x+68;
y1=y+55;
}
public void moveDownAndLeft() {
isMoveLeft=true;
y+=1;
x-=1;
x1=x+68;
y1=y+55;
}
public Image selectImage(int level){//进化
if(level<2){
return DataImg.fish08;
}
else if(level==2){
return DataImg.fish12;
}
else if(level==3){
return DataImg.fish03;
}
else {
return DataImg.fish17;
}
}
public void action(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
change=(++change)%step;
}
},20,500);
}
}
5.结语
在FishFrame.java里运行main就可以开始游戏
原本我的课设是有登入界面的(涉及数据库这里已经删除了。。长这样)