1

我正在尝试自己制作一个简单的项目。这个项目就像俄罗斯方块游戏一样工作。矩形对象是用计时器创建的,并且随机以 3 种不同的颜色创建。对象保留在列表中。我用 moveRectangle() 和 control() 函数检查了 Y 的对齐情况。如果三个相同颜色的并排或在块的顶部,它们将被移除并由上面的块替换它们。那是我的问题。我已经尝试了各种方法,但我做不到。

这适用于创建矩形对象和控制对象的 x 和 y 坐标;

    package p1;

import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.Timer;

    public class DropObject {


    private  int yukseklik;
    private int block;
    private Color r;
    //private static int sayac=-1;
    private static int cntr;
    private Rectangle object;
    private static int sx=60;
    private static int [] sy=new int[9];
    public static int a=3;
    public static Color [] colorR=new Color[25];




    public DropObject(int yukseklik,int x,int y,int size,Color r)
    {   
    x=sx;
    //y=sy;
    this.r=EventRect.RColor();
    this.yukseklik=yukseklik;
    //set();
    this.object=new Rectangle(x,y,size,size);

    }

    /*public void set(){
        colorR[cntr]=this.r;
        //System.out.println("Renk: "+colorR[cntr]);
        cntr++;

    }*/


    public static int getSX(){
        return sx;
    }

    public static void setSX(int x){
        sx=x;
    }

    public static int getSY(){

        return sy[a];
    }

    public static void setSY(int y){
        sy[a]=y;

    }

    public Color getColor(){
        //colorR[++sayac]=this.r;
        return this.r;
    }

    public  int getYukseklik(){
        return yukseklik;
    }
    public void setYukseklik(int yukseklik){
        this.yukseklik=yukseklik;

    }
    public Rectangle getObject(){
        return object;
    }
    public void setObject(Rectangle object){
        this.object=object;
        this.object.x=sx;
    }

         }

EventRect 类提供对象运动并指定对象 y 坐标位置;

package p1;


import java.awt.Button;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D; 
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
//import java.util.Timer;
import java.util.TimerTask;

import javax.swing.Timer;

import java.util.Random;

import javax.swing.JPanel;

public class EventRect extends JPanel {

private static int yukseklik=340;
private static Color BlockC;
private DropObject koordinat;
private int zheight=yukseklik;
private int fheight=yukseklik;
private int sheight=yukseklik;
private int theight=yukseklik;
private int foheight=yukseklik;
private int fiheight=yukseklik;
private int ssheight=yukseklik;
private int seheight=yukseklik;
private int seiheight=yukseklik;
private int counter=-1;
private int counter1=-1;
private int counter0=-1;





private List<DropObject> objects=new LinkedList<DropObject>();
private LinkedList<TimerTask> tasklist=new LinkedList<TimerTask>();
Timer timet;
int i=1;

public EventRect(){
addKeyListener(new InputKey());
setFocusable(true);
//System.out.println((objects.size()));
koordinat=new DropObject(yukseklik,60,-20,20,BlockC);
objects.add(koordinat); 
startSampling();
//timet=new Timer(10,this);
//timet.start();
}




@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;
for(DropObject o : objects){
    Rectangle r=o.getObject();
    g2d.setColor(o.getColor());
    //System.out.println(r.x);
    g2d.fillRect(r.x, r.y, r.width+1, r.height+1);
   // System.out.println(objects.size());
}


}

public void moveRectangle(){
for(int i=(objects.size()-1);i>=(objects.size()-1);i--){
    DropObject o=objects.get(i);
    Rectangle r=o.getObject();
    if(DropObject.a==0){

       DropObject.setSY(zheight);
           o.setYukseklik(DropObject.getSY());

      }
    if(DropObject.a==1){

       DropObject.setSY(fheight);
           o.setYukseklik(DropObject.getSY());


      }
    if(DropObject.a==2){

       DropObject.setSY(sheight);
           o.setYukseklik(DropObject.getSY());


      }
    if(DropObject.a==3){
           DropObject.setSY(theight);
           o.setYukseklik(DropObject.getSY());


           }


    if(DropObject.a==4){

       DropObject.setSY(foheight);
           o.setYukseklik(DropObject.getSY());

      }
    if(DropObject.a==5){

       DropObject.setSY(fiheight);
           o.setYukseklik(DropObject.getSY());


      }
    if(DropObject.a==6){

           DropObject.setSY(ssheight);
           o.setYukseklik(DropObject.getSY());

      }
    if(DropObject.a==7){

       DropObject.setSY(seheight);
           o.setYukseklik(DropObject.getSY());

      }
    if(DropObject.a==8){

       DropObject.setSY(seiheight);
           o.setYukseklik(DropObject.getSY());

      }



    if(o.getYukseklik()>=0){
        if(r.y<o.getYukseklik()){
            r.y+=r.height;
            o.setObject(r); 

        }else{
            o.setYukseklik(o.getYukseklik()-r.height);

        }

    }

    if(r.y == o.getYukseklik()){
         control();

         objects.add(new DropObject(o.getYukseklik(),60,-20,20,BlockC));


    }   
}
}


