All pastes #459744 Raw Edit

Stuff

public text v1 · immutable
#459744 ·published 2007-04-26 17:36 UTC
rendered paste body
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

public class Snake extends Frame implements Runnable,WindowListener,KeyListener {
	private static final long serialVersionUID = -3029394778317566533L;
	
	public static final int FPS = 30;
	public static final int GAMEAREAWIDTH = 20;
	public static final int GAMEAREAHEIGHT = 20;
	public static final int GAMEAREABGCOLOR = 0xFFFFFF;
	public static final int GAMEAREABORDERCOLOR = 0xFFFFFF;
	public static final int BLOCKSIZE = 16;
	public static final int NUMOFFOODS = 80;
	
	public static final int STATE_NORMAL = 0;
	public static final int STATE_STOPPED = 1;
	
	public static boolean cont;
	public static Snake inst;
	public boolean inProgress;
	
	public int score;
	
	public static final Random randGen = new Random(System.currentTimeMillis());
	
    Thread drawThread;
    Graphics bbGraphics;
    Image bbImage;
    long lastUpdate;
    long lastMove;
    
    Boolean[] keys;
    int state;
    
    Follower snake;
    Food[] foods;
    Point direction;
	
	public static void main(String[] args) {
    	cont = true;
    	while(cont) {
    		inst = new Snake();
    		while(inst.inProgress) {
    			try {
    				Thread.sleep(1000);
    			} catch(Exception e) {}
    		}
    	}
    	System.exit(0);
	}
	
	public Snake() {
    	inProgress = true;
    	// SET UP WINDOW
    	this.setTitle("Snake : 1");
    	this.setResizable(false);
    	this.setBackground(Color.white);
    	this.setForeground(Color.black);
    	this.addWindowListener(this);
    	this.addKeyListener(this);
    	this.setVisible(true);
    	this.setSize(getInsets().left+getInsets().right+GAMEAREAWIDTH*BLOCKSIZE, getInsets().top+getInsets().bottom+GAMEAREAHEIGHT*BLOCKSIZE);
		Dimension dim = getToolkit().getScreenSize();
		Rectangle abounds = getBounds();
		this.setLocation((dim.width - abounds.width) / 2, (dim.height - abounds.height) / 2);

    	// SET UP KEYS
    	keys = new Boolean[256];
    	synchronized(keys) {
        	for(int i=0;i<keys.length;i++) {
        		keys[i] = Boolean.FALSE;
        	}    		
    	}
    	
    	score = 1;
    	
    	// SNAKE
    	snake = new Follower(0,0,true);
    	direction = new Point(1,0);
    	
    	// FOOD
    	foods = new Food[NUMOFFOODS];
    	for(int i=0;i<foods.length;i++) {
    		foods[i] = new Food(0,0);
    		foods[i].shuffle(snake);
    	}
    	
    	// STATE
    	state = STATE_NORMAL;
    	
    	// SET UP BACKBUFFER
    	bbImage = this.createImage(this.getWidth(), this.getHeight());
    	bbGraphics = bbImage.getGraphics();
    	drawThread = new Thread(this);
    	
    	// START DRAWING
    	drawThread.start();
	}
	
    public void dispose() {
    	inProgress = false;
    	super.dispose();
    }
    
    public void paint(Graphics g) {
    	if(bbImage!=null && bbGraphics!=null)
    		draw(g);
    }
    
    public void update(Graphics g) {
    	if(bbImage!=null && bbGraphics!=null)
    		draw(g);
    }
    
    public void run() {
    	while(true) {
    		lastUpdate = System.currentTimeMillis();
    		checkKeys();
    		processEvents();
    		repaint();
    		try {Thread.sleep(Math.max(1,lastUpdate+1000/FPS-System.currentTimeMillis()));}
    		catch(Exception e) {}
    	}
    }
    
    public void checkKeys() {
    	// check for key presses...
    	// remember - TRUE means pressed, null means acknowledged, FALSE means released
    	synchronized(keys) {
    		//if(state==STATE_STOPPED) return;
    		
    		if(keys[KeyEvent.VK_UP]==Boolean.TRUE && direction.y!=1) {
    			direction = new Point(0,-1);
    			keys[KeyEvent.VK_UP] = null;
    		}
    		else if(keys[KeyEvent.VK_LEFT]==Boolean.TRUE && direction.x!=1) {
    			direction = new Point(-1,0);
    			keys[KeyEvent.VK_LEFT] = null;
    		}
    		else if(keys[KeyEvent.VK_RIGHT]==Boolean.TRUE && direction.x!=-1) {
    			direction = new Point(1,0);
    			keys[KeyEvent.VK_RIGHT] = null;
    		}
    		else if(keys[KeyEvent.VK_DOWN]==Boolean.TRUE && direction.y!=-1) {
    			direction = new Point(0,1);
    			keys[KeyEvent.VK_DOWN] = null;
    		}
    		else if(keys[KeyEvent.VK_F2]==Boolean.TRUE) {
    			this.dispose();
    		}
    	}
    }
    
