C# .NET 4.0 Drag and drop between two applications - c#

So I'd really like to drag and drop data between two instances of an application; however, if there is data present at the target point where I am dropping, I would like to swap that data with what is being dropped.
I'm trying to use a MemoryMappedFIle, and that seems to work most of the time, but it's not perfect. For example, if I do the drag / drop too quickly, the target data is simply overwritten (I assume it's not being written to the MemoryMappedFile quickly enough). Does anyone have any recommendations?
This is what I currently have:
private void pbSprite_MouseDown(object sender, MouseEventArgs e)
{
PictureBox pb = (PictureBox)(sender);
DataObject data = new DataObject();
if (pb.Name == pbSprite.Name)
{
data = new DataObject(DataFormats.Serializable, frmpkm);
}
else
{
data = new DataObject(DataFormats.Serializable, frmpkm2);
}
pb.DoDragDrop(data, DragDropEffects.Move);
MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateOrOpen("name", 1000, MemoryMappedFileAccess.ReadWrite);
using (MemoryMappedViewAccessor FileMap = MemoryMapped.CreateViewAccessor())
{
PKMDS.Pokemon otherpkm = new PKMDS.Pokemon();
for (int i = 0; i < Marshal.SizeOf(otherpkm); i++)
{
FileMap.Read<byte>(i, out otherpkm.Data[i]);
}
if (pb.Name == pbSprite.Name)
{
frmpkm.Data = otherpkm.Data;
}
else
{
frmpkm2.Data = otherpkm.Data;
}
lblData.Text = frmpkm.SpeciesName;
lblData2.Text = frmpkm2.SpeciesName;
pbSprite.Image = frmpkm.Sprite;
pbSprite2.Image = frmpkm2.Sprite;
}
}
private void pbSprite_DragDrop(object sender, DragEventArgs e)
{
if (e.Data != null)
{
PictureBox pb = (PictureBox)(sender);
PKMDS.Pokemon otherpkm = (PKMDS.Pokemon)e.Data.GetData(DataFormats.Serializable);
MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateOrOpen("name", 1000, MemoryMappedFileAccess.ReadWrite);
using (MemoryMappedViewAccessor FileMap = MemoryMapped.CreateViewAccessor())
{
for (int i = 0; i < Marshal.SizeOf(frmpkm); i++)
{
if (pb.Name == pbSprite.Name)
{
FileMap.Write<byte>(i, ref frmpkm.Data[i]);
}
else
{
FileMap.Write<byte>(i, ref frmpkm2.Data[i]);
}
}
}
if (pb.Name == pbSprite.Name)
{
frmpkm.Data = otherpkm.Data;
}
else
{
frmpkm2.Data = otherpkm.Data;
}
lblData.Text = frmpkm.SpeciesName;
lblData2.Text = frmpkm2.SpeciesName;
pbSprite.Image = frmpkm.Sprite;
pbSprite2.Image = frmpkm2.Sprite;
}
}

Two possible things to try
Move the call to pb.DoDragDrop(data, DragDropEffects.Move); after the creation of the memory mapped file. This will cause a delay in the start of the drag/drop action but should ensure that the data has been written to the file.
The other alternative is to write the data to the mmf in a separate thread and have it set and Event when the data is written. Then pbSprite_DragDrop can wait for the event to be signaled before reading from the file.

Related

Implementing a "Continuous Capture" with single image snaps

I have some code below that can take the current Image and displaying it whenever I click a PushSnap Button. How can I go about having it continuously capturing and displaying the updated image in an interval (say 100 ms)
private void PushSnap_Click(object sender, EventArgs e)
{
if (mycam == null)
{
MessageBox.Show("Internal Error: mycam is null");
return; // internal error
}
string text = "";
if (IsMyFormStatus_Opened())
{
if (!mydcam.buf_alloc(3))
{
MessageBox.Show("Frame allocation failed");
return;
}
}
// start acquisition
mycam.m_capmode = CAMCAP_START.SNAP; //one time capturing where Acquisition will start after m_nFrameCount frames
if (!mycam.cap_start())
{
return;
}
MyFormStatus_Acquiring();
MyThreadCapture_Start();
}
The Following MyThreadCapture_Start()
private void MyThreadCapture_Start()
{
m_threadCapture = new Thread(new ThreadStart(OnThreadCapture));
m_threadCapture.IsBackground = true;
m_threadCapture.Start();
}
and the following OnThreadCapture()
private void OnThreadCapture()
{
using (mycamwait = new MycamWait())
{
while (True)
{
CAMWAIT eventmask = CAMWAIT.CAPEVENT.FRAMEREADY | CAMWAIT.CAPEVENT.STOPPED;
DCAMWAIT eventhappened = DCAMWAIT.NONE;
if (mycamwait.start(eventmask, ref eventhappened))
{
if (eventhappened & CAMWAIT.CAPEVENT.FRAMEREADY)
{
int NewestFrame = 0;
int FrameCount = 0;
if (mycam.cap_transferinfo(ref NewestFrame, ref FrameCount))
{
MyUpdateImage(iNewestFrame);
}
}
if (eventhappened & CAMWAIT.CAPEVENT.STOPPED)
{
bContinue = false;
if (m_cap_stopping == false && mycam.m_capmode == CAMCAP_START.SNAP)
{
//cap_stop() happens automatically, therefore update the main dialog
//MySnapCaptureFinished();
}
}
}
}
}
Afterwards the Display is updated in the following way
private void UpdateDisplay()
{
Image oldImg = PicDisplay.Image;
if (m_bitmap != null)
{
// Show center of image
Int32 y0 = (m_image.height - PicDisplay.Height) / 2;
Int32 x0 = (m_image.width - PicDisplay.Width) / 2;
Rectangle rc = new Rectangle(x0, y0, PicDisplay.Width, PicDisplay.Height);
Bitmap bmp = new Bitmap(PicDisplay.Width, PicDisplay.Height, PixelFormat.Format24bppRgb);
using (var gr = Graphics.FromImage(bmp))
{
gr.DrawImage(m_bitmap, 0, 0, rc, GraphicsUnit.Pixel);
}
PicDisplay.Image = bmp;
PicDisplay.Refresh();
}
else
{
PicDisplay.Image = null;
}
if (oldImg != null)
oldImg.Dispose();
}
I would really recommend using Tasks instead of Threads. That should let you update your methods to take parameters and return results:
Image CaptureImage(); // I.e. similar code to OnThreadCapture
UpdateDisplay(Image);
And capture an image like:
public async void PushSnap_Click(){
...
try{
var image = await Task.Run(CaptureImage);
DisplayImage(image);
}
catch{
// Handle exceptions
}
That should let you simply rewrite your capture code to use a loop if you want live capture:
while(showLiveImagesBool){
var image = await Task.Run(CaptureImage);
DisplayImage(image);
}
The await-part should ensure the UI thread is not blocked while waiting for an image to be captured. If you do not want to show every image you might use a timer instead of a loop, just pick a timer that runs on the UI thread.
Keep in mind that showing live images will require a bit more performance, so you might need to optimize display and/or capture code. Ideally you should reuse image buffers when doing the capturing and displaying, otherwise you will allocate a fair amount of large objects that require a 2 gen GC to clean up.

Images slideshow with fade animation

I am writing a theater mode section in music player. The requirements is to loop through a folder containing images of any type(png, jpeg, gif) and show in a picture box with 5 seconds delay for images of type (png,jpeg) and delay time for gif should be the actual gif time duration. Also there should be fade transition between images when switch from one image to another in a single picture box. All need to be done when software is idle lets say for 60 seconds
Problem
Currently the playing song directory has 'img' folder containing 3 png
images and 3 gif. The first attempt to read
Helper.theaterImagesInfo.ToList() works pretty well
foreach (var img in Helper.theaterImagesInfo.ToList())
It starts to display 3 png images with 5 seconds delay and gif images
with the actual gif duration delay. but if i click picturebox to close theaterform as soon as the form is opened again after 60 seconds of idle state of software and loop continue
to iterate again. The default image is shown with
starting 2 png images from 'img' folder the 3rd png is skipped and then 4th gif starts
to play for few seconds not the actual gif duration and continued in wrong order as well as incorrect delay, Seems like while loop is always running in background. therfore it becomes choppy.
Desired Solution
Whenever i play song theaterform should be displayed and start to show images from folder ( in the same sequence and delay) even if the theaterform is opened again after 60 seconds if the song is still playing. Also if there is a way to show fade when changing image in a single picturebox
Code here
Program.cs
internal static class Program
{
public static Timer IdleTimer = new Timer();
readonly static int miliseconds =
Convert.ToInt32(TimeSpan.FromSeconds(60).TotalMilliseconds);
internal static MainForm f = null;
static public TheaterForm tf;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MessageFilter limf = new MessageFilter();
Application.AddMessageFilter(limf);
Application.Idle += new EventHandler(Application_Idle);
IdleTimer.Interval = miliseconds;
IdleTimer.Tick += TimeDone;
IdleTimer.Start();
f = new MainForm();
tf = new TheaterForm();
var app = new MyApplication();
app.Run(Environment.GetCommandLineArgs());
Application.Idle -= new EventHandler(Application_Idle);
}
static private void Application_Idle(Object sender, EventArgs e)
{
if (!IdleTimer.Enabled) // not yet idling?
IdleTimer.Start();
}
static private void TimeDone(object sender, EventArgs e)
{
IdleTimer.Stop();
if (MainForm.waveOut.PlaybackState == PlaybackState.Playing)
{
if (!Helper.IsTheaterOpen)
{
if (Form.ActiveForm == f)
{
Helper.IsTheaterOpen = true;
tf.WindowState = FormWindowState.Maximized;
tf.Bounds = Screen.PrimaryScreen.Bounds;
tf.x = 1;
tf.ShowDialog(f);
}
}
}
else
{
if (!Helper.IsTheaterOpen)
{
if (Form.ActiveForm == f)
{
Helper.IsTheaterOpen = true;
tf.WindowState = FormWindowState.Maximized;
tf.Bounds = Screen.PrimaryScreen.Bounds;
tf.x = 0;
tf.ShowDialog(f);
}
}
}
}
}
public class MyApplication : WindowsFormsApplicationBase
{
protected override void OnCreateMainForm()
{
MainForm = Program.f;
}
protected override void OnCreateSplashScreen()
{
SplashScreen = new SplashForm();
}
}
Helper.cs
internal class Helper
{
public static bool IsTheaterOpen { get; set; }
public struct ImageInfo
{
public bool IsAnimated;
public int durationInMilliseconds;
public Image ImageHere;
}
public static List<ImageInfo> theaterImagesInfo = new List<ImageInfo>(10);
}
MainForm.cs
/*
* Every song directory has one folder named img that contains images and gif relevant
to the song album
*/
private int GetGifDuration(Image img)
{
int delay = 0, this_delay = 0, index = 0;
FrameDimension frameDimension = new FrameDimension(img.FrameDimensionsList[0]);
int frameCount = img.GetFrameCount(frameDimension);
for (int f = 0; f < frameCount; f++)
{
this_delay = BitConverter.ToInt32(img.GetPropertyItem(20736).Value, index) * 10;
delay += (this_delay < 100 ? 100 : this_delay); // Minimum delay is 100 ms
index += 4;
}
return delay;
}
private void PlayAudio()
{
// Getting images from folder and storing in struct on every song play
if (Directory.Exists(Path.GetDirectoryName(CurrentPlayingMusicUrl) + "\\img"))
{
var files =
Directory.EnumerateFiles(Path.GetDirectoryName(CurrentPlayingMusicUrl) +
"\\img", "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".png") ||
s.EndsWith(".jpg") || s.EndsWith(".jpeg") || s.EndsWith(".gif"));
Helper.theaterImagesInfo.Clear();
foreach (var imagePath in files.ToArray())
{
using (System.Drawing.Image image = System.Drawing.Image.FromFile(imagePath))
{
if (image.RawFormat.Equals(ImageFormat.Gif))
{
Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = true, durationInMilliseconds = GetGifDuration(image), ImageHere = Image.FromFile(imagePath) });
}
else
{
Helper.theaterImagesInfo.Add(new Helper.ImageInfo { IsAnimated = false, durationInMilliseconds = 5000, ImageHere = Image.FromFile(imagePath) });
}
}
}
}
else
{
Helper.theaterImagesInfo.Clear();
Program.tf.x = 0;
}
}
TheaterForm.cs
public partial class TheaterForm : Form
{
public TheaterForm()
{
InitializeComponent();
SetDefaultImage();
}
/*
* Getting Default image from top(root) directory ex. AllMusic. If no 'img' folder
found in song album directory ex. AllMusic -> Justin Bieber -> (img folder not
exist)song1, song2, song3 etc.
*/
private async void SetDefaultImage()
{
string path = KJ_Player.Properties.Settings.Default["MusicFolder"] + "\\img";
if (Directory.Exists(path))
{
var files = Directory.EnumerateFiles(path, "*",
SearchOption.AllDirectories).Where(s => s.EndsWith(".png") ||
s.EndsWith(".jpg") || s.EndsWith(".jpeg"));
await Task.Run(() =>
{
if(files != null && files.Count()>0)
{
PictureBox1.Image = Image.FromFile(files.FirstOrDefault());
}
});
}
}
public int x=1;
private async void TheaterForm_Shown(object sender, EventArgs e)
{
if (this.PictureBox1.Image == null) SetDefaultImage();
if (Helper.theaterImagesInfo != null && Helper.theaterImagesInfo.Count > 0)
{
while (x == 1)
{
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
this.PictureBox1.Image = img.ImageHere;
await Task.Delay(img.durationInMilliseconds);
}
catch { }
}
else
{
try
{
await Task.Delay(img.durationInMilliseconds);
this.PictureBox1.Image = img.ImageHere;
}
catch { }
}
}
}
SetDefaultImage();
}
}
private void PictureBoxTheater_Click(object sender, EventArgs e)
{
this.x = 0;
if (this.PictureBox1.Image != null) this.PictureBox1.Image=null;
Helper.IsTheaterOpen = false;
this.Close();
}
}
Most likely you just need to break out of that foreach loop:
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
this.PictureBox1.Image = img.ImageHere;
await Task.Delay(img.durationInMilliseconds);
}
catch { }
}
else
{
try
{
await Task.Delay(img.durationInMilliseconds);
if (this.x == 1) {
this.PictureBox1.Image = img.ImageHere;
}
}
catch { }
}
if (this.x == 0) {
break; // exit the for loop early
}
}

