全位运算实现的俄罗斯方块-J2SE版

package tetris;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;



public class Tetris
{
	public static void main(String[] args)
	{
		long[] shapes = {0x88c002e06220e80l, 0x8e02260e200c88l, 0x8c8004e02620e40l, 0xcc00cc00cc00ccl,
						 0x6c08c4006c08c4l, 0xc604c800c604c8l, 0x8888000f8888000fl};
		GameFrame frame = new GameFrame();
		
		Shape player = new Shape(shapes[0]);
		GameRound round = new GameRound(shapes, player, (byte)32, (byte)15, (byte)20, (byte) 20);
		GamePanel panel = new GamePanel(round, player);
		frame.add(panel);
		
		
		frame.setVisible(true);
		frame.repaint();

	}
	
	@SuppressWarnings("serial")
	private static class GameFrame extends JFrame
	{
		
        public GameFrame()
        {
        	setIgnoreRepaint(true);
    		setUndecorated(true);
    		setBounds(0, 0, 800, 480);
    		setLocationRelativeTo(null);
    		setLayout(null);
    		setDefaultCloseOperation(EXIT_ON_CLOSE);
        }
	}
	
	@SuppressWarnings("serial")
    private static class GamePanel extends JPanel implements Runnable
	{
		private GameRound round;
		private Shape player;
        public GamePanel(GameRound round, Shape player)
        {
        	this.round = round;
        	this.player = player;
	        setBounds(0, 0, 800, 480);
	        setLayout(null);
	        setFocusable(true);
	        requestFocus();
	        addKeyListener(new KeyHandle());
	        new Thread(this).start();
        }
		
		@Override
        public void paint(Graphics g)
        {
        	//清屏
        	g.setColor(Color.WHITE);
			g.fillRect(0, 0, 800, 480);
			g.setColor(Color.BLACK);
			g.drawRect(0, 0, 799, 479);
			
			round.show(g);
			player.show(g);
        }
		
		public void run()
        {
			int num = 0;
        	while(true)
        	{
        		if(num++ > 1000000)
        			num = 0;
        		if(num % 1000 == 0)
        			processKeyEvent(new KeyEvent(GamePanel.this, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_DOWN, (char)KeyEvent.VK_DOWN));
        		repaint();
        		try
                {
	                Thread.sleep(1);
                }
                catch (InterruptedException e)
                {
	                e.printStackTrace();
                }
        	}
        }
		
		private class KeyHandle extends KeyAdapter
		{
			@Override
            public void keyPressed(KeyEvent e)
            {
				 switch(e.getKeyCode())
				 {
			    	case KeyEvent.VK_DOWN:
			    		round.moveDown();
					   break;
				    case KeyEvent.VK_LEFT:
				    	round.moveLeft();
					   break;
				    case KeyEvent.VK_RIGHT:
				    	round.moveRight();
					   break;
				    case KeyEvent.VK_UP:
				    	round.moveUp();
					   break;
				    case KeyEvent.VK_ENTER:
				    	byte oldleft = player.getBoundsLeft();
				    	byte oldright = player.getBoundsRight();
				    	player.nextFrame();
				    	if(round.collide(0, 0))
				    	{
				    		player.prevFrame();
				    	}
				    	else 
				    	{
							if(player.getX() < 0)
							{
								player.setX((byte)(player.getX() + (oldleft - player.getBoundsLeft())));
							}
							else if(player.getX() > 31- 3)
							{
								player.setX((byte)(player.getX() - (oldright - player.getBoundsRight())));
							}
						}
				    	break;
				    case KeyEvent.VK_ESCAPE:
				    	System.exit(0);
						   break;
				}
            }
		}
	}
	
	private static class GameRound
	{
		private final byte GAME_ROUND_WIDTH;
		private final byte GAME_ROUND_HEIGHT;
		
		private final byte GAME_TILE_WIDTH;
		private final byte GAME_TILE_HEIGHT;
		
		private final long[] SHAPES;
		private final int[] GAME_DATA;
		private Shape player;
		
