// Iceblox// By Karl Hörnell, April 8 1996import java.awt.*;import java.awt.image.*;import java.net.*;public final class iceblox extends java.applet.Applet implements Runnable{	int i,j,k;	final int playX=390,playY=330,mainX=390,mainY=348,smalls=48,blockX=13,blockY=11;	final int animP[]={7,8,9,8,10,11,12,11,4,5,6,5,1,2,3,2};	final int animF[]={32,33,34,35,36,35,34,33};	final int levFlame[]={2,3,4,2,3,4},levRock[]={5,6,7,8,9,10};	final int levSpeed[]={3,3,3,5,5,5},levIce[]={35,33,31,29,27,25};	final int effMax=5;	int playArea[];	int gameState,counter,dir,inFront,inFront2,level,coins;	int effLevel,lives=3;	int x[],y[],dx[],dy[],motion[],look[],creature[],ccount[],actors,flames;	int sideIX[]={0,-1,1,-15,15},coorDx[]={0,-30,30,0,0},coorDy[]={0,0,0,-30,30};	Image collection,offImage,playField,small[],title;	Graphics offGraphics,playGraphics,tempG;	MediaTracker tracker;	ImageFilter filter;	ImageProducer collectionProducer;	long snooze=100,score;	Thread game;	Math m;	public void init()	{		setBackground(Color.black);		offImage=createImage(mainX,mainY);		offGraphics=offImage.getGraphics();		offGraphics.setColor(Color.black);		offGraphics.fillRect(0,0,mainX,mainY);		playField=createImage(playX,playY);		playGraphics=playField.getGraphics();		playGraphics.setColor(Color.black);		tracker=new MediaTracker(this);		collection = getImage(getCodeBase(),"iceblox.gif");		tracker.addImage(collection,0);		try		{			tracker.waitForID(0);		}			catch(InterruptedException e) {}		collectionProducer=collection.getSource();		small=new Image[smalls];		k=0;i=0;j=0;		while (k<smalls)		{			filter=new CropImageFilter(j*30,i*30,30,30);			small[k]=createImage(new FilteredImageSource(				collectionProducer,filter));			tracker.addImage(small[k],1);/*			small[k]=createImage(30,30);			tempG=small[k].getGraphics();			tempG.drawImage(collection,-j*30,-i*30,this);*/			k++;			j++;			if (j==8)			{				j=0;				i++;			}		}		filter=new CropImageFilter(0,180,224,64);		title=createImage(new FilteredImageSource(				collectionProducer,filter));		tracker.addImage(title,1);				playArea=new int[(blockX+2)*(blockY+3)];		x=new int[20];		y=new int[20];		dx=new int[20];		dy=new int[20];		look=new int[20];		motion=new int[20];		creature=new int[20];		ccount=new int[20];				gameState=7;		try		{			tracker.waitForID(1);		}			catch(InterruptedException e) {}		resize(mainX,mainY);	}	public void run()	{		while (game !=null)		{			try			{				game.sleep(snooze);			} catch (InterruptedException e) {}			counter=(counter+1)&255;			switch (gameState)			{				case 0:					prepareField();					break;				case 1:					showField();					break;				case 2:					gameLoop();					break;				case 3:					happyPenguin();					break;				case 4:					clearField();					break;				case 5:					fixDeath();					break;				case 6:					gameOver();					break;				case 7:					drawIntro1();					break;				case 8:					waitIntro1();					break;				case 9:					drawIntro2();					break;				case 10:					waitIntro2();					break;				case 11:					drawIntro3();					break;				case 12:					waitIntro3();					break;				default:					break;			}			repaint();		}	}	public void start()	{		if (game==null)		{			game=new Thread(this);			game.start();		}	}	public void stop()	{		if ((game!=null)&&(game.isAlive()))		{			game.stop();		}		game=null;	}	public boolean keyDown(java.awt.Event e,int key)	{		if (gameState==2)		{			switch (key)			{				case 97:					dir=1; // A:Left					break;				case 100:					dir=2; // D:Right					break;				case 107:					dir=3; // K:Up					break;				case 109:					dir=4; // M:Down					break;				default:					break;			}		}		else if ((gameState>6)&&(key==32))			gameState=0;		return false;	}		public boolean keyUp(java.awt.Event e,int key)	{		dir=0;		return false;	}		public void prepareField()	{		int i,j,p,q;		if (level>effMax)			effLevel=effMax;		else			effLevel=level;		offGraphics.setColor(Color.black);		offGraphics.fillRect(0,0,mainX,mainY);		playGraphics.setColor(Color.black);		playGraphics.fillRect(0,0,playX,playY);		offGraphics.setColor(Color.lightGray);		offGraphics.fill3DRect(0,mainY-playY-4,mainX,4,true);		offGraphics.setColor(Color.white);		offGraphics.drawString("SCORE:",2,12);		updateScore(0);		offGraphics.drawString("LEVEL:  "+(level+1),125,12);		offGraphics.drawString("SPARE LIVES:",220,12);		for (i=0;i<lives;i++)			offGraphics.drawImage(small[13],300+i*15,-16,this);		for (i=0;i<(blockX+2)*(blockY+3);i++)			playArea[i]=1;		for (i=1;i<=blockY;i++)			for (j=1;j<=blockX;j++)				playArea[i*(blockX+2)+j]=0;		playArea[blockX+3]=1; // Make room for start square		i=0;		while (i<levIce[effLevel]) // Ice cubes		{			p=1+(int)(m.random()*blockX);			q=1+(int)(m.random()*blockY);			if (playArea[q*(blockX+2)+p]==0)			{				playArea[q*(blockX+2)+p]=2;				playGraphics.drawImage(small[16],(p-1)*30,(q-1)*30,this);				i++;			}		}		i=0;		while (i<levRock[effLevel]) // Rock		{			p=1+(int)(m.random()*blockX);			q=1+(int)(m.random()*blockY);			if (playArea[q*(blockX+2)+p]==0)			{				playArea[q*(blockX+2)+p]=1;				playGraphics.drawImage(small[14],(p-1)*30,(q-1)*30,this);				i++;			}		}		i=0;		while (i<5) // Coins		{			p=1+(int)(m.random()*blockX);			q=1+(int)(m.random()*blockY);			if (playArea[q*(blockX+2)+p]==0)			{				playArea[q*(blockX+2)+p]=10;				playGraphics.drawImage(small[24],(p-1)*30,(q-1)*30,this);				i++;			}		}		playArea[blockX+3]=0; // Clear start square		gameState=1;		snooze=100;		counter=0;		motion[0]=0;		actors=1;		coins=0;		flames=0;		look[0]=0;		x[0]=30;		y[0]=30;		dx[0]=6;		dy[0]=6;		look[0]=2;		creature[0]=1;		for (i=0;i<20;i++)			ccount[i]=0;	}	public void showField()	{		Graphics saveGraphics;		saveGraphics=offGraphics.create();		offGraphics.clipRect(playX/2-(counter*playX/2/30),mainY-playY+		playY/2-(counter*playY/2/30),counter*playX/30,counter*playY/30);		offGraphics.drawImage(playField,0,mainY-playY,this);		if (counter==30)		{			gameState=2;			snooze=100;		}		offGraphics=saveGraphics;	}	public void gameLoop()	{		if (flames<levFlame[effLevel])		{			if (x[0]<(playX/2))				x[actors]=playX+30;			else				x[actors]=0;			y[actors]=30*(1+(int)(m.random()*blockY));			j=(y[actors]/30)*(blockX+2)+x[actors]/30;			motion[actors]=0;			dx[actors]=levSpeed[effLevel];			dy[actors]=levSpeed[effLevel];			creature[actors]=4;			if ((playArea[j+1]==0)||(playArea[j-1]==0))			{				actors++;				flames++;			}		}		for (i=0;i<actors;i++)		{			ccount[i]++;			switch(motion[i])			{				case 1:					x[i]-=dx[i];					break;				case 2:					x[i]+=dx[i];					break;				case 3:					y[i]-=dy[i];					break;				case 4:					y[i]+=dy[i];					break;				default:					break;			}			j=(y[i]/30)*(blockX+2)+x[i]/30;			switch(creature[i])			{				case 1: // Penguin					if ((x[i]%30 == 0)&&(y[i]%30 == 0))						motion[i]=0;					if (motion[i]==0)					{						inFront=playArea[j+sideIX[dir]];						if ((j+2*sideIX[dir])<0)							inFront2=1;						else							inFront2=playArea[j+2*sideIX[dir]];						if (inFront==0)							motion[i]=dir;						else						{							if ((inFront2==0)&&((inFront==2)||(inFront==10))) // Push ice block?							{								if (inFront==2)								{									creature[actors]=2;									look[actors]=16;								}								else								{									creature[actors]=3;									look[actors]=24;								}								x[actors]=x[i]+coorDx[dir];								y[actors]=y[i]+coorDy[dir];								dx[actors]=15;								dy[actors]=15;								playGraphics.fillRect(x[actors]-30,y[actors]-30,30,30);								motion[actors]=dir;								actors++;								playArea[j+sideIX[dir]]=0;							}							else if ((inFront>1)&&(inFront<18)) // Crack ice							{								playArea[j+sideIX[dir]]++;								if (inFront==9) // All cracked?								{									playGraphics.fillRect(x[i]+coorDx[dir]-30,y[i]+coorDy[dir]-30,30,30);																		playArea[j+sideIX[dir]]=0;									updateScore(5);								}								else if (inFront==17)								{									playGraphics.fillRect(x[i]+coorDx[dir]-30,y[i]+coorDy[dir]-30,30,30);																		playArea[j+sideIX[dir]]=0;									updateScore(100);									coins++;								}								else									playGraphics.drawImage(small[inFront+15],x[i]+coorDx[dir]-30,y[i]+coorDy[dir]-30,this);							}						}					}					if (motion[i]!=0)						look[i]=animP[(motion[i]-1)*4+counter%4];					for (k=1;k<actors;k++)						if (creature[k]==4)							if (((x[k]-x[i])<20)&&((x[i]-x[k])<20)&&((y[k]-y[i])<20)&&((y[i]-y[k])<20))							{								creature[k]=6;								x[k]=0;								y[k]=0;								motion[k]=0;								ccount[i]=0;								dx[i]=0;								dy[i]=0;								creature[i]=7;							}					break;									case 2: // Moving ice block					if ((x[i]%30 == 0)&&(y[i]%30 == 0)&&(playArea[j+sideIX[motion[i]]]!=0))					{						playArea[j]=2;						playGraphics.drawImage(small[16],x[i]-30,y[i]-30,this);						removeActor(i);					}					break;				case 3: // Moving frozen coin					if ((x[i]%30 == 0)&&(y[i]%30 == 0)&&(playArea[j+sideIX[motion[i]]]!=0))					{						playArea[j]=10;						playGraphics.drawImage(small[24],x[i]-30,y[i]-30,this);						removeActor(i);					}					break;				case 4: // Flame					look[i]=animF[counter%8];					if (motion[i]==0)						motion[i]=(int)(1+m.random()*4);					if ((x[i]%30 == 0)&&(y[i]%30 == 0)) // Track penguin					{						if (((x[i]-x[0])<3)&&((x[0]-x[i])<3))						{							if (y[i]>y[0])								motion[i]=3;							else								motion[i]=4;						}						else if (((y[i]-y[0])<3)&&((y[0]-y[i])<3))						{							if (x[i]>x[0])								motion[i]=1;							else								motion[i]=2;						}						if (playArea[j+sideIX[motion[i]]]!=0)							motion[i]=0;					}					for (k=1;k<actors;k++) // Colliding with moving block?						if ((creature[k]&254)==2)							if (((x[k]-x[i])<30)&&((x[i]-x[k])<30)&&((y[k]-y[i])<30)&&((y[i]-y[k])<30))							{								creature[i]=5;								k=actors;								look[i]=37;								motion[i]=0;								ccount[i]=0;								updateScore(50);							}					break;				case 5: // Flashing "50"					look[i]=37+(counter&1);					if (ccount[i]>20)					{						flames--;						removeActor(i);					}					break;				case 6: // Dummy					break;				case 7: // Skeleton					if (ccount[i]<8)						look[i]=39+ccount[i];					else if (ccount[i]<30)						look[i]=47;					else					{						lives--;						if (lives<0)							gameState=5;						else						{							actors=1;							flames=0;							counter=0;							dx[i]=6;							dy[i]=6;							creature[0]=1;							look[0]=2;							offGraphics.setColor(Color.black);							offGraphics.fillRect(300,0,45,14);							for (k=0;k<lives;k++)								offGraphics.drawImage(small[13],300+k*15,-16,this);						}					}					break;				default:					break;			}		}		if (coins>4)		{			gameState=3;			updateScore(1000);			counter=0;			coins=0;			offGraphics.drawImage(playField,0,mainY-playY,this);		}	}	public void happyPenguin()	{		if (counter>35)		{			level++;			gameState=4;			counter=0;		}	}	public void clearField()	{		offGraphics.setColor(Color.black);		offGraphics.fillRect(playX/2-(playX*counter/30),mainY-playY/2-(playY*counter/30),			playX*counter/15,playY*counter/15);		if (counter>14)			gameState=0;	}	public void fixDeath()	{		offGraphics.setColor(Color.black);		offGraphics.fillRect(0,0,mainX,mainY);		offGraphics.setColor(Color.white);		offGraphics.drawString("GAME OVER",175,100);		offGraphics.drawString("You scored "+score,160,130);		offGraphics.drawImage(small[2],190,150,this);		counter=0;		gameState=6;	}	public void gameOver()	{		if (counter>80)			gameState=7;	}	public void drawIntro1()	{		level=0;		score=0;		lives=3;		offGraphics.setColor(Color.black);		offGraphics.fillRect(0,0,mainX,mainY);		offGraphics.setColor(Color.white);		offGraphics.drawImage(title,(mainX-224)/2,10,this);		offGraphics.drawString("ACTORS AND OBJECTS",145,97);		offGraphics.drawImage(small[2],140,110,this);		offGraphics.drawString("Pixel Pete, the penguin",180,130);		offGraphics.drawImage(small[34],120,150,this);		offGraphics.drawImage(small[32],140,150,this);		offGraphics.drawString("Evil flames",180,170);		offGraphics.drawImage(small[16],140,190,this);		offGraphics.drawString("Ice cube",180,210);		offGraphics.drawImage(small[14],140,230,this);		offGraphics.drawString("Solid rock",180,250);		offGraphics.drawImage(small[24],140,270,this);		offGraphics.drawString("Frozen gold coin",180,290);		offGraphics.drawString("Press SPACE to start",138,330);		counter=0;		gameState=8;	}		public void waitIntro1()	{		offGraphics.setColor(Color.black);		offGraphics.fillRect(120,150,50,30);		offGraphics.drawImage(small[animF[(counter+2)&7]],120,150,this);		offGraphics.drawImage(small[animF[counter&7]],140,150,this);		if (counter>70)			gameState=9;	}	public void drawIntro2()	{		offGraphics.setColor(Color.black);		offGraphics.fillRect(0,75,mainX,230);		offGraphics.setColor(Color.white);		offGraphics.drawString("HOW TO PLAY",165,97);		offGraphics.drawImage(small[2],140,110,this);		offGraphics.drawString("Move up, down, left and right",180,122);		offGraphics.drawString("with the K, M, A and D keys",180,137);		offGraphics.drawImage(small[10],70,150,this);		offGraphics.drawImage(small[16],140,150,this);		offGraphics.drawString("Walk against ice cubes",180,162);		offGraphics.drawString("to move them out of the way",180,177);		offGraphics.drawLine(110,160,136,160);		offGraphics.drawLine(116,169,136,169);		offGraphics.drawImage(small[10],80,190,this);		offGraphics.drawImage(small[18],110,190,this);		offGraphics.drawImage(small[16],140,190,this);		offGraphics.drawString("Walk against blocked",180,202);		offGraphics.drawString("ice cubes to crack them",180,217);		offGraphics.drawImage(small[28],110,230,this);		offGraphics.drawImage(small[9],140,230,this);		offGraphics.drawString("Free the gold coins by",180,242);		offGraphics.drawString("crushing the ice around them",180,257);		offGraphics.drawImage(small[9],80,270,this);		offGraphics.drawImage(small[32],140,270,this);		offGraphics.drawLine(110,280,126,280);		offGraphics.drawLine(110,289,130,289);		offGraphics.drawString("And watch out",180,282);		offGraphics.drawString("for the flames",180,297);		gameState=10;		counter=0;	}		public void waitIntro2()	{		offGraphics.setColor(Color.black);		offGraphics.drawImage(small[1+(counter % 12)],140,110,this);		offGraphics.fillRect(140,270,30,30);		offGraphics.drawImage(small[animF[counter&7]],140,270,this);		if (counter>80)			gameState=11;	}	public void drawIntro3()	{		offGraphics.setColor(Color.black);		offGraphics.fillRect(0,75,mainX,230);		offGraphics.setColor(Color.white);		offGraphics.drawString("SCORING",180,97);		offGraphics.drawImage(small[10],110,110,this);		offGraphics.drawImage(small[18],140,110,this);		offGraphics.drawString("Breaking ice,",180,122);		offGraphics.drawString("5 points",180,137);		offGraphics.drawImage(small[33],60,150,this);		offGraphics.drawImage(small[16],80,150,this);		offGraphics.drawImage(small[9],140,150,this);		offGraphics.drawLine(112,160,126,160);		offGraphics.drawLine(112,169,130,169);		offGraphics.drawString("Putting out flame",180,162);		offGraphics.drawString("with ice, 50 points",180,177);		offGraphics.drawImage(small[10],110,190,this);		offGraphics.drawImage(small[27],140,190,this);		offGraphics.drawString("Freeing coin,",180,202);		offGraphics.drawString("100 points",180,217);		for (j=0;j<5;j++)			offGraphics.drawImage(small[15],100-9*j,230,this);		offGraphics.drawImage(small[39],140,230,this);		offGraphics.drawString("Taking all coins and advancing",180,242);		offGraphics.drawString("to next level, 1000 points",180,257);		gameState=12;		counter=0;	}		public void waitIntro3()	{		offGraphics.setColor(Color.black);		offGraphics.fillRect(60,150,20,30);		offGraphics.drawImage(small[animF[counter&7]],60,150,this);		offGraphics.drawImage(small[16],80,150,this);		if (counter>70)			gameState=7;	}	public void removeActor(int i)	{		int j;		for (j=i;j<actors;j++)		{			x[j]=x[j+1];			y[j]=y[j+1];			dx[j]=dx[j+1];			dy[j]=dy[j+1];			look[j]=look[j+1];			motion[j]=motion[j+1];			creature[j]=creature[j+1];		}		actors--;	}	public void updateScore(long i)	{		score+=i;		offGraphics.setColor(Color.black);		offGraphics.fillRect(50,0,60,12);		offGraphics.setColor(Color.white);		offGraphics.drawString(String.valueOf(score),50,12);	}	public void paint(Graphics g)	{		g.drawImage(offImage,0,0,this);	}	public void update(Graphics g)	{		int k;		switch (gameState)		{			case 2: // Playing				offGraphics.drawImage(playField,0,mainY-playY,this);				for (k=0;k<actors;k++)					offGraphics.drawImage(small[look[k]],x[k]-30,y[k]-30+mainY-playY,this);				break;			case 3:				offGraphics.drawImage(small[39*(counter&1)],x[0]-30,y[0]-30+mainY-playY,this);				break;			default:				break;		}				paint(g);	}}