Click here to Skip to main content
15,896,154 members
Articles / Mobile Apps

Nerdkill game for PocketPC

Rate me:
Please Sign up or sign in to vote.
4.46/5 (29 votes)
28 Jun 2004CPOL13 min read 101.8K   1.2K   35  
A shoot'em up platform in C# for the .NET Compact Framework.
//*******************************************************************
/*

	Solution:	NerdkillPocket
	Project:	NerdkillPocket
	File:		Resourcerer.cs

	Copyright 2003, 2004, Raphael MOLL.

	This file is part of NerdkillPocket.

	NerdkillPocket is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	NerdkillPocket is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with NerdkillPocket; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

*/
//*******************************************************************

using System;
using System.IO;
using System.Drawing;
using System.Reflection;
using System.Collections;

using Alfray.Nerdkill.Engine;

//*************************************
namespace Alfray.Nerdkill.Resources
{

	//**************************************
	/// <summary>
	/// Summary description for Resourcerer.
	/// </summary>
	//**************************************
	public class Resourcerer: IEngineResources
	{
		//-------------------------------------------
		//----------- Public Constants --------------
		//-------------------------------------------


		//-------------------------------------------
		//----------- Public Properties -------------
		//-------------------------------------------



		//-------------------------------------------
		//----------- Public Methods ----------------
		//-------------------------------------------


		//******************
		public Resourcerer()
		{
			mSpriteTable = new Hashtable();
			mSoundTable = new Hashtable();
		}



		//********************************************
		public bool SetContext(IEngineContext context)
		{
			mContext = context;
			return true;
		}



		#region IEngineResources Members


		//*******************
		/// <summary>
		/// Inherited from IDisposable
		/// </summary>
		//*******************
		public void Dispose()
		{
			clearSprites();
			clearSounds();
		}


		//************************************
		public Icon LoadIcon(string leaf_name)
		{
			// leaf_name is the leaf base name (no extension)

			// will try with extension .icon
			string [] ext_list = { ".ico" };


			// try to find a file within the resources

			try
			{
				System.Type st = this.GetType();
				if (st != null)
				{
					Assembly assembly = st.Assembly;

					// get a list of all resources names (note: these are FULL names, which
					// include the namespace of this class, a period and the filename)
					string [] names = assembly.GetManifestResourceNames();

					string ns_period = st.Namespace + ".";

					foreach(string ext in ext_list)
					{
						try
						{
							string filename = ns_period + leaf_name + ext;

							foreach(string name in names)
							{
								if (name == filename)
								{
									// Bitmap bmp = new Bitmap(this.GetType(), filename);
									Icon ico = new Icon(assembly.GetManifestResourceStream(filename));
									if (ico != null)
										return ico;
								}
							}
						}
						catch(Exception ex)
						{
							System.Diagnostics.Debug.Write(ex.Message, "\nLoadIcon [rsrc " + leaf_name + ext + "]");
						}
					}
				}
			}
			catch(Exception ex)
			{
				System.Diagnostics.Debug.Write(ex.Message, "\nLoadIcon [rsrc " + leaf_name + "]");
			}

			System.Diagnostics.Trace.Assert(false, "Can't find icon '" + leaf_name + "' in resources!");

			return null;
		}



		//****************************************
		public Bitmap LoadBitmap(string leaf_name)
		{
			// leaf_name is the leaf base name (no extension)

			// will try with extensions .png, .jpg and .gif
			string [] ext_list = { ".png", ".jpg", ".gif" };


			// try to find a file within the resources

			try
			{
				System.Type st = this.GetType();
				if (st != null)
				{
					Assembly assembly = st.Assembly;

					// get a list of all resources names (note: these are FULL names, which
					// include the namespace of this class, a period and the filename)
					string [] names = assembly.GetManifestResourceNames();

					string ns_period = st.Namespace + ".";

					foreach(string ext in ext_list)
					{
						try
						{
							string filename = ns_period + leaf_name + ext;

							foreach(string name in names)
							{
								if (name == filename)
								{
									// Bitmap bmp = new Bitmap(this.GetType(), filename);
									Bitmap bmp = new Bitmap(assembly.GetManifestResourceStream(filename));
									if (bmp != null)
										return bmp;
								}
							}
						}
						catch(Exception ex)
						{
							System.Diagnostics.Debug.Write(ex.Message, "\nLoadBitmap [rsrc " + leaf_name + ext + "]");
						}
					}
				}
			}
			catch(Exception ex)
			{
				System.Diagnostics.Debug.Write(ex.Message, "\nLoadBitmap [rsrc " + leaf_name + "]");
			}

			System.Diagnostics.Trace.Assert(false, "Can't find bitmap '" + leaf_name + "' in resources!");

			return null;
		}