		private Random ran = new Random();
    	
        public GameRound(long[] shapes, Shape player, byte width, byte height, byte twidth, byte theight)
        {
        	//初始化游戏区域的宽和高
        	//该宽高并不是实际的宽高
        	//而是指横、纵格子的数量
	        GAME_ROUND_WIDTH = width;
	        GAME_ROUND_HEIGHT = height;
	        
	        //初始化每个格子的宽和高
	        GAME_TILE_WIDTH = twidth;
	        GAME_TILE_HEIGHT = theight;
	        
	        SHAPES = shapes;
	        this.player = player;
	        GAME_DATA = new int[GAME_ROUND_HEIGHT];
	        GAME_DATA[GAME_ROUND_HEIGHT - 2] = 0xaaaaaaaa;
	        GAME_DATA[GAME_ROUND_HEIGHT - 1] = -1;
	    }
        
        public void show(Graphics g)
        {
        	g.setColor(Color.WHITE);
			g.fillRect(0, 0, 800, 480);
			g.setColor(Color.RED);
			g.drawRect(0, 0, 799, 479);
			
			//渲染数据区
        	for (int i = 0; i < GAME_ROUND_WIDTH; i++)
            {
                for (int j = 0; j < GAME_ROUND_HEIGHT; j++)
                {
                	if(((GAME_DATA[j] >> GAME_ROUND_WIDTH-1-i) & 1) == 1)
                		g.setColor(Color.RED);
                	else
                		g.setColor(Color.GREEN);
                	g.fillRect(i * GAME_TILE_WIDTH, j * GAME_TILE_HEIGHT, GAME_TILE_WIDTH, GAME_TILE_HEIGHT);
                    
                    g.setColor(Color.BLACK);
                    g.drawRect(i * GAME_TILE_WIDTH, j * GAME_TILE_HEIGHT, GAME_TILE_WIDTH, GAME_TILE_HEIGHT);
                }
            }
        }
        
        public void moveDown()
        {
        	if(player.getY() < 14 - 3 + player.getBoundsButtom())
        	{	
        		if(!collide(0,1))
        			player.y++;
        		else
        			shapeDown();
        	}
        	else
        		shapeDown();
        }
        
        public void moveUp()
        {
        	if(!collide(0, -1))
        	{
        		player.y--;
        	}
        }
        
        public void moveLeft()
        {
        	if(player.getX() > 0 - player.getBoundsLeft())
        	{	
        		if(!collide(-1,0))
        			player.x--;
        	}
        }
        
        public void moveRight()
        {
        	if(player.getX() < 31 - 3 + player.getBoundsRight())
        	{	
        		if(!collide(+1,0))
        			player.x++;
        	}
        }
        
        public boolean collide(int x, int y)
        {
        	int a,b;
        	for (int shift = player.getBoundsButtom(); shift < 4; shift++)
            {
        		if(player.getX() < 0)
					a = (((((int)player.getFrameData() << (16 + ((3 - shift) << 2) - (player.getX() + x)))) & 0xf0000000));
				else
					a = (((((int)player.getFrameData() << (16 + ((3 - shift) << 2)))) & 0xf0000000) >>> player.getX() + x);
    			b = (GAME_DATA[player.getY() + 3 - shift + y]);
    			if( (a & b) != 0)
    			{
    				return true;
    			}
            }
    		return false;
        }
        
        public void shapeDown()
        {
        	int down = 0;
    		if(player.getY() >= 12)
    			down = player.getY()+3;
    		else
    			down = player.getY() + 3;
    		for (int shift = player.getBoundsButtom(); shift < 4; shift++)
            {
    			if(player.getX() > -1)
    				GAME_DATA[down-shift] |= (((((int)player.getFrameData() << (16 + ((3 - shift) << 2)))) & 0xf0000000) >>> player.getX());
    			else
    				GAME_DATA[down-shift] |= (((((int)player.getFrameData() << (16 + ((3 - shift) << 2) - player.getX()))) & 0xf0000000));
            }
        	
        	for (int i = GAME_DATA.length - 1; i >= 0; i--)
            {
    	        if(GAME_DATA[i] == -1)
    	        {
    	        	int[] tmp = new int[i];
    	        	System.arraycopy(GAME_DATA, 0, tmp, 0, tmp.length);
    	        	System.arraycopy(tmp, 0, GAME_DATA, 1, tmp.length);
    	        }
            }
        	randomShape();
        }
        
