Java小游戏实战开发——贪吃蛇网络游戏 1、Direction类
Direction:用于存放上下左右四个键。
package com.games;
/*
*枚举:就是几个固定的常量
*/
public enum Direction{
UP,DOWN,LEFT,RIGHT
}
2、Snake类
Snake,蛇类:一条蛇有多个节点,使用LinkedList集合出储存Node节点
初始化蛇身体,蛇出生地有6个节点
package com.games;
import java.util.LinkedList;
/**
*Snake类表示蛇
* 一条蛇有多个节点,使用LinkedList集合存储Node节点
* 蛇出生的地方有6个节点
*/
public class Snake {
//蛇的身体
private LinkedList body;
//蛇的运动方向
private Direction direction = Direction.LEFT;
//蛇是否活着
private boolean isLiving = true;
//构造方法,在创造Snake对象时执行
public Snake(){
//初始化蛇身体
initSnake();
}
//初始化蛇身体
private void initSnake(){
//创建集合
body= new LinkedList<>();
//创建6个节点放在集合中
body.add(new Node(16,20));
body.add(new Node(17,20));
body.add(new Node(18,20));
body.add(new Node(19,20));
body.add(new Node(20,20));
body.add(new Node(21,20));
}
//蛇会沿着蛇头的方向移动
//控制蛇移动:在蛇头的运动方向添加一个节点,然后把蛇尾的最后一个节点删除
public void move(){
if(isLiving) {
//获取蛇头
Node head = body.getFirst();
switch (direction) {
case UP:
//在蛇头上边头添加节点
body.addFirst(new Node(head.getX(), head.getY() - 1));
break;
case DOWN:
body.addFirst(new Node(head.getX(), head.getY() + 1));
break;
case LEFT:
body.addFirst(new Node(head.getX() - 1, head.getY()));
break;
case RIGHT:
body.addFirst(new Node(head.getX() + 1, head.getY()));
break;
}
//删除蛇尾的最后节点
body.removeLast();
//判断蛇是否撞墙
head = body.getFirst();
if(head.getX() < 0 || head.getY() < 0 || head.getX() >= 40 || head.getY() >= 40){
isLiving = false;
}
//判断蛇是否碰到自己的身体
for(int i = 1; i < body.size(); i++){
Node node = body.get(i);
if(head.getX() == node.getX() && head.getY() == node.getY()){
isLiving = false;
}
}
}
}
public LinkedList getBody() {
return body;
}
public void setBody(LinkedList body) {
this.body = body;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
//吃食物;沿着蛇头的移动方向添加一个节点
public void eat(Node food){
//获取蛇头
Node head = body.getFirst();
switch (direction) {
case UP:
//在蛇头上边头添加节点
body.addFirst(new Node(head.getX(), head.getY() - 1));
break;
case DOWN:
body.addFirst(new Node(head.getX(), head.getY() + 1));
break;
case LEFT:
body.addFirst(new Node(head.getX() - 1, head.getY()));
break;
case RIGHT:
body.addFirst(new Node(head.getX() + 1, head.getY()));
break;
}
}
}
3、Node类
节点类:每一条蛇是由若干个节点组成的,每一个节点有横纵坐标来确定位置
package com.games;
import java.util.Random;
/**
*节点类:每一条蛇是由若干个节点组成的,每一个节点有横纵坐标来确定位置
*/
public class Node {
private int x;
private int y;
public Node(){
}
public Node(int x,int y){
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
//随机生成位置
public void random(){
//创建Random对象
Random r = new Random();
//随机生成横坐标
this.x = r.nextInt(40);
//随机生成纵坐标
this.y = r.nextInt(40);
}
}
4、MainFrame类
实现:
(1)initFrame()方法:初始化窗体参数;设置窗体宽高、窗体默认位置、关闭按钮的作用和窗体大小不可变。
(2)initGamePanel()方法:继承JPanel()类,重写paint()方法,初始化游戏棋盘,在paint()方法中绘制棋盘中的内容,即清空棋盘、绘制横竖线条、绘制蛇和食物,最后把棋盘添加到窗体中。
(3)initSnake()方法:初始化蛇;创建Snake类,在Snake类中初始化蛇的初始位置、构造move()方法和eat()方法。move()方法实现蛇沿着蛇头方向移动、判断蛇是否撞墙和碰到自己身体的功能;eat()方法实现当食物与蛇头重合,会沿蛇头的移动方向添加一个节点。。
(4)initFood()方法:初始化食物;创建Node类,在Node类中用随机数实现食物位置的随机生成。
(5)initTimer()方法:初始化定时器;设置定时任务,根据游戏状态和direction变量设置蛇移动操作,进行食物判定,判断食物与蛇头是否重合,如果重合调用eat()方法并再次随机生成食物。使用定时器,调用repaint()方法实时更新界面。
(6)setKeyListener()方法:设置键盘监听,当键盘按下时,调用keyPressed(KeyEvent e)方法,获取键盘输入,根据键盘输入让蛇随着Direction方向移动。
代码如下:
package com.games;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.LinkedList;
import java.util.TimerTask;
public class MainFrame extends JFrame {
//蛇
private Snake snake;
//游戏棋盘
private JPanel jPanel;
//定时器,在规定时间内调用蛇移动的方法
private Timer timer;
//食物
private Node food;
public MainFrame() throws HeadlessException {
//初始化窗体参数
initFrame();
//初始化游戏棋盘
initGamePanel();
//初始化蛇
initSnake();
//初始化食物
initFood();
//初始化定时器
initTimer();
//设置键盘监听,让蛇随着上下左右方向移动
setKeyListener();
}
private void initFood(){
food = new Node();
food.random();
}
private void setKeyListener(){
addKeyListener(new KeyAdapter() {
//当键盘按下时,会自动调用此方法
@Override
public void keyPressed(KeyEvent e) {
//键盘中的每一个键都有一个自己的编号
switch (e.getKeyCode()){
case KeyEvent.VK_UP://上键
if(snake.getDirection() != Direction.DOWN){
//修改蛇的运动方向
snake.setDirection(Direction.UP);
}
break;
case KeyEvent.VK_DOWN://下键
if(snake.getDirection() != Direction.UP){
snake.setDirection(Direction.DOWN);
}
break;
case KeyEvent.VK_LEFT://左键
if(snake.getDirection() != Direction.RIGHT){
snake.setDirection(Direction.LEFT);
}
break;
case KeyEvent.VK_RIGHT://右键
if(snake.getDirection() != Direction.LEFT){
snake.setDirection(Direction.RIGHT);
}
break;
}
}
});
}
private void initTimer(){
timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
snake.move();
//判断食物与蛇头是否重合
Node head = snake.getBody().getFirst();
if(head.getX() == food.getX() && head.getY() == food.getY()){
snake.eat(food);
food.random();
}
//重绘游戏棋盘
jPanel.repaint();
}
};
//每100毫秒,执行一次定时任务
//蛇的移动速度,如果想改变移动速度,改变最后一个参数即可
timer.scheduleAtFixedRate(timerTask,0,200);
}
private void initSnake(){
snake = new Snake();
}
public void initGamePanel(){
jPanel = new JPanel(){
//绘制棋盘中的内容
public void paint(Graphics g){
//清空棋盘
g.clearRect(0,0,600,600);
//Graphics g 可以看做是一个画笔,提供了很多方法可以来绘制一些基本图形(直线、矩形)
//绘制40条横线
for(int i = 0;i <= 40; i++){
g.drawLine(0,i*15,600,i*15);
}
//绘制40条竖线
for(int i = 0; i <= 40; i++){
g.drawLine(i*15,0,i*15,600);
}
//绘制蛇
LinkedList body = snake.getBody();
for(Node node : body){
g.fillRect(node.getX()*15,node.getY()*15,15,15);
}
//绘制食物
g.fillRect(food.getX()*15,food.getY()*15,15,15);
}
};
//把棋盘添加到窗体中
add(jPanel);
}
//初始化窗体参数
public void initFrame(){
//设置窗体宽高
setSize(610,640);
//设置窗体默认位置
setLocation(408,408);
//设置关闭按钮的作用
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗体大小不可变
setResizable(false);
}
public static void main(String[] args) {
//创建窗体对象,并显示
new MainFrame().setVisible(true);
}
}