全位運算實現的俄羅斯方塊 J2ME版

import java.util.Random;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;



public class TetrisMidlet extends MIDlet
{
	private GameCanvas gameCanvas = null;
	private Display dis = null;
	public TetrisMidlet()
	{
		long[] shapes = {0x88c002e06220e80l, 0x8e02260e200c88l, 0x8c8004e02620e40l, 0xcc00cc00cc00ccl,
				 0x6c08c4006c08c4l, 0xc604c800c604c8l, 0x8888000f8888000fl};

		Shape player = new Shape(shapes[0]);
		GameRound round = new GameRound(shapes, player, (byte)32, (byte)15, (byte)7, (byte) 7);
		GameCanvas panel = new GameCanvas(round, player);
		gameCanvas = new GameCanvas(round,player);
		dis = Display.getDisplay(this);
		
	}
	
	protected void destroyApp(boolean arg0) throws MIDletStateChangeException{}
	
	protected void pauseApp(){}
	
	protected void startApp() throws MIDletStateChangeException
	{
		System.out.println("11111");
		dis.setCurrent(gameCanvas);
		gameCanvas.repaint();
	}
	
	
	
	class GameCanvas extends Canvas implements Runnable
	{
		public static final int VK_UP = -1;
		public static final int VK_DOWN = -2;
		public static final int VK_LEFT = -3;
		public static final int VK_RIGHT = -4;
		public static final int VK_FIRE = -5;
		public static final int VK_SOFT2 = -7;
		
		private GameRound round;
		private Shape player;
		
		public GameCanvas(GameRound round, Shape player)
		{
//			super(false);
			setFullScreenMode(true);
			this.round = round;
        	this.player = player;
        	new Thread(this).start();
		}
		
		public void paint(Graphics g)
		{
        	//清屏
        	g.setColor(-1);
			g.fillRect(0, 0, 800, 480);
			g.setColor(0);
			g.drawRect(0, 0, 799, 479);
			
			round.show(g);
			player.show(g);
		}
		
		public void run()
		{
			long taken = System.currentTimeMillis();
			long keyTaken = System.currentTimeMillis();
        	while(true)
        	{
        		if(System.currentTimeMillis() - taken > 1000)
        		{
        			taken = System.currentTimeMillis();
        			keyEvent(VK_DOWN);
        			
        		}
        		
        		if(System.currentTimeMillis() - keyTaken > 50 && keepKeyCode != Integer.MAX_VALUE)
        		{
        			keyTaken = System.currentTimeMillis();
        			keyEvent(keepKeyCode);
        		}
        		repaint();
        		try
                {
	                Thread.sleep(1);
                }
                catch (InterruptedException e)
                {
	                e.printStackTrace();
                }
        	}
		}
		
		public void keyPressed(int keycode)
        {
			 keepKeyCode = keycode;
        }
		
		

		protected void keyReleased(int keyCode)
        {
			keepKeyCode = Integer.MAX_VALUE;
        }



		int keepKeyCode = Integer.MAX_VALUE;
		public void keyEvent(int keycode)
		{
			switch(keycode)
			 {
		    	case VK_DOWN:
		    		round.moveDown();
				   break;
			    case VK_LEFT:
			    	round.moveLeft();
				   break;
			    case VK_RIGHT:
			    	round.moveRight();
				   break;
			    case VK_UP:
			    	round.moveUp();
				   break;
			    case VK_FIRE:
			    	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 VK_SOFT2:
			    	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(0xFFFFFF);
			g.fillRect(0, 0, 800, 480);
			g.setColor(0xFF0000);
			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(0xFF0000);
                	else
                		g.setColor(0x00FF00);
                	g.fillRect(i * GAME_TILE_WIDTH, j * GAME_TILE_HEIGHT, GAME_TILE_WIDTH, GAME_TILE_HEIGHT);
                    
                    g.setColor(0x000000);
                    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(0x0000FF);
    					g.fillRect((x + bit) * 7, (y+shift) * 7, 7, 7);
        			}
                }
			}
			g.setColor(0xFFFF00);
			g.drawRect(x * 7 + 1, y * 7 + 1, 28, 28);
		}
		
		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;
        }
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章