In this episode, we continue with the floaters.  Among some strange new things that we'll have to deal with concerning the 
floaters is how to set the properties of the floater using the editor.  Other things like using the floater arraylist and file 
I/O should be common knowledge by now.

First, we will only be concerning ourselves with getting multiple floaters.  This should be simple by now, but I'll show it 
again (as always).
Declaration:

		ArrayList floaters;
		/* This holds all of the floaters that are in the level */
Initialization - replace this:
			floater = new levfloater(new Rectangle(480, 280, thefloatersize, thefloatersize), 5, 5, 16, 16, desgperiodic.cosinefxn, desgperiodic.sinefxn );
			// Set up floater information.
With this:
			floaters = new ArrayList(10);
			floaters.Add(new levfloater(new Rectangle(480, 280, thefloatersize, thefloatersize), 5, 5, 16, 16, desgperiodic.cosinefxn, desgperiodic.sinefxn ));
			floaters.Add(new levfloater(new Rectangle(100, 100, thefloatersize, thefloatersize), 5, 5, 16, 16, desgperiodic.cosinefxn, desgperiodic.stable));
			// Put some floaters' information into the floater list.
To draw these floaters, replace the existing code for drawing one floater with:
			foreach (levfloater floater in floaters) 
			{
				gfx.DrawImage(floatbmp, floater.Loc);
				// Draw the floater.
			}
And to support multiple floater movement, we use a For Loop, as shown below. Notice that I am not using a For Each loop. This is because we are changing the value of the floater. Since Floater is a structure, not a class reference, we have to assign the Floater to a floater variable, modify the floater variable, and put it back in the arraylist. This is similar to what we did with the coins (when they were collected, they were set to empty rectangles). Also, notice that the FloatTick does not go into this loop. It only needs to be incremented once:
			for (lv = 0; lv < floaters.Count; lv++) 
			{

				//Get a floater from the arraylist and move it.
				floater = (levfloater)floaters[lv];

				switch (floater.HorizFxn) 
				{
					case desgperiodic.cosinefxn:
						dx = (int)(floater.radispeedX * Math.Cos((double)floater.XFrequency * floattick / thefrequencydivider));
						break;
					case desgperiodic.sinefxn:
						dx = (int)(floater.radispeedX * Math.Sin((double)floater.XFrequency * floattick / thefrequencydivider));
						break;
					default:
						dx = 0;
						break;
				}
				//Calculates how much to move horizontally.
				switch (floater.VertFxn) 
				{
					case desgperiodic.cosinefxn:
						dy = (int)(floater.radispeedY * Math.Cos((double)floater.YFrequency * floattick / thefrequencydivider));
						break;
					case desgperiodic.sinefxn:
						dy = (int)(floater.radispeedY * Math.Sin((double)floater.YFrequency * floattick / thefrequencydivider));
						break;
					default:
						dy = 0;
						break;
				}
				//Calculates how much to move vertically.

				floater.Offset(dx, dy);
				//And then the floater is moved.

				floaters[lv] = floater;
				//Must set the floater back into the array, otherwise changes above are discarded.
			}
			floattick += 1;
And we also have to check if any of the floaters have touched the player, so in the collision checks, change the existing code to this:
				foreach (levfloater floater in floaters) 
				{
					if (playerloc.IntersectsWith(floater.Loc )) 
					{
						// Touched the floater.
						isgoner = true;

						playerveloc = PFMain.thesbarinitialvelocity;
					}
				}
