开始写第一篇博客。
先从Java的基础开始,写的这个贪食蛇小游戏只是一个最简化的,利用Java自带的图形来构建的,所以比较简陋一些。
主要是运用了Swing里面的一些知识,Swing相对awt来说,兼容性以及对于画面的呈现等方面都有优势,因此,大多数图形界面都是用Swing去编写。
贪吃蛇,可以用几个部分去写,先构造界面、蛇身、球的属性,然后对三个部分详细写,增加事件监听,用画板画出来。最难的部分在于蛇的移动的判定以及撞墙的判定,这里在蛇的移动上面是先把界面分成一个一个的小格,每一个小格代表蛇的一部分,这样移动起来就是在表格中移动,相对好理解一些。撞墙的判定是头碰到边缘就会结束。
package Game;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
@SuppressWarnings("serial")
public class Game extends JFrame {
//首先设置好界面 以及 蛇 球的各个属性 让他们线呈现出来 之后在进行移动 吃东西等的判断
//面板的长和宽
private int WIDTH = 800;
private int HEIGHT = 800;
//每个格子长宽
private int size = 20;
//多少个格子
private int rate = WIDTH/size;
//蛇的属性 在蛇的属性这个方面也可以用面向对象的思想
private int[] snake_x;//蛇的横坐标 用数组的形式储存
private int[] snake_y;//蛇的纵坐标
private int length;//蛇的长度
private int Direction ;
private int speed= 1;//一次移动一格
private int[] move_x ={speed,-speed,0,0};
private int[] move_y ={0,-0,speed,-speed};
//初始化
public void inital() {
snake_x = new int[rate];
snake_y = new int[rate];
length = 3;
//蛇的初始坐标,一开始显示的位置
snake_x[0] = 5;
snake_y[0] = 5;
snake_x[1] = 4;
snake_y[1] = 5;
snake_x[2] = 3;
snake_y[2] = 5;
}
//球的属性
private int ball_x = random.nextInt(rate)*size;
private int ball_y = random.nextInt(rate)*size;
private int ball_size = 20;
boolean flag = true;
Timer time = null;
//画板
class Mycanvas extends JPanel{
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
if (flag) {//存活状态下设置各个物体的属性
g.setColor(Color.GREEN);
g.fillOval(ball_x, ball_y, ball_size, ball_size);
for(int i = 0; i < length; i++) {
g.setColor(Color.blue);
g.fillRect(snake_x[i] * size, snake_y[i] * size, size, size);
}
}else {//游戏结束时各个物体的属性
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.ITALIC, 60));
g.drawString("GAME OVER", 300, 300);
}
}
}
private Mycanvas mycanvas = new Mycanvas();
Game(){
super("贪吃蛇");
this.inital();
mycanvas.setPreferredSize(new Dimension(WIDTH, HEIGHT));
this.add(mycanvas);
//增加监听事件
ActionListener al = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(flag) {
for(int i = length -1; i >0; i--) {//蛇的移动的条件 后一个变成前一个,位置的改变
snake_x[i] = snake_x[i-1];
snake_y[i] = snake_y[i-1];
}
snake_x[0] += move_x[Direction];//在判定蛇往哪移动后,蛇进行相应的移动
snake_y[0] += move_y[Direction];
}
//撞到边缘
if(snake_x[0] < 0 || snake_x[0] > (WIDTH - size)/size ||snake_y[0] < 0 || snake_y[0] >(HEIGHT -size)/size ) {
flag = false;
}
//撞到自己
for(int i =1; i <length ;i++) {
if(snake_x[0] == snake_x[i] && snake_y[0] == snake_y[i]) {
flag = false;
}
}
//吃到食物
if(snake_x[0]*size == ball_x && snake_y[0]*size == ball_y) {
length++;
snake_x[length-1] = ball_x/size;
snake_y[length-1] = ball_y/size;
ball_x=random.nextInt(rate)*size;
ball_y=random.nextInt(rate)*size;
}
mycanvas.repaint();
}
};
this.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
//键盘监听事件 上下左右分别对应不用的Direction 而Direction又决定了蛇的移动方向
//这样就能通过上下左右来控制蛇的移动了
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
switch(e.getKeyCode()) {
case KeyEvent.VK_UP :
if(Direction !=2 ) {
Direction = 3;
}
break;
case KeyEvent.VK_DOWN :
if(Direction !=3) {
Direction = 2;
}
break;
case KeyEvent.VK_LEFT :
if(Direction !=0 ) {
Direction = 1;
}
break;
case KeyEvent.VK_RIGHT :
if(Direction !=1) {
Direction = 0;
}
break;
default :
break;
}
//画板的重绘
mycanvas.repaint();
}
});
//设置刷新时间 也就是闪烁频率
time = new Timer(200, al);
time.start();
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
}
//主类 执行
public static void main(String[] args) {
new Game();
}
}
不管是写贪吃蛇还是别的小游戏,写代码都应从简到繁,先写出大体的轮廓,然后对相应的功能进行一步一步的完善,这个贪吃蛇写的简单了一点,所以一些东西是直接定义拿过来用的。很多时候面向对象很好用,特别是东西多了之后,一个对象一个类,这样逻辑就会很清晰,然后到最后直接调用就可以。