		//**********************
		public bool LoadSounds()
		{
			int i;

			// -- discard existing sounds --

			clearSounds();


			// -- load all sounds --

			for(i = 0; i < RConstants.NbSoundFun; i++)
				insertSound(String.Format("nerdfun{0}.wav", i+1), RConstants.SoundId.FunVariant, false, i);

			for(i = 0; i < RConstants.NbSoundDeadAh; i++)
				insertSound(String.Format("n_ah{0}.wav", i+1), RConstants.SoundId.DeadAhVariant, false, i);

			insertSound("nerd_in.wav",	RConstants.SoundId.NerdIn,		false, 0);
			insertSound("nerd_out.wav",	RConstants.SoundId.NerdOut,		false, 0);
			insertSound("n_elec1.wav",	RConstants.SoundId.Elec,		false, 0);
			insertSound("n_explos.wav",	RConstants.SoundId.Explode,		false, 0);
			insertSound("n_gun1.wav",	RConstants.SoundId.Gun,			false, 0);
			insertSound("n_mine.wav",	RConstants.SoundId.Mine,		false, 0);
			insertSound("n_roul2.wav",	RConstants.SoundId.Bull,		false, 0);
			insertSound("n_select.wav",	RConstants.SoundId.Select,		false, 0);

			insertSound("n_gun2.wav",	RConstants.SoundId.UziRepeat,	true,  0);
			insertSound("n_roul1.wav",	RConstants.SoundId.BullRepeat,	true,  0);


			return true;
		}


		//***********************
		public bool LoadSprites()
		{
			Bitmap bmp;
			int i;

			// -- discard existing sprites --

			clearSprites();

			// -- process splashscreen --

			/*
			bmp = LoadBitmap("splashscreen");

			insertSprite(bmp, RConstants.SpriteId.SplashScreen, 0, 0, 0, 240, 272, false, 1);

			bmp.Dispose();	// RM 20040516 fix dispose bitmaps
			*/

			// -- process background --

			bmp = LoadBitmap("background");

			insertSprite(bmp, RConstants.SpriteId.MainBackground, 0, 0, 0, 480, 268, false, 1);

			bmp.Dispose();	// RM 20040516 fix dispose bitmaps

			
			// -- menu/weapons panel -- 

			bmp = LoadBitmap("board256");

			insertSprite(bmp, RConstants.SpriteId.MenuBackground,	0, 0,0, 240, 48, false, 1);

			bmp.Dispose();	// RM 20040516 fix dispose bitmaps


			// -- process sprites --

			bmp = LoadBitmap("sprites256");

			for(i=0; i<2; i++)
			{
				// nerd fix, right, top, left, bottom
				insertSprite(bmp, RConstants.SpriteId.NerdFix,		i, i+0,0, 1,1, true);
				insertSprite(bmp, RConstants.SpriteId.NerdMovRight,	i, i+2,0, 1,1, true);
				insertSprite(bmp, RConstants.SpriteId.NerdMovUp,	i, i+0,2, 1,1, true);
				insertSprite(bmp, RConstants.SpriteId.NerdMovLeft,	i, i+2,1, 1,1, true);
				insertSprite(bmp, RConstants.SpriteId.NerdMovDown,	i, i+0,1, 1,1, true);

				// nerd electrocuted
				insertSprite(bmp, RConstants.SpriteId.NerdElec,		i, i+4,0, 1,1, true);

				// bulldozer
				insertSprite(bmp, RConstants.SpriteId.Bulldozer,	i, i*2,3, 2,2, true);

				// coke
				insertSprite(bmp, RConstants.SpriteId.CokeCan,		i, i*2+4,3, 2,2, true);
			}
			
			// painfully dead
			insertSprite(bmp, RConstants.SpriteId.NerdDeadNormal,	0, 4,1, 1,1, true);
			insertSprite(bmp, RConstants.SpriteId.NerdDeadExploded,	0, 5,1, 1,1, true);
			insertSprite(bmp, RConstants.SpriteId.NerdDeadShade,	0, 6,1, 1,1, true);

			// dead electrocuted
			insertSprite(bmp, RConstants.SpriteId.NerdDeadElec,		0, 6,0, 1,1, true);
			
			// shoot target
			insertSprite(bmp, RConstants.SpriteId.ShootImpact,		0, 7,0, 1,1, true);

			// mines
			insertSprite(bmp, RConstants.SpriteId.MineNormal,		0, 4,2, 1,1, true);
			insertSprite(bmp, RConstants.SpriteId.MineExploding,	0, 5,2, 1,1, true);

			// the one-dot nerd finder point
			insertSprite(bmp, RConstants.SpriteId.NerdFinderPoint,		0, 7*kBlockSize,1*kBlockSize,  1, 1, false, 1);
			insertSprite(bmp, RConstants.SpriteId.NerdFinderBack,		0, 7*kBlockSize,2*kBlockSize, 12, 7, false, 1);

			bmp.Dispose();	// RM 20040516 fix dispose bitmaps

			// inactive + active menu/weapons
			
			bmp = LoadBitmap("weapons24");

			for(i=0; i<2; i++)
			{
				insertSprite(bmp, RConstants.SpriteId.WeaponGun,		i, 0+i*4,0, 1,1, true, 24);
				insertSprite(bmp, RConstants.SpriteId.WeaponUzi,		i, 1+i*4,0, 1,1, true, 24);
				insertSprite(bmp, RConstants.SpriteId.WeaponMine,		i, 2+i*4,0, 1,1, true, 24);
				insertSprite(bmp, RConstants.SpriteId.WeaponElec,		i, 3+i*4,0, 1,1, true, 24);

				insertSprite(bmp, RConstants.SpriteId.WeaponBull,		i, 0+i*4,1, 1,1, true, 24);
				insertSprite(bmp, RConstants.SpriteId.WeaponCoke,		i, 1+i*4,1, 1,1, true, 24);
				insertSprite(bmp, RConstants.SpriteId.WeaponDynamite,	i, 2+i*4,1, 1,1, true, 24);
				insertSprite(bmp, RConstants.SpriteId.WeaponFlag,		i, 3+i*4,1, 1,1, true, 24);
			}

			bmp.Dispose();	// RM 20040516 fix dispose bitmaps

			return true;
		}





