700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【Java游戏开发项目-01贪吃蛇】强烈推荐Java小白练手!!!

【Java游戏开发项目-01贪吃蛇】强烈推荐Java小白练手!!!

时间:2024-06-29 13:04:34

相关推荐

【Java游戏开发项目-01贪吃蛇】强烈推荐Java小白练手!!!

文章目录

一丶游戏效果二、游戏架构三、代码设计1.窗体架构2.游戏嵌板3.图像绘制与显示4.视窗刷新与按键监听5.食物刷新与小蛇死亡判断6.游戏暂停与重新开始

一丶游戏效果

二、游戏架构

一个Java项目可以有多种设计模式,MVC,工厂,单例等等。

但在本次项目中,我们将介绍最基础的知识,在后续项目中逐步升级。

贪吃蛇项目的基本架构是窗体为主体,在面板中执行游戏操作,并在面板中绘制贪吃蛇图像和显示用户操作

三、代码设计

1.窗体架构

public class StartGame {public static void main(String[] args) {JFrame jFrame =new JFrame();jFrame .setTitle("贪吃豆");int width= Toolkit.getDefaultToolkit().getScreenSize().width;int height=Toolkit.getDefaultToolkit().getScreenSize().height;jFrame .setBounds((width-700)/2,(height-700)/2,700,700);jFrame .setResizable(false);jFrame .setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);GamePanel gamePanel= new GamePanel();jFrame.add(gamePanel);jFrame .setVisible(true);}}

窗体方面我们利用Java中的JFrame创建一个窗体,并利用Toolkit获取屏幕大小,使的窗体能够正常显示在电脑中央

同时,这个main方法也是程序的入口,可以看出,我们在StartGame中加入了gamePanel这个对象,而我们的图像显示和游戏逻辑全部封装在GamePanel这个类中

2.游戏嵌板

Panel ,中文意思为“嵌板”。这个嵌板相当于窗体上的一个区域,我们可以根据自己的需求放置嵌板,并在对应的嵌板中设计我们的功能。这个项目只有一个嵌板。

package com.Karthus.game;import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.util.Random;public class GamePanel extends JPanel {int[] snakeX=new int[200];int[] snakeY=new int[200];int length;String direction;boolean isStart;boolean isDie;boolean isHungry;int foodX=200;int foodY=200;Timer timer;public GamePanel(){init();this.setFocusable(true);this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);int keyCode=e.getKeyCode();if(keyCode==KeyEvent.VK_SPACE){if(isDie){init();repaint();}else{isStart=!isStart;repaint();}}if (keyCode==KeyEvent.VK_UP){direction="u";}if (keyCode==KeyEvent.VK_DOWN){direction="d";}if (keyCode==KeyEvent.VK_RIGHT){direction="r";}if (keyCode==KeyEvent.VK_LEFT){direction="l";}}});timer =new Timer(100, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if(isStart){for(int i=length-1;i>0;i--){snakeX[i]=snakeX[i-1];snakeY[i]=snakeY[i-1];}if("r".equals(direction)){snakeX[0]+=25;}if("l".equals(direction)){snakeX[0]-=25;}if("u".equals(direction)){snakeY[0]-=25;}if("d".equals(direction)){snakeY[0]+=25;}if(snakeX[0]>700){snakeX[0]=0;}if(snakeX[0]<0){snakeX[0]=675;}if(snakeY[0]>700){snakeY[0]=0;}if(snakeY[0]<0){snakeY[0]=675;}if(snakeX[0]==foodX&&snakeY[0]==foodY){length++;foodX=new Random().nextInt(27)*25;foodY=(new Random().nextInt(26)+1)*25;isHungry=false;}for(int i=length-1;i>0;i--){if(snakeX[i]==snakeX[0]&&snakeY[i]==snakeY[0]){isDie=true;isStart=false;}}repaint();}}});timer.start();}public void init(){length=3;snakeX[0]=175;snakeY[0]=275;snakeX[1]=150;snakeY[1]=275;snakeX[2]=125;snakeY[2]=275;direction="r";isStart=false;isDie=false;isHungry=true;}@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);this.setBackground(new Color(231, 214, 214));g.setColor(new Color(252, 252, 252));g.fillRect(0,0,700,700);if(isDie){g.setColor(new Color(65, 193, 193));g.setFont(new Font("微软雅黑",Font.BOLD,30));g.drawString("游戏死亡,按空格键重新开始",200,300);}switch (direction){case "r":Images.right.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "l":Images.left.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "u":Images.up.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "d":Images.down.paintIcon(this,g,snakeX[0],snakeY[0]);break;}if(isHungry) {for (int i = 1; i < length; i++) {Images.body.paintIcon(this, g, snakeX[i], snakeY[i]);isHungry=false;}}else {for (int i = 1; i < length-1; i++) {Images.body.paintIcon(this, g, snakeX[i], snakeY[i]);}}Images.food.paintIcon(this,g,foodX,foodY);if(!isStart&&!isDie){g.setColor(new Color(65, 193, 193));g.setFont(new Font("微软雅黑",Font.BOLD,30));g.drawString("点击空格开始游戏",200,300);}}}

