java小游戏-java小游戏-大鱼吃小鱼
1 创建窗口
创建GameApp类
public class GameApp extends JFrame {
//宽高
int width = 1440;
int height = 900;
void launch(){
this.setVisible(true);
this.setSize(width,height);
this.setLocationRelativeTo(null);
//设置游戏窗口不可改变
this.setResizable(false);
this.setTitle("大鱼吃小鱼");
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
GameApp gameApp = new GameApp();
gameApp.launch();
}
}
2 添加背景图
先上传准备的图片
创建GameUtils类
/**
* 工具类
*/
public class GameUtils {
//背景图片
public static Image bjimg = Toolkit.getDefaultToolkit().createImage("img/bj.jpg");
}
在GameApp类重写paint方法
@Override
public void paint(Graphics g) {
g.drawImage(GameUtils.bjimg,0,0,null);
}
3 启动封面
在GameApp类添加参数,修改paint方法
//游戏状态 0 未开始 1 游戏中 2 通关失败 3 通关完成 4 暂停
static int state = 0;
@Override
public void paint(Graphics g) {
g.drawImage(GameUtils.bjimg,0,0,null);
switch (state){
case 0:
g.drawImage(GameUtils.bjimg,0,0,null);
g.setColor(Color.pink);
g.setFont(new Font("仿宋",Font.BOLD,80));
g.drawString("开始",700,500);
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}
4 启动页面的点击事件
在GameApp类添加鼠标监听事件
void launch(){
...
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//鼠标监听事件
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if(e.getButton() == 1 && state == 0){//鼠标左键点击
state = 1;
repaint();
}
}
});
}
5 游戏开始时的背景添加
创建Bj类
/**
* 背景类
*/
public class Bj {
void paintSelf(Graphics g){
g.drawImage(GameUtils.bjimg,0,0,null);
}
}
在GameApp类中引用
Bj bj = new Bj();
void launch(){
...
while (true){
repaint();
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void paint(Graphics g) {
g.drawImage(GameUtils.bjimg,0,0,null);
switch (state){
case 0:
g.drawImage(GameUtils.bjimg,0,0,null);
g.setColor(Color.pink);
g.setFont(new Font("仿宋",Font.BOLD,80));
g.drawString("开始",700,500);
break;
case 1:
bj.paintSelf(g);
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
}
6 双缓存解决闪屏问题
在GameApp类添加画屏
Image offScreenImage = null;
@Override
public void paint(Graphics g) {
//懒加载模式初始化对象
offScreenImage = createImage(width,height);
Graphics graphics = offScreenImage.getGraphics();
switch (state){
case 0:
graphics.drawImage(GameUtils.bjimg,0,0,null);
graphics.setColor(Color.pink);
graphics.setFont(new Font("仿宋",Font.BOLD,80));
graphics.drawString("开始",700,500);
break;
case 1:
bj.paintSelf(graphics);
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
g.drawImage(offScreenImage,0,0,null);
}
7 地方第一条小鱼的添加
在GameUtils类添加敌方小鱼图片
//敌方鱼类
public static Image enemy1_img = Toolkit.getDefaultToolkit().createImage("img/finsh1_r.gif");
创建Enemy类
/**
* 敌方类
*/
public class Enemy {
//定义图片
Image image;
//定义物体坐标
int x,y;
int width,height;
//移动速度
int speed;
//方向 1 从左到右 -1 从右到左
int dir = 1;
//类型
int type;
//分值
int count;
//绘制自身方法
public void paintSelf(Graphics g){
g.drawImage(image,x,y,width,height,null);
}
//获取自身矩形用于碰撞检测
public Rectangle getRec(){
return new Rectangle(x,y,width,height);
}
}
创建Enemy_1_L类
/**
* 敌方鱼的左类
*/
public class Enemy_1_L extends Enemy{
public Enemy_1_L(){
this.x = -45;
this.y = (int)(Math.random()*700 + 100);
this.width = 45;
this.height = 69;
this.speed = 10;
this.count = 1;
this.type = 1;
this.image = GameUtils.enemy1_img;
}
}
在GameApp类创建敌方鱼类对象,修改paint方法
//敌方鱼类
Enemy enemy = new Enemy_1_L();
public void paint(Graphics g) {
...
switch (state){
...
case 1:
bj.paintSelf(graphics);
enemy.x += enemy.speed;
enemy.paintSelf(graphics);
break;
case 2:
...
}
8 敌方左方小鱼批量添加
在GameUtils类创建敌方鱼集合
//敌方鱼类集合
public static List<Enemy> enemyList = new ArrayList<>();
修改GameApp类添加方法
double random;
//计数器
int time = 0;
void launch() {
...
while (true) {
repaint();
time++;
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void paint(Graphics g) {
...
switch (state){
...
case 1:
bj.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
break;
case 2:
...
}
void logic() {
//敌方鱼生成
if (time % 10 == 0) {
enemy = new Enemy_1_L();
GameUtils.enemyList.add(enemy);
}
//移动方向
for (Enemy e : GameUtils.enemyList) {
e.x = e.x + e.dir * e.speed;
}
}
9 我方鱼生成
在GameUtils添加参数
//我方鱼类
public static Image myFishimg_l = Toolkit.getDefaultToolkit().createImage("img/myfishimg_l.gif");
public static Image myFishimg_r = Toolkit.getDefaultToolkit().createImage("img/myfishimg_r.gif");
//我方鱼方向
static boolean UP = false;
static boolean DOWN = false;
static boolean LEFT = false;
static boolean RIGHT = false;
创建MyFish类
/**
* 我方鱼类
*/
public class MyFish {
//图片
Image image;
//坐标
int x = 700, y = 500;
int width = 50, height = 50;
//移动速度
int speed = 20;
//等级
int level = 1;
void logic() {
if (GameUtils.UP) {
y = y - speed;
}
if (GameUtils.DOWN) {
y = y + speed;
}
if (GameUtils.LEFT) {
x = x - speed;
image = GameUtils.myFishimg_l;
}
if (GameUtils.RIGHT) {
x = x + speed;
image = GameUtils.myFishimg_r;
}
}
//绘制自身方法
public void paintSelf(Graphics g) {
logic();
g.drawImage(image, x, y, width, height, null);
}
//获取自身矩形方法,用于碰撞判断
public Rectangle getRec() {
return new Rectangle(x, y, width, height);
}
}
在GameApp类引用对象
//我方鱼
MyFish myFish = new MyFish();
void launch() {
...
@Override
public void keyReleased(KeyEvent e) {//键抬起
super.keyReleased(e);
if(e.getKeyCode() == KeyEvent.VK_UP){//↑
GameUtils.UP = false;
}
if(e.getKeyCode() == KeyEvent.VK_DOWN){//↓
GameUtils.DOWN = false;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){//←
GameUtils.LEFT = false;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){//→
GameUtils.RIGHT = false;
}
}
});
while (true) {
...
@Override
public void paint(Graphics g) {
...
case 1:
bj.paintSelf(graphics);
myFish.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
g.drawImage(offScreenImage, 0, 0, null);
}
10 我方鱼吃敌方小鱼的碰撞检测
在GameApp类修改logic方法
void logic() {
//敌方鱼生成
if (time % 10 == 0) {
enemy = new Enemy_1_L();
GameUtils.enemyList.add(enemy);
}
//移动方向
for (Enemy e : GameUtils.enemyList) {
e.x = e.x + e.dir * e.speed;
//我方鱼与敌方鱼碰撞检测
if(myFish.getRec().intersects(e.getRec())){
System.out.println("碰撞了");
e.x = -200;
e.y = -200;
}
}
}
11 游戏积分的实现
在GameUtils类添加常量
//分数
static int count = 0;
在MyFish类修改方法
//绘制自身方法
public void paintSelf(Graphics g) {
logic();
g.drawImage(image, x, y, width + GameUtils.count, height+ GameUtils.count, null);
}
//获取自身矩形方法,用于碰撞判断
public Rectangle getRec() {
return new Rectangle(x, y, width + GameUtils.count, height + GameUtils.count);
}
在GameApp类修改相关方法
@Override
public void paint(Graphics g) {
...
case 1:
bj.paintSelf(graphics);
//打印积分
graphics.setColor(Color.ORANGE);
graphics.setFont(new Font("仿宋", Font.BOLD, 50));
graphics.drawString("积分" + GameUtils.count,200,120);
myFish.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
g.drawImage(offScreenImage, 0, 0, null);
}
void logic() {
...
//移动方向
for (Enemy e : GameUtils.enemyList) {
e.x = e.x + e.dir * e.speed;
//我方鱼与敌方鱼碰撞检测
if(myFish.getRec().intersects(e.getRec())){
System.out.println("碰撞了");
e.x = -200;
e.y = -200;
GameUtils.count = GameUtils.count+e.count;
}
}
}
12 关卡的设置
在GameUtils类添加常量
//关卡的等级
static int level = 0;
在GameApp类修改相关方法
@Override
public void paint(Graphics g) {
....
case 3:
myFish.paintSelf(graphics);
graphics.setColor(Color.orange);
graphics.setFont(new Font("仿宋", Font.BOLD, 80));
graphics.drawString("积分" + GameUtils.count,200,120);
graphics.drawString("胜利",400,500);
break;
case 4:
break;
}
g.drawImage(offScreenImage, 0, 0, null);
}
void logic() {
//关卡的难度
if (GameUtils.count < 5) {
GameUtils.level = 0;
myFish.level = 1;
}else if(GameUtils.count <= 15){
GameUtils.level = 1;
}else if(GameUtils.count <= 50){
GameUtils.level = 2;
myFish.level = 2;
}else if(GameUtils.count <= 150){
GameUtils.level = 3;
myFish.level = 3;
}else if(GameUtils.count <= 300){
GameUtils.level = 4;
myFish.level = 3;
}else if(GameUtils.count > 300){
state = 3;
}
//敌方鱼生成
...
}
13 界面绘制
在GameUtils类添加方法
//绘制文字的工具方法
public static void drawWord(Graphics g,String str,Color color,int size,int x,int y){
g.setColor(color);
g.setFont(new Font("仿宋", Font.BOLD, size));
g.drawString(str,x,y);
}
在GameApp类修改相关方法
@Override
public void paint(Graphics g) {
//懒加载模式初始化对象
offScreenImage = createImage(width, height);
Graphics graphics = offScreenImage.getGraphics();
bj.paintSelf(graphics,myFish.level);
switch (state) {
case 0:
break;
case 1:
myFish.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
break;
case 2:
break;
case 3:
myFish.paintSelf(graphics);
break;
case 4:
break;
}
g.drawImage(offScreenImage, 0, 0, null);
}
在Bj类修改paintSelf方法
void paintSelf(Graphics g, int fishLevel) {
g.drawImage(GameUtils.bjimg, 0, 0, null);
switch (GameApp.state) {
case 0:
GameUtils.drawWord(g, "开始", Color.red, 80, 700, 500);
break;
case 1:
GameUtils.drawWord(g, "积分" + GameUtils.count, Color.orange, 50, 200, 120);
GameUtils.drawWord(g, "难度" + GameUtils.level, Color.orange, 50, 600, 120);
GameUtils.drawWord(g, "等级" + fishLevel, Color.orange, 50, 1000, 120);
break;
case 2:
break;
case 3:
GameUtils.drawWord(g, "积分" + GameUtils.count, Color.orange, 50, 200, 120);
GameUtils.drawWord(g, "难度" + GameUtils.level, Color.orange, 50, 600, 120);
GameUtils.drawWord(g, "等级" + fishLevel, Color.orange, 50, 1000, 120);
GameUtils.drawWord(g, "胜利", Color.orange, 80, 700, 500);
break;
case 4:
break;
default:
}
}
14 右侧敌方鱼的生成和多种鱼的生成
在GameUtils类添加参数
//敌方鱼类
public static Image enemy1_img = Toolkit.getDefaultToolkit().createImage("img/finsh1_r.gif");
public static Image enemyr_img = Toolkit.getDefaultToolkit().createImage("img/finsh1_l.gif");
public static Image enemyl_2img = Toolkit.getDefaultToolkit().createImage("img/finsh2_r.png");
public static Image enemyr_2img = Toolkit.getDefaultToolkit().createImage("img/finsh2_l.png");
public static Image enemyl_3img = Toolkit.getDefaultToolkit().createImage("img/finsh3_r.png");
public static Image enemyr_3img = Toolkit.getDefaultToolkit().createImage("img/finsh3_l.png");
创建Enemy_1_R类,Enemy_2_L类,Enemy_2_R类,Enemy_3_L类,Enemy_3_R类
public class Enemy_1_R extends Enemy_1_L {
public Enemy_1_R(){
this.x = 1400;
dir = -1;
this.image = GameUtils.enemyr_img;
}
}
public class Enemy_2_L extends Enemy{
public Enemy_2_L(){
this.x = -100;
this.y = (int)(Math.random()*700 + 100);
this.width = 100;
this.height = 100;
this.speed = 5;
this.count = 2;
this.type = 2;
this.image = GameUtils.enemyl_2img;
}
}
public class Enemy_2_R extends Enemy_2_L{
public Enemy_2_R(){
this.x = 1400;
dir = -1;
this.image = GameUtils.enemyr_2img;
}
}
public class Enemy_3_L extends Enemy{
public Enemy_3_L(){
this.x = -300;
this.y = (int)(Math.random()*700 + 100);
this.width = 300;
this.height = 150;
this.speed = 15;
this.type = 3;
this.image = GameUtils.enemyl_3img;
}
@Override
public Rectangle getRec() {
return new Rectangle(x+40,y+30,width-80,height-60);
}
}
public class Enemy_3_R extends Enemy_3_L{
public Enemy_3_R(){
this.x = 1400;
dir = -1;
this.image = GameUtils.enemyr_3img;
}
}
在GameApp类修改相关方法
@Override
public void paint(Graphics g) {
//懒加载模式初始化对象
offScreenImage = createImage(width, height);
Graphics graphics = offScreenImage.getGraphics();
bj.paintSelf(graphics, myFish.level);
switch (state) {
case 0:
break;
case 1:
myFish.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
break;
case 2:
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
break;
case 3:
myFish.paintSelf(graphics);
break;
case 4:
break;
}
g.drawImage(offScreenImage, 0, 0, null);
}
void logic() {
....
random = Math.random();
//敌方鱼生成
switch (GameUtils.level) {
case 4:
case 3:
case 2:
if (time % 30 == 0) {
if (random > 0.5) {
enemy = new Enemy_3_L();
} else {
enemy = new Enemy_3_R();
}
GameUtils.enemyList.add(enemy);
}
case 1:
if (time % 20 == 0) {
if (random > 0.5) {
enemy = new Enemy_2_L();
} else {
enemy = new Enemy_2_R();
}
GameUtils.enemyList.add(enemy);
}
case 0:
if (time % 10 == 0) {
if (random > 0.5) {
enemy = new Enemy_1_L();
} else {
enemy = new Enemy_1_R();
}
GameUtils.enemyList.add(enemy);
}
break;
default:
}
//移动方向
for (Enemy e : GameUtils.enemyList) {
e.x = e.x + e.dir * e.speed;
//我方鱼与敌方鱼碰撞检测
if (myFish.getRec().intersects(e.getRec())) {
if (myFish.level >= e.type) {
System.out.println("碰撞了");
e.x = -200;
e.y = -200;
GameUtils.count = GameUtils.count + e.count;
} else {
state = 2;
}
}
}
}
在Bj类添加失败绘制
void paintSelf(Graphics g, int fishLevel) {
g.drawImage(GameUtils.bjimg, 0, 0, null);
switch (GameApp.state) {
...
case 2:
GameUtils.drawWord(g, "积分" + GameUtils.count, Color.orange, 50, 200, 120);
GameUtils.drawWord(g, "难度" + GameUtils.level, Color.orange, 50, 600, 120);
GameUtils.drawWord(g, "等级" + fishLevel, Color.orange, 50, 1000, 120);
GameUtils.drawWord(g, "失败", Color.orange, 80, 700, 500);
break;
case 3:
...
}
}
15 boss鱼的添加
在GameUtils类添加参数
public static Image bossimg = Toolkit.getDefaultToolkit().createImage("img/boss.gif");
创建BossEnemy类
public class BossEnemy extends Enemy{
public BossEnemy(){
this.x = -1000;
this.y = (int)(Math.random()*700 + 100);
this.width = 340;
this.height = 340;
this.speed = 100;
this.count = 0;
this.type = 10;
this.image = GameUtils.bossimg;
}
}
在GameApp类修改相关方法
//boss鱼
BossEnemy boss;
//是否生成boss
boolean isBoss = false;
@Override
public void paint(Graphics g) {
//懒加载模式初始化对象
offScreenImage = createImage(width, height);
Graphics graphics = offScreenImage.getGraphics();
bj.paintSelf(graphics, myFish.level);
switch (state) {
case 0:
break;
case 1:
myFish.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
if(isBoss){
boss.x = boss.x + boss.dir*boss.speed;
boss.paintSelf(graphics);
if(boss.x < 0){
graphics.setColor(Color.red);
graphics.fillRect(boss.x,boss.y,2400,boss.height/30);
}
}
break;
case 2:
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
if(isBoss){
boss.paintSelf(graphics);
}
break;
case 3:
myFish.paintSelf(graphics);
break;
case 4:
break;
}
g.drawImage(offScreenImage, 0, 0, null);
}
void logic() {
...
random = Math.random();
//敌方鱼生成
switch (GameUtils.level) {
case 4:
if(time%60==0){
if(random > 0){
boss = new BossEnemy();
isBoss = true;
}
}
case 3:
case 2:
if (time % 30 == 0) {
if (random > 0.5) {
enemy = new Enemy_3_L();
} else {
enemy = new Enemy_3_R();
}
GameUtils.enemyList.add(enemy);
}
case 1:
if (time % 20 == 0) {
if (random > 0.5) {
enemy = new Enemy_2_L();
} else {
enemy = new Enemy_2_R();
}
GameUtils.enemyList.add(enemy);
}
case 0:
if (time % 10 == 0) {
if (random > 0.5) {
enemy = new Enemy_1_L();
} else {
enemy = new Enemy_1_R();
}
GameUtils.enemyList.add(enemy);
}
break;
default:
}
//移动方向
for (Enemy e : GameUtils.enemyList) {
e.x = e.x + e.dir * e.speed;
if(isBoss){
if(boss.getRec().intersects(e.getRec())){
e.x = -200;
e.y = -200;
}
if(boss.getRec().intersects(myFish.getRec())){
state =2;
}
}
//我方鱼与敌方鱼碰撞检测
if (myFish.getRec().intersects(e.getRec())) {
if (myFish.level >= e.type) {
System.out.println("碰撞了");
e.x = -200;
e.y = -200;
GameUtils.count = GameUtils.count + e.count;
} else {
state = 2;
}
}
}
}
16 暂停功能和重新开始功能实现
在GameApp类修改相关方法
void launch() {
...
//鼠标监听事件
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if (e.getButton() == 1 && state == 0) {//鼠标左键点击
state = 1;
repaint();
}
if (e.getButton() == 1 && (state == 2 || state == 3)) {
reGame();
state =1;
}
}
});
//键盘移动
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {//键按压
super.keyPressed(e);
....
if (e.getKeyCode() == KeyEvent.VK_SPACE) {//空格键
switch (state){
case 1:
state =4;
GameUtils.drawWord(getGraphics(),"游戏暂停!!!",Color.red,50,600,400);
break;
case 4:
state =1;
break;
}
}
}
...
}
@Override
public void paint(Graphics g) {
...
switch (state) {
case 0:
break;
case 1:
myFish.paintSelf(graphics);
logic();
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
if(isBoss){
boss.x = boss.x + boss.dir*boss.speed;
boss.paintSelf(graphics);
if(boss.x < 0){
graphics.setColor(Color.red);
graphics.fillRect(boss.x,boss.y,2400,boss.height/30);
}
}
break;
case 2:
for (Enemy e : GameUtils.enemyList) {
e.paintSelf(graphics);
}
if(isBoss){
boss.paintSelf(graphics);
}
break;
case 3:
myFish.paintSelf(graphics);
break;
case 4:
return;
default:
}
g.drawImage(offScreenImage, 0, 0, null);
}
//重新开始
void reGame(){
GameUtils.enemyList.clear();
time = 0;
myFish.level = 1;
GameUtils.count = 0;
myFish.x = 700;
myFish.y = 500;
myFish.width = 50;
myFish.height = 50;
boss = null;
isBoss = false;
}