将图片加载进来
运用到对象的思想,把图片路径变成对象,把图片变成对象:
package game;
import com.sun.jndi.toolkit.url.UrlUtil;
import javax.swing.*;
import java.net.URL;
/*
用于获取游戏中所涉及到图片。
* */
public class images {
// 将图片所在的路径封装成一个对象:
public static URL bodyURL = images.class.getResource("/images/body.png");
public static URL foodURL = images.class.getResource("/images/food.png");
public static URL upURL = images.class.getResource("/images/up.png");
public static URL downURL = images.class.getResource("/images/down.png");
public static URL leftURL = images.class.getResource("/images/left.png");
public static URL rightURL = images.class.getResource("/images/right.png");
public static URL imgURL = images.class.getResource("/images/img.png");
// 将图片封装成程序中的一个对象
public static ImageIcon bodyImg = new ImageIcon(bodyURL);
public static ImageIcon foodImg = new ImageIcon(foodURL);
public static ImageIcon upImg = new ImageIcon(upURL);
public static ImageIcon downImg = new ImageIcon(downURL);
public static ImageIcon leftImg = new ImageIcon(leftURL);
public static ImageIcon rightImg = new ImageIcon(rightURL);
public static ImageIcon imgImg = new ImageIcon(imgURL);
}
创建窗体,也是游戏的启动程序
设置窗口的标题
在屏幕的位置
窗体的大小
打开关闭窗体时关闭程序
窗体大小不可改变
package game;
import javax.swing.*;
import java.awt.*;
public class StartGame {
// 这是一个main方法,启动程序的入口:
public static void main(String[] args) {
// 创建一个窗口:
JFrame jf = new JFrame();
// 给窗体传建一个标题:
jf.setTitle("第一次的尝试:贪吃蛇小游戏 by GuiPengCheng");
// 设置窗体大小不可调节
jf.setResizable(false);
// 关闭窗口的同时,程序要关闭:
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 创建面板:
GamePanel gamePanel = new GamePanel();
// 写入窗体:
jf.add(gamePanel);
// 设置窗体坐标:窗体大小 默认情况下窗体是隐藏的:
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
jf.setBounds((width-800)/2,(height-800)/2,800,800);
jf.setVisible(true);
}
}
创建面板
首先要继承java的面板类:Jpanel 才能实现其功能
package game;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
//继承了JPanel以后,才能实现其功能
public class GamePanel extends JPanel {
// 相当于一个图形版本的main启动方法
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 填充背景颜色:
this.setBackground(new Color(151, 234, 162));
// 画顶部图片:
// this是指当前画板,g是指使用的画笔
images.imgImg.paintIcon(this,g,18,10);
// 调节画笔颜色:
g.setColor(new Color(239, 226, 141, 255));
// 画一个矩形:
g.fillRect(2,65,780,700);
}
画一个静态小蛇,改变蛇头方向
在面板类中定义小蛇的各参数,再定义小蛇如何运动。
以下代码仅仅是小蛇的:
先初始化蛇头和蛇身,放在x和y的数组里,保存的是相当于窗口的坐标。
然后蛇长,蛇头
蛇长在每次吃食物是都会增加,蛇身在改变字符时switch判断,进行图片的调整。
蛇身的循环是依据蛇长判断的。
// 初始化一个小蛇:
int[] snakeX = new int[200];
int[] snakeY = new int[200];
int length;//蛇长;
String direction; //蛇头方向
//--------------------------------------------
public void init(){
// 初始化蛇头:
snakeX[0]=175;
snakeY[0]=275;
// 初始化第一节
snakeX[1]=150;
snakeY[1]=275;
// 初始化第二节
snakeX[2]=125;
snakeY[2]=275;
// 初始化蛇长
length =3;
// 蛇头方向
direction = "R";//u,d,l,r
}
// -----------------------------------------------
// 画蛇:
// 1.蛇头
// images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
switch (direction){
case "R" :images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
case "L" :images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
case "D" :images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
case "U" :images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
}
// 2.身子
// images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
// images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);
for (int i = 1; i < length; i++) {
images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
}
加入监听,空格判断开始
加入构造器,和定义一个初始化方法,方法用来存储初始化的数值,以后每次开始运行程序,构造器会先调用初始化数据的方法。
构造器用来(监听键盘输入,实现动作),
// 写一个构造器:
public GamePanel(){
init();
// 将焦点定位在面板上
this.setFocusable(true);
// 加入监听
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int KeyCode = e.getKeyCode();
switch (KeyCode){
case KeyEvent.VK_SPACE: //监听空格
{
if(Die){
init(); //恢复初始状态
Die = false;
}
else {
Start = !Start;
repaint();//调用下面的图形启动器方法
}
};break;
case KeyEvent.VK_UP:
{
direction = "D";//向上
};break;
case KeyEvent.VK_DOWN:
{
direction = "U";//向下
};break;
case KeyEvent.VK_LEFT:
{
direction = "L";//向左
};break;
case KeyEvent.VK_RIGHT:
{
direction = "R";//向右
};break;
}
}
});
}
小蛇动起来
需要在构造器中创建一个定时器,每100毫秒监听一次交互事件
动起来的前提条件是游戏开始,并且小蛇活着
然后蛇头是在不同的方向加减25
蛇身是循环递减,把前一项的值赋给后一项,实现蛇蛇的前进
然后对蛇的出界进行一个修订
启动定时器
// 初始化定时器
timer = new Timer(100, new ActionListener() {
// 事件监听:
// 每100毫秒监听一次动作,放在下面那个方法里
@Override
public void actionPerformed(ActionEvent e) {
if(Start&&Die ==false){//游戏开始并且小蛇活着
// 蛇身
for (int i = length-1; i >0; i--) {
snakeX[i]=snakeX[i-1];
snakeY[i]=snakeY[i-1];
}
// 蛇头
switch (direction){
case "R":snakeX[0] +=25;break;
case "L":snakeX[0] -=25;break;
case "U":snakeY[0] +=25;break;
case "D":snakeY[0] -=25;break;
}
// 防止蛇超出边界
if(snakeX[0]>800){
snakeX[0]=25;
}
if(snakeX[0]<25){
snakeX[0]=800;
}
if(snakeY[0]<100){
snakeY[0]=700;
}
if(snakeY[0]>700){
snakeY[0]=100;
}
repaint();//刷新界面
}
});
// 定时器必须要启动
timer.start();
吃食物
使用Rodam随机生成数字,来实现食物在界面的随机显示
在吃食物时,蛇头的坐标和食物的坐标完全吻合,此时食物改变位置
画积分,画倒计时
在吃食物时,每完成一次,积分数据改变,并且由于定时器的刷新界面,把积分数据实时的现实在面板上
// 检测碰撞动作:蛇吃食物
time = time-0.06;
if((int) time == 0 ){
foodX = ((new Random().nextInt(30)+1)*25);
foodY = ((new Random().nextInt(24)+4)*25);
time = 7;
}
if(snakeX[0] == foodX && snakeY[0] == foodY){
// 蛇长度+1
length++;
// 食物随机改变,每过二十秒刷新 也就是十二次
foodX = ((new Random().nextInt(30)+1)*25);
foodY = ((new Random().nextInt(24)+4)*25);
time = 7;
// 吃上食物积分加十;
score +=10;
}
死亡判定
蛇头跟任意蛇身坐标相等
// 死亡判断:
for (int i = 1; i < length; i++) {
if(snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]){
Die = true;
}
画食物:
images.foodImg.paintIcon(this,g,foodX,foodY);
// 画积分:
g.setColor(new Color(0x1515EE));
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("积分:"+score,390,40);
// 倒计时:
g.setColor(new Color(0x1515EE));
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("倒计时:"+Math.round(time),60,40);
// 判断游戏的启动状态
if(Start == false && Die == false) {
g.setColor(new Color(0x0B77F8));
g.setFont(new Font("微软雅黑", Font.BOLD, 40));
g.drawString("点击空格开始游戏", 250, 330);
}
// 死亡
if(Die) {
g.setColor(new Color(0xE30A0A));
g.setFont(new Font("微软雅黑", Font.BOLD, 25));
g.drawString("你输了,按空格重新开始", 250, 330);
}