    public void processEvents() {
    	// move snake, generate new snake tail if necessary, whatever.
    	if(state==STATE_NORMAL && lastUpdate>lastMove+150) {
    		snake.moveBy(direction.x, direction.y);
    		if(snake.collidesWithSelf()) gameOver();
    		else {
        		for(int i=0;i<foods.length;i++) {
        			if(foods[i].intersects(snake)) {
        				snake.eat();
        				foods[i].shuffle(snake);
        			}
        		}
    		}
    		lastMove = lastUpdate;
    	}
    }
    
    public void gameOver() {
    	state = STATE_STOPPED;
    	this.setTitle("Snake : "+score+((state==STATE_STOPPED)?" [game over]":""));
    }
    
    public void incrementScore() {
    	score++;
    	this.setTitle("Snake : "+score+((state==STATE_STOPPED)?" [game over]":""));
    }
    
    public void draw(Graphics g) {
    	bbGraphics.clearRect(0,0,getWidth(),getHeight());
    	//----------------------------------
    	
    	snake.draw(bbGraphics);
    	for(int i=0;i<foods.length;i++)
    		foods[i].draw(bbGraphics);
    	
    	//----------------------------------
    	g.drawImage(bbImage,0,0,null);
    }
    
	public void windowActivated(WindowEvent e) {}
	public void windowClosed(WindowEvent e) {}
	public void windowClosing(WindowEvent e) {cont = false; this.dispose();}
	public void windowDeactivated(WindowEvent e) {}
	public void windowDeiconified(WindowEvent e) {}
	public void windowIconified(WindowEvent e) {}
	public void windowOpened(WindowEvent e) {}
	
	public void keyTyped(KeyEvent e) {}
	public void keyPressed(KeyEvent e) {
		synchronized(keys) {
			if(keys[e.getKeyCode()]==Boolean.FALSE) keys[e.getKeyCode()] = Boolean.TRUE;
		}
	}
	public void keyReleased(KeyEvent e) {
		synchronized(keys) {
			keys[e.getKeyCode()] = Boolean.FALSE;			
		}
	}
	
	protected class Follower {
		Point pos;
		Follower next;
		boolean head;
		
		public Follower(int x, int y, boolean head) {
			pos = new Point(x,y);
			this.head = head;
		}
		
		public Follower(int x, int y) {
			this(x,y,false);
		}
		
		public void draw(Graphics g) {
			g.setColor(Color.blue);
			g.fillOval(getInsets().left+pos.x*BLOCKSIZE,getInsets().top+pos.y*BLOCKSIZE,BLOCKSIZE,BLOCKSIZE);
			if(head) {
				g.setColor(Color.black);
				g.fillOval(getInsets().left+pos.x*BLOCKSIZE+BLOCKSIZE/4,getInsets().top+pos.y*BLOCKSIZE+BLOCKSIZE/4,BLOCKSIZE/2,BLOCKSIZE/2);
			}
			if(next!=null) next.draw(g);
		}
		
		public void moveTo(int x, int y) {
			if(pos.x==x&&pos.y==y) return;
			if(next!=null) next.moveTo(pos.x,pos.y);
			pos.x=x;
			pos.y=y;
			
			if(x<0||y<0||x>GAMEAREAWIDTH-1||y>GAMEAREAHEIGHT-1) gameOver();
		}
		
		public void moveBy(int x, int y) {
			this.moveTo(pos.x+x,pos.y+y);
		}
		
		public void eat() {
			if(next==null) {
				next = new Follower(pos.x,pos.y);
				incrementScore();
			} else {
				next.eat();
			}
		}
		
		public boolean collidesWithSelf() {
			return (next==null)? false : next.intersects(pos.x,pos.y);
		}
		
		public boolean intersects(int x, int y) {
			if(pos.x==x && pos.y==y) return true;
			else return (next==null)?false:next.intersects(x, y);
		}
	}
	
	protected class Food {
		Point pos;
		public Food(int x, int y) {
			pos = new Point(x,y);
		}
		
		public boolean intersects(Follower f) {
			return f.intersects(pos.x,pos.y);
		}
		
		public void shuffle(Follower f) {
			this.shuffle(new Follower[]{f});
		}
		
		public void shuffle(Follower[] fs) {
			if(fs.length<1) return;
			LABEL1:
				while(true) {
					pos.x = randGen.nextInt(GAMEAREAWIDTH);
					pos.y = randGen.nextInt(GAMEAREAHEIGHT);
					for(int i=0;i<fs.length;i++)
						if(fs[i].intersects(pos.x, pos.y)) continue LABEL1;
					
					break;
				}
		}
		
		public void draw(Graphics g) {
			g.setColor(Color.green);
			g.fillOval(getInsets().left+pos.x*BLOCKSIZE,getInsets().top+pos.y*BLOCKSIZE,BLOCKSIZE,BLOCKSIZE);
		}
	}
}