		//**************************************************
		public RSprite GetSprite(RConstants.SpriteId sprite)
		{
			return GetSprite(sprite, 0);
		}



		//*************************************************************
		public RSprite GetSprite(RConstants.SpriteId sprite, int frame)
		{
			// get the sprite for 'frame'
			// if there's no such frame, take any existing lower frame

			for(; frame >= 0; frame--)
			{
				SSpriteKey key;
				key.mId = sprite;
				key.mFrame = frame;

				RSprite sp = (RSprite) mSpriteTable[key];

				if (sp != null)
					return sp;
			}

			return null;
		}





		//**********************************************
		public RSound GetSound(RConstants.SoundId sound)
		{
			return GetSound(sound, 0);
		}



		//*************************************************************
		public RSound GetSound(RConstants.SoundId sound, int variation)
		{
			// fail if there's no sound device
			if (!mContext.Sound.HasSound)
				return null;

			// get the sound for 'variation'
			// if there's no such variation, take any existing lower variation

			for(; variation >= 0; variation--)
			{
				SSoundKey key;
				key.mId = sound;
				key.mVariation = variation;

				RSound snd = (RSound) mSoundTable[key];

				if (snd != null)
					return snd;
			}

			return null;
		}


		#endregion

		//-------------------------------------------
		//----------- Private Methods ---------------
		//-------------------------------------------


		//*****************
		void clearSprites()
		{
			if (mSpriteTable == null)
				return;

			foreach(RSprite sp in mSpriteTable.Values)
			{
				mContext.Render2D.DisposeBuffer(sp.SpriteData);
			}

			mSpriteTable.Clear();
		}


		//****************
		void clearSounds()
		{
			if (mSoundTable == null)
				return;

			foreach(RSound sd in mSoundTable.Values)
			{
				mContext.Sound.DisposeBuffer(sd.SoundData);
			}

			mSoundTable.Clear();
		}


		//****************************************************
		bool insertSprite(Bitmap source,
						  RConstants.SpriteId id, int frame,
						  int x, int y, int width, int height,
						  bool transparent)
		{
			return insertSprite(source, id, frame, x, y, width, height, transparent, kBlockSize);
		}


