GUI编程3--贪吃蛇之界面绘制
贪吃蛇
帧:如果时间片足够小,就是动画,一秒30帧。连起来动画,拆开就是静态的图片。
键盘监听
定时器Timer
- 定义数据
- 画上去
- 监听事件
键盘监听
事件监听游戏状态timer(每个Timer对象是单个后台线程),按预定频率触发ActionEvent事件的源组件
回去补图excel表格上画蛇的截图
放图片可以放在跟目录下,也可以放在当前目录下
StratGame.java
package snake;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
// Game start class
public class StartGame {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame();
frame.setBounds(10, 10, 900, 720);
//size is fixed
frame.setResizable(false);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//Game should in panel
frame.add(new GamePanel());
frame.setVisible(true);
}
}
GamePanel.java
package snake;
import java.awt.Color;
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.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements KeyListener, ActionListener {
// snake length
int length;
int[] snakeX = new int[600];
int[] snakeY = new int[500];
String fx;
// food coordinate
int foodx;
int foody;
Random random = new Random();
//Score
int score;
// game status start or stop,defalut is stop(false)
boolean isStart = false;
// game failed?
boolean isFail = false;
// Timer 100ms one time,它是一个按预定频率触发ActionEvent事件的源组件,利用它可以实现动态效果
// Timer( int delay, ActionListener
// actionListener(绑定监听器每隔delay长的时间,不断调用监听器的actionperformed函数));
Timer timer = new Timer(200, this);
// constructer call init method
public GamePanel() {
init();
// get focus
this.setFocusable(true);
// get key monitor event
this.addKeyListener(this);
timer.start();
}
// init method
public void init() {
length = 3;
snakeX[0] = 100;
snakeY[0] = 100;// head
snakeX[1] = 75;
snakeY[1] = 100;// first body block
snakeX[2] = 50;
snakeY[2] = 100;// second body block
fx = "R";
// put food randomly
foodx = 25 + 25 * random.nextInt(34);
foody = 75 + 25 * random.nextInt(24);
score = 0;
}
// Paint panel, all the things in our game using this paint brush
@Override
protected void paintComponent(Graphics g) {
// TODO Auto-generated method stub
super.paintComponent(g);// clear screen
// paint static panel
this.setBackground(Color.white);
Data.header.paintIcon(this, g, 25, 11);
// paint rectangle
g.fillRect(25, 75, 850, 600);
//draw score
g.setColor(Color.white);
g.setFont(new Font("Microsoft YaHei", Font.BOLD, 15));
g.drawString("Length: "+ length, 750, 35);
g.drawString("Score: "+ score, 750, 50);
// draw food
Data.food.paintIcon(this, g, foodx, foody);
// draw head
if ("R".equals(fx)) {
// draw static snake, init snake head towards right
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if ("L".equals(fx)) {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if ("U".equals(fx)) {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
} else if ("D".equals(fx)) {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
}
// draw body
for (int i = 1; i < length; i++)
Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
if (isStart == false) {
g.setColor(Color.white);
g.setFont(new Font("Microsoft YaHei", Font.BOLD, 40));
g.drawString("push spacing to start", 300, 300);
}
if (isFail == true) {
g.setColor(Color.red);
g.setFont(new Font("Microsoft YaHei", Font.BOLD, 40));
g.drawString("game failed", 300, 300);
}
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
int keyCode = e.getKeyCode();
// if press space button
if (keyCode == KeyEvent.VK_SPACE) {
if (isFail) {
isFail = false;
init();
} else {
isStart = !isStart;
}
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 keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
// evnent monitor use fixed time to refresh, like 10/s
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (isStart && isFail == false) {
if (snakeX[0] == foodx && snakeY[0] == foody) {
//length & score increase
length++;
score += 10;
// create food again
foodx = 25 + 25 * random.nextInt(34);
foody = 75 + 25 * random.nextInt(24);
}
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
if (fx.equals("R")) {
snakeX[0] += 25;
// boundary judgement
if (snakeX[0] > 850) {
snakeX[0] = 25;
}
}
if (fx.equals("L")) {
snakeX[0] -= 25;
// boundary judgement
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
}
if (fx.equals("U")) {
snakeY[0] -= 25;
// boundary judgement
if (snakeY[0] < 75) {
snakeY[0] = 650;
}
}
if (fx.equals("D")) {
snakeY[0] += 25;
// boundary judgement
if (snakeY[0] > 650) {
snakeY[0] = 75;
}
}
// bump to itself
for (int i = 1; i < length; i++) {
if (snakeX[0] == snakeX[i] & snakeY[0] == snakeY[i]) {
isFail = true;
}
}
repaint();
// timer.start();
}
}
}
Data.java
package snake;
import java.net.URL;
import javax.swing.ImageIcon;
// data center
public class Data {
//absolute path start with /,current project, relative path
public static URL headerUrl = Data.class.getResource("statics/header.png");
public static ImageIcon header = new ImageIcon(headerUrl);
public static URL upUrl = Data.class.getResource("statics/up.png");
public static URL downUrl = Data.class.getResource("statics/down.png");
public static URL leftUrl = Data.class.getResource("statics/left.png");
public static URL rightUrl = Data.class.getResource("statics/right.png");
public static URL bodyUrl = Data.class.getResource("statics/body.png");
public static URL foodUrl = Data.class.getResource("statics/food.png");
public static ImageIcon up = new ImageIcon(upUrl);
public static ImageIcon down = new ImageIcon(downUrl);
public static ImageIcon left = new ImageIcon(leftUrl);
public static ImageIcon right = new ImageIcon(rightUrl);
public static ImageIcon body = new ImageIcon(bodyUrl);
public static ImageIcon food = new ImageIcon(foodUrl);
}
优化思路 待实现
积分越高等级越高,等级越高timer定时频率越快
小蛇撞墙增加失败判断
食物分不同颜色,不同分数身体增长长度不同,或者减少长度,或者小蛇死掉
小蛇转向方向,不能和原来的方向正相反
鼠标控制方向
游戏记录存数据库
连击对战
登录
博客有点圆

浙公网安备 33010602011771号