Saving a bitmap from a variable gives "invalid parameter"

I need to save an image to disk that came from a web-cam between 5 and 10 seconds ago from when the "save" command comes in via serial port.
To get there, I have the webcam going into a pictureBox.Image (using opencv4), and then 2 Bitmap variables. Every 5 seconds a timer ticks, and Stored_bitmap_2 = Stored_bitmap_1, then Stored_bitmap_1 = (bitmap) pictureBox.Image.
When the right serial command comes in, I try to
Stored_image_2.Save("C:\Users\GreenWorld\Desktop\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
and I get a run-time error of invalid parameter.
When I do the same thing in a stand-alone project with some buttons (inside the button-click event handler), it works every time.
When I do this inside the serialPort_DataReceived handler, I get all kinds of cross-thread errors. So, I moved the save attempt to its own subroutine, and that fixed that but now this.
I am by no means a professional programmer, I'm an engineer with a simple problem and I can usually write a little simplistic code to fix my immediate issue. Please go easy on me in the explanation :-)
Sample code:
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace Weld_picture
{
public partial class Form1 : Form
{
// Create class-level accessible variables
int Welding_camera_ID = 1;
VideoCapture capture;
Mat frame;
Bitmap image;
private Thread camera;
bool isCameraRunning = false;
string Serial_command = "";
Bitmap Stored_image_1;
Bitmap Stored_image_2;
bool Image_saved = false;
string Station_ID = "GWM-PWS-01";
string File_name = "";
private void CaptureCamera() // from someone else's sample code
{
camera = new Thread(new ThreadStart(CaptureCameraCallback));
camera.Start();
}
private void CaptureCameraCallback() // from someone else's sample code
{
frame = new Mat();
capture = new VideoCapture(Welding_camera_ID);
capture.Open(Welding_camera_ID);
if (capture.IsOpened())
{
while (isCameraRunning)
{
capture.Read(frame);
image = BitmapConverter.ToBitmap(frame);
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
pictureBox1.Image = image;
}
}
}
public Form1()
{
InitializeComponent();
SerialPort1.Open();
}
private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string dummy;
char CR = (char)0x0D;
while (SerialPort1.BytesToRead > 0)
{
Serial_command += (char)SerialPort1.ReadByte();
}
while (Serial_command.IndexOf(CR) > 0)
{
dummy = Serial_command.Substring(0, Serial_command.IndexOf(CR));
Serial_command = Serial_command.Substring(Serial_command.IndexOf(CR) + 1, (Serial_command.Length - (Serial_command.IndexOf(CR) + 1)));
Serial_command.Trim();
dummy.Trim();
proc_Process_serial_data(dummy);
}
}
//*************************************************************************************************************************************
/* the first timer is a 5-second interval. It's the "memory" function so that if/when the save-to-disk is triggered I can store the last-time-shutter-open image */
//*************************************************************************************************************************************
private void Timer_picture_interval_Tick(object sender, EventArgs e)
{
checkBox1.Checked = !checkBox1.Checked;
Timer_picture_interval.Stop();
Stored_image_2 = Stored_image_1;
Stored_image_1 = (Bitmap) pictureBox1.Image;
Timer_picture_interval.Start();
}
//*************************************************************************************************************************************
// the second timer is a 30-second interval. It's the way to turn capture off if the PLC/camera box somehow goes off-line
//*************************************************************************************************************************************
private void Timer_camera_powerdown_Tick(object sender, EventArgs e)
{
if (isCameraRunning)
capture.Release();
isCameraRunning = false;
Timer_picture_interval.Stop();
}
//*************************************************************************************************************************************
private void proc_Process_serial_data(string Serial_string)
{
if (Serial_string.IndexOf("Still here") > 0)
{
if (!isCameraRunning)
CaptureCamera();
isCameraRunning = true;
}
if (Serial_string.IndexOf("Sun's up") > 0)
{
Timer_picture_interval.Start();
Timer_camera_powerdown.Start();
}
if (Serial_string.IndexOf("It's dark") > 0)
{
if ((Stored_image_2 != null) && (!Image_saved)) // in case there's 2 subsequent requests to save the same thing (weld stutter)
{
File_name = "C:\\Users\\GreenWorld\\Desktop\\" + Station_ID + " D" + DateTime.Now.ToString("yyyy_MM_dd THH_mm_ss") + ".jpg";
Stored_image_2.Image.Save("C:\\Users\\GreenWorld\\Desktop\\test.bmp" , System.Drawing.Imaging.ImageFormat.Bmp );
Image_saved = true;
Timer_picture_interval.Stop();
}
Timer_camera_powerdown.Start();
}
}
}
}
You likely be able to fix the cros-threading error by simply calling your proc_Process_serial_data() method within an Invoke() call.
Change:
proc_Process_serial_data(dummy);
To:
this.Invoke((MethodInvoker)delegate ()
{
proc_Process_serial_data(dummy);
});
Also, these two lines aren't actually doing anything:
Serial_command.Trim();
dummy.Trim();
To Trim() the strings, you have capture the returned strings and re-assign them to the original variables:
Serial_command = Serial_command.Trim();
dummy = dummy.Trim();

