首页 > 编程语言 >Java学习之路--GUI编程--贪吃蛇小游戏

Java学习之路--GUI编程--贪吃蛇小游戏

时间:2023-09-20 18:45:51浏览次数:52  
标签:25 Java -- GUI snakeX snakeY 小蛇 public

贪吃蛇小游戏界面实现四步走
1.定义数据
2.面板里将数据画上去
3.监听事件
键盘
事件

package com.gui.snake;

import javax.swing.*;
import java.net.URL;

//2023.3.28 GUI编程--贪吃蛇小游戏的实现--数据中心(只有一堆图片的数据) --贪吃蛇各个部分的导入--图片文件夹有两种导入方式,
// 一种是直接拖那些图片到需要放的位置,一种是先建一个statics包(这个包专门用来存放静态文件),再将图片拖了放这个包里
public class Data {

//相对路径 txt.jpg
//绝对路径 /../.. /--相当于当前的目录
public static URL headerURL = Data.class.getResource("statics/header.png");//获取贪吃蛇头部图片的资源
public static ImageIcon header = new ImageIcon(headerURL);//将获得的图片放入图片图标中

public static URL bodyURL = Data.class.getResource("statics/body.png");//获取贪吃蛇肢体图片的资源
public static URL rightURL = Data.class.getResource("statics/right.png");//获取贪吃蛇右边头图片的资源
public static URL leftURL = Data.class.getResource("statics/left.png");//获取贪吃蛇左边头图片的资源
public static URL upURL = Data.class.getResource("statics/up.png");//获取贪吃蛇上方头图片的资源
public static URL downURL = Data.class.getResource("statics/down.png");//获取贪吃蛇下方头图片的资源
public static URL foodURL = Data.class.getResource("statics/food.png");//获取贪吃蛇食物图片的资源

public static ImageIcon body = new ImageIcon(bodyURL);//将获得的图片放入图片图标中
public static ImageIcon right = new ImageIcon(rightURL);//将获得的图片放入图片图标中
public static ImageIcon left = new ImageIcon(leftURL);//将获得的图片放入图片图标中
public static ImageIcon up = new ImageIcon(upURL);//将获得的图片放入图片图标中
public static ImageIcon down = new ImageIcon(downURL);//将获得的图片放入图片图标中
public static ImageIcon food = new ImageIcon(foodURL);//将获得的图片放入图片图标中
}

//
package com.gui.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