Now that that is done, you should have two decently functioning floaters on the form.
The next task would be to add floaters to the form using the editor. However, we are facing a problem because we have to create a new floater. Our previous endeavors required us to only create a rectangle at runtime, but now we have to find some way of setting the radius, frequency, and the periodic function to use. Clearly, we can't do this with just the mouse (aside from having loads of non-obvious shortcuts). We'll need to make a dialog form. So, press Ctrl+Shift+A (that's File->Add New Item) and add a new form to the project. Name it whatever you want, but mine is named FloaterEd. Now, let's add some NumericUpDown controls. Add one for the radispeed X (1), one for radispeed Y (2), one for frequency X (3), and one for frequency Y (4). To do the enumeration, we should add two comboboxes or listboxes. You can add whichever one you want, but I'm going to use comboboxes since they are so small. Now, for the numericupdown controls, we will set the maximum size for the radispeed. The radispeed is the radius times the frequency (divided by the frequencydivider of course), the radius should be no larger than 400 (half the width of the form), and, let's say the frequency shouldn't be any larger than 40, equal to 5120 / 128 (which is quite fast - you can try it - but ultimately the speed depends on the period of the periodic function that we are using). So, the maximum value for the radispeed should be 5120 * 400 which is about 204800. The chances of us using a number that high are quite low, but eventually we'll come back to make this easier. Now, we set the first two numericupdowns to have a maximum of 204800 and a minimum of -204800. The second two are the frequency functions and, as mentioned before, the maximum is 5120 (divided by the frequencydivider). The minimum would be 0 for even and odd periodic functions like cosine and sine, but we may have periodic functions that are neither even nor odd, so we'll set the minimum to -5120 for now. My comboboxes have their dropdownstyles both set to dropdownlist. We can also add some labels to this form so that we're not guessing when we edit the floater properties. Now, we need to add an OK button to the form. In this OK button, we will collect our values, convert them to integers and return a levfloater structure with everything set except for the rectangle. But, before we do that, we need to get the comboboxes working. We can use the Enum.GetNames to get an array containing the names of the elements in the enumeration. This will be handy because we will not have to update this form when we add more periodic functions.
		private void FloaterEd_Load(object sender, System.EventArgs e)
		{
			comboBox1.Items.AddRange(System.Enum.GetNames(desgperiodic.stable.GetType()));
			comboBox2.Items.AddRange(System.Enum.GetNames(desgperiodic.stable.GetType()));
			//lists all of the periodic functions in the combobox.
		}
Nothing to it, right? Now, for the OK button. We need to allow the game form to interact with the floater on this form. So, first, we'll declare a private LevFloater variable and make a readonly accessor so that we can return this LevFloater variable to the other form.
		private levfloater flot;
		// Floater data that will be passed onto the game form.
		public levfloater Floater 
		{
			get 
			{
				return flot;
			}
		}
Then, we need to add the coding for the OK button.
		private void button1_Click(object sender, System.EventArgs e)
		{
			desgperiodic hf = (desgperiodic)comboBox1.SelectedIndex;
			desgperiodic vf = (desgperiodic)comboBox2.SelectedIndex;
			//Extract functions from enumeration by way of the index.
			int xrspd = (int)this.numericUpDown1.Value;
			int yrspd = (int)this.numericUpDown2.Value;
			int xfreq = (int)this.numericUpDown3.Value;
			int yfreq = (int)this.numericUpDown4.Value;
			//extract floater properties from nud controls.

			//At this point, we know everything about the floater except where it is...
			//this will be determined by the editor.
			flot = new levfloater(Rectangle.Empty, xrspd, yrspd, xfreq, yfreq, hf, vf);
			//The floater is ready... we close the form.
			this.Close();
		}
And, we are finished with this form. Now, we return to the main game form, where we will begin adding the editor support and interface for floaters. First, we go to the KeyDown event so we can assign a key that denotes that we are using Floaters. "F" would be a logical choice.
			else if (e.KeyCode == Keys.F) 
			{
				if (!ismousedown)
				{
					modobject = 'F';
				}
			}
And, now we go to the MouseUp event, where the object that we have just drawn will be added to the appropriate form collection. Here, we'll have to show the form so that we can get the final six properties set on the floater. This has to be done before we assign the rectangle to the floater. Remember that we initialized the floater to have an empty rectangle, so we have to overwrite this rectangle to complete the floater.
				case 'F':
					FloaterEd F = new FloaterEd();
					//Create the new prompt form.
					levfloater ftr;
					clock.Stop();
					//Stops the timer so that it doesn't run in excess while we are putting in floater info.
					F.ShowDialog();
					//Show dialog.  Execution continues when it closes.
					ftr = F.Floater;
					//Get data from form to our floater.
					ftr.Loc = new Rectangle(initialpt.X, initialpt.Y, thefloatersize, thefloatersize);
					//Set the location property that we know now.
					floaters.Insert(0, ftr);
					//Insert into list of floaters.
					//Note that after we add the floater to the form, its current movement is not indicative of its movement
					//immediately after we load from the file.
					clock.Start();
					break;
So, the floater will not be moving in the same circle or whatever shape assigned to it. The shape will be shifted somehow based on the value of FloatTick. But, it should work.
Now, to put these floaters into the file. This might seem easy:
				bw.Write(floaters.Count);
				//Write floaters to the file.
				foreach (levfloater floater in floaters) 
				{
					bw.Write(floater.Loc.Left);
					bw.Write(floater.Loc.Top);
					bw.Write(floater.radispeedX);
					bw.Write(floater.radispeedY);
					bw.Write(floater.XFrequency);
					bw.Write(floater.YFrequency);
					bw.Write(floater.HorizFxn);
					bw.Write(floater.VertFxn);
				}
And that's all there is to it, right? Wrong. Why? We remembered not to save the right and bottom of the floater. Keep in mind that the floaters are moving the whole while, so, if you were to save this one file over and over again, you'd probably find the floaters mysteriously drift over to the right side of the screen. So, how do we fix this so that our floaters don't drift upon each save and load? A. Disable the floater movement block. B. Disable the floattick increment. C. Disable the timer enabling event. Disabling the timer enabling event would stop the floaters from moving, but it would also stop any new drawings from being made. Disabling the floattick increment would not stop the movement of the floaters. The correct answer is A., to disable the floater movement in the CharacterMovement sub. Now, how do we disable the entire For loop? Well, since we do not want the floaters to move while we are in the editor (the TESTversion), we will simply wrap the entire block in #if !TESTversion Then ... #endif Note that this is the same problem that occurs if you collect a coin before you save the level. You'd see one or more coins have magically teleported to the upper left corner of the screen, because, despite them being collected, their coordinates remain in the coins arraylist. Wrapping the coin collection block with the same #If compilation block would prevent coins from being collected while the testversion is running. You could also remove the coins from the arraylist, but I'm not going to do that. Set up some floaters and save them to file.
Now, to load the floaters back from file, we just add this.
			floaters = new ArrayList(br.ReadInt32());
			// Floater count.
			for (lv = 0; lv < floaters.Capacity; lv++) 
			{
				floaters.Add(new levfloater(new Rectangle(br.ReadInt32(), br.ReadInt32(), thefloatersize, thefloatersize), br.ReadInt32(), br.ReadInt32(),
					br.ReadInt32(), br.ReadInt32(), (desgperiodic)br.ReadInt32(), (desgperiodic)br.ReadInt32()));
				//Put all of this information.  It's important that the integers are written to the file in order of their parameters.
				//Otherwise, we'd need temporary variables to reroute the data coming from file.
			}
Notice, we have to use casts to convert the enumeration value back from an Integer. Don't forget to remove this from the load procedure:
			floaters = new ArrayList(10);
			floaters.Add(new levfloater(new Rectangle(480, 280, thefloatersize, thefloatersize), 5, 5, 16, 16, desgperiodic.cosinefxn, desgperiodic.sinefxn ));
			floaters.Add(new levfloater(new Rectangle(100, 100, thefloatersize, thefloatersize), 5, 5, 16, 16, desgperiodic.cosinefxn, desgperiodic.stable));
			// Put some floaters' information into the floater list.
Undefine the TESTversion #constant so you can see the floaters move. That concludes this section on floaters. Next, we'll do a little bit of scenario handling for the jumping.