(心得二)java俄罗斯方块小游戏编写心得
? ? 在“java俄羅斯方塊小游戲編寫心得01”中已經(jīng)將游戲界面完成,那么接下來就是要讓方塊動起來。
? ? 我們之前在寫Cell類時,曾經(jīng)給每個最基本小方塊定義了三個方法,即左移、右移、下落,而七種方塊皆是由四個最基本小方塊組成,所以我們可以在Tetromino類中定義一個七種方塊自動下落方法,然后在方法中對七種方塊的四個最基本小方塊分別調(diào)最基本小方塊的下落方法,這樣就可以使七種小方塊動起來。左移、右移皆是如此。
代碼如下:
package com.practict;
public class Tetromino {
?? ?protected Cell[] cells=new Cell[4];
?? ?public void moveLeft() {
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?c.Left();
?? ??? ?}
?? ?}
?? ?public void moveRight() {
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?c.right();
?? ??? ?}
?? ?}
?? ?public void softMoveDrop() {
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?c.drop();
?? ??? ?}
?? ?}
}
僅僅這樣還不足以使小方塊動起來,我們需要在程序運行時自動調(diào)用該方法,現(xiàn)在我們想,當(dāng)點開俄羅斯方塊這個游戲時,這個游戲便已經(jīng)開始,由此,我們可以定義一個start()方法,來封裝所有游戲開始后可以進(jìn)行的操作,包括游戲自動進(jìn)行的和認(rèn)為操控的如變形、右移等,然后在主方法中創(chuàng)建完窗體后對該方法進(jìn)行自動調(diào)用,現(xiàn)在,這個小方塊才算動起來了。
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
?? ?public void start(){
?? ??? ?currentOne.softMoveDrop();
?? ?}
?? ?public static void main(String[] args){
?? ??? ?JFrame jf=new JFrame("火拼俄羅斯");
?? ??? ?Tetris tetris=new Tetris();
?? ??? ?jf.add(tetris);
?? ??? ?jf.setVisible(true);
?? ??? ?jf.setSize(535,595);
?? ??? ?jf.setLocationRelativeTo(null);
?? ??? ?jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
?? ??? ?tetris.start();
?? ?}
}
? ? 當(dāng)再次運行,我們發(fā)現(xiàn)他仍然沒有下落,當(dāng)程序運行后,start()方法只調(diào)用了一次,相應(yīng)的,其中currentOne.moveDrop()方法也只調(diào)用了一次,那么如果想讓他動起來,就得使得方法不斷的去自己調(diào)用,所以,此處我們需要一個死循環(huán)來讓系統(tǒng)不斷的自動調(diào)用moveDrop方法
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
?? ?public void start(){
?????? ?while(true){
?????????? ?currentOne.softMoveDrop();
?????? ?}
?? ?}
}
? ? 現(xiàn)在我們再次運行,發(fā)現(xiàn)仍然沒有下落,這是因為雖然面板在啟動時會自動調(diào)用paing(Graphics g)方法,但是也僅僅只是調(diào)用一次,所以系統(tǒng)只畫出了最初的界面的樣子,雖然在后臺我們的方塊在下落,但是面板并沒有將其畫出,那么現(xiàn)在我們就需要一個repaint()方法來重新將游戲界面畫出,那么這樣,我們就可以肉眼看到方塊在下落了
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
?? ?public void start(){
?????? ?while(true){
?????????? ?currentOne.softMoveDrop();
?????????? ?repaint();
?????? ?}
?? ?}
}
? ? 再次運行,發(fā)現(xiàn)界面上竟然沒有了方塊!為什么呢?這涉及到一個系統(tǒng)線程的問題,因為系統(tǒng)的運算速度非常快,所以我們還沒有看到方塊最開始到下落,他就已經(jīng)落到了最下面,直至消失,所以現(xiàn)在我們需要一個小方法來控制系統(tǒng)的運行速度,使其能夠使得我們?nèi)庋劭梢?#xff0c;其中,Thread.sleep()方法中的參數(shù)單位為ms。
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
?? ?public void start(){
?????? ?while(true){
?????????? ?try{
?????????????? ?Thread.sleep(500);
?????????? ?}catch(InterruptedException e){
?????????????? ?e.printStackTrace;
?????????? ?}
?????????? ?currentOne.softMoveDrop();
?????????? ?repaint();
?????? ?}
?? ?}
}
? ? 現(xiàn)在我們再運行后可以發(fā)現(xiàn),方塊已經(jīng)可以開始下落了,但是我們也可以發(fā)現(xiàn)一個問題,方塊無法停留在最下層,那么現(xiàn)在我們就需要一個方法來使方塊當(dāng)下落到最底層后使其停留在最底層,而不是消失在最底層。由此,我們可以定義一個canDrop()方法,當(dāng)滿足此方法時,調(diào)用softMoveDrop()方法,當(dāng)不滿足時,便停留在最底層。我們再來分析,什么情況下不可下落?當(dāng)然是當(dāng)方塊下落到最底層時或者下一層有方塊,那么如何表示?。
注:當(dāng)判斷語句進(jìn)行判斷時,若第一個對象滿足if條件,則余下對象不再進(jìn)行遍歷判斷,所以,這是第一次想到的不可行方法:我們的墻是由一個二維數(shù)組組成的,公有20行20列,換句話說,就是當(dāng)小方塊的行屬性小于19時,是可以下落的,那么我們就可以對最CurrentOne方塊的每個最基本小方塊的行屬性進(jìn)行遍歷,當(dāng)小于19時,可以下落。
更:當(dāng)某方塊的row+1行的col列有方塊時,或者行數(shù)等于19時是不可下落的。
代碼如下:?
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
public boolean canDrop() {
?? ??? ?Cell[] cells=currentOne.cells;
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?int row=c.getRow();
?? ??? ??? ?int col=c.getCol();
?? ??? ??? ?if(row==19) {
?? ??? ??? ??? ?return false;
?? ??? ??? ?}
?? ??? ??? ?if(wall[row+1][col]!=null) {
?? ??? ??? ??? ?return false;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return true;
?? ?}
? ? 現(xiàn)在方塊已經(jīng)可以停留在最底層,可是實際上小方塊并未真正落到界面內(nèi),如果要做到方塊真正的嵌入墻內(nèi),就要讓該方塊將墻填滿,所以現(xiàn)在需要一個langToWall()方法來實現(xiàn)該功能。
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
public void landToWall() {
?? ??? ?Cell[] cells=currentOne.cells;
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?int row=c.getRow();
?? ??? ??? ?int col=c.getCol();
?? ??? ??? ?wall[row][col]=c;
?? ??? ?}
?? ?}
}
? ? 現(xiàn)在呢,游戲已經(jīng)有一點小小的效果了,那么我們現(xiàn)在需要人和游戲進(jìn)行交互,也就是通過鍵盤來對方塊進(jìn)行操控,怎樣進(jìn)行操控呢,對鍵盤進(jìn)行監(jiān)聽,創(chuàng)建監(jiān)聽器及適配器后將其添加到游戲面板上,之后我們再想,如果桌面上當(dāng)前打開了多個頁面,那監(jiān)聽程序究竟監(jiān)聽哪一個?所以我們需要加入一個requestFocus()方法來確定當(dāng)當(dāng)前界面獲取焦點后才進(jìn)行監(jiān)聽游戲界面。
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
public void start() {
?? ??? ?KeyListener l=new KeyAdapter() {
?? ??? ??? ?public void keyPressed(KeyEvent e) {
?? ??? ??? ??? ?int code=e.getKeyCode();
?? ??? ??? ??? ?switch(code) {
?? ??? ??? ??? ?case KeyEvent.VK_LEFT:
?? ??? ??? ??? ??? ?currentOne.moveLeft();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?case KeyEvent.VK_RIGHT:
?? ??? ??? ??? ??? ?currentOne.moveRight();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?case KeyEvent.VK_DOWN:
?? ??? ??? ??? ??? ?currentOne.moveDrop();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?repaint();
?? ??? ??? ?}
?? ??? ?};
?? ??? ?this.addKeyListener(l);
?? ??? ?this.requestFocus();
}
? ? 此時,我們再次運行可以看到已經(jīng)可以左右移動了,但是如果移動出界的話會拋出異常,同時方塊停止下落,所以我們現(xiàn)在需要就好像方塊停在最底層一樣的方法來判斷是否處于邊界,如果處于邊界的話我們應(yīng)該阻止方塊繼續(xù)向該方向移動,同樣,如果該方塊的左邊位置或者右邊位置在移動前已經(jīng)有方塊在該位置,我們也應(yīng)該阻止方塊的繼續(xù)移動,所以我們應(yīng)該封裝兩個方法,判斷出界方法outOfBounds()和coincident()方法。
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
?? ??? ?public boolean outOfBounds() {
?? ??? ?Cell[] cells=currentOne.cells;
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?int col=c.getCol();
?? ??? ??? ?int row=c.getRow();
?? ??? ??? ?if(col<0||col>9||row<0||row>19) {
?? ??? ??? ??? ?return true;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return false;
?? ?}
?? ?public boolean coincident() {
?? ??? ?Cell[] cells=currentOne.cells;
?? ??? ?for(Cell c:cells) {
?? ??? ??? ?int row=c.getRow();
?? ??? ??? ?int col=c.getCol();
?? ??? ??? ?if(wall[row][col]!=null) {
?? ??? ??? ??? ?return true;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return false;
?? ?}
? ? 現(xiàn)在我們可以在監(jiān)聽器中加入這兩個判斷語句來實現(xiàn)越界及重合判斷,與其加入到監(jiān)聽器中,不如直接生成一個左移右移等的方法,在此方法中進(jìn)行該判斷,監(jiān)聽器中就只調(diào)用該方法,此種做法可以使代碼更加簡潔明了。在下面代碼所示中,有兩個下落的方法一個是軟下落,一個是硬下落,什么是軟下落,就是當(dāng)我們在按下鍵時方塊會加快下落的速度,當(dāng)我們松開下鍵時,方塊會恢復(fù)到自動下落的狀態(tài),硬下落是當(dāng)我們按空格鍵時(我將硬下落的鍵設(shè)置為空格),方塊會直接下落到底部。
代碼如下:
package com.practict;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
? ? public void start() {
?? ??? ?KeyListener l=new KeyAdapter() {
?? ??? ??? ?public void keyPressed(KeyEvent e) {
?? ??? ??? ??? ?int code=e.getKeyCode();
?? ??? ??? ??? ?switch(code) {
?? ??? ??? ??? ?case KeyEvent.VK_LEFT:
?? ??? ??? ??? ??? ?moveLeftAction();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?case KeyEvent.VK_RIGHT:
?? ??? ??? ??? ??? ?moveRightAction();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?case KeyEvent.VK_DOWN:
?? ??? ??? ??? ??? ?softMoveDropAction();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?case KeyEvent.VK_SPACE:
?? ??? ??? ??? ??? ?hardMoveDropAction();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?repaint();
?? ??? ??? ?}
?? ??? ?};
?? ??? ?this.addKeyListener(l);
?? ??? ?this.requestFocus();
}
? ? public void moveLeftAction() {
?? ??? ?currentOne.moveLeft();
?? ??? ?if(outOfBounds()||coincident()) {
?? ??? ??? ?currentOne.moveRight();
?? ??? ?}
?? ?}
?? ?public void moveRightAction() {
?? ??? ?currentOne.moveRight();
?? ??? ?if(outOfBounds()||coincident()) {
?? ??? ??? ?currentOne.moveLeft();
?? ??? ?}
?? ?}
?? ?public void softMoveDropAction() {
?? ??? ?if(canDrop()) {
?? ??? ??? ?currentOne.moveDrop();
?? ??? ?}else {
?? ??? ??? ?landToWall();
?? ??? ??? ?currentOne=nextOne;
?? ??? ??? ?nextOne=Tetromino.RandomeOne();
?? ??? ?}
?? ?}
?? ?public void hardMoveDropAction() {
?? ??? ?while(canDrop()) {
?? ??? ??? ?currentOne.moveDrop();
?? ??? ?}
?? ??? ?landToWall();
?? ??? ?currentOne=nextOne;
?? ??? ?nextOne=Tetromino.RandomeOne();
?? ?}
? ? 現(xiàn)在,我們再次移動方塊時不僅左右移動不會出界,還增加了兩項功能,軟下落和硬下落,現(xiàn)在的游戲已經(jīng)開始有點意思了,那我們現(xiàn)在需要干什么?我們知道,方塊不僅僅只有一種形態(tài),他們都是可以變形的,或者有兩種形態(tài),或者四種,現(xiàn)在,我們需要將這四種狀態(tài)寫出來。如何去寫,我們可以可以先在Tetromino類中寫一個State內(nèi)部類,來表示狀態(tài),之后在Tetromino類中定義一個狀態(tài)數(shù)組,因為七個方塊的狀態(tài)是不相同的,所以我們需要分別在七個方塊的類中定義該方塊的四種狀態(tài)。
代碼如下:
package com.practict;
public class Tetromino {
?? ?protected State[] states;
?? ?public class State{
?? ??? ?protected int row0,col0,row1,col1,row2,col2,row3,col3;
?? ??? ?public State() {}
?? ??? ?public State(int row0, int col0, int row1, int col1, int row2, int col2, int row3, int col3) {
?? ??? ??? ?super();
?? ??? ??? ?this.row0 = row0;
?? ??? ??? ?this.col0 = col0;
?? ??? ??? ?this.row1 = row1;
?? ??? ??? ?this.col1 = col1;
?? ??? ??? ?this.row2 = row2;
?? ??? ??? ?this.col2 = col2;
?? ??? ??? ?this.row3 = row3;
?? ??? ??? ?this.col3 = col3;
?? ??? ?}
?? ??? ?public int getRow0() {
?? ??? ??? ?return row0;
?? ??? ?}
?? ??? ?public void setRow0(int row0) {
?? ??? ??? ?this.row0 = row0;
?? ??? ?}
?? ??? ?public int getCol0() {
?? ??? ??? ?return col0;
?? ??? ?}
?? ??? ?public void setCol0(int col0) {
?? ??? ??? ?this.col0 = col0;
?? ??? ?}
?? ??? ?public int getRow1() {
?? ??? ??? ?return row1;
?? ??? ?}
?? ??? ?public void setRow1(int row1) {
?? ??? ??? ?this.row1 = row1;
?? ??? ?}
?? ??? ?public int getCol1() {
?? ??? ??? ?return col1;
?? ??? ?}
?? ??? ?public void setCol1(int col1) {
?? ??? ??? ?this.col1 = col1;
?? ??? ?}
?? ??? ?public int getRow2() {
?? ??? ??? ?return row2;
?? ??? ?}
?? ??? ?public void setRow2(int row2) {
?? ??? ??? ?this.row2 = row2;
?? ??? ?}
?? ??? ?public int getCol2() {
?? ??? ??? ?return col2;
?? ??? ?}
?? ??? ?public void setCol2(int col2) {
?? ??? ??? ?this.col2 = col2;
?? ??? ?}
?? ??? ?public int getRow3() {
?? ??? ??? ?return row3;
?? ??? ?}
?? ??? ?public void setRow3(int row3) {
?? ??? ??? ?this.row3 = row3;
?? ??? ?}
?? ??? ?public int getCol3() {
?? ??? ??? ?return col3;
?? ??? ?}
?? ??? ?public void setCol3(int col3) {
?? ??? ??? ?this.col3 = col3;
?? ??? ?}
?? ??? ?public String toString() {
?? ??? ??? ?return "state [row0=" + row0 + ", col0=" + col0 + ", row1=" + row1 + ", col1=" + col1 + ", row2=" + row2
?? ??? ??? ??? ??? ?+ ", col2=" + col2 + ", row3=" + row3 + ", col3=" + col3 + "]";
?? ??? ?}
?? ?}
}
? ? 現(xiàn)在狀態(tài)類定義好了,接下來我們就在每個方塊類中定義該方塊的狀態(tài),當(dāng)我們旋轉(zhuǎn)方塊時,我們都需要有一個軸,而根據(jù)我們“java俄羅斯方塊小游戲編寫心得01”中的圖,我們可以以第0塊基本小方塊為軸進(jìn)行旋轉(zhuǎn),即第0塊的行列均為0,其他基本小方塊的行列均在此基礎(chǔ)上進(jìn)行書寫,有幾個狀態(tài)就寫new幾個State類的對象,依據(jù)State類的構(gòu)造方法,在row,col,row1,col1,row2,col2,row3,col3上寫對應(yīng)的狀態(tài)的形狀的行列。
代碼如下:
package com.CSDN;
public class I extends Tetromino{
?? ?public I() {
?? ??? ?states=new State[2];
?? ??? ?states[0]=new State(0,0,0,-1,0,1,0,2);
?? ??? ?states[1]=new State(0,0,-1,0,1,0,2,0);
?? ?}
}
package com.CSDN;
public class J extends Tetromino {
?? ?public J() {
?? ??? ?cells[0]=new Cell(0,4,Tetris.J);
?? ??? ?cells[1]=new Cell(0,3,Tetris.J);
?? ??? ?cells[2]=new Cell(0,5,Tetris.J);
?? ??? ?cells[3]=new Cell(1,5,Tetris.J);
?? ??? ?states=new State[4];
?? ??? ?states[0]=new State(0,0,0,-1,0,1,1,1);
?? ??? ?states[1]=new State(0,0,-1,0,1,0,1,-1);
?? ??? ?states[2]=new State(0,0,0,1,0,-1,-1,-1);
?? ??? ?states[3]=new State(0,0,1,0,-1,0,-1,1);
?? ?}
}
package com.CSDN;
public class L extends Tetromino {
?? ?public L() {
?? ??? ?cells[0]=new Cell(0,4,Tetris.L);
?? ??? ?cells[1]=new Cell(0,3,Tetris.L);
?? ??? ?cells[2]=new Cell(0,5,Tetris.L);
?? ??? ?cells[3]=new Cell(1,3,Tetris.L);
?? ??? ?states=new State[4];
?? ??? ?states[0]=new State(0,0,0,-1,0,1,1,-1);
?? ??? ?states[1]=new State(0,0,-1,0,1,0,-1,-1);
?? ??? ?states[2]=new State(0,0,0,1,0,-1,-1,1);
?? ??? ?states[3]=new State(0,0,1,0,-1,0,1,1);
?? ?}
}
package com.CSDN;
public class O extends Tetromino {
?? ?public O() {
?? ??? ?cells[0]=new Cell(0,4,Tetris.O);
?? ??? ?cells[1]=new Cell(0,5,Tetris.O);
?? ??? ?cells[2]=new Cell(1,4,Tetris.O);
?? ??? ?cells[3]=new Cell(1,5,Tetris.O);
?? ??? ?states=new State[1];
?? ??? ?states[0]=new State(0,0,0,1,1,0,1,1);
?? ?}
}
package com.CSDN;
public class S extends Tetromino{
?? ?public S() {
?? ??? ?cells[0]=new Cell(0,4,Tetris.S);
?? ??? ?cells[1]=new Cell(0,5,Tetris.S);
?? ??? ?cells[2]=new Cell(1,3,Tetris.S);
?? ??? ?cells[3]=new Cell(1,4,Tetris.S);
?? ??? ?states=new State[4];
?? ??? ?states[0]=new State(0,0,0,1,1,-1,1,0);
?? ??? ?states[1]=new State(0,0,1,0,-1,-1,0,-1);
?? ??? ?states[2]=new State(0,0,0,-1,-1,1,-1,0);
?? ??? ?states[3]=new State(0,0,-1,0,1,1,0,1);
?? ?}
}
package com.CSDN;
public class T extends Tetromino{
?? ?public T() {
?? ??? ?cells[0]=new Cell(0,4,Tetris.T);
?? ??? ?cells[1]=new Cell(0,3,Tetris.T);
?? ??? ?cells[2]=new Cell(0,5,Tetris.T);
?? ??? ?cells[3]=new Cell(1,4,Tetris.T);
?? ??? ?states=new State[4];
?? ??? ?states[0]=new State(0,0,0,-1,0,1,1,0);
?? ??? ?states[1]=new State(0,0,-1,0,1,0,0,-1);
?? ??? ?states[2]=new State(0,0,0,1,0,-1,-1,0);
?? ??? ?states[3]=new State(0,0,1,0,-1,0,0,1);
?? ?}
}
package com.CSDN;
public class Z extends Tetromino {
?? ?public Z() {
?? ??? ?cells[0]=new Cell(1,4,Tetris.Z);
?? ??? ?cells[1]=new Cell(0,3,Tetris.Z);
?? ??? ?cells[2]=new Cell(0,4,Tetris.Z);
?? ??? ?cells[3]=new Cell(1,5,Tetris.Z);
?? ??? ?states=new State[4];
?? ??? ?states[0]=new State(0,0,-1,-1,-1,0,0,1);
?? ??? ?states[1]=new State(0,0,-1,1,0,1,1,0);
?? ??? ?states[2]=new State(0,0,1,1,1,0,0,-1);
?? ??? ?states[3]=new State(0,0,-1,-1,0,-1,-1,0);
?? ?}
}
? ? 現(xiàn)在各個方塊的狀態(tài)已經(jīng)定義完成,我們在按上鍵時方塊會旋轉(zhuǎn),可是怎么旋轉(zhuǎn)?我們僅僅有了狀態(tài),而狀態(tài)僅僅是相對于第0塊基本小方塊的相對位置,并不是真正的行列,所以我們需要一個方法來得出小方塊變化后的行列位置,即變化后小方塊的各個基本小方塊的行列,也可以說是定義一個小方塊旋轉(zhuǎn)的方法,我們現(xiàn)在思考這樣一個問題,當(dāng)我們的小方塊在邊界時,我們是不是也有可能會旋轉(zhuǎn)出界,從而引發(fā)數(shù)組下標(biāo)越界異常呢?答案是當(dāng)然會,所以我們效仿之前判斷越界的方法,我們每一次按上鍵都是向右旋轉(zhuǎn),當(dāng)我們在邊界發(fā)現(xiàn)越界時,我們可以使其向左旋轉(zhuǎn),這樣就避免了出現(xiàn)異常,所以我們不光需要一個向右旋轉(zhuǎn)的方法,我們還需要一個向左旋轉(zhuǎn)的方法。
代碼如下:
package com.CSDN;
public class Tetromino {
?? ?protected Cell[] cells=new Cell[4];
?? ?private int count=100000;
?? ?public void rotateRight() {
?? ??? ?count++;
?? ??? ?State s=states[count%states.length];
?? ??? ?Cell c=cells[0];
?? ??? ?int row=c.getRow();
?? ??? ?int col=c.getCol();
?? ??? ?cells[1].setRow(row+s.row1);
?? ??? ?cells[1].setCol(row+s.col1);
?? ??? ?cells[2].setRow(row+s.row2);
?? ??? ?cells[2].setCol(row+s.col2);
?? ??? ?cells[3].setRow(row+s.row3);
?? ??? ?cells[3].setCol(row+s.col3);
?? ?}
?? ?public void rotateLeft() {
?? ??? ?count--;
?? ??? ?State s=states[count%states.length];
?? ??? ?Cell c=cells[0];
?? ??? ?int row=c.getRow();
?? ??? ?int col=c.getCol();
?? ??? ?cells[1].setRow(row+s.row1);
?? ??? ?cells[1].setCol(col+s.col1);
?? ??? ?cells[2].setRow(row+s.row2);
?? ??? ?cells[2].setCol(col+s.col2);
?? ??? ?cells[3].setRow(row+s.row3);
?? ??? ?cells[3].setCol(col+s.col3);
?? ?}
}
? ? 此時,我們的方法都封裝好,那么接下來我們所需要做的就是在主類中去調(diào)用它實現(xiàn)對游戲的操控。
代碼如下:
package com.CSDN;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JPanel{
?? ?public void start() {
?? ??? ?KeyListener l=new KeyAdapter() {
?? ??? ??? ?public void keyPressed(KeyEvent e) {
?? ??? ??? ??? ?int code=e.getKeyCode();
?? ??? ??? ??? ?switch(code) {
?? ??? ??? ??? ??? ?case KeyEvent.VK_UP:
?? ??? ??? ??? ??? ?rotateAction();
?? ??? ??? ??? ??? ?break;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?repaint();
?? ??? ??? ?}
?? ??? ?};
?? ??? ?this.addKeyListener(l);
?? ??? ?this.requestFocus();
?? ?}
?? ??? ?public void rotateAction() {
?? ??? ?currentOne.rotateRight();
?? ??? ?if(outOfBounds()||coincident()) {
?? ??? ??? ?currentOne.rotateLeft();
?? ??? ?}
?? ?}
}
? ? 現(xiàn)在我們再運行代碼,基本的左右移動,上變形,即軟硬下落都可以使用,都已經(jīng)進(jìn)行了實現(xiàn),游戲也已經(jīng)開發(fā)到了2/3,余下的開發(fā)會在java俄羅斯方塊小游戲編寫心得03中繼續(xù)演示。
總結(jié)
以上是生活随笔為你收集整理的(心得二)java俄罗斯方块小游戏编写心得的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 值得注意的ibatis动态sql语法格式
- 下一篇: 微擎本地服务器站点注册,微擎站点添加了多