//2023.3.27/3.28/3.29/3.30/3.31/4.1/4.2 GUI编程--贪吃蛇小游戏练习--游戏面板的实现
public class GamePanel extends JPanel implements KeyListener, ActionListener {//GamePanel类继承JPanel类,实现KeyListener接口和ActionListener接口
//定义蛇的数据结构
int length;//蛇的长度
int[] snakeX = new int[600];//蛇的X坐标 25*25
int[] snakeY = new int[500];//蛇的Y坐标 25*25
String fx;//定义一个变量fx实现蛇头的方向改变

//食物的坐标
int foodX;
int foodY;
Random random = new Random();//随机数Random,用来改变随机生成食物
int score;//定义一个得分score,用来实现贪吃蛇的积分面板用
int failSum;//定义一个变量记录失败次数 失败次数判断没写好,所以注释掉

//游戏当前的状态:开始,停止
boolean isStart = false;//默认游戏是处于没有开始状态

boolean isFail = false;//定义变量来判断游戏状态失败,Fail(失败),默认游戏是不失败状态

//定时器 以毫秒(ms)为单位 1000ms = 1s
Timer timer = new Timer(100, this);//是以毫秒为单位 delay:100 100毫秒刷新(执行)一次

//构造器 2023.4.1
public GamePanel() {
init();
//获得焦点和键盘事件
this.setFocusable(true);//获得焦点事件
this.addKeyListener(this);//获得键盘的监听事件 GamePanel实现了KeyListener接口,所以这里()写this就行
timer.start();//游戏一开始定时器就启动
}

//初始化方法
public void init() {
length = 3;//蛇的初始长度3节
snakeX[0] = 100;
snakeY[0] = 100;//蛇脑袋的坐标
snakeX[1] = 75;
snakeY[1] = 100;//蛇第一个身体的坐标
snakeX[2] = 50;
snakeY[2] = 100;//蛇第二个身体的坐标
fx = "R";//小蛇初始方向向右

//把食物随机分布在界面上!
foodX = 25 + 25 * random.nextInt(34);//随机生成食物X的坐标 34 是
foodY = 75 + 25 * random.nextInt(24);//随机生成食物Y的坐标

//积分初始为0
score = 0;

}

//绘制面板,我们游戏中的所有东西都使用这个面板来画
@Override
protected void paintComponent(Graphics g) {//画组件(paintComponent)
super.paintComponent(g);//清屏,不写这一句的话面板会不停的闪烁
//绘制静态的面板
this.setBackground(Color.WHITE);//设置背景颜色为白色
Data.header.paintIcon(this, g, 25, 11);//头部广告栏画上去
g.fillRect(25, 75, 850, 600);//默认的游戏界面 fillRect(画矩形)

//画积分
g.setColor(Color.black);//积分板颜色为黑色
g.setFont(new Font("微软雅黑", Font.BOLD, 20));//设置字体 "微软雅黑"--字体样式,Font.BOLD(字体加粗),size:40(字体大小)
g.drawString("小蛇长度:" + length, 550, 25);//画(记录)小蛇的长度的变化
g.drawString("游戏分数:" + score, 550, 45);//画(记录)小蛇吃食物的分数变化

//画食物 2023.4.2 小蛇吃食物实际是蛇小蛇头碰到食物它身体覆盖掉食物,然后小蛇的长度加1 ,这里如果先画小蛇的话食物和小蛇的身体就会出现重叠的情况
Data.food.paintIcon(this, g, foodX, foodY);//把食物画在界面上

//把小蛇画上去
//写条件语句if判断蛇头方向 2023.3.30
if (fx.equals("R")) {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始方向向右
} else if (fx.equals("L")) {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始方向向左
} else if (fx.equals("U")) {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始方向向上
} else if (fx.equals("D")) {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始方向向下
}

//写循环是为了让蛇实现动起来的效果
for (int i = 1; i <= length; i++) {
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);//蛇的身体的坐标,用循环不停变换X,Y的坐标,实现蛇动起来
}

//游戏状态 写if判断游戏处于未开始状态 2023.3.31
if (isStart == false) {
g.setColor(Color.white);//设置字体颜色
g.setFont(new Font("微软雅黑", Font.BOLD, 40));//设置字体 "微软雅黑"--字体样式,Font.BOLD(字体加粗),size:40(字体大小)
g.drawString("按下空格开始游戏", 300, 300);//画需要设置的字体内容和xy位置
}
// Data.body.paintIcon(this,g,snakeX[0],snakeY[0]);//蛇的第一个身体的坐标
// Data.body.paintIcon(this,g,snakeX[2],snakeY[2]);//蛇的第二个身体的坐标

if (isFail == true) {//如果游戏失败 2023.4.2
g.setColor(Color.red);//设置字体颜色,失败的字体颜色为红色
g.setFont(new Font("微软雅黑", Font.BOLD, 40));//设置字体 "微软雅黑"--字体样式,Font.BOLD(字体加粗),size:40(字体大小)
g.drawString("游戏失败,按下空格重新开始", 300, 300);//画需要设置的字体内容和xy位置
}
}

@Override //重写KeyListener接口的方法
public void keyTyped(KeyEvent e) {

}

//2023.3.31 键盘监听事件
@Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();//获得键盘按键是哪一个

if (keycode == KeyEvent.VK_SPACE) {//如果按下的键位是空格键
if (isFail) {//如果游戏失败,则按下按键重新开始
//重新开始
isFail = false;
init();//数据回到初始状态
} else {
isStart = !isStart;//取反,这里不写isStart = true 是因为这样写控制不了小蛇停下,取反写法,按下空格键开始,再按空格键停止

}
repaint();//重新画小蛇
}

