您好,欢迎访问一九零五行业门户网

Java编写小游戏教程:不贪吃蛇游戏

代码蛇、药丸的抽象坐标 point.java
记录横纵坐标值。
package cn.xeblog.snake.model;import java.util.objects;/** * 坐标 * * @author anlingyi * @date 2022/8/2 3:35 pm */public class point { public int x; public int y; public point(int x, int y) { this.x = x; this.y = y; } @override public boolean equals(object o) { if (this == o) return true; if (o == null || getclass() != o.getclass()) return false; point point = (point) o; return x == point.x && y == point.y; } @override public int hashcode() { return objects.hash(x, y); } @override public string tostring() { return "point{" + "x=" + x + ", y=" + y + '}'; }}
移动方向 direction.java
提供上、下、左、右四个移动方向的枚举。
package cn.xeblog.snake.model;/** * @author anlingyi * @date 2022/8/2 5:25 pm */public enum direction { up, down, left, right}
蛇 snake.java
存储蛇身坐标信息,提供蛇身移动、移除蛇尾坐标、获取蛇头、蛇尾坐标、蛇身长度等方法。
这里讲一下蛇移动的实现原理:游戏开始时,会固定一个移动方向,蛇会一直朝着这个方向移动,我们可以通过方向键改变蛇的移动方向,蛇的移动其实就是将蛇身的坐标移动一下位置,比如蛇身长度(不包含蛇头)为6,移动时,只需将蛇身位置为5的坐标移到位置为6的坐标去,位置为4的坐标移动到位置为5的坐标去,简单来说就是将前一个的坐标换到它后面一个去,这是蛇身的移动,蛇头的移动需要单独计算,如果是上下方向移动,那就是对y坐标的加减操作,向上运动需要减一个蛇身的高度,向下则与之相反,需要加一个蛇身的高度,左右运动同理。
package cn.xeblog.snake.model;import java.util.list;/** * 蛇 * * @author anlingyi * @date 2022/8/2 3:32 pm */public class snake { public static int width = 10; public static int height = 10; /** * 蛇身坐标列表 */ public list<point> body; public snake(list<point> body) { this.body = body; } /** * 添加蛇身坐标 * * @param x * @param y */ public void add(int x, int y) { this.body.add(new point(x * width, y * height)); } /** * 移除蛇尾坐标 */ public void removelast() { int size = size(); if (size == 0) { return; } this.body.remove(size - 1); } /** * 获取蛇头坐标 * * @return */ public point gethead() { if (size() > 0) { return this.body.get(0); } return null; } /** * 获取蛇尾坐标 * * @return */ public point gettail() { int size = size(); if (size > 0) { return this.body.get(size - 1); } return null; } /** * 蛇身长度 * * @return */ public int size() { return this.body.size(); } /** * 蛇移动 * * @param direction 移动方向 */ public void move(direction direction) { if (size() == 0) { return; } for (int i = this.size() - 1; i > 0; i--) { // 从蛇尾开始向前移动 point point = this.body.get(i); point nextpoint = this.body.get(i - 1); point.x = nextpoint.x; point.y = nextpoint.y; } // 蛇头移动 point head = gethead(); switch (direction) { case up: head.y -= height; break; case down: head.y += height; break; case left: head.x -= width; break; case right: head.x += width; break; } }}
药丸 pill.java
存储“药丸“的坐标、类型信息。
package cn.xeblog.snake.model;/** * 药丸 * * @author anlingyi * @date 2022/8/2 4:49 pm */public class pill { public static int width = 10; public static int height = 10; /** * 坐标 */ public point point; /** * 药丸类型 */ public pilltype pilltype; public enum pilltype { /** * 红色药丸 */ red(5), /** * 蓝色药丸 */ blue(2), /** * 绿色药丸 */ green(1), ; /** * 分数 */ public int score; pilltype(int score) { this.score = score; } } public pill(int x, int y, pilltype pilltype) { this.point = new point(x * width, y * height); this.pilltype = pilltype; }}
游戏界面初始化一些信息,比如游戏界面的宽高、定时器、一些状态标识(是否停止游戏、游戏是否胜利)、监听一些按键事件(空格键开始/暂停游戏、四个方向键控制蛇移动的方向),绘制游戏画面。
当检测到游戏开始时,初始化蛇、“药丸”的位置信息,然后启动定时器每隔一段时间重新绘制游戏画面,让蛇可以动起来。
当检测到蛇咬到自己或者是蛇撞墙时,游戏状态将会被标记为“游戏失败”,绘制游戏结束画面,并且定时器停止,如果蛇身为0,则游戏结束,游戏状态标记为“游戏胜利”。
package cn.xeblog.snake.ui;import cn.xeblog.snake.model.direction;import cn.xeblog.snake.model.pill;import cn.xeblog.snake.model.point;import cn.xeblog.snake.model.snake;import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.util.arraylist;import java.util.collections;import java.util.random;/** * @author anlingyi * @date 2022/8/2 3:51 pm */public class snakegameui extends jpanel implements actionlistener { /** * 宽度 */ private int width; /** * 高度 */ private int height; /** * 蛇 */ private snake snake; /** * 药丸 */ private pill pill; /** * 移动方向 */ private direction direction; /** * 停止游戏标记 */ private boolean stop; /** * 游戏状态 0.初始化 1.游戏胜利 2.游戏失败 */ private int state = -1; /** * 定时器 */ private timer timer; /** * 移动速度 */ private int speed = 100; /** * 分数 */ private int score; /** * 特殊药丸列表 */ private arraylist<pill.pilltype> specialpill; public snakegameui(int width, int height) { this.width = width; this.height = height; this.timer = new timer(speed, this); this.stop = true; initpanel(); } /** * 初始化 */ private void init() { this.score = 0; this.state = 0; this.stop = true; this.timer.setdelay(speed); initsnake(); initpill(); generatepill(); repaint(); } /** * 初始化游戏面板 */ private void initpanel() { this.setpreferredsize(new dimension(this.width, this.height)); this.addkeylistener(new keyadapter() { @override public void keypressed(keyevent e) { if (stop && e.getkeycode() != keyevent.vk_space) { return; } switch (e.getkeycode()) { case keyevent.vk_up: if (direction == direction.down) { break; } direction = direction.up; break; case keyevent.vk_down: if (direction == direction.up) { break; } direction = direction.down; break; case keyevent.vk_left: if (direction == direction.right) { break; } direction = direction.left; break; case keyevent.vk_right: if (direction == direction.left) { break; } direction = direction.right; break; case keyevent.vk_space: if (state != 0) { init(); } stop = !stop; if (!stop) { timer.start(); } break; } } }); } /** * 初始化蛇 */ private void initsnake() { this.direction = direction.left; int maxx = this.width / snake.width; int maxy = this.height / snake.height; this.snake = new snake(new arraylist<>()); this.snake.add(maxx - 2, 3); this.snake.add(maxx - 1, 3); this.snake.add(maxx - 1, 2); this.snake.add(maxx - 1, 1); for (int i = maxx - 1; i > 0; i--) { this.snake.add(i, 1); } for (int i = 1; i < maxy - 1; i++) { this.snake.add(1, i); } for (int i = 1; i < maxx - 1; i++) { this.snake.add(i, maxy - 2); } } /** * 初始化药丸 */ private void initpill() { this.specialpill = new arraylist<>(); for (int i = 0; i < 5; i++) { this.specialpill.add(pill.pilltype.red); } for (int i = 0; i < 10; i++) { this.specialpill.add(pill.pilltype.blue); } collections.shuffle(specialpill); } /** * 生成药丸 */ private void generatepill() { // 是否获取特殊药丸 boolean getspecialpill = new random().nextint(6) == 3; pill.pilltype pilltype; if (getspecialpill && this.specialpill.size() > 0) { // 生成特殊药丸 int index = new random().nextint(this.specialpill.size()); pilltype = this.specialpill.get(index); this.specialpill.remove(index); } else { // 生成绿色药丸 pilltype = pill.pilltype.green; } // 随机坐标 int x = new random().nextint(this.width / pill.width - 1); int y = new random().nextint(this.height / pill.height - 1); this.pill = new pill(x, y, pilltype); } @override protected void paintcomponent(graphics g) { super.paintcomponent(g); graphics2d g2 = (graphics2d) g; g2.setrenderinghint(renderinghints.key_text_antialiasing, renderinghints.value_text_antialias_on); g2.setrenderinghint(renderinghints.key_antialiasing, renderinghints.value_antialias_on); g2.setcolor(new color(66, 66, 66)); g2.fillrect(0, 0, this.width, this.height); if (this.snake != null) { // 画蛇 g2.setcolor(new color(255, 255, 255)); for (int i = this.snake.size() - 1; i >= 0; i--) { point point = this.snake.body.get(i); if (i == 0) { // 蛇头 g2.setcolor(new color(255, 92, 92)); } else { g2.setcolor(new color(215, 173, 173)); } g2.fillrect(point.x, point.y, snake.width, snake.height); } } if (this.pill != null) { // 画药丸 color pillcolor; switch (this.pill.pilltype) { case red: pillcolor = new color(255, 41, 41); break; case blue: pillcolor = new color(20, 250, 243); break; default: pillcolor = new color(97, 255, 113); break; } g2.setcolor(pillcolor); g2.filloval(pill.point.x, pill.point.y, pill.width, pill.height); } if (state > 0) { // 显示游戏结果 string tips = "游戏失败!"; if (state == 1) { tips = "游戏胜利!"; } g2.setfont(new font("", font.bold, 20)); g2.setcolor(new color(208, 74, 74)); g2.drawstring(tips, this.width / 3, this.height / 3); g2.setfont(new font("", font.plain, 18)); g2.setcolor(color.white); g2.drawstring("得分:" + this.score, this.width / 2, this.height / 3 + 50); } if (stop) { g2.setfont(new font("", font.plain, 18)); g2.setcolor(color.white); g2.drawstring("按空格键开始/暂停游戏!", this.width / 4, this.height - 50); } } @override public void actionperformed(actionevent e) { // 是否吃药 boolean isate = false; if (!this.stop) { // 移动蛇 this.snake.move(this.direction); point head = this.snake.gethead(); if (head.equals(this.pill.point)) { // 吃药了 isate = true; // 药丸分数 int getscore = this.pill.pilltype.score; // 累计分数 this.score += getscore; for (int i = 0; i < getscore; i++) { // 移除蛇尾 this.snake.removelast(); if (this.snake.size() == 0) { // 游戏胜利 this.state = 1; this.stop = true; break; } } pill = null; if (this.score % 10 == 0) { int curspeed = this.timer.getdelay(); if (curspeed > 30) { // 加速 this.timer.setdelay(curspeed - 10); } } } if (state == 0) { // 判断蛇有没有咬到自己或是撞墙 int maxwidth = this.width - this.snake.width; int maxheight = this.height - this.snake.height; boolean ishitwall = head.x > maxwidth || head.x < 0 || head.y > maxheight || head.y < 0; boolean isbiting = false; for (int i = this.snake.size() - 1; i > 0; i--) { if (head.equals(this.snake.body.get(i))) { isbiting = true; break; } } if (ishitwall || isbiting) { // 游戏失败 this.state = 2; this.stop = true; } } } if (this.stop) { this.timer.stop(); } else if (isate) { // 重新生成药丸 generatepill(); } repaint(); }}
启动类游戏启动入口。
package cn.xeblog.snake;import cn.xeblog.snake.ui.snakegameui;import javax.swing.*;/** * 启动游戏 * * @author anlingyi * @date 2022/8/2 3:41 pm */public class startgame { public static void main(string[] args) { jframe frame = new jframe(); frame.setdefaultcloseoperation(windowconstants.exit_on_close); frame.setvisible(true); frame.setresizable(false); frame.settitle("不贪吃蛇"); frame.setsize(400, 320); frame.setlocationrelativeto(null); jpanel gamepanel = new snakegameui(400, 300); frame.add(gamepanel); gamepanel.requestfocus(); }}
以上就是java编写小游戏教程:不贪吃蛇游戏的详细内容。
其它类似信息

推荐信息