Communication between objects in C# issue

I'm trying to provide communication between two objects that can be best described as turn - based. What I mean by that is that the first object(a Game class) has multiple goals which are specified in a database, and the second object represents a class that is used to play animations from sprite sheets. My goal currently is to show an introductory animation in the Game class(that I have done), show the player his first goal. Then the class expects user input in the form of animation parameters which are then passed as a list to be animated.
Once the animation is complete, I check if the goal is met. If it is met, and it is not the last one, I need to go back to the Game class, show the next goal, play a sort off explanation, then expect user input and this repeats until all goals are satisfied.
This is Windows Phone 8.1 Silverlight.
Here is the code of the Game class(most relevant snippets):
public Game(GamePage gp, int chapterNum)
{
currentClickedCommand = null;
currentClickedSlot = null;
gamePage = gp;
chapterNumber = chapterNum;
isAnimationComplete = false;
//chosenCommands = new string[5];
gamePage.characterRectangle.Visibility = System.Windows.Visibility.Collapsed;
Thread AnimationThread = new Thread(playIntroAnimation);
AnimationThread.Start();
Thread loadingThread = new Thread(loadControls);
loadingThread.Start();
}
These two threads are used to play the animation(animation thread), and the other one waits for a static variable to be set to true to load user input controls. The code:
private void loadControls()
{
while (!InformationObject.isSequenceComplete) { }
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// loadGoals();
showCurrentGoal();
gamePage.CommandGrid.Visibility = System.Windows.Visibility.Visible;
gamePage.SlotGrid.Visibility = System.Windows.Visibility.Visible;
gamePage.mainCanvas.Background = null;
gamePage.characterRectangle.Visibility = Visibility.Collapsed;
loadCommands();
loadSlots();
});
}
This is the method which plays the animation sequence that the user selected:
public void AnimateCurrentAnimationInSequence(Rectangle container) {
AnimationParams currentParams = sequenceToAnimate[currentAnimationInSequence];
DoubleAnimation fadeInAnimation = new DoubleAnimation();
fadeOutAnimation = new DoubleAnimation();
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null)
{
PlayerInteraction currentInteraction = sequencePlayerInteractions[CurrentInteraction];
TalkBubble interactionBubble = new TalkBubble(currentInteraction.Value);
interactionBubble.setWidthHeight((int)container.Width, (int)container.Height);
talkBubble = interactionBubble;
onCanvas.Children.Add(talkBubble);
Canvas.SetLeft(talkBubble, Canvas.GetLeft(container) + 30);
Canvas.SetTop(talkBubble, Canvas.GetTop(container) + 30);
}
// ovdje razdvojiti po tipu
if (!currentParams.IsMoveType)
{
ImageBrush imageBrush = new ImageBrush() { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top };
imageBrush.Transform = new CompositeTransform();
imageBrush.ImageSource = currentParams.Sheet;
container = setRectangleProperties(container, currentParams.Width, currentParams.Height, imageBrush);
// Storyboard za animaciju
Storyboard sb = new Storyboard();
if (currentParams.Loop) sb.RepeatBehavior = RepeatBehavior.Forever; // odredjujem da li je na repeat
// Animacija za talk bubble
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null)
{
fadeInAnimation.From = 0.0;
fadeInAnimation.To = 1.0;
fadeInAnimation.Completed += new EventHandler(fadeIn_complete);
fadeInAnimation.FillBehavior = FillBehavior.HoldEnd;
Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath(UIElement.OpacityProperty));
Storyboard.SetTarget(fadeInAnimation, talkBubble);
}
// Animacija sheeta preko frameova
int time = 0; // vrijeme kojim odredjujem trajanja frameova
ObjectAnimationUsingKeyFrames frm = createFrames(currentParams.Repetitions, time, currentParams.Width, currentParams.NumberOfFrames); // inicijaliziram frameove animacije sheeta
frm.BeginTime = new TimeSpan(0, 0, 0);
fadeInAnimation.Duration = TimeSpan.FromMilliseconds(400);
Storyboard.SetTarget(frm, container.Fill);
Storyboard.SetTargetProperty(frm, new PropertyPath("(ImageBrush.Transform).(CompositeTransform.TranslateX)"));
sb.Children.Add(frm);
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null) sb.Children.Add(fadeInAnimation);
sb.Completed += new EventHandler(animationInSequence_Complete);
sb.Begin();
}
else {
cameFromSequenceAnimate = true;
AnimateMove(container, currentParams.Direction, currentParams.Steps);
}
}
private void animationInSequence_Complete(object sender, EventArgs e)
{
if (!(currentAnimationInSequence + 1 == animationCount))
{
if (sequencePlayerInteractions.Count != 0 && sequencePlayerInteractions != null) { if (!(CurrentInteraction + 1 == interactionCount)) CurrentInteraction++; }
currentAnimationInSequence++;
AnimateCurrentAnimationInSequence(currentContainer);
}
else
{
// Goal satisfaction
if (CurrentCommandIDs != null && CurrentCommandIDs.Count != 0)
{
bool has = true;
List<string> sequenceID = new List<string>();
foreach (AnimationParams ap in sequenceToAnimate) sequenceID.Add(ap.AnimationID);
for (int i = 0; i < CurrentCommandIDs.Count; i++)
{
if (!sequenceID.Contains(CurrentCommandIDs[i])) has = false;
}
if (has) { InformationObject.isCriteriaMet = true;
InformationObject.setCurrentGoal(InformationObject.currentGoal + 1);
}
else InformationObject.isCriteriaMet = false;
}
KidCode.Game.isSequenceComplete = true;
InformationObject.isSequenceComplete = true;
currentAnimationInSequence = 0;
CurrentInteraction = 0;
}
}
Now, after the animation is done, I need to somehow return back to the game class to basically repeat this. I tried using a static class(InformationObject)
to store information about current goals but I wasn't able to utilize it
Thanks for any help!