//小蛇移动 --写这段控制小蛇上下左右的方向移动
if (keycode == KeyEvent.VK_UP) {//如果按下的键位置是上键
fx = "U";
} else if (keycode == KeyEvent.VK_DOWN) {//如果按下的键位是下键
fx = "D";
} else if (keycode == KeyEvent.VK_LEFT) {//如果按下的键位是左键
fx = "L";
} else if (keycode == KeyEvent.VK_RIGHT) {//如果按下的键位是右键
fx = "R";
}
}

@Override
public void keyReleased(KeyEvent e) {
}

//事件监听--需要通过固定事件来刷新 1s = 10次
//重写ActionListener接口的方法
@Override
public void actionPerformed(ActionEvent e) {
if (isStart && isFail == false) {//如果游戏是开始状态并且不处于失败状态,就让小蛇动起来

//吃食物
if (snakeX[0] == foodX && snakeY[0] == foodY) {//如果小蛇的x坐标等于食物的x坐标并且小蛇的y坐标等于食物的y坐标
//长度 + 1
length++;//这里的长度加1 是指小蛇每吃一个食物,长度就加1,身体节数
score = score + 10;//每吃一个食物分数加10
//再次随机食物
foodX = 25 + 25 * random.nextInt(34);//34是
foodY = 75 + 25 * random.nextInt(24);
}

//小蛇移动
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];//小蛇向前移动一节 小蛇x坐标的改变,
snakeY[i] = snakeY[i - 1];//小蛇y坐标的改变
}
//走向 小蛇上下左右的走向
if (fx.equals("R")) {
snakeX[0] = snakeX[0] + 25;
if (snakeX[0] > 850) {//边界判断 --写这一块是因为按下空格小蛇右移出右边窗口边界,小蛇就从这一行最左边重头再来
snakeX[0] = 25;
}
} else if (fx.equals("L")) {
snakeX[0] = snakeX[0] - 25;
if (snakeX[0] < 25) {//边界判断 --写这一块是因为按下空格小蛇左移出左边窗口边界,小蛇就从这一行最右边重头再来
snakeX[0] = 850;
}
} else if (fx.equals("U")) {
snakeY[0] = snakeY[0] - 25;
if (snakeY[0] < 75) {//边界判断
snakeY[0] = 650;
}
} else if (fx.equals("D")) {
snakeY[0] = snakeY[0] + 25;
if (snakeY[0] > 650) {//边界判断
snakeY[0] = 75;
}
}
}

//失败判断,小蛇撞到自己就算失败或者小蛇头撞到窗口边界就失败
for (int i = 1; i < length; i++) {
if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {//同一时间,小蛇出现同一个部位或不同部位坐标相同时候(即小蛇撞到自己),就算失败
isFail = true;

// else if (snakeX[0] == 850 || snakeY[0] == 650){//如果小蛇的头撞到窗口宽(长)边的边界或者小蛇的头撞到高边的边界,就算失败
// isFail = true;
// }
}


repaint();//重画(页面)一次小蛇
}
// timer.start();//定时器开启!

}
}

//
package com.gui.snake;

import javax.swing.*;

//2023.3.27 GUI编程--贪吃蛇小游戏的实现--界面实现 Snake--蛇 这个类是游戏的主启动类
//游戏开始
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame();//创建窗体对象

frame.setBounds(10,10,900,720);//设置初始位置和窗体大小 这里设置的宽900,高720是计算得出的,不能乱来
frame.setResizable(false);//设置窗体大小不可变,就是窗体大小固定的意思 false--不可变 true-可变
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//JFrame 默认关闭窗口的事件方法

//正常的游戏界面都应该放在面板上
frame.add(new GamePanel());//将面板添加到窗体中

frame.setVisible(true);//设置可见性
}
}

标签:25,Java,--,GUI,snakeX,snakeY,小蛇,public
From: https://www.cnblogs.com/CaiDingChao/p/17718070.html