		//****************************************************
		bool insertSprite(Bitmap source,
						  RConstants.SpriteId id, int frame,
						  int x, int y, int width, int height,
						  bool transparent, int size_coef)
		{
			// sx/sy and width/height are expressed in multiples of 32 pixels
			x *= size_coef;
			y *= size_coef;
			width *= size_coef;
			height *= size_coef;

			// extract the requested portion of the source bitmap
			// use the same pixel format
			// .Net Compact does not have Bitmap.Clone nor Bitmap.PixelFormat

			// create the sprite data
			Rectangle area = new Rectangle(x, y, width, height);
			Object data = mContext.Render2D.CreateBuffer(source, area, transparent);

			// create the sprite info
			RSprite sprite = new RSprite(id, /*new Point(x, y),*/ new Size(width, height), transparent, data);

			// create the hash table key
			SSpriteKey key = new SSpriteKey();
			key.mId = id;
			key.mFrame = frame;

			// insert in the hash table
			mSpriteTable.Add(key, sprite);

			return true;
		}


		//*************************************
		bool insertSound(string filename,
						 RConstants.SoundId id,
						 bool auto_repeat,
						 int variation)
		{
			// fail if there's no sound device
			if (!mContext.Sound.HasSound)
				return false;

			try
			{
				Assembly assembly = Assembly.GetCallingAssembly();
				Stream stream = assembly.GetManifestResourceStream(this.GetType(), filename);

				System.Diagnostics.Debug.Assert(stream != null);

				// getting the stream failed... how odd!
				if (stream == null)
					return false;

				// create the sound buffer
				Object data = mContext.Sound.CreateBuffer(stream);

				System.Diagnostics.Debug.Assert(data != null);
				// this is unlikely...
				if (data == null)
					return false;

				// create the sound
				RSound sound = new RSound(id, auto_repeat, data);

				// create the hash table key
				SSoundKey key = new SSoundKey();
				key.mId = id;
				key.mVariation = variation;

				// insert in the hash table
				mSoundTable.Add(key, sound);

				return true;
			}
			catch(Exception ex)
			{
				System.Diagnostics.Debug.Write(ex.ToString());
				// RM 20040512 .Net Compact does not have Trace.Fail
				System.Diagnostics.Trace.Assert(false, "Sound " + filename + " failed to load!", ex.Message);
			}

			return false;
		}



		//-------------------------------------------
		//----------- Private Types -----------------
		//-------------------------------------------

		//-----------------------
		private struct SSpriteKey
		{
			public RConstants.SpriteId	mId;
			public int					mFrame;

			public override int GetHashCode()
			{
				return ((int)mId) * 4 + mFrame;
			}
		}


		//----------------------
		private struct SSoundKey
		{
			public RConstants.SoundId	mId;
			public int					mVariation;

			public override int GetHashCode()
			{
				return ((int)mId) * 256 + mVariation;
			}
		}


		//-------------------------------------------
		//----------- Private Attributes ------------
		//-------------------------------------------

		private const int	kBlockSize = 16;

		private IEngineContext mContext;

		private Hashtable	mSpriteTable;
		private Hashtable	mSoundTable;


	} // class Resourcerer
} // namespace Alfray.Nerdkill.Resources


//---------------------------------------------------------------
//
//	$Log: Resourcerer.cs,v $
//	Revision 1.3  2004/05/27 17:25:06  ralf
//	Scroll event for directional keys
//	
//	Revision 1.2  2004/05/26 08:49:18  ralf
//	Polishing.
//	
//	Revision 1.1.1.1  2004/05/24 14:21:58  ralf
//	Stable port to PockerPC/.Net Compact Framework.
//	Uses .Net/GDI+ for graghic. Uses WinCE's SoundPlay for sound.
//	
//---------------------------------------------------------------

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
Raphael is a senior software engineer with a background in electronics engineering.
He enjoys programming in C++ since 1994.
He developed professional software for the BeOS and now focuses on Windows, MacOS and Linux software development.
He uses C++, C#, Java,VB.Net, PHP, Bash and Perl on a regular basis. He is familiar with C, Objective-C, VB6, Python, ML, Haskell, Lisp, Scheme, some obsolete languages (Basic and Pascal) and x86/Motorola assembly languages.
Raphael is a big fan of the .Net platform.
A number of open source personal projects can be found on his web site.

Comments and Discussions