2013-12-01 4 views
1

У меня проблемы с Тетрисом. Поэтому, прежде всего, у меня есть класс Shape, а затем подклассы Shape для каждого типа фигуры. Это как форма подкласс выглядит следующим образом:Ошибка вращения Java Tetris

public class SquareShape extends Shape { 
    public SquareShape(){ 
     coords = squareShapeCoords; 
     shape = SQUARESHAPE; 
    } 
} 

В классе Shape У меня есть метод поворота следующим образом:

protected void setX(int i, int x) { coords[i][0] = x; } 
protected void setY(int i, int y) { coords[i][1] = y; } 
public int x(int i) { return coords[i][0]; } 
public int y(int i) { return coords[i][1]; } 

public Shape rotate(){ 
     if (this.getShape().equals(SQUARESHAPE)) return this; 
     Shape newShape = new Shape(); 
     newShape.shape = this.shape; 
     for (int i = 0; i < 4; i++) { 
      newShape.setX(i, y(i)); 
      newShape.setY(i, -x(i)); 
     } 
     return newShape; 
} 

Обратите внимание, что я храню координаты каждой формы в 2D-массивов. Кроме того, это мой игровой движок класса:

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class GameEngine extends JPanel implements ActionListener{ 

    private final int HEIGHT = 15; 
    private final int WIDTH = 10; 
    private int score; 
    int coordX = 0; 
    int coordY = 0; 
    Timer timer; 
    boolean isFinishedFalling = false; 
    boolean isRunning = false; 
    boolean isPaused = false; 
    Shape block; 
    String[] shapes; 


    public GameEngine(){ 
     setFocusable(true); 
     block = new Shape(); 
     timer = new Timer(600, this); 
     timer.start(); 
     addMouseListener(new MAdapter()); 
     addMouseWheelListener(new WheelAdapter()); 
     addKeyListener(new KAdapter()); 
     setBackground(Color.BLACK); 
     shapes = new String[WIDTH * HEIGHT]; 
     clearShapes(); 
    } 

    int squareWidth() { return (int) getSize().getWidth()/WIDTH; } 
    int squareHeight() { return (int) getSize().getHeight()/HEIGHT; } 
    String shapeAt(int x, int y) { return shapes[(y * WIDTH) + x]; } 
    public int getScore() {return score;} 

    public void actionPerformed(ActionEvent e){ 
     if(isFinishedFalling){ 
      isFinishedFalling = false; 
      newBlock(); 
     } else moveDown(); 
    } 

    private boolean move(Shape newShape, int newCoordX, int newCoordY) 
    { 
     for (int i = 0; i < 4; ++i) { 
      int x = newCoordX + newShape.x(i); 
      int y = newCoordY - newShape.y(i); 
      if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return false; 
      if (!shapeAt(x, y).equals(Shape.DEFAULTSHAPE)) return false; 
     } 

     block = newShape; 
     coordX = newCoordX; 
     coordY = newCoordY; 
     repaint(); 
     return true; 
    } 

    private boolean moveLeft() { return move(block, coordX-1, coordY);} 
    private boolean moveRight() { return move(block, coordX+1, coordY);} 
    private boolean moveDown(){ 
     if(!move(block, coordX, coordY-1)){ 
      blockIsDown(); 
      return false; 
     } else return true; 
    } 

    private void dropDown(){ 
     int y = coordY; 
     while(y>0){ 
      if(!move(block, coordX, y-1)) break; 
      y -= 1; 
     } 
     blockIsDown(); 
    } 

    private boolean rotate() { return move(block.rotate(), coordX, coordY);} 

    private void blockIsDown(){ 
     for(int i=0; i<4; i++){ 
      int a = coordX + block.x(i); 
      int b = coordY - block.y(i); 
      shapes[b * WIDTH + a] = block.getShape(); 
     } 
     clearFullLines(); 
     if(!isFinishedFalling) newBlock(); 
    } 

    private void clearFullLines(){ 
     int fullLines = 0; 
     for(int i = HEIGHT-1; i>=0; i--){ 
      boolean lineFull = true; 
      for(int j=0; j<WIDTH; j++){ 
       if(shapeAt(j, i).equals(Shape.DEFAULTSHAPE)){ 
        lineFull = false; 
        break; 
       } 
      } 
      if(lineFull){ 
       fullLines++; 
       for(int m=i; m<HEIGHT-1; m++){ 
        for(int n=0; n<WIDTH; n++) 
         shapes[(m*WIDTH) + n] = shapeAt(n, m+1); 
       } 
      } 
     } 
     if(fullLines>0){ 
      score += fullLines*100; 
      isFinishedFalling = true; 
      block.setShape(Shape.DEFAULTSHAPE); 
      repaint(); 
     } 

    } 

    private void newBlock() 
    { 
     block = new RandomShape(); 
     coordX = WIDTH/2 + 1; 
     coordY = HEIGHT - 1 + block.minY(); 

     if (!move(block, coordX, coordY)) { 
      block.setShape(Shape.DEFAULTSHAPE); 
      timer.stop(); 
      isRunning = false; 
     } 
    } 

    private void clearShapes(){ 
     for(int i=0; i< WIDTH * HEIGHT; i++) shapes[i] = Shape.DEFAULTSHAPE; 
    } 

    private void drawSquare(Graphics g, int x, int y, String shape){ 
     Color color = Color.BLACK; 
     if(shape.equals(Shape.ZSHAPE)) color = Color.GREEN; 
     if(shape.equals(Shape.SSHAPE)) color = Color.RED; 
     if(shape.equals(Shape.LINESHAPE)) color = Color.CYAN; 
     if(shape.equals(Shape.TSHAPE)) color = Color.BLUE; 
     if(shape.equals(Shape.SQUARESHAPE)) color = Color.YELLOW; 
     if(shape.equals(Shape.LSHAPE)) color = Color.MAGENTA; 
     if(shape.equals(Shape.MIRROREDLSHAPE)) color = Color.ORANGE; 

     g.setColor(color); 
     g.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2); 
     g.setColor(color.brighter()); 
     g.drawLine(x, y + squareHeight() - 1, x, y); 
     g.drawLine(x, y, x + squareWidth() - 1, y); 

     g.setColor(color.darker()); 
     g.drawLine(x + 1, y + squareHeight() - 1, x + squareWidth() - 1, y + squareHeight() - 1); 
     g.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, x + squareWidth() - 1, y + 1); 
    } 

    public void paint(Graphics g){ 
     super.paint(g); 
     Dimension size = getSize(); 
     int top = (int) size.getHeight() - HEIGHT * squareHeight(); 
     for(int i=0; i<HEIGHT; i++){ 
      for(int j=0; j<WIDTH; j++){ 
       String s = shapeAt(j, HEIGHT-i-1); 
       if(!s.equals(Shape.DEFAULTSHAPE)) 
        drawSquare(g, j * squareWidth(), top + i * squareHeight(), s); 
      } 
     } 
     if(!block.getShape().equals(Shape.DEFAULTSHAPE)){ 
      for(int i=0; i<4; i++){ 
       int x = coordX + block.x(i); 
       int y = coordY - block.y(i); 
       drawSquare(g, x * squareWidth(), top + (HEIGHT - y - 1) * squareHeight(), block.getShape()); 
      } 
     } 
    } 

    public void start(){ 
     if(isPaused) return; 
     isRunning = true; 
     isFinishedFalling = false; 
     score = 0; 
     clearShapes(); 
     newBlock(); 
     timer.start(); 
    } 

    private void pause(){ 
     if(!isRunning) return; 
     isPaused = !isPaused; 
     if(isPaused){ 
      timer.stop(); 

     } else{ 
      timer.start(); 

     } 
     repaint(); 
    } 

    class MAdapter extends MouseAdapter{ 
     public void mouseClicked(MouseEvent e){ 
      if (!isRunning || block.getShape().equals(Shape.DEFAULTSHAPE) || isPaused) return; 
      int buttonPressed = e.getButton(); 
      if(buttonPressed == MouseEvent.BUTTON1) moveLeft(); 
      if(buttonPressed == MouseEvent.BUTTON2) rotate(); 
      if(buttonPressed == MouseEvent.BUTTON3) moveRight(); 
     } 
    } 

    class WheelAdapter implements MouseWheelListener{ 
     public void mouseWheelMoved(MouseWheelEvent e){ 
      if (!isRunning || block.getShape().equals(Shape.DEFAULTSHAPE) || isPaused) return; 
      int wheelRotation = e.getWheelRotation(); 
      if(wheelRotation == 1) moveDown(); 
      if(wheelRotation == -1) dropDown(); 
     } 
    } 

    class KAdapter extends KeyAdapter{ 
     public void keyPressed(KeyEvent e){ 
      if (!isRunning || block.getShape().equals(Shape.DEFAULTSHAPE) || isPaused) return; 
      int key = e.getKeyCode(); 
      if(key == KeyEvent.VK_SPACE) pause(); 
     } 
    } 
} 