相关文章

  • USB的4根线接法
    USB线一共四针,其中两针是数据线,两针是电源线包括接地,红线:电源正极(接线上的标识为:+5V或VCC)、白线:负电压数据线(标识为:Data-或USBPort-)、绿线:正电压数据线(标识为:Data+或USBPort+)、黑线:接地(标识为:GND)。一般的排列顺序是VCC、D-、D+、GND,排列是固定的,但是有两种方向,数据线接错顶......
  • c++ 访问全局变量
      #include<iostream>usingnamespacestd;inta{1};intmain(){inta{123};cout<<"外部的a:"<<a<<endl;//外部的a:123{cout<<"外部的a:"<<a<<endl;//外部的a:123......
  • Docker ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/contai
     错误排查:都会用 2那里 搜索 ,答案又是满天飞,且抄手一大帮! 正确实的方式:  tail-200f/var/log/messages    查看日志,具体定位! ......
  • Spring Batch数据导入导出深入探讨
    介绍SpringBatch是一个轻量级的批处理框架,它提供了一种简单的方式来处理大量数据。在本文中,我们将深入探讨SpringBatch的数据导入导出功能。数据导入SpringBatch提供了多种方式来导入数据,包括从文件、数据库、Web服务等。下面我们将分别介绍这些方式。从文件导入SpringBat......
  • MySQL存储引擎架构深入探讨
    前言MySQL是目前最流行的关系型数据库之一,其存储引擎架构是其核心特性之一。本文将深入探讨MySQL存储引擎架构,包括InnoDB、MyISAM、Memory等常见存储引擎的特点和使用场景。InnoDBInnoDB是MySQL的默认存储引擎,也是最常用的存储引擎之一。它支持事务、行级锁、外键等特性,适合于高......
  • Kibana中的数据导入与清洗技巧
    前言Kibana是一个非常强大的数据可视化工具,但是在使用Kibana之前,我们需要将数据导入到Elasticsearch中,并进行清洗和预处理。本文将介绍如何使用Logstash和Elasticsearch进行数据导入和清洗。LogstashLogstash是一个开源的数据收集引擎,它可以从各种来源收集数据,并将数据转换为Ela......
  • 深入探讨Kafka消息时间戳与事件处理机制
    背景Kafka是一个高性能、分布式的消息队列系统,被广泛应用于大数据领域。在Kafka中,每个消息都有一个时间戳,用于表示消息的产生时间。在实际应用中,我们需要对消息进行处理,并根据时间戳进行相关的业务逻辑处理。本文将深入探讨Kafka消息时间戳与事件处理机制。Kafka消息时间戳在Kaf......
  • 使用openssl创建ssl证书,用于测试https服务
    一个web站点要对外提供https服务就需要ssl证书,ssl证书可以从云服务厂商那里购买,通常也能申请到免费的,但是如果只是为了测试,则可以使用openssl来创建ssl证书。下面是完整的生成过程:第一步:创建私钥opensslgenrsa-outserver.key2048第二步:创建签名请求文件opensslreq-new-key......
  • 武汉星起航:连接中国卖家与亚马逊全球市场的桥梁
    作为业内实力雄厚的亚马逊跨境电商孵化服务商,武汉星起航电子商务有限公司(以下简称“星起航”)致力于连接中国卖家与全球市场,为他们提供全方位的亚马逊跨境电商解决方案。多年来,我们积累了丰富的经验,见证了跨境电子商务从起初的萌芽发展到如今的蓬勃兴盛,成为推动中国外贸发展的新业态......
  • 无涯教程-JavaScript - CHISQ.DIST函数
    描述CHISQ.DIST函数返回卡方分布。卡方分布通常用于研究样本中某物百分比的变化,如人们每天看电视的时间所占的比Example。语法CHISQ.DIST(x,deg_freedom,cumulative)争论Argument描述Required/OptionalXThevalueatwhichyouwanttoevaluatethedistribution.R......