我的一位学生设计的俄罗斯方块游戏
来源:互联网 发布:天行VPN软件下载 编辑:程序博客网 时间:2024/05/29 11:48
Game.java
package net.handson.russianBox;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
/** *//**
*
* @author 汪燕飞
* @version 1.0
* time: 2008-3
*
*/
public class Game extends JFrame...{
private JPanel bgPanel;
private int score = 0;
JMenuItem startMenuItem,quitMenuItem,stopMenuItem;
private JLabel scoreLabel;// 显示分数的标签
private boolean isKeyEnable = false;
private Shape shape = null;;
private RunThread runThread;
private GamePanel gamePanel;
private BackgroundMatrix bgMatrix;
public static final int UP = 1;
public static final int LEFT = 2;
public static final int RIGHT = 3;
public static final int DOWN = 4;
private Object lock = new Object();
private String aboutMessage = "<html><p>Author: 汪燕飞</p><p>copy right: Anhui HandsOn training company</p></html>";
private String helpMessage = "<html><b>游戏控制参考</b></p><p>向上方向键为变形</p><p>向下方向键为下移</p><p>向左方向键为左移</p><p>向右方向键为右移</p><p>游戏进行过程中可以选择暂停,暂停后可以选择继续游戏</p></html>";
public Game() ...{
super("俄罗斯方块");
runThread = new RunThread();
setBackground(Color.cyan);
setLayout(new BorderLayout());
bgPanel =(JPanel)getContentPane();
initBgPanel();
initMenuBar();
setSize(400, 480);
addKeyListener(new MyKeyListener());
addWindowListener(new WindowAdapter() ...{
public void windowClosing(WindowEvent e) ...{
System.exit(0);
}
});
setToScreenCenter();
setResizable(false);
setVisible(true);
}
private void initBgPanel() ...{
bgMatrix = new BackgroundMatrix();
bgMatrix.init();
gamePanel = new GamePanel(bgMatrix);
gamePanel.setVisible(true);
bgPanel.add(gamePanel,BorderLayout.CENTER);
scoreLabel = new JLabel("得分:" + score);
scoreLabel.setFont(new Font("1", 1, 16));
scoreLabel.setBackground(new Color(55550255));
JPanel eastPanel=new JPanel(new FlowLayout(FlowLayout.CENTER));
eastPanel.add(scoreLabel);
bgPanel.add(new JPanel(),BorderLayout.NORTH);
bgPanel.add(new JPanel(),BorderLayout.SOUTH);
bgPanel.add(new JPanel(),BorderLayout.WEST);
bgPanel.add(eastPanel,BorderLayout.EAST);
bgPanel.addKeyListener(new MyKeyListener());
}
private void initMenuBar()...{
JMenuBar menuBar=new JMenuBar();
MyActionListener actionListener=new MyActionListener();
JMenu controlMenu = new JMenu("控制(c)");
controlMenu.setMnemonic('c');
startMenuItem=new JMenuItem("开始");
startMenuItem.setBackground(Color.LIGHT_GRAY);
startMenuItem.setActionCommand("start");
startMenuItem.addActionListener(actionListener);
controlMenu.add(startMenuItem);
stopMenuItem=new JMenuItem("停止");
stopMenuItem.setBackground(Color.LIGHT_GRAY);
stopMenuItem.setActionCommand("stop");
stopMenuItem.setEnabled(false);
stopMenuItem.addActionListener(actionListener);
controlMenu.add(stopMenuItem);
quitMenuItem=new JMenuItem("退出");
quitMenuItem.setBackground(Color.LIGHT_GRAY);
quitMenuItem.setActionCommand("quit");
quitMenuItem.addActionListener(actionListener);
controlMenu.add(quitMenuItem);
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('H');
JMenuItem helpItem = new JMenuItem("help");
helpItem.setActionCommand("help");
helpItem.addActionListener(actionListener);
JMenuItem aboutItem = new JMenuItem("about");
aboutItem.setActionCommand("about");
aboutItem.addActionListener(actionListener);
helpMenu.add(helpItem);
helpMenu.add(aboutItem);
menuBar.add(controlMenu);
menuBar.add(helpMenu);
this.setJMenuBar(menuBar);
}
private void setToScreenCenter()...{
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int locationX = (dimension.width-this.getSize().width)/2;
int locationY = (dimension.height-this.getSize().height)/2;
this.setLocation(locationX, locationY);
}
/** *//**
* 开始游戏
*/
private void gameStart()...{
startMenuItem.setText("暂停");
stopMenuItem.setEnabled(true);
isKeyEnable = true;
shape = new Shape();
gamePanel.setShape(shape);
runThread.start();
}
/** *//**
* 将游戏暂停
*/
private void gamePause()...{
startMenuItem.setText("继续");
runThread.end();
isKeyEnable = false;
}
/** *//**
* 将暂停的游戏继续下去
*/
private void gameResume()...{
startMenuItem.setText("暂停");
runThread.restart();
isKeyEnable = true;
}
/** *//**
* 游戏重新开始时进行的一些处理
*/
public void gameRestart() ...{
startMenuItem.setText("暂停");
bgMatrix.init();
gamePanel.setBgMatrix(bgMatrix);
isKeyEnable = true;
score = 0;
scoreLabel.setText("得分: " + score);
shape = new Shape();
gamePanel.setShape(shape);
runThread = new RunThread();
runThread.start();
}
/** *//**
* 游戏结束的一些处理
*/
public void gameOver() ...{
isKeyEnable = false;
runThread.end();
startMenuItem.setBounds(900, 400, 110, 30);
startMenuItem.setText("重新开始");
}
private void quit()...{
boolean isRun=runThread.isRun;
runThread.end();
isKeyEnable = false;
if (JOptionPane.showConfirmDialog(null, "确定退出游戏?") == JOptionPane.OK_OPTION) ...{
System.exit(0);
}else...{
if(isRun)...{
gameResume();
}
}
}
/** *//**
* 消除一行时同时进行加分
* @param rows
*/
private void addScore(int rows) ...{
if (rows != 0) ...{
switch (rows) ...{
case 1:
score += 10;
break;
case 2:
score += 30;
break;
case 3:
score += 60;
break;
case 4:
score += 100;
break;
default:
break;
}
}
}
public class MyActionListener implements ActionListener ...{
public void actionPerformed(ActionEvent e) ...{
String command = e.getActionCommand();
if (command.equals("start")) ...{
stopMenuItem.setEnabled(true);
if (startMenuItem.getText().equals("开始")) ...{
gameStart();
} else if (startMenuItem.getText().equals("暂停")) ...{
gamePause();
} else if (startMenuItem.getText().equals("继续")) ...{
gameResume();
} else if (startMenuItem.getText().equals("重新开始")) ...{
gameRestart();
}
}else if(command.equals("stop"))...{
gameOver();
stopMenuItem.setEnabled(false);
}else if (command.equals("quit")) ...{
quit();
}else if(command.equals("help"))...{
showWindow(helpMessage);
}else if(command.equals("about"))...{
showWindow(aboutMessage);
}
}
}
private void showWindow(String message)...{
JOptionPane.showMessageDialog(this, message);
}
/** *//**
* 保持当前形状的一个副本,然后可以对副本进行尝试移动,如果不能移动就放弃当前副本,如果可以移动,则将当前形状变换为当前副本形状
* @param shape 当前形状
* @param tempShape 一个临时形状,做为当前形状的一个副本
*/
private void copyPreShape(Shape shape, Shape tempShape) ...{
tempShape.setLeft(shape.getLeft());
tempShape.setStatus(shape.getStatus());
tempShape.setTop(shape.getTop());
}
/** *//**
* 当形状不可再往下移动时调用此方法,将形状merge到背景中,并消除可以消除的行
*/
private void mergeShapeToBg() ...{
bgMatrix.mergeShape(shape);
int cancelRows = bgMatrix.cancelRows(shape);
if (cancelRows > 0) ...{
addScore(cancelRows);
scoreLabel.setText("得分: " + score);
}
shape = new Shape();
if (bgMatrix.isOverlap(shape)) ...{
gameOver();
} else ...{
gamePanel.setShape(shape);
}
}
/** *//**
* 判断当前形状是否可以向指定的方向移动
* @param shape 当前形状
* @param direction 需要移动的方向 <br>
* Game.UP, Game.LEFT, Game.RIGHT, Game.DOWN
* @return 如果可以移动返回true, 否则返回false
*/
public boolean isMoveAble(Shape shape, int direction) ...{
Shape tempShape = new Shape();
copyPreShape(shape, tempShape);
switch (direction) ...{
case UP:
tempShape.rotate();
return !bgMatrix.isOverlap(tempShape);
case LEFT:
tempShape.moveLeft();
return !bgMatrix.isOverlap(tempShape);
case RIGHT:
tempShape.moveRight();
return !bgMatrix.isOverlap(tempShape);
case DOWN:
tempShape.moveDown();
return !bgMatrix.isOverlap(tempShape);
default:
return false;
}
}
private class MyKeyListener implements KeyListener ...{
public void keyPressed(KeyEvent e) ...{
synchronized (lock) ...{
if (isKeyEnable) ...{
switch (e.getKeyCode()) ...{
case KeyEvent.VK_UP:
if (isMoveAble(shape, UP)) ...{
shape.rotate();
}
break;
case KeyEvent.VK_DOWN:
if (isMoveAble(shape, DOWN)) ...{
shape.moveDown();
}
break;
case KeyEvent.VK_LEFT:
if (isMoveAble(shape, LEFT)) ...{
shape.moveLeft();
}
break;
case KeyEvent.VK_RIGHT:
if (isMoveAble(shape, RIGHT)) ...{
shape.moveRight();
}
break;
default:
break;
}
}
}
}
public void keyReleased(KeyEvent e) ...{
}
public void keyTyped(KeyEvent e) ...{
}
}
/** *//**
* 重画游戏界面及将形状定时往下移动
* @author smm
*
*/
private class RunThread extends Thread ...{
boolean isRun = false;
/** *//**
* end or pause game
*/
public void end() ...{
isRun = false;
}
/** *//**
* restart game
*/
public void restart() ...{
isRun = true;
}
public void run() ...{
final int repaintGap = 640;
isRun = true;
gamePanel.setGameRunningStatus(true);
int sleepedMills=0;
while (true) ...{
try ...{
sleep(80);
} catch (Exception e) ...{
e.printStackTrace();
}
if (! isRun) ...{
continue;
}
synchronized (lock) ...{
sleepedMills += 80;
gamePanel.repaint();
if (!isMoveAble(shape, DOWN)) ...{
sleepedMills = 0;
mergeShapeToBg();
}
else if(sleepedMills == repaintGap)...{
shape.moveDown();
sleepedMills=0;
}
}
}
}
}
public static void main(String[] args) ...{
new Game();
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
/** *//**
*
* @author 汪燕飞
* @version 1.0
* time: 2008-3
*
*/
public class Game extends JFrame...{
private JPanel bgPanel;
private int score = 0;
JMenuItem startMenuItem,quitMenuItem,stopMenuItem;
private JLabel scoreLabel;// 显示分数的标签
private boolean isKeyEnable = false;
private Shape shape = null;;
private RunThread runThread;
private GamePanel gamePanel;
private BackgroundMatrix bgMatrix;
public static final int UP = 1;
public static final int LEFT = 2;
public static final int RIGHT = 3;
public static final int DOWN = 4;
private Object lock = new Object();
private String aboutMessage = "<html><p>Author: 汪燕飞</p><p>copy right: Anhui HandsOn training company</p></html>";
private String helpMessage = "<html><b>游戏控制参考</b></p><p>向上方向键为变形</p><p>向下方向键为下移</p><p>向左方向键为左移</p><p>向右方向键为右移</p><p>游戏进行过程中可以选择暂停,暂停后可以选择继续游戏</p></html>";
public Game() ...{
super("俄罗斯方块");
runThread = new RunThread();
setBackground(Color.cyan);
setLayout(new BorderLayout());
bgPanel =(JPanel)getContentPane();
initBgPanel();
initMenuBar();
setSize(400, 480);
addKeyListener(new MyKeyListener());
addWindowListener(new WindowAdapter() ...{
public void windowClosing(WindowEvent e) ...{
System.exit(0);
}
});
setToScreenCenter();
setResizable(false);
setVisible(true);
}
private void initBgPanel() ...{
bgMatrix = new BackgroundMatrix();
bgMatrix.init();
gamePanel = new GamePanel(bgMatrix);
gamePanel.setVisible(true);
bgPanel.add(gamePanel,BorderLayout.CENTER);
scoreLabel = new JLabel("得分:" + score);
scoreLabel.setFont(new Font("1", 1, 16));
scoreLabel.setBackground(new Color(55550255));
JPanel eastPanel=new JPanel(new FlowLayout(FlowLayout.CENTER));
eastPanel.add(scoreLabel);
bgPanel.add(new JPanel(),BorderLayout.NORTH);
bgPanel.add(new JPanel(),BorderLayout.SOUTH);
bgPanel.add(new JPanel(),BorderLayout.WEST);
bgPanel.add(eastPanel,BorderLayout.EAST);
bgPanel.addKeyListener(new MyKeyListener());
}
private void initMenuBar()...{
JMenuBar menuBar=new JMenuBar();
MyActionListener actionListener=new MyActionListener();
JMenu controlMenu = new JMenu("控制(c)");
controlMenu.setMnemonic('c');
startMenuItem=new JMenuItem("开始");
startMenuItem.setBackground(Color.LIGHT_GRAY);
startMenuItem.setActionCommand("start");
startMenuItem.addActionListener(actionListener);
controlMenu.add(startMenuItem);
stopMenuItem=new JMenuItem("停止");
stopMenuItem.setBackground(Color.LIGHT_GRAY);
stopMenuItem.setActionCommand("stop");
stopMenuItem.setEnabled(false);
stopMenuItem.addActionListener(actionListener);
controlMenu.add(stopMenuItem);
quitMenuItem=new JMenuItem("退出");
quitMenuItem.setBackground(Color.LIGHT_GRAY);
quitMenuItem.setActionCommand("quit");
quitMenuItem.addActionListener(actionListener);
controlMenu.add(quitMenuItem);
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('H');
JMenuItem helpItem = new JMenuItem("help");
helpItem.setActionCommand("help");
helpItem.addActionListener(actionListener);
JMenuItem aboutItem = new JMenuItem("about");
aboutItem.setActionCommand("about");
aboutItem.addActionListener(actionListener);
helpMenu.add(helpItem);
helpMenu.add(aboutItem);
menuBar.add(controlMenu);
menuBar.add(helpMenu);
this.setJMenuBar(menuBar);
}
private void setToScreenCenter()...{
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int locationX = (dimension.width-this.getSize().width)/2;
int locationY = (dimension.height-this.getSize().height)/2;
this.setLocation(locationX, locationY);
}
/** *//**
* 开始游戏
*/
private void gameStart()...{
startMenuItem.setText("暂停");
stopMenuItem.setEnabled(true);
isKeyEnable = true;
shape = new Shape();
gamePanel.setShape(shape);
runThread.start();
}
/** *//**
* 将游戏暂停
*/
private void gamePause()...{
startMenuItem.setText("继续");
runThread.end();
isKeyEnable = false;
}
/** *//**
* 将暂停的游戏继续下去
*/
private void gameResume()...{
startMenuItem.setText("暂停");
runThread.restart();
isKeyEnable = true;
}
/** *//**
* 游戏重新开始时进行的一些处理
*/
public void gameRestart() ...{
startMenuItem.setText("暂停");
bgMatrix.init();
gamePanel.setBgMatrix(bgMatrix);
isKeyEnable = true;
score = 0;
scoreLabel.setText("得分: " + score);
shape = new Shape();
gamePanel.setShape(shape);
runThread = new RunThread();
runThread.start();
}
/** *//**
* 游戏结束的一些处理
*/
public void gameOver() ...{
isKeyEnable = false;
runThread.end();
startMenuItem.setBounds(900, 400, 110, 30);
startMenuItem.setText("重新开始");
}
private void quit()...{
boolean isRun=runThread.isRun;
runThread.end();
isKeyEnable = false;
if (JOptionPane.showConfirmDialog(null, "确定退出游戏?") == JOptionPane.OK_OPTION) ...{
System.exit(0);
}else...{
if(isRun)...{
gameResume();
}
}
}
/** *//**
* 消除一行时同时进行加分
* @param rows
*/
private void addScore(int rows) ...{
if (rows != 0) ...{
switch (rows) ...{
case 1:
score += 10;
break;
case 2:
score += 30;
break;
case 3:
score += 60;
break;
case 4:
score += 100;
break;
default:
break;
}
}
}
public class MyActionListener implements ActionListener ...{
public void actionPerformed(ActionEvent e) ...{
String command = e.getActionCommand();
if (command.equals("start")) ...{
stopMenuItem.setEnabled(true);
if (startMenuItem.getText().equals("开始")) ...{
gameStart();
} else if (startMenuItem.getText().equals("暂停")) ...{
gamePause();
} else if (startMenuItem.getText().equals("继续")) ...{
gameResume();
} else if (startMenuItem.getText().equals("重新开始")) ...{
gameRestart();
}
}else if(command.equals("stop"))...{
gameOver();
stopMenuItem.setEnabled(false);
}else if (command.equals("quit")) ...{
quit();
}else if(command.equals("help"))...{
showWindow(helpMessage);
}else if(command.equals("about"))...{
showWindow(aboutMessage);
}
}
}
private void showWindow(String message)...{
JOptionPane.showMessageDialog(this, message);
}
/** *//**
* 保持当前形状的一个副本,然后可以对副本进行尝试移动,如果不能移动就放弃当前副本,如果可以移动,则将当前形状变换为当前副本形状
* @param shape 当前形状
* @param tempShape 一个临时形状,做为当前形状的一个副本
*/
private void copyPreShape(Shape shape, Shape tempShape) ...{
tempShape.setLeft(shape.getLeft());
tempShape.setStatus(shape.getStatus());
tempShape.setTop(shape.getTop());
}
/** *//**
* 当形状不可再往下移动时调用此方法,将形状merge到背景中,并消除可以消除的行
*/
private void mergeShapeToBg() ...{
bgMatrix.mergeShape(shape);
int cancelRows = bgMatrix.cancelRows(shape);
if (cancelRows > 0) ...{
addScore(cancelRows);
scoreLabel.setText("得分: " + score);
}
shape = new Shape();
if (bgMatrix.isOverlap(shape)) ...{
gameOver();
} else ...{
gamePanel.setShape(shape);
}
}
/** *//**
* 判断当前形状是否可以向指定的方向移动
* @param shape 当前形状
* @param direction 需要移动的方向 <br>
* Game.UP, Game.LEFT, Game.RIGHT, Game.DOWN
* @return 如果可以移动返回true, 否则返回false
*/
public boolean isMoveAble(Shape shape, int direction) ...{
Shape tempShape = new Shape();
copyPreShape(shape, tempShape);
switch (direction) ...{
case UP:
tempShape.rotate();
return !bgMatrix.isOverlap(tempShape);
case LEFT:
tempShape.moveLeft();
return !bgMatrix.isOverlap(tempShape);
case RIGHT:
tempShape.moveRight();
return !bgMatrix.isOverlap(tempShape);
case DOWN:
tempShape.moveDown();
return !bgMatrix.isOverlap(tempShape);
default:
return false;
}
}
private class MyKeyListener implements KeyListener ...{
public void keyPressed(KeyEvent e) ...{
synchronized (lock) ...{
if (isKeyEnable) ...{
switch (e.getKeyCode()) ...{
case KeyEvent.VK_UP:
if (isMoveAble(shape, UP)) ...{
shape.rotate();
}
break;
case KeyEvent.VK_DOWN:
if (isMoveAble(shape, DOWN)) ...{
shape.moveDown();
}
break;
case KeyEvent.VK_LEFT:
if (isMoveAble(shape, LEFT)) ...{
shape.moveLeft();
}
break;
case KeyEvent.VK_RIGHT:
if (isMoveAble(shape, RIGHT)) ...{
shape.moveRight();
}
break;
default:
break;
}
}
}
}
public void keyReleased(KeyEvent e) ...{
}
public void keyTyped(KeyEvent e) ...{
}
}
/** *//**
* 重画游戏界面及将形状定时往下移动
* @author smm
*
*/
private class RunThread extends Thread ...{
boolean isRun = false;
/** *//**
* end or pause game
*/
public void end() ...{
isRun = false;
}
/** *//**
* restart game
*/
public void restart() ...{
isRun = true;
}
public void run() ...{
final int repaintGap = 640;
isRun = true;
gamePanel.setGameRunningStatus(true);
int sleepedMills=0;
while (true) ...{
try ...{
sleep(80);
} catch (Exception e) ...{
e.printStackTrace();
}
if (! isRun) ...{
continue;
}
synchronized (lock) ...{
sleepedMills += 80;
gamePanel.repaint();
if (!isMoveAble(shape, DOWN)) ...{
sleepedMills = 0;
mergeShapeToBg();
}
else if(sleepedMills == repaintGap)...{
shape.moveDown();
sleepedMills=0;
}
}
}
}
}
public static void main(String[] args) ...{
new Game();
}
}
GamePanel.java
package net.handson.russianBox;
import java.awt.*;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
/** *//**
* 绘制游戏的面板
* @author 汪燕飞
*
*/
public class GamePanel extends JPanel ...{
private Shape shape;
private BackgroundMatrix bgMatrix;
private int[][] bgM;
private Image img;
private Graphics bg;
private boolean gameIsRunning;
/** *//**
* 绘制游戏的面板
* @param bgMatrix
*/
public GamePanel(BackgroundMatrix bgMatrix)...{
this.bgMatrix = bgMatrix;
bgM=bgMatrix.getValues();
setSize(bgMatrix.WIDTH,bgMatrix.HEIGHT);
setVisible(true);
}
/** *//**
* 设置背景的形状
* @param bgMatrix
*/
public void setBgMatrix(BackgroundMatrix bgMatrix)...{
this.bgMatrix=bgMatrix;
}
/** *//**
* 设置移动的形状
* @param shape
*/
public void setShape(Shape shape)...{
this.shape=shape;
}
public void addNotify()...{
super.addNotify();
img=createImage(bgMatrix.WIDTH, bgMatrix.HEIGHT);
}
/** *//**
* 通过设置游戏是否在进行来决定是否画出移动形状
* @param isRun
*/
public void setGameRunningStatus(boolean isRun)...{
gameIsRunning=isRun;
}
public void paintComponent(Graphics g)...{
super.paintComponent(g);
bg = img.getGraphics();
paintBgMatrix(bg);
if(gameIsRunning)...{
paintShape(bg);
}
bg.dispose();
g.drawImage (img, 0, 0, this);
}
/** *//**
* 画出游戏背景
* @param g
*/
private void paintBgMatrix(Graphics g)...{
for(int i = 0; i < bgM.length; i ++)...{
for(int j = 0; j < bgM[0].length; j ++)...{
if(bgM [i][j] == 1)...{
g.setColor(Color.black);
g.fillRect( bgMatrix.cellDistance *j , bgMatrix.cellDistance *i, bgMatrix.cellWidth, bgMatrix.cellHeight);
}
else...{
g.setColor(Color.lightGray);
g.fillRect( bgMatrix.cellDistance *j , bgMatrix.cellDistance *i, bgMatrix.cellWidth, bgMatrix.cellHeight);
}
}
}
}
/** *//**
* 画出游戏中移动的形状
* @param g
*/
private void paintShape(Graphics g)...{
for(int k=0;k<Shape.POINT_NUMBER;k++)...{
int i=shape.getLeft()+shape.getPoint(k).x;
int j=shape.getTop()+shape.getPoint(k).y;
g.setColor(Color.black);
g.fillRect( bgMatrix.cellDistance *i , bgMatrix.cellDistance *j, bgMatrix.cellWidth, bgMatrix.cellHeight);
}
}
}
import java.awt.*;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
/** *//**
* 绘制游戏的面板
* @author 汪燕飞
*
*/
public class GamePanel extends JPanel ...{
private Shape shape;
private BackgroundMatrix bgMatrix;
private int[][] bgM;
private Image img;
private Graphics bg;
private boolean gameIsRunning;
/** *//**
* 绘制游戏的面板
* @param bgMatrix
*/
public GamePanel(BackgroundMatrix bgMatrix)...{
this.bgMatrix = bgMatrix;
bgM=bgMatrix.getValues();
setSize(bgMatrix.WIDTH,bgMatrix.HEIGHT);
setVisible(true);
}
/** *//**
* 设置背景的形状
* @param bgMatrix
*/
public void setBgMatrix(BackgroundMatrix bgMatrix)...{
this.bgMatrix=bgMatrix;
}
/** *//**
* 设置移动的形状
* @param shape
*/
public void setShape(Shape shape)...{
this.shape=shape;
}
public void addNotify()...{
super.addNotify();
img=createImage(bgMatrix.WIDTH, bgMatrix.HEIGHT);
}
/** *//**
* 通过设置游戏是否在进行来决定是否画出移动形状
* @param isRun
*/
public void setGameRunningStatus(boolean isRun)...{
gameIsRunning=isRun;
}
public void paintComponent(Graphics g)...{
super.paintComponent(g);
bg = img.getGraphics();
paintBgMatrix(bg);
if(gameIsRunning)...{
paintShape(bg);
}
bg.dispose();
g.drawImage (img, 0, 0, this);
}
/** *//**
* 画出游戏背景
* @param g
*/
private void paintBgMatrix(Graphics g)...{
for(int i = 0; i < bgM.length; i ++)...{
for(int j = 0; j < bgM[0].length; j ++)...{
if(bgM [i][j] == 1)...{
g.setColor(Color.black);
g.fillRect( bgMatrix.cellDistance *j , bgMatrix.cellDistance *i, bgMatrix.cellWidth, bgMatrix.cellHeight);
}
else...{
g.setColor(Color.lightGray);
g.fillRect( bgMatrix.cellDistance *j , bgMatrix.cellDistance *i, bgMatrix.cellWidth, bgMatrix.cellHeight);
}
}
}
}
/** *//**
* 画出游戏中移动的形状
* @param g
*/
private void paintShape(Graphics g)...{
for(int k=0;k<Shape.POINT_NUMBER;k++)...{
int i=shape.getLeft()+shape.getPoint(k).x;
int j=shape.getTop()+shape.getPoint(k).y;
g.setColor(Color.black);
g.fillRect( bgMatrix.cellDistance *i , bgMatrix.cellDistance *j, bgMatrix.cellWidth, bgMatrix.cellHeight);
}
}
}
Sharp.java
package net.handson.russianBox;
import java.awt.Point;
/** *//**
* 该类用于表示游戏中运动的形状,一个形状可理解为4×4的数组,实际只是由四点表示而成。类中top, left描述形状在背景中的x,y坐标,而point数组中的值则
* 依次表示形状中的四个点相对于形状左上角的偏移量
* @author 汪燕飞
*
*/
public class Shape ...{
public static final int POINT_NUMBER = 4;
private Point point[];
private int top, left;
private int status;
/** *//**
* 随机得到一个形状,形状默认位于背景的顶部中间位置
*/
public Shape()...{
top=0;
left=7;
status=(int)(Shapes.SHAPE_NUMBER*Math.random());
point = Shapes.shapes[status];
}
/** *//**
*
* @param index
* @return 返回相应的index指定的Point值, index应该>=0, <4. Point代表该点相对形状左上角的偏移量
*/
public Point getPoint(int index)...{
return point[index];
}
/** *//**
*
* @return 返回表示形状的四个点
*/
public Point[] getPoints()...{
return point;
}
/** *//**
*
* @return 返回用以表示当前形状的一个状态
*/
public int getStatus()...{
return this.status;
}
/** *//**
* 通过设置status来设置形状
* @param status
*/
public void setStatus(int status)...{
this.status=status;
point = Shapes.shapes[status];
}
/** *//**
* 当前形状往下移动
*/
public void moveDown()...{
top += 1;
}
/** *//**
* 当前形状往左移动
*/
public void moveLeft()...{
left -= 1;
}
/** *//**
* 当前形状往右移动
*/
public void moveRight()...{
left+=1;
}
/** *//**
* 将形状进行旋转
*/
public void rotate()...{
status += 1;
if(status % 4 == 0)...{
status -= 4;
}
point = Shapes.shapes[status];
}
/** *//**
*
* @return 得到当前形状在背景中的x坐标,及最左边的坐标值
*/
public int getLeft() ...{
return left;
}
/** *//**
* 设置当前形状的x值,及最左边的坐标值
* @param left
*/
public void setLeft(int left) ...{
this.left = left;
}
/** *//**
*
* @return 得到当前形状在背景中的y坐标,及最顶上的坐标值
*/
public int getTop() ...{
return top;
}
/** *//**
* 设置当前形状的y值,及最顶部的坐标值
* @param top
*/
public void setTop(int top) ...{
this.top = top;
}
}
/** *//**
* 用来描述所有的形状,在shape类中通过设置status来与具体形状进行关联
* @author smm
* @see Shape
*
*/
interface Shapes ...{
int SHAPE_NUMBER = 20;
Point[][] shapes = new Point[][]...{
// shape 田
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
// shape T
...{new Point(0,1), new Point(1,0), new Point(1,1), new Point(1,2)},
...{new Point(0,0), new Point(1,0), new Point(1,1), new Point(2,0)},
...{new Point(0,0), new Point(0,1), new Point(0,2), new Point(1,1)},
...{new Point(0,1), new Point(1,0), new Point(1,1), new Point(2,1)},
//shape l
...{new Point(0,1), new Point(1,1), new Point(2,1), new Point(3,1)},
...{new Point(1,0), new Point(1,1), new Point(1,2), new Point(1,3)},
...{new Point(0,1), new Point(1,1), new Point(2,1), new Point(3,1)},
...{new Point(1,0), new Point(1,1), new Point(1,2), new Point(1,3)},
//shape L
...{new Point(0,0), new Point(1,0), new Point(2,0), new Point(2,1)},
...{new Point(0,0), new Point(0,1), new Point(0,2), new Point(1,0)},
...{new Point(0,0), new Point(0,1), new Point(1,1), new Point(2,1)},
...{new Point(0,2), new Point(1,0), new Point(1,1), new Point(1,2)},
//shape 7
...{new Point(0,1), new Point(1,1), new Point(2,0), new Point(2,1)},
...{new Point(0,0), new Point(1,0), new Point(1,1), new Point(1,2)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(2,0)},
...{new Point(0,0), new Point(0,1), new Point(0,2), new Point(1,2)},
};
}
import java.awt.Point;
/** *//**
* 该类用于表示游戏中运动的形状,一个形状可理解为4×4的数组,实际只是由四点表示而成。类中top, left描述形状在背景中的x,y坐标,而point数组中的值则
* 依次表示形状中的四个点相对于形状左上角的偏移量
* @author 汪燕飞
*
*/
public class Shape ...{
public static final int POINT_NUMBER = 4;
private Point point[];
private int top, left;
private int status;
/** *//**
* 随机得到一个形状,形状默认位于背景的顶部中间位置
*/
public Shape()...{
top=0;
left=7;
status=(int)(Shapes.SHAPE_NUMBER*Math.random());
point = Shapes.shapes[status];
}
/** *//**
*
* @param index
* @return 返回相应的index指定的Point值, index应该>=0, <4. Point代表该点相对形状左上角的偏移量
*/
public Point getPoint(int index)...{
return point[index];
}
/** *//**
*
* @return 返回表示形状的四个点
*/
public Point[] getPoints()...{
return point;
}
/** *//**
*
* @return 返回用以表示当前形状的一个状态
*/
public int getStatus()...{
return this.status;
}
/** *//**
* 通过设置status来设置形状
* @param status
*/
public void setStatus(int status)...{
this.status=status;
point = Shapes.shapes[status];
}
/** *//**
* 当前形状往下移动
*/
public void moveDown()...{
top += 1;
}
/** *//**
* 当前形状往左移动
*/
public void moveLeft()...{
left -= 1;
}
/** *//**
* 当前形状往右移动
*/
public void moveRight()...{
left+=1;
}
/** *//**
* 将形状进行旋转
*/
public void rotate()...{
status += 1;
if(status % 4 == 0)...{
status -= 4;
}
point = Shapes.shapes[status];
}
/** *//**
*
* @return 得到当前形状在背景中的x坐标,及最左边的坐标值
*/
public int getLeft() ...{
return left;
}
/** *//**
* 设置当前形状的x值,及最左边的坐标值
* @param left
*/
public void setLeft(int left) ...{
this.left = left;
}
/** *//**
*
* @return 得到当前形状在背景中的y坐标,及最顶上的坐标值
*/
public int getTop() ...{
return top;
}
/** *//**
* 设置当前形状的y值,及最顶部的坐标值
* @param top
*/
public void setTop(int top) ...{
this.top = top;
}
}
/** *//**
* 用来描述所有的形状,在shape类中通过设置status来与具体形状进行关联
* @author smm
* @see Shape
*
*/
interface Shapes ...{
int SHAPE_NUMBER = 20;
Point[][] shapes = new Point[][]...{
// shape 田
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(1,1)},
// shape T
...{new Point(0,1), new Point(1,0), new Point(1,1), new Point(1,2)},
...{new Point(0,0), new Point(1,0), new Point(1,1), new Point(2,0)},
...{new Point(0,0), new Point(0,1), new Point(0,2), new Point(1,1)},
...{new Point(0,1), new Point(1,0), new Point(1,1), new Point(2,1)},
//shape l
...{new Point(0,1), new Point(1,1), new Point(2,1), new Point(3,1)},
...{new Point(1,0), new Point(1,1), new Point(1,2), new Point(1,3)},
...{new Point(0,1), new Point(1,1), new Point(2,1), new Point(3,1)},
...{new Point(1,0), new Point(1,1), new Point(1,2), new Point(1,3)},
//shape L
...{new Point(0,0), new Point(1,0), new Point(2,0), new Point(2,1)},
...{new Point(0,0), new Point(0,1), new Point(0,2), new Point(1,0)},
...{new Point(0,0), new Point(0,1), new Point(1,1), new Point(2,1)},
...{new Point(0,2), new Point(1,0), new Point(1,1), new Point(1,2)},
//shape 7
...{new Point(0,1), new Point(1,1), new Point(2,0), new Point(2,1)},
...{new Point(0,0), new Point(1,0), new Point(1,1), new Point(1,2)},
...{new Point(0,0), new Point(0,1), new Point(1,0), new Point(2,0)},
...{new Point(0,0), new Point(0,1), new Point(0,2), new Point(1,2)},
};
}
BackgroundMatrix.java
package net.handson.russianBox;
import java.awt.Point;
public class BackgroundMatrix ...{
public final int ROWS = 20;
public final int COLUMNS = 15;
private int[][] values=new int[ROWS][COLUMNS];
public final int WIDTH=300;
public final int HEIGHT=400;
public final int cellDistance =20;//单元块之间的距离
public final int cellWidth=18 , cellHeight=18;//单元块的宽和高
/** *//**
* 将当前移动的形状合并到背景中,成为背景的一部分
* @param shape
*/
public void mergeShape(Shape shape)...{
int left = shape.getLeft();
int top = shape.getTop();
Point point = null;
for(int i=0; i<Shape.POINT_NUMBER; i++)...{
point = shape.getPoint(i);
values[top + point.y][left + point.x] = 1;
}
}
/** *//**
*
* @return 得到表示背景状态的二维数组,数组元素中1表示该格占用,0表示该格为空
*/
public int[][] getValues()...{
return values;
}
/** *//**
* 背景初始化
*/
public void init()...{
for(int i=0;i<ROWS;i++)...{
for(int j=0;j<COLUMNS;j++)...{
values[i][j]=0;
}
}
}
/** *//**
* 判断当前移动的形状是否跟背景形状有冲突
* @param shape 进行检测是否可以移动的shape
* @return 如果shape跟背景有重叠的地方,则返回true, 否则返回false, 可以用此方法来判断shape是否可以进行移动
*/
public boolean isOverlap(Shape shape)...{
int left = shape.getLeft();
int top = shape.getTop();
Point point = null;
for(int i=0; i<Shape.POINT_NUMBER; i++)...{
point = shape.getPoint(i);
if(left + point.x <0 || left+point.x>COLUMNS-1)...{
return true;
}
if(top + point.y <0 || top+point.y>ROWS-1)...{
return true;
}
if(values[top + point.y][left + point.x] == 1)...{
return true;
}
}
return false;
}
/** *//**
*
* @param shape 需要进行计算的形状
* @return 返回shape中最大的y坐标,该坐标是指相到形状左上角的坐标,而不是在背景中的坐标,在判断当前shape是否可以下移时需要用到
*/
public int getMaxY(Shape shape)...{
int max = 0;
for(int i = 0; i < Shape.POINT_NUMBER; i ++)...{
if(shape.getPoint(i).y > max)...{
max = shape.getPoint(i).y ;
}
}
return max;
}
/** *//**
*
* @param values 需要进行判断的某行的值
* @return 如果该行可以被消除则返回true, 否则返回false
*/
private boolean isRowCancelAble(int values[])...{
for(int i=0; i<COLUMNS; i++)...{
if(values[i]==0)...{
return false;
}
}
return true;
}
/** *//**
* 消除rowIndex表示的行。具体是依次先上一行的值下移,然后将顶行值置为0,
* @param rowIndex
*/
private void clearRow(int rowIndex)...{
for(int y = rowIndex; y >= 1 ; y--)...{
for(int x = 0; x < COLUMNS; x ++)...{
values[y][x] = values[y-1][x];
}
}
//消除最顶上一行
for(int x = 0; x<COLUMNS; x ++)...{
values[0][x] = 0;
}
}
/** *//**
* 当形状不可再下移时,需要将其与当前背景合并,并消除相应的已满足消除条件的行
* @param shape 当前形状
* @return 返回有多少行被消除
*/
public int cancelRows(Shape shape)...{
int rows=0;
for(int i=shape.getTop(); i<=getMaxY(shape)+shape.getTop(); i++)...{
if(! isRowCancelAble(values[i]))...{
continue;
}
clearRow(i);
rows++;
}
return rows;
}
}
import java.awt.Point;
public class BackgroundMatrix ...{
public final int ROWS = 20;
public final int COLUMNS = 15;
private int[][] values=new int[ROWS][COLUMNS];
public final int WIDTH=300;
public final int HEIGHT=400;
public final int cellDistance =20;//单元块之间的距离
public final int cellWidth=18 , cellHeight=18;//单元块的宽和高
/** *//**
* 将当前移动的形状合并到背景中,成为背景的一部分
* @param shape
*/
public void mergeShape(Shape shape)...{
int left = shape.getLeft();
int top = shape.getTop();
Point point = null;
for(int i=0; i<Shape.POINT_NUMBER; i++)...{
point = shape.getPoint(i);
values[top + point.y][left + point.x] = 1;
}
}
/** *//**
*
* @return 得到表示背景状态的二维数组,数组元素中1表示该格占用,0表示该格为空
*/
public int[][] getValues()...{
return values;
}
/** *//**
* 背景初始化
*/
public void init()...{
for(int i=0;i<ROWS;i++)...{
for(int j=0;j<COLUMNS;j++)...{
values[i][j]=0;
}
}
}
/** *//**
* 判断当前移动的形状是否跟背景形状有冲突
* @param shape 进行检测是否可以移动的shape
* @return 如果shape跟背景有重叠的地方,则返回true, 否则返回false, 可以用此方法来判断shape是否可以进行移动
*/
public boolean isOverlap(Shape shape)...{
int left = shape.getLeft();
int top = shape.getTop();
Point point = null;
for(int i=0; i<Shape.POINT_NUMBER; i++)...{
point = shape.getPoint(i);
if(left + point.x <0 || left+point.x>COLUMNS-1)...{
return true;
}
if(top + point.y <0 || top+point.y>ROWS-1)...{
return true;
}
if(values[top + point.y][left + point.x] == 1)...{
return true;
}
}
return false;
}
/** *//**
*
* @param shape 需要进行计算的形状
* @return 返回shape中最大的y坐标,该坐标是指相到形状左上角的坐标,而不是在背景中的坐标,在判断当前shape是否可以下移时需要用到
*/
public int getMaxY(Shape shape)...{
int max = 0;
for(int i = 0; i < Shape.POINT_NUMBER; i ++)...{
if(shape.getPoint(i).y > max)...{
max = shape.getPoint(i).y ;
}
}
return max;
}
/** *//**
*
* @param values 需要进行判断的某行的值
* @return 如果该行可以被消除则返回true, 否则返回false
*/
private boolean isRowCancelAble(int values[])...{
for(int i=0; i<COLUMNS; i++)...{
if(values[i]==0)...{
return false;
}
}
return true;
}
/** *//**
* 消除rowIndex表示的行。具体是依次先上一行的值下移,然后将顶行值置为0,
* @param rowIndex
*/
private void clearRow(int rowIndex)...{
for(int y = rowIndex; y >= 1 ; y--)...{
for(int x = 0; x < COLUMNS; x ++)...{
values[y][x] = values[y-1][x];
}
}
//消除最顶上一行
for(int x = 0; x<COLUMNS; x ++)...{
values[0][x] = 0;
}
}
/** *//**
* 当形状不可再下移时,需要将其与当前背景合并,并消除相应的已满足消除条件的行
* @param shape 当前形状
* @return 返回有多少行被消除
*/
public int cancelRows(Shape shape)...{
int rows=0;
for(int i=shape.getTop(); i<=getMaxY(shape)+shape.getTop(); i++)...{
if(! isRowCancelAble(values[i]))...{
continue;
}
clearRow(i);
rows++;
}
return rows;
}
}
- 我的一位学生设计的俄罗斯方块游戏
- J2ME游戏俄罗斯方块的设计与改良
- 我的俄罗斯方块
- 一个MIDP俄罗斯方块游戏的设计和实现
- 一个MIDP俄罗斯方块游戏的设计和实现 (转)
- 一个MIDP俄罗斯方块游戏的设计和实现
- 俄罗斯方块的设计
- 俄罗斯方块的设计思路
- android游戏开发之我的小小游戏3——俄罗斯方块游戏3
- android游戏开发之我的小小游戏3——俄罗斯方块游戏4
- android游戏开发之我的小小游戏3——俄罗斯方块游戏5
- 大一写的俄罗斯方块游戏
- Qt做的俄罗斯方块游戏
- JS 写的俄罗斯方块游戏
- 俄罗斯方块游戏的shell脚本
- Qt做的俄罗斯方块游戏
- CocosCreater的俄罗斯方块游戏实现
- “俄罗斯方块”游戏设计
- sqldr load 以及extract data 的中文问题--
- [转]Mysql忘记密码解决办法
- 提高ASP.Net应用程序性能的十大方法
- GridView操作Xml数据源(添加、删除、修改)
- SMTP协议
- 我的一位学生设计的俄罗斯方块游戏
- 什么是联机分析处理(OLAP)
- 谷歌收购DoubleClick获批准
- Shell正则表达式 & Grep正则表达式 & shell字符串处理
- Pku acm 1062 昂贵的聘礼 数据结构题目解题报告(七)—单源最短路径:Dijkstra算法
- MyEclipse+Resin3.1.x 实现Web工程自动部署
- 如何防止IE缓存jsp文件
- 学习JAVA推荐的基本书
- 关联、聚合、合成与依赖