我正在尝试自己制作一个简单的项目。这个项目的工作方式类似于俄罗斯方块游戏.Rectangle对象是用计时器创建的,随机有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());
}
}
答案 0 :(得分:0)
我曾经实施过类似游戏的俄罗斯方块,我通过跟踪数据结构检测到碰撞和填充区域的方式
在这个模型之后,它可以检测碰撞以及填充区域。如果您希望颜色处理方式不同,则可以为单元格的每种颜色指定1,2,3..so。希望有所帮助。
答案 1 :(得分:0)
这是我基于您原始代码和想法的经过大量修改的解决方案。它实现了一种面向对象的方法来跟踪块。它使用块列表来表示每列。它还有一个ArrayList来存储对屏幕上所有块的引用,以便我们可以循环绘制。对不起它不会是你的母语,但希望你仍然可以理解它。您需要的主要代码存储在BlockBuster类中,该类处理块的邻接检测和删除。您应该将每个类分离到自己的文件中。
Block.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;
}
}
BlockManager.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;
}
}
Column.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();
}
}
InputKey.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);
}
}
}
}
Main.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());
}
}