void control(){
    if(DropObject.a==0){
           zheight-=20;
           DropObject.setSY(zheight);

      }
     if(DropObject.a==1){
           fheight-=20;
           DropObject.setSY(fheight);

      }

     if(DropObject.a==2){
           sheight-=20;
           DropObject.setSY(sheight);

      }


      if(DropObject.a==3){

           theight-=20;
           DropObject.setSY(theight);

      }

      if(DropObject.a==4){
            foheight-=20;
            DropObject.setSY(foheight);

        }
      if(DropObject.a==5){
            fiheight-=20;
            DropObject.setSY(fiheight);

        }
      if(DropObject.a==6){
            ssheight-=20;
            DropObject.setSY(ssheight);

        }
      if(DropObject.a==7){
            seheight-=20;
            DropObject.setSY(seheight);

        }
      if(DropObject.a==8){
            seiheight-=20;
            DropObject.setSY(seiheight);

      }


    }



void startSampling(){
TimerTask task=new TimerTask(){
    public void run(){
        moveRectangle();
        repaint();


    }
};
java.util.Timer timer=new java.util.Timer();
timer.scheduleAtFixedRate(task,0,150);
tasklist.add(task);

}

void stopSampling(){
if(tasklist.isEmpty()){
    return;
}
tasklist.removeFirst().cancel();
}

public static Color RColor(){
Color [] Array={Color.blue,Color.pink,Color.gray};
Random random=new Random();
BlockC=Array[random.nextInt(Array.length)];
 return BlockC;
}
}

键盘动作;

   package p1;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class InputKey extends KeyAdapter{

    public void keyPressed(KeyEvent e){
        int keys=e.getKeyCode();
        if(keys==KeyEvent.VK_RIGHT){
            //System.out.println("saga kaydi");
            if(DropObject.getSX()<160)
            DropObject.setSX(DropObject.getSX()+20);
            if(DropObject.a<8){
            DropObject.a++;
            System.out.println("a nin degeri: "+DropObject.a);
            }

        }
        else if(keys==KeyEvent.VK_LEFT){
            if(DropObject.getSX()>0)

            DropObject.setSX(DropObject.getSX()-20);
            if(DropObject.a>0){
                DropObject.a--;

                }


        }
    }

}



package p1;

import java.awt.Color;
import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Main implements Runnable{

@Override 
public void run(){

JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container=frame.getContentPane();
container.setLayout(new GridLayout(0,1));
container.add(new EventRect());

frame.setSize(197,400);
frame.setVisible(true);
//container.setBackground(Color.BLUE);


}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Main());

}

}
4

2 回答 2

0

我曾经实现过类似俄罗斯方块的游戏,我检测碰撞和填充区域的方式是遵循数据结构

  1. 你的形状要安定下来的整个空间是一个用数组表示的网格,最初为 0,在块落下的单元格上填充为 1。
  2. 每个块也是一个方形网格,其形状通过在需要的地方填充 1 来定义。

在这个模型之后,检测碰撞和填充区域变得微不足道。如果您希望对颜色进行不同处理,您可以为单元格的每种颜色分配 1,2,3..so on。希望有帮助。

于 2013-07-20T03:35:18.580 回答
0

这是我根据您的原始代码和想法进行了大量修改的解决方案。它实现了一种面向对象的方法来跟踪块。它使用块列表来表示每一列。它还有一个 ArrayList 来存储对屏幕上所有块的引用,以便我们可以循环进行绘图。抱歉,它不会是您的母语,但希望您仍然可以理解它。您需要的主要代码存储在 BlockBuster 类中,该类处理邻接检测和块的删除。您应该将每个类分开到自己的文件中。

块.java

package p1;

import java.awt.Color;
import java.awt.Rectangle;
import java.util.Random;

public class Block {

