Java俄罗斯方块旋转错误
我对俄罗斯方块有些问题。首先,我有一个类Shape,然后是每个Shape类型的Shape子类。这是形状子类的外观:Java俄罗斯方块旋转错误,java,swing,debugging,rotation,tetris,Java,Swing,Debugging,Rotation,Tetris,我对俄罗斯方块有些问题。首先,我有一个类Shape,然后是每个Shape类型的Shape子类。这是形状子类的外观: public class SquareShape extends Shape { public SquareShape(){ coords = squareShapeCoords; shape = SQUARESHAPE; } } 在Shape类中,我有一个旋转方法,如下所示: protected void setX(int i,
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;
}
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;
}
protectedvoidsetx(inti,intx){coords[i][0]=x;}
受保护的void setY(inti,inty){coords[i][1]=y;}
公共整数x(整数i){返回坐标[i][0];}
公共整数y(整数i){返回坐标[i][1];}
公共形状旋转(){
如果(this.getShape().equals(SQUARESHAPE))返回该值;
形状newShape=新形状();
newShape.shape=this.shape;
对于(int i=0;i<4;i++){
新闻形态setX(i,y(i));
新闻形态setY(i,-x(i));
}
返回新闻形状;
}
请注意,我将每个形状的坐标存储在二维数组中。
另外,这是我的游戏引擎类:
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();
}
}
}
import javax.swing.*;
导入java.awt.*;
导入java.awt.event.*;
公共类GameEngine扩展JPanel实现ActionListener{
私人最终内部高度=15;
私有最终整数宽度=10;
个人智力得分;
int-coordX=0;
int-coordY=0;
定时器;
布尔值isFinishedFalling=false;
布尔值isRunning=false;
布尔值isPaused=false;
形状块;
字符串[]形状;
公共游戏引擎(){
设置聚焦(真);
块=新形状();
定时器=新定时器(600,此);
timer.start();
addMouseListener(新MAdapter());
addMouseWheelListener(新的WheelAdapter());
addKeyListener(新的KAdapter());
挫折背景(颜色:黑色);
形状=新字符串[宽度*高度];
透明形状();
}
int squareWidth(){return(int)getSize().getWidth()/WIDTH;}
int squareHeight(){return(int)getSize().getHeight()/HEIGHT;}
字符串shapeAt(intx,inty){returnshapes[(y*WIDTH)+x];}
public int getScore(){return score;}
已执行的公共无效操作(操作事件e){
如果(已完成校准){
isFinishedFalling=错误;
纽布洛克();
}else向下移动();
}
私有布尔移动(形状新形状、int-newCoordX、int-newCoordY)
{
对于(int i=0;i<4;++i){
int x=newCoordX+newShape.x(i);
int y=newCoordY-newShape.y(i);
如果(x<0 | | x>=宽度| | y<0 | | y>=高度)返回false;
如果(!shapeAt(x,y).equals(Shape.DEFAULTSHAPE))返回false;
}
块=新闻形状;
coordX=newCoordX;
coordY=新coordY;
重新油漆();
返回true;
}
私有布尔moveLeft(){返回move(block,coordX-1,coordY);}
私有布尔moveRight(){return move(block,coordX+1,coordY);}
私有布尔moveDown(){
如果(!移动(块,坐标x,坐标-1)){
blockIsDown();
返回false;
}否则返回true;
}
私有无效下拉列表(){
int y=坐标;
而(y>0){
如果(!move(block,coordX,y-1))中断;
y-=1;
}
blockIsDown();
}
私有布尔旋转(){返回移动(block.rotate(),coordX,coordY);}
私有void blockIsDown(){
对于(int i=0;i=0;i--){
布尔lineFull=true;
对于(int j=0;j删除旋转方法,为每个形状和所有4个旋转添加硬编码旋转数组。第一个索引应为旋转索引(0-3)
然后将成员变量添加到形状基类,并将旋转更改为类似以下内容:
public void rotate(Boolean rotateRight) {
if (rotateRight) {
rotation++;
else {
rotation--;
}
if (rotation < 0) {
rotation = 3;
}
if (rotation > 3) {
rotation = 0;
}
}
然后用这个int[][](或者int[]如果你想展平数组)画出合适的正方形谢谢你的回复,但是在进一步调查之后,我发现了问题所在。
问题在于旋转方法:
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;
}
这是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值之前保存X值,如下所示:
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;
}
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;
}
公共形状旋转(){
如果(this.getShape().equals(SQUARESHAPE))返回该值;
形状newShape=新形状();
newShape.shape=this.shape;
int[]oldX={this.x(0),this.x(1),this.x(2),this.x(3)};
对于(int i=0;i<4;i++){
新闻形态setX(i,-y(i));
新闻形态setY(i,oldX[i]);
}
返回新闻形状;
}
您应该为每个形状创建一个颜色字段,而不是一系列if语句。您不需要旋转方法,只需在一个静态数组中硬编码每个工件配置。这是工件的4个数组。