以上是GamePanel嵌板的全部内容。由于程序较简单,我们将蛇的属性放置于该嵌板中。下面会详细介绍嵌板中的内容。

3.图像绘制与显示

想要绘制图像,首先得拿到图片资源

程序中获取图片的方法有很多种,这里我们将所有图片文件放入images文件夹中

点击Build,选择reBuild project

会生成一个out文件,这些文件时JVM运行的文件,也就是JAVA虚拟机,图片的路径将保存在这个文件中

新建一个images类,将需要的图片数据放入这个类中

public class Images {public static URL upUrl =Images.class.getResource("/images/head_up.png");public static URL rightUrl =Images.class.getResource("/images/head_right.png");public static URL leftUrl =Images.class.getResource("/images/head_left.png");public static URL downUrl =Images.class.getResource("/images/head_down.png");public static URL bodyUrl =Images.class.getResource("/images/body.png");public static URL barUrl =Images.class.getResource("/images/topBar.png");public static URL foodUrl=Images.class.getResource("/images/food.png");public static ImageIcon up =new ImageIcon(upUrl);public static ImageIcon right =new ImageIcon(rightUrl);public static ImageIcon left =new ImageIcon(leftUrl);public static ImageIcon down =new ImageIcon(downUrl);public static ImageIcon body =new ImageIcon(bodyUrl);public static ImageIcon bar=new ImageIcon(barUrl);public static ImageIcon food=new ImageIcon(foodUrl);}

收集到图片资源后就可以开始绘制了

在GamePanel中有一个绘制方法

@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);this.setBackground(new Color(231, 214, 214));}

g就相当于画笔,而每次生成一个嵌板对象时,都将自动调用该方法

对于整个嵌板就相当于一个坐标系,一张图片,我们想要放在嵌板中的某个地方,我们要考虑的问题,这个图片展多大空间,在嵌板的那个位置?

因此我们在GamePanel定义了蛇的二维坐标,并定义了蛇头位置朝向

下面给出蛇的画法

switch (direction){case "r":Images.right.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "l":Images.left.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "u":Images.up.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "d":Images.down.paintIcon(this,g,snakeX[0],snakeY[0]);break;}for(int i=1;i<length;i++)Images.body.paintIcon(this, g, snakeX[i], snakeY[i]);

4.视窗刷新与按键监听

游戏必须得要动起来才是游戏,贪吃蛇也要能够自己动起来,并且能够监听键盘的方向键

首先在GamePanel类中加入监听方法

this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);int keyCode=e.getKeyCode();if(keyCode==KeyEvent.VK_SPACE){if(isDie){init();repaint();}else{isStart=!isStart;repaint();}}if (keyCode==KeyEvent.VK_UP){direction="u";}if (keyCode==KeyEvent.VK_DOWN){direction="d";}if (keyCode==KeyEvent.VK_RIGHT){direction="r";}if (keyCode==KeyEvent.VK_LEFT){direction="l";}}}

监听按键利用适配器模式

我们知道游戏刷新的本质是视图的刷新,也就是说我们要不断重复执行嵌板中的画图方法,我们定义一个Timer计时器让他计时刷新

即让是刷新我们还要弄清楚小蛇每次移动的算法,那么小蛇每次移动都是由后一节向前一节传递,而头部的刷新是由小蛇运动的方向决定的,刷新代码如下

timer =new Timer(100, new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if(isStart){for(int i=length-1;i>0;i--){snakeX[i]=snakeX[i-1];snakeY[i]=snakeY[i-1];}if("r".equals(direction)){snakeX[0]+=25;}if("l".equals(direction)){snakeX[0]-=25;}if("u".equals(direction)){snakeY[0]-=25;}if("d".equals(direction)){snakeY[0]+=25;}if(snakeX[0]>700){snakeX[0]=0;}if(snakeX[0]<0){snakeX[0]=675;}if(snakeY[0]>700){snakeY[0]=0;}if(snakeY[0]<0){snakeY[0]=675;}if(snakeX[0]==foodX&&snakeY[0]==foodY){length++;foodX=new Random().nextInt(27)*25;foodY=(new Random().nextInt(26)+1)*25;isHungry=false;}for(int i=length-1;i>0;i--){if(snakeX[i]==snakeX[0]&&snakeY[i]==snakeY[0]){isDie=true;isStart=false;}}repaint();}}});timer.start();}

repaint将会重新执行paintComponent方法

5.食物刷新与小蛇死亡判断

每次吃完一个食物后将有新事物刷新,同时蛇身变长

if(snakeX[0]==foodX&&snakeY[0]==foodY){length++;foodX=new Random().nextInt(27)*25;foodY=(new Random().nextInt(26)+1)*25;isHungry=false;}

小蛇死亡的判断则是判断蛇头与蛇身的坐标是否重合

for(int i=length-1;i>0;i--){if(snakeX[i]==snakeX[0]&&snakeY[i]==snakeY[0]){isDie=true;isStart=false;}}

6.游戏暂停与重新开始

在游戏过程中如果要暂停或者游戏死亡后要重新开始,这就需要控制嵌板的画图计时,因此加入了isStart判定

空格监听

if(keyCode==KeyEvent.VK_SPACE){if(isDie){init();repaint();}else{isStart=!isStart;repaint();}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。