    /**
     * Color
     */
    private Color color;
    /**
     * The pixel coordinate bounding rectangle for the block.
     */
    private Rectangle bounds;
    /**
     * the integer column
     */
    private int column;

    /**
     * Creates a new instance of a block at the specified
     * 
     * @param y Distance in pixels from the top of the form.
     * @param column The integer column index (0-8)
     * @param size The integer size.
     */
    public Block(int y, int column, int size) {
        this.color = RandomColor();
        this.bounds = new Rectangle(20*column, y, size, size);
        this.column = column;
    }

    /**
     * Gets the color of this block.
     * @return the color of this block.
     */
    public Color getColor() {
        return this.color;
    }

    /**
     * Gets the pixel bounds for this block.
     * @return The bounds.
     */
    public Rectangle getBounds() {
        return bounds;
    }

    /**
     * Sets the bounds for this block.
     * @param object 
     */
    public void setBounds(Rectangle object) {
        this.bounds = object;
    }

    /**
     * This is Elevation in units of blocks, like column 
     * @return 
     */
    public int getLevel(){
        return (340 - this.getBounds().y)/20;
    }

    /**
     * Gets the bottom of the block.
     * @return 
     */
    public int getBottom(){
        return this.bounds.y + this.bounds.height;
    }

    /**
     * Gets the integer column index of the block (0-8)
     * @return the column
     */
    public int getColumn() {
        return column;
    }

    /**
     * Sets the integer column index of the block (0-8)
     * @param column the column to set
     */
    public void setColumn(int column) {
        this.column = column;
    }

    /**
     * Generates a random color.
     * @return Color
     */
    public static Color RandomColor() {
        Color[] Array = {Color.blue, Color.pink, Color.gray};
        Random random = new Random();
        return Array[random.nextInt(Array.length)];
    }
}

BlockBuster.java

package p1;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

/**
 * This class handles the work of finding adjacent blocks.
 * To delete blocks ONLY if the blocks are horizontally adjacent,
 * then you can remove the "Up" and "Down" sections.
 * @author Ted
 */
public class BlockBuster {

    private List<Block> queue;
    private List<Block> bustList;

    /**
     * Creates a new instance of the BlockBuster class.
     */
    public BlockBuster() {
        queue = new ArrayList<Block>();
    }

    /**
     * This method busts the blocks of with matching colors
     */
    public void bustBlocks() {
        Block block = BlockManager.getInstance().getFallingBlock();
        bustList = new ArrayList<Block>();
        queue.add(block);
        while (queue.size() > 0) {
           Block current = queue.get(0);
           addMatchingNeighbors(current);
           queue.remove(0);
           if(!bustList.contains(current)){
                bustList.add(current);
           }

        }
        if(bustList.size() > 2){
          for(Block busted : bustList){
              BlockManager.getInstance().RemoveBlock(busted);
              List<Block> check = BlockManager.getInstance().getAllBlocks();
              if(check.contains(busted)){
                boolean stop = true;
              }
          }
        }
    }

    /**
     * This method adds neighbors that match in color to the queue
     * as long as they don't already exist in the queue or bustlist.
     * @param block The current block to consider.
     */
    private void addMatchingNeighbors(Block block) {
        // currently only check by 4 connectivity
        int x = block.getColumn();
        int y = block.getLevel();
        Color color = block.getColor();

        // left
        Block leftBlock = getBlock(x - 1, y);
        if(colorMatches(color, leftBlock)){
             queue.add(leftBlock);
        }
        // Right
        Block rightBlock = getBlock(x + 1, y);
        if(colorMatches(color, rightBlock)){
            queue.add(rightBlock);

        }
        // Up
        Block upBlock = getBlock(x, y + 1);
        if(colorMatches(color, upBlock)){
            queue.add(upBlock);

        }

        Block downBlock = getBlock(x, y-1);
        if(colorMatches(color, downBlock)){
            queue.add(downBlock);
        }

    }

    /**
     * This tests whether the block's color matches the specified
     * color, and whether or not the block is already in a list.
     * @param color The color that should match for deletion.
     * @param block The block to be removed.
     * @return 
     */
    public boolean colorMatches(Color color, Block block){
       if(block == null){
           return false;
       }
       if(bustList.contains(block)){
           return false;
       }
       if(queue.contains(block)){
           return false;
       }
       return (block.getColor().equals(color));
    }

