【实例简介】
java基础编写的俄罗斯方块
【实例截图】
【核心代码】
package com.akxy.yp.tetris;
//Frame 框, 相框 JFrame窗口框
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* 俄罗斯方块
* 俄罗斯方块 扩展了 空白面板, 添加了属性: 墙, 正在下落
* 的方块和下一个方块.
*/
public class Tetris extends JPanel {
private int score;//累计分数
private int lines;//销毁的行数
private Cell[][] wall;//(墙 20行X10列)
private Tetromino tetromino;//正在下落的(4格方块,有7种形态)
privateTetromino nextOne;//下一个准备下落的方块
/** 背景图片 */
private static BufferedImage background;
private static BufferedImage overImage;
public static BufferedImage T;
public static BufferedImage S;
public static BufferedImage I;
public static BufferedImage L;
public static BufferedImage J;
public static BufferedImage O;
public static BufferedImage Z;
public static final int ROWS = 20;//行
public static final int COLS = 10;//列
//将图片素材, 复制到包中.
/** 使用静态代码块加载静态的图片 */
static{
try{
//Tetris.class的同一个包中找 "tetris.png"
background=ImageIO.read(
Tetris.class.getResource("tetris.png"));
overImage=ImageIO.read(
Tetris.class.getResource("game-over.png"));
T=ImageIO.read(
Tetris.class.getResource("T.png"));
I=ImageIO.read(
Tetris.class.getResource("I.png"));
S=ImageIO.read(
Tetris.class.getResource("S.png"));
Z=ImageIO.read(
Tetris.class.getResource("Z.png"));
J=ImageIO.read(
Tetris.class.getResource("J.png"));
L=ImageIO.read(
Tetris.class.getResource("L.png"));
O=ImageIO.read(
Tetris.class.getResource("O.png"));
}catch(Exception e){
e.printStackTrace();
}
}
/** JPanel paint() paint画
* 重写 paint() 修改原有的绘制方法
**/
@Override
public void paint(Graphics g) {
//画背景, 画墙, 画正在下落的方块 画下一个方块...
g.drawImage(background, 0, 0, null);
g.translate(15, 15);//坐标系平移
paintWall(g);//画墙
paintTetromino(g);//画正在下落的方块
paintNextOne(g);
paintScore(g);
g.translate(-15, -15);
if(gameOver){
g.drawImage(overImage, 0, 0, null);
}
//g.setColor(new Color(0x0000ff));
//g.drawRect(10, 10, 50, 80);
}
public static final int FONT_COLOR=0x667799;
public static final int FONT_SIZE=30;
private void paintScore(Graphics g) {
int x = 290;
int y = 160;
g.setColor(new Color(FONT_COLOR));
Font font = g.getFont();//取得g当前字体
font = new Font(font.getName(),
font.getStyle(), FONT_SIZE);
g.setFont(font);//更改了g的字体
String str = "SCORE:" score;
g.drawString(str, x, y);
y =56;
str = "LINES:" lines;
g.drawString(str, x, y);
y =56;
str = "[P]Pause";
if(pause){
str = "[C]Continue";
}
if(gameOver){
str = "[S]Start!";
}
g.drawString(str, x, y);
}
private void paintNextOne(Graphics g) {
if(nextOne==null){
return;
}
//将每个格子的row,col 换算为x,y 然后贴图
Cell[] cells = nextOne.cells;
for(int i=0; i
//i = 0 1 2 3
Cell cell = cells[i];
//cell 每个格子
int x = (cell.getCol() 10)*CELL_SIZE;
int y = (cell.getRow() 1)*CELL_SIZE;
g.drawImage(cell.getImage(),
x-1, y-1, null);
}
}
public void paintTetromino(Graphics g){
//System.out.println("paint:" tetromino);
if(tetromino==null){
return;
}
//将每个格子的row,col 换算为x,y 然后贴图
Cell[] cells = tetromino.cells;
for(int i=0; i
//i = 0 1 2 3
Cell cell = cells[i];
//cell 每个格子
int x = cell.getCol() * CELL_SIZE;
int y = cell.getRow() * CELL_SIZE;
g.drawImage(cell.getImage(),
x-1, y-1, null);
}
}
public static final int CELL_SIZE = 26;
/** 画墙 */
private void paintWall(Graphics g){
for(int row=0; row
Cell[] line = wall[row];
//line 代表墙上的每一行
for(int col=0; col
Cell cell = line[col];
//cell 代表墙上的每个格子
int x=col*CELL_SIZE;
int y=row*CELL_SIZE;
if(cell==null){
//g.drawRect(x,y,CELL_SIZE,CELL_SIZE);
}else{
g.drawImage(cell.getImage(),
x-1, y-1, null);
}
}
}
}
/** 在Tetris 添加启动方法 action() */
public void action(){
wall = new Cell[ROWS][COLS];
startAction();
//wall[2][2] = new Cell(2,2, T);
//tetromino = Tetromino.randomOne();
//System.out.println(
//"After rendomOne:" tetromino);
//nextOne = Tetromino.randomOne();
//处理键盘按下事件, 在按下按键时候执行下落方法
KeyAdapter l = new KeyAdapter(){
@Override //key 按键 Pressed按下了
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();//[c]
if(key==KeyEvent.VK_Q){
System.exit(0);//结束Java进程
}
if(gameOver){
if(key==KeyEvent.VK_S){
startAction();
repaint();
}
return;
}
if(pause){//pause = true
if(key==KeyEvent.VK_C){
continueAction();
repaint();
}
return;
}
switch (key) {
case KeyEvent.VK_DOWN:softDropAction();break;
case KeyEvent.VK_RIGHT:moveRightAction();break;
case KeyEvent.VK_LEFT:moveLeftAction();break;
case KeyEvent.VK_SPACE:hardDropAction();break;
case KeyEvent.VK_UP:rotateRightAction();break;
case KeyEvent.VK_P:pauseAction();break;
}
repaint();//再画一次!
}
};
//下落流程: 监听键盘事件->如果下箭头按下->
//执行下落算法tetromino.softDrop()->
// 修改每个格子对象的数据->调用repaint()->
// 尽快调用paint()->paint方法会根据当前的数据
// 重新绘制界面 -> 看到移动以后的方块了
//绑定事件到当前面板
this.requestFocus();
this.addKeyListener(l);
}
/** 在Tetris 类上添加方法, 向右移动的流程控制 */
public void moveRightAction(){
//尝试先向右移动, 如果发现超出了边界, 就
//向左移动, 修正回来.
tetromino.moveRight();//coincide重叠
if(outOfBounds() || coincide()){
tetromino.moveLeft();
}
}
/** 检查正在下落的方块是否与墙上的砖块重叠 */
private boolean coincide() {
Cell[] cells = tetromino.cells;
for(int i=0; i
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
//如果墙的row,col位置上有格子,就重叠了!
if(row>=0 && row
col>=0 && col<=COLS &&
wall[row][col]!=null){
return true;//重叠
}
}
return false;
}
/** 检查当前正在下落的方块是否出界了 */
private boolean outOfBounds(){
Cell[] cells = tetromino.cells;
for(int i=0; i
Cell cell = cells[i];
int col = cell.getCol();
if(col<0 || col>=COLS){
return true;
}
}
return false;
}
public void moveLeftAction(){
tetromino.moveLeft();
if(outOfBounds() || coincide()){
tetromino.moveRight();
}
}
/** 下落流程控制 */
public void softDropAction(){
if(canDrop()){
tetromino.softDrop();
}else{
landIntoWall();
destoryLines();
checkGameOverAction();
tetromino = nextOne;
nextOne = Tetromino.randomOne();
}
}
private static int[] scoreTable ={0,1,10,50,100};
// 0 1 2 3 4
private void destoryLines() {
int lines = 0;
for(int row=0; row
if(fullCells(row)){
deleteRow(row);
lines ;
}
}
this.score = scoreTable[lines];
this.lines =lines;
}
private void deleteRow(int row) {
for(int i=row; i>=1; i--){
System.arraycopy(
wall[i-1], 0, wall[i], 0, COLS);
}
Arrays.fill(wall[0], null);
}
/** 检查当前行的每个格子, 如果有null返回false
* 否则返回 true */
private boolean fullCells(int row) {
Cell[] line = wall[row];
for(Cell cell: line){
if(cell==null){return false; }
}
return true;
}
private void landIntoWall() {
Cell[] cells = tetromino.cells;
for(int i=0; i
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
wall[row][col]=cell;
}
}
/** 检查当前的方块是否能够下落, 返回true能够下落 */
private boolean canDrop() {
Cell[] cells = tetromino.cells;
for(int i=0; i
Cell cell = cells[i];
int row = cell.getRow();
if(row == ROWS-1){
return false;
}
}
for(Cell cell: cells){//Java 5 以后可以使用
int row = cell.getRow() 1;
int col = cell.getCol();
if(row>=0 && row
col>=0 && col<=COLS &&
wall[row][col]!=null){
return false;
}
}
return true;
}
/** 硬下落流程, 下落到不能下落为止
* 绑定到 空格(VK_SPACE)事件上
* */
public void hardDropAction(){
while(canDrop()){
tetromino.softDrop();
}
landIntoWall();
destoryLines();
checkGameOverAction();
tetromino = nextOne;
nextOne = Tetromino.randomOne();
}
/** 在Tetris类中添加 旋转流程控制方法 */
public void rotateRightAction(){
tetromino.rotateRight();
if(outOfBounds() || coincide()){
tetromino.rotateLeft();
}
}
private Timer timer;
private boolean pause;
private boolean gameOver;
private long interval = 600;//间隔时间
/** 在Tetris类中添加 开始流程控制 */
public void startAction(){
pause = false; gameOver = false;
score = 0; lines=0;
clearWall();
tetromino = Tetromino.randomOne();
nextOne = Tetromino.randomOne();
timer = new Timer();
timer.schedule(new TimerTask(){
public void run(){
softDropAction();
repaint();
}
}, interval, interval);
}
private void clearWall() {
//Arrays.fill(wall, null);
for(Cell[] line: wall){
Arrays.fill(line, null);
}
//for(int i=0; i
//Arrays.fill(wall[i], null);
//}
}
/** 在Tetris类中添加暂停方法 */
public void pauseAction(){
timer.cancel();
pause = true;
}
public void continueAction(){
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
softDropAction();
repaint();
}
}, interval, interval);
pause = false;
}
public void checkGameOverAction(){
if(wall[0][4]!=null){
gameOver = true;
timer.cancel();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
//在加载Tetris类的时候, 会执行静态代码块
//静态代码块,装载了图片素材, 为图片对象
Tetris tetris = new Tetris();
//tetris.setBackground(new Color(0x0000ff));
frame.add(tetris);
frame.setSize(530, 580);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);//在显示窗口时候,会"尽快"
tetris.action();
//的调用paint()方法绘制界面
}
}