How to search for two similar images (memory game)

i try to search for 2 similar images (like in a memory game)
i know how to do it, but it for sure is not the best way i guess...
anyone has a better solution?
here is the code how i have done it
private void first_button (object sender, System.Windows.Input.GestureEventArgs e) //so button get pressed
{
field_one = true;
StoryboardBack11.Begin();
StoryboardBack11.Completed += new EventHandler(AfterAnimation);
i = i + 1;
}
// same for the other buttons
private void AfterAnimation(object sender, EventArgs e) //check here after storyboard completed
{if (i == 2) // check after 2 clicks
{
i = 0;
if (field_one == true && field_two == true)
{
if (imageUri_one.Equals(imageUri_two))
{
Fade_one.Begin(); //Storyboard starts
Fade_two.Begin();
field_one = false;
field_two = false;
}
}
//and this for every possible combination
//-> here is my problem because it is a lot to copy paste and thus not optimal i guess
if (field_one == true && field_three == true)
{
if (imageUri_one.Equals(imageUri_three))
{
Fade_one.Begin();
Fade_three.Begin();
field_one = false;
field_three = false;
}
}
// here is the shuffeling of the images
private void test1(object sender, System.Windows.Input.GestureEventArgs e)
{
List<string> Test = new List<string>(); //list of the images
Test.Add("Art1.png");
Test.Add("Art1.png");
Test.Add("Art2.png");
Test.Add("Art2.png");
Test.Add("Art3.png");
Test.Add("Art3.png");
Test.Shuffle(); //they get randomly shuffled here and then realigned
imageUri_one = Test[0];
imageUri_two = Test[1];
imageUri_three = Test[2];
// ..... and so on
// put the new image Uri to a button -> the same 6 time for everey button
BitmapImage bm_one = new BitmapImage(new Uri(#imageUri_one, UriKind.RelativeOrAbsolute));
image11.Source = bm_one; //but it in xaml Source
}
so the thing is that i want to make the Uri flexible, so that i can shuffle different Uri when using another list and this should already work. but is there a more elegant way to check for similar images?
hope the question is clear :)
Pseudo-code:
public class MyElement
{
public bool IsPressed { get; set; }
public string Uri { get; set; }
... anything else you want to know about that one tile
}
then build the logical board
MyElement[,] tiles = new MyElement[8, 8];
for(int i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
tiles[i, j] = new MyElement { IsPressed = false; Uri = whatever; ... };
}
}
Now create the "physical" board with the buttons and assign a custom value for all buttons which contains it's coordinates.
Create one click handler where you check the tiles array for that coordinate and check it's MyElement object. Assign this click handler to all button click event.

Categories

Resources