    /**
     * This finds a block at the specified column and height.
     * @param column The integer column index (0-8)
     * @param height The integer level (in blocks)
     * @return a Block
     */
    public Block getBlock(int column, int level) {

        Column[] columns = BlockManager.getInstance().getColumns();
        if (column >= 0 && column < 10) {
            if (columns[column].getBlocks().size() > level && level >= 0) {
                Block result = columns[column].getBlocks().get(level);
                if(bustList.contains(result)){
                    return null;
                }
                return result;
            }
        }
        return null;
    }
}

块管理器.java

package p1;

import java.util.ArrayList;
import java.util.List;

/**
 * This is a singleton to control the blocks and is visible
 * from the other classes in the application.
 * @author Ted
 */
public class BlockManager {

    /**
     * The single instance of a falling block.
     */
    private Block fallingBlock;

    /**
     * All blocks on the page, including the falling one.
     */
    private List<Block> allBlocks;

    /**
     * The array of columns at the bottom, containing blocks.
     */
    private Column[] columns;

    /**
     * Creates an instance of a BlockManager class.  As part
     * of the singleton pattern, this is private so that
     * you can only access the shared instance.
     */
    private BlockManager() {
        allBlocks = new ArrayList<Block>();
        columns = new Column[9];
        for(int i = 0; i < 9; i++)
        {
            columns[i] = new Column();
        }
    }

    /**
     * Gets the single shared instance of the singleton.
     * @return BlockManager
     */
    public static BlockManager getInstance() {
        return BlockManagerHolder.INSTANCE;
    }
    private static class BlockManagerHolder {
        private static final BlockManager INSTANCE = new BlockManager();
    }

    /**
     * Adds a new falling block to the top of the control.
     */
    public void AddBlock(){
        fallingBlock = new Block(0, 3, 20);
        allBlocks.add(fallingBlock);
    }

    /**
     * Removes the specified block.
     * @param block 
     */
    public void RemoveBlock(Block block){
        allBlocks.remove(block);
        List<Block> blocks = columns[block.getColumn()].getBlocks();
        if(blocks.size() > block.getLevel()){
           for(int i = block.getLevel(); i < blocks.size(); i++)
           {
               // Make blocks above this block drop.
               blocks.get(i).getBounds().y += 20;

           }
        }
        columns[block.getColumn()].getBlocks().remove(block);
    }



    /**
     * Gets the falling block.
     * @return the fallingBlock
     */
    public Block getFallingBlock() {
        return fallingBlock;
    }

    /**
     * Sets the falling block.
     * @param fallingBlock the fallingBlock to set
     */
    public void setFallingBlock(Block fallingBlock) {
        this.fallingBlock = fallingBlock;
    }

    /**
     * Gets the list of all blocks visible on the form,
     * including the falling block.
     * @return the allBlocks
     */
    public List<Block> getAllBlocks() {
        return allBlocks;
    }

    /**
     * Sets the list of all blocks visible on the form,
     * including the falling block.
     * @param allBlocks the allBlocks to set
     */
    public void setAllBlocks(List<Block> allBlocks) {
        this.allBlocks = allBlocks;
    }

    /**
     * Gets the array of columns containing blocks at the bottom.
     * @return the columns
     */
    public Column[] getColumns() {
        return columns;
    }

    /**
     * Sets the array of columns containing blocks at the bottom.
     * @param columns the columns to set
     */
    public void setColumns(Column[] columns) {
        this.columns = columns;
    }


}

列.java

package p1;

import java.util.ArrayList;
import java.util.List;

/**
 * A Column is an object that contains a list of the blocks stored
 * in a vertical stack at the bottom of the game.  Each block object
 * points to the same object instance in allBlocks.
 * @author Ted
 */
public class Column {
    private static int maxHeight = 340;
    private List<Block> blocks;

    /**
     * Gets the maximum vertical pixel height of the form.
     * @return the maxHeight
     */
    public static int getMaxHeight() {
        return maxHeight;
    }

    /**
     * Sets the maximum vertical pixel height of the form.
     * @param aMaxHeight the maxHeight to set
     */
    public static void setMaxHeight(int aMaxHeight) {
        maxHeight = aMaxHeight;
    }


    /**
     * Creates a new instance of the column class.
     */
    public Column(){
        blocks = new ArrayList<Block>();
    }

    /**
     * Gets the amount of space remaining in this column
     * @return 
     */
    public int getDepthRemaining(){
        return maxHeight - getBlockHeight();
    }

    /**
     * Gets the total height of all the blocks in this column
     * @return 
     */
    public int getBlockHeight(){
        int height = 0;
        for(Block block : blocks){
            height += block.getBounds().height;
        }
        return height;
    }