        public void randomShape()
        {
        	player.initShape(SHAPES[Math.abs(ran.nextInt() % 7)], (byte)(Math.abs(ran.nextInt() % 4)));
        }
    }
	
	private static class Shape
	{
		private long data;
		private byte curr_frame;
		private short frame_data;
		
		private byte bounds_left;
		private byte bounds_right;
		private byte bounds_buttom;
		
		private byte x;
		private byte y;
		
		public Shape(long data)
        {
        	this(data, (byte)0);
	    }
		
		public Shape(long data, byte curr_frame)
        {
        	initShape(data, curr_frame);
	    }
		
		public void initShape(long data, byte curr_frame)
		{
			this.data = data;
        	setCurrentFrame(curr_frame);
        	initBounds();
        	setX((byte)14);
        	setY((byte)0);
		}
		
		public short getFrameData()
		{
			return this.frame_data;
		}
		
		public void show(Graphics g)
		{
			for (int shift = 0; shift < 4; shift++)
            {
        		for (int bit = 0; bit < 4; bit++)
                {
        			if((((frame_data >> ((3 - shift) << 2)) >> (3 - bit)) & 1) == 1)
        			{
        				g.setColor(Color.BLUE);
    					g.fillRect((x + bit) * 20, (y+shift) * 20, 20, 20);
        			}
                }
			}
			g.setColor(Color.YELLOW);
			g.drawRect(x * 20 + 1, y * 20 + 1, 79, 79);
		}
		
		public void nextFrame()
		{
			setCurrentFrame(++curr_frame > 3 ? 0 : curr_frame);
			initBounds();
		}
		
		public void prevFrame()
		{
			setCurrentFrame(--curr_frame < 0 ? 3 : curr_frame);
			initBounds();
		}
		
		private void setCurrentFrame(byte curr_frame)
		{
			this.curr_frame = curr_frame;
			this.frame_data = (short) (data >> ((3 - curr_frame) << 4));
		}

		private void initBounds()
		{
			bounds_left = 0;
			if((frame_data & 0x8888) == 0)
			{
				if((frame_data & 0x4444) == 0)
				{
					if((frame_data & 0x2222) == 0)
						bounds_left = 3;
					else
						bounds_left = 2;
				}
				else
					bounds_left = 1;
			}	
			
			bounds_right = 0;
			A:if((frame_data & 0x1111) == 0)
			{
				if((frame_data & 0x2222) == 0)
				{
					if((frame_data & 0x4444) == 0)
					{
						bounds_right = 3;
						break A;
					}
					bounds_right = 2;
					break A;
				}
				bounds_right = 1;
			}	
			
			bounds_buttom = 0;
			A:if((frame_data & 0x000f) == 0)
			{
				if((frame_data & 0x00f0) == 0)
				{
					if((frame_data & 0x0f00) == 0)
					{
						bounds_buttom = 3;
						break A;
					}
					bounds_buttom = 2;
					break A;
				}
				bounds_buttom = 1;
			}				
		}
		
		public byte getBoundsLeft()
		{
			return bounds_left;
		}
		
		public byte getBoundsRight()
		{
			return bounds_right;
		}
		
		public byte getBoundsButtom()
		{
			return bounds_buttom;
		}

		public byte getX()
        {
        
	        return x;
        }

		public void setX(byte x)
        {
        
	        this.x = x;
        }

		public byte getY()
        {
        
	        return y;
        }

		public void setY(byte y)
        {
        
	        this.y = y;
        }
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值