Моя проблема заключается в следующем: Когда я пытаюсь повернуть блоки, он хорошо работает в первый раз, но это портит полностью, если я пытаюсь повернуть их в второй раз.

Это должно быть моя линия форма:

line

И это моя L форма (желтая):

l

Обратите внимание, что это не просто графическая ошибка, игра рассматривает элементы как один квадрат, или два соответственно. Я искал несколько часов в своем коде, чтобы понять, в чем проблема, но мне не повезло. Любая помощь была бы оценена

+0

вы должны сделать поле цвета для каждой формы вместо серии, если заявления – vandale

+2

Вам не нужно метод вращения, просто скопируйте конфигурацию каждой части в статическом массиве. Это 4 массива для куска. – Fernando

ответ

0

Извлеките метод поворота, добавьте жестко закодированный массив вращения каждой формы и все 4 оборота. Первый индекс должен быть индекс вращения (0-3)

затем добавить переменную-член в форме базового класса и изменить вращение на что-то вроде:

public void rotate(Boolean rotateRight) { 
    if (rotateRight) { 
    rotation++; 
    else { 
    rotation--; 
    } 
    if (rotation < 0) { 
    rotation = 3; 
    } 
    if (rotation > 3) { 
    rotation = 0; 
    } 
} 

Затем сделать некоторые новые функции, как

public int[][] getCurrentRotation() { 
    return shapeMatrix[rotation]; 
} 

и использовать эту ИНТ [] [] (или INT [], если вы хотите, чтобы сгладить массив), чтобы сделать соответствующие квадраты

2

Спасибо за ответы, но после дальнейшего расследования, Я узнал, в чем проблема. Проблемы была с циклическим сдвигом методом:

public Shape rotate(){ 
     if (this.getShape().equals(SQUARESHAPE)) return this; 
     Shape newShape = new Shape(); 
     newShape.shape = this.shape; 
     for (int i = 0; i < 4; i++) { 
      newShape.setX(i, -y(i)); 
      newShape.setY(i, x(i)); 
     } 
     return newShape; 
} 

я добавил к адаптеру мыши следующий код, чтобы увидеть, что происходит с координатами текущего блока:

if(buttonPressed == MouseEvent.BUTTON2) { 
       System.out.println(Arrays.deepToString(block.getCoords())); 
       rotate(); 
      } 

Это выход для SShape:

[[0, -1], [0, 0], [1, 0], [1, 1]] 
[[1, 0], [0, 0], [0, 1], [-1, 1]] 
[[0, 0], [0, 0], [-1, -1], [-1, -1]] 
[[0, 0], [0, 0], [1, 1], [1, 1]] 
[[0, 0], [0, 0], [-1, -1], [-1, -1]] 
[[0, 0], [0, 0], [1, 1], [1, 1]] 
[[0, 0], [0, 0], [-1, -1], [-1, -1]] 

Первая строка содержит исходные координаты, которые я дал для SShape. Вторая строка содержит модифицированные координаты после метода rotate(). Как вы можете видеть, X принимает значение -Y, а Y принимает значение X. В третьей строке, однако, X принимает значение -Y, но Y принимает обновленное значение X вместо предыдущего, так что X = Y из третьей строки и далее.Чтобы решить эту проблему, я сделал массив для хранения значений X перед обновлением его следующим образом:

public Shape rotate(){ 
     if (this.getShape().equals(SQUARESHAPE)) return this; 
     Shape newShape = new Shape(); 
     newShape.shape = this.shape; 
     int[] oldX = {this.x(0), this.x(1), this.x(2), this.x(3)}; 
     for (int i = 0; i < 4; i++) { 
      newShape.setX(i, -y(i)); 
      newShape.setY(i, oldX[i]); 
     } 
     return newShape; 
} 
+0

+1 для поиска и публикации результатов. –

Смежные вопросы