    /**
     * Gets the list of blocks associated with this column.
     * The 0 index is at the bottom.
     * @return the dropObjects
     */
    public List<Block> getBlocks() {
        return blocks;
    }

    /**
     * Sets the list of blocks associated with this column.
     * @param dropObjects the dropObjects to set
     */
    public void setBlocks(List<Block> dropObjects) {
        this.blocks = dropObjects;
    }
}

EventRect.java

package p1;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.LinkedList;
import java.util.TimerTask;
import javax.swing.Timer;
import javax.swing.JPanel;

/**
 * EventRect is the main form for the game.
 */
public class EventRect extends JPanel {
    /**
     * @return the fallingBlock
     */
    public static Block getFallingBlock() {
        return BlockManager.getInstance().getFallingBlock();
    }

    private BlockBuster blockBuster;
    private LinkedList<TimerTask> tasklist = new LinkedList<TimerTask>();
    Timer timet;
    int i = 1;

    /**
     * Creates a new instance of the main form for the project.
     */
    public EventRect() {
        BlockManager.getInstance().AddBlock();
        this.blockBuster = new BlockBuster();
        addKeyListener(new InputKey());
        setFocusable(true);
        startSampling();
    }

    /**
     * Paints all the blocks onto the screen, including the falling block.
     * @param g The Graphics surface of the form.
     */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        for (Block dropObject : BlockManager.getInstance().getAllBlocks()) {
            Rectangle bounds = dropObject.getBounds();
            g2d.setColor(dropObject.getColor());
            g2d.fillRect(bounds.x, bounds.y, bounds.width + 1, bounds.height + 1);
        }
    }

    /**
     * This handles the downward motion of the falling block.
     */
    public void moveRectangle() {
        Column[] columns = BlockManager.getInstance().getColumns();
        if(getFallingBlock().getBounds().getY() >= 
          columns[getFallingBlock().getColumn()].getDepthRemaining()){
            // We hit the top of the column, so add this block to the column
            columns[getFallingBlock().getColumn()].getBlocks().add(getFallingBlock());
            blockBuster.bustBlocks();
            BlockManager.getInstance().AddBlock();
        }
        else{
            BlockManager.getInstance().getFallingBlock().getBounds().y += 20;
        }
    }

    /**
     * This method was made final because it is called from the
     * constructor.  This starts game timers (from original post).
     */
    final void startSampling() {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                moveRectangle();
                repaint();
            }
        };
        java.util.Timer timer = new java.util.Timer();
        timer.scheduleAtFixedRate(task, 0, 150);
        tasklist.add(task);
    }

    /**
     * This method removes the timer from the tasklist.
     */
    void stopSampling() {
        if (tasklist.isEmpty()) {
            return;
        }
        tasklist.removeFirst().cancel();
    }


}

输入键.java

package p1;

import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/**
 * This class handles the movement of blocks.  This 
 * class was modified to include collision detection
 * with blocks in a neighboring column.
 */
public class InputKey extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent e) {
        int keys = e.getKeyCode();
        Block block = EventRect.getFallingBlock();
        if (block == null) {
            return;
        }
        Rectangle rect = block.getBounds();
        if (keys == KeyEvent.VK_RIGHT) {
            //Check for right bounds
            if (rect.x < 160) {
                // Check to see if we run into another block
                int level = block.getLevel();
                int column = block.getColumn();
                if (BlockManager.getInstance().getColumns()[column + 1].getBlocks().size() > level) {
                    // we ran into a block
                    return;
                }
                rect.x += 20;
                block.setColumn(rect.x / 20);
            }
        } else if (keys == KeyEvent.VK_LEFT) {
            // Check for left bounds
            if (rect.x > 0) {
                // Check to see if we run into another block
                int level = block.getLevel();
                int column = block.getColumn();
                if (BlockManager.getInstance().getColumns()[column + 1].getBlocks().size() > level) {
                    // we ran into a block
                    return;
                }
                rect.x -= 20;
                block.setColumn(rect.x / 20);
            }
        }
    }
}

主.java

package p1;

import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * This class runs the program.
 * @author Ted
 */
public class Main implements Runnable {

    @Override
    public void run() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container container = frame.getContentPane();
        container.setLayout(new GridLayout(0, 1));
        container.add(new EventRect());
        frame.setSize(197, 400);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Main());
    }
}
于 2013-07-20T12:47:54.573 回答