Worm Game

<< Gridworld Tile Game | FinalProjectsTrailIndex | Hunt the Wumpus >>

Worm.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.ArrayList;


public class Worm {
	private ArrayList<Rectangle> segments;
	private int dir;
	public static final int NORTH=0,EAST=90,SOUTH=180, WEST=270;
	private Rectangle bounds;
	private Color color;
	public Worm(int x, int y, int size, Rectangle bounds){
		segments = new ArrayList<Rectangle>();
		dir= EAST;
		this.bounds =bounds;
		segments.add(new Rectangle(x,y,size,size));
		addSegment();
		addSegment();
		color=Color.MAGENTA;
	}
	public boolean addSegment(){
		//make a copy of the last segment
		Rectangle tail = new Rectangle(segments.get(segments.size()-1));
		// if possible move to the left of the last segment
		tail.translate(-1*tail.width, 0);
		if (bounds.contains(tail)){
			segments.add(tail);
			return true;
		}		
		return false; //coun't add segment
	}
	public boolean move(){
		//get a copy of the head
		Rectangle head=new Rectangle(segments.get(0));
		int dx=0;
		int dy=0;
		if (dir==NORTH)
			dy=-1*head.height;
		if (dir==SOUTH)
			dy=head.height;
		if (dir==EAST)
			dx=head.width;
		if (dir==WEST)
			dx=-1*head.width;
		head.translate(dx, dy);
		if (bounds.contains(head)){			
			//segments move to previous segments position
			segments.remove(segments.size()-1);
			segments.add(0, head);
			return true;
		}
		return false;// ran into edge
	}
	public void setDirection(int d){
		dir=d;
	}
	public int getDirection(){
		return dir;
	}
	public void setColor(Color c){
		color=c;
	}
	public Color getColor(){
		return color;
	}
	public void draw(Graphics g){
		g.setColor(Color.BLACK);
		for(Rectangle s:segments)
			g.fillOval(s.x, s.y, s.width, s.height);
		g.setColor(color);
		for(Rectangle s:segments)
			g.fillOval(s.x+2, s.y+2, s.width-4, s.height-4);
	}
	public int getLength() {
		return segments.size();
	}

	public boolean isTwisted(){
		for(int i=0; i<segments.size()-1;i++)
			for(int j=i+1;j<segments.size();j++)
				if (segments.get(i).intersects(segments.get(j)))
					return true;
		return false;
	}
	public boolean intersects(Rectangle r){
		for(int i=0; i<segments.size()-1;i++)
			for(int j=i+1;j<segments.size();j++)
				if (segments.get(i).intersects(r))
					return true;
		return false;
	}
	public Rectangle getBounds(){
		return bounds;
	}
	public Rectangle getHead(){
		return segments.get(0);
	}
}

Prize.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;


public class Prize 
{
	private int value;
	BufferedImage img;
	Rectangle box;
	public Prize(int value, int width, int height, Worm w){
		this.value=value;
		Rectangle bounds=w.getBounds();
		int x = randomInt(bounds.x, bounds.x+bounds.width-width);
		int y = randomInt(bounds.y, bounds.y+bounds.height-height);
		box = new Rectangle(x,y,width, height);
		while(!bounds.contains(box) || w.intersects(box)){
			x = randomInt(bounds.x, bounds.x+bounds.width-width);
			y = randomInt(bounds.y, bounds.y+bounds.height-height);
			box = new Rectangle(x,y,width, height);
		}
	}
	private int randomInt(int a, int b) {
		int low = Math.min(a, b);
		int hi = Math.max(a, b);	
		return low+(int)((hi-low+1)*Math.random());
	}
	public void setImage(String filename)
	{
		try
		{
			img = ImageIO.read(getClass().getResource("/"+filename));

		} catch (Exception e) {

		}
	}
	public void setImage(BufferedImage img){
		this.img=img;
	}

	public void draw(Graphics g){
		if (img==null){
			g.setColor(Color.RED);
			g.fillOval(box.x, box.y, box.width, box.height);
		}else{
			g.drawImage(img, box.x, box.y, box.width, box.height, null);
		}
	}
	public boolean isEaten(Worm w){
		return box.intersects(w.getHead());
	}
}

WormTester.java

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
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 javax.swing.Timer;


public class WormTester extends Applet implements KeyListener, ActionListener
{
	private Rectangle area;
	private Image screen2;
	private Graphics g2;
	private Worm w;
	private Timer timer;
	private static final Color brown = new Color(100,50,25);
	private int addSgmtTic, prizeTic;
	private String message;
	private Prize p;

	public void init(){
		area = new Rectangle(20, 20, 700,500);
		w = new Worm(200,300,20,area);
		addKeyListener(this);
		screen2 = createImage(getWidth(),getHeight());
		g2 = screen2.getGraphics();
		this.setFocusable(true);
		this.requestFocus();
		timer = new Timer (100, this);
		addSgmtTic=0;
		prizeTic=0;
		message="";
		timer.start();

	}
	public void paint(Graphics g){
		screen2 = createImage(getWidth(),getHeight());
		g2 = screen2.getGraphics();
		g2.setColor(Color.WHITE);
		g2.fillRect(0, 0, getWidth(), getHeight());
		g2.setColor(brown);
		g2.fillRect(area.x, area.y, area.width, area.height);

		w.draw(g2);
		if (p!=null)
			p.draw(g2);

		g2.setColor(Color.BLUE);
		g2.drawString("Length is "+w.getLength(), area.x, area.y+area.height+20);

		g2.drawString(message, area.x+200, area.y+area.height+20);
		// finally draw to actual screen:
		g.drawImage(screen2, 0,0,this);
	}
	public void update(){
		repaint();
	}
	@Override
	public void keyTyped(KeyEvent e) {}

	@Override
	public void keyPressed(KeyEvent e) {}

	@Override
	public void keyReleased(KeyEvent e) {
		int code = e.getKeyCode();
		if (w.getDirection()!=Worm.EAST &&
			(code == KeyEvent.VK_LEFT || 
			code== KeyEvent.VK_A )  
			){
				w.setDirection(Worm.WEST);				
		} 
		if (w.getDirection()!=Worm.WEST &&
			(code == KeyEvent.VK_RIGHT || 
			code == KeyEvent.VK_D)){
			w.setDirection(Worm.EAST);
		}
		if (w.getDirection()!=Worm.SOUTH &&
				(code == KeyEvent.VK_UP || 
				code == KeyEvent.VK_W)){
				w.setDirection(Worm.NORTH);
		}
		if (w.getDirection()!=Worm.NORTH &&
				(code == KeyEvent.VK_DOWN || 
				code == KeyEvent.VK_S)){
				w.setDirection(Worm.SOUTH);
		}
		w.move();
		repaint();
	}
	@Override
	public void actionPerformed(ActionEvent e) {//from the timer
		addSgmtTic++;
		if (addSgmtTic>20){			
			if (w.addSegment())//reset if sucessful
				addSgmtTic=0;
		}
		prizeTic++;
		if (prizeTic>30){
			p=new Prize(10, 20, 20, w);
			prizeTic=0;
		}
		message="";
		if (!w.move())
			message="Wall collision detected";
		if(w.isTwisted())
			message+=" Collision with self detected";
		if(p!=null && p.isEaten(w)){
			message+=" Prize eaten!";
			p=null;
			//increase score?
		}
		repaint();

	}

}