Communication between objects in C# issue - c#

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!

Related

Adding Multiple Images to a Form in C#

So I am trying to add several images (Music Notes) in the form of PictureBox to a form, but despite all my efforts, only the first music note is being displayed, and all preceding music notes are not.
Key_MouseUp Event (occurs when the mouse is lifted up after a piano key is pressed):
private void Key_MouseUp(object sender, MouseEventArgs e)
{
foreach (MusKey mk in panel1.Controls)
{
if (sender == mk) //true for the specific key pressed on the Music Keyboard
{
if (e.Button == MouseButtons.Left)
{
timer1.Enabled = false;
sp.Stop();
string bNoteShape = null;
// ticks -> milliseconds
if (count > 15)
{
bNoteShape = "SemiBreve";
duration = 2000;
}
else if (count > 10 && count <= 15)
{
bNoteShape = "DotMinim";
duration = 1000;
}
else if (count > 5 && count <= 10)
{
bNoteShape = "Minim";
duration = 500;
}
else if (count > 2 && count <= 5)
{
bNoteShape = "Crotchet";
duration = 250;
}
else if (count >= 1.25 && count <= 2)
{
bNoteShape = "Quaver";
duration = 125;
}
else
{
bNoteShape = "Semi-Quaver";
duration = 63;
}
MusicNote mn = new MusicNote(mk.getMusicNote(), duration, bNoteShape, mk.getNote());
Notes.Add(mn);
panel2.Controls.Add(mn); //adding MusicNote component to MusicStaff (panel2) collection
}
}
}
}
Music Note Class and Constructor:
class MusicNote : PictureBox
{
public int notepitch;
public int noteduration;
public String noteshape;
public String note;
enum Accid { sharp, flat, sole };
String NoteImage_path = "C:\\Users\\Luke Xuereb\\Documents\\University\\Year 2\\Semester 1\\Object Oriented Programming\\Piano Assignment\\Notes-Images\\";
static int xLoc = 50;
static int yLoc = 30;
bool dragging = false;
System.Timers.Timer timer1 = new System.Timers.Timer();
public MusicNote(int iNotepitch, int iDuration, String iBnoteShape, String iNote)
{
notepitch = iNotepitch;
noteduration = iDuration;
noteshape = iBnoteShape;
note = iNote;
ImageLocation = NoteImage_path + noteshape + ".bmp";
BackColor = Color.Beige;
Location = new Point(xLoc, yLoc);
xLoc += 15;
}
I have been several days stuck on this problem, and am quite convinced that the logic of the code is correct (which is in fact why the first Music Note is always displayed).
Is there a problem when it comes to displaying several pictureboxes? A new picturebox is created everytime a new music note is created, since class MusicNote inherits from class PictureBox.
Alternatively, is there a better option for my current problem, instead of using PictureBox?
Any help would be massively appreciated. Thank you!

MediaElement not always playing video in WPF application

we created a test application were users interact with it using gestures. Each user gets to interact with all gestures in a sequential manner. When the users first is introduced to a new gesture, a small instructional movie is played for the user showing him how to perform that gesture. The movie should first play on the main screen, and then after playing once should loop on the second monitor until the next gesture starts, when it should then close the secondary video screen and start the process over. This is where we are running into problems.
The movies all get loaded up fine, and actually most of the time play correctly. The problem is that sometimes, the movie does not actually start in the secondary monitor. They load up fine but never actually start. This is not something we can reliably reproduce, this happens sometimes at random.
This is the code that we have for the VideoPlayer window at the moment:
public partial class VideoWindow : Window {
static VideoWindow currentVideoWindow;
public VideoWindow(GestureDirection direction, GestureType type, bool reopen = false)
{
if(currentVideoWindow != null) {
currentVideoWindow.CloseWindow();
currentVideoWindow = this;
}
else {
currentVideoWindow = this;
}
GestureParser.Pause(!reopen);
InitializeComponent();
this.Title = type + " " + direction;
this.Show();
videoMediaElement.LoadedBehavior = MediaState.Manual;
videoMediaElement.UnloadedBehavior = MediaState.Manual;
string videoDirectory = #"techniques/";
string video = direction.ToString() + "_" + type.ToString() + ".mp4";
if (Screen.AllScreens.Length > 1) {
int secScreen = Screen.AllScreens.Length == 2 ? 0 : 2;
int mainScreen = Screen.AllScreens.Length == 2 ? 1 : 0;
Screen s = reopen ? Screen.AllScreens[secScreen] : Screen.AllScreens[mainScreen];
System.Drawing.Rectangle r = s.WorkingArea;
this.Top = r.Top;
this.Left = r.Left;
this.Topmost = true;
this.Show();
this.WindowStyle = WindowStyle.None;
this.WindowState = WindowState.Maximized;
}
else {
Screen s = Screen.AllScreens[0];
System.Drawing.Rectangle r = s.WorkingArea;
this.Top = r.Top;
this.Left = r.Left;
this.Show();
}
String videoPath = CreateAbsolutePathTo(videoDirectory + video);
if (File.Exists(videoPath)) {
Uri videoUri = new Uri(videoPath, UriKind.Relative);
videoMediaElement.Source = videoUri;
}
if (reopen) {
this.Activate();
canvasWindow.Activate();
videoMediaElement.MediaEnded += (sender, args) => {
videoMediaElement.Stop();
videoMediaElement.Position = TimeSpan.Zero;
};
} else {
videoMediaElement.MediaEnded += (sender, args) => {
this.CloseWindow();
var t = new VideoWindow(direction, type, true);
};
}
videoMediaElement.Play();
Task task = Task.Factory.StartNew(() =>
{
while(GetMediaState(videoMediaElement) != MediaState.Play)
{
videoMediaElement.Play();
}
});
}
private MediaState GetMediaState(MediaElement myMedia)
{
FieldInfo hlp = typeof(MediaElement).GetField("_helper", BindingFlags.NonPublic | BindingFlags.Instance);
object helperObject = hlp.GetValue(myMedia);
FieldInfo stateField = helperObject.GetType().GetField("_currentState", BindingFlags.NonPublic | BindingFlags.Instance);
MediaState state = (MediaState)stateField.GetValue(helperObject);
return state;
}
static CanvasWindow canvasWindow;
public static void SetCanvasWindow(CanvasWindow window) {
canvasWindow = window;
}
private static string CreateAbsolutePathTo(string mediaFile) {
return Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, mediaFile);
}
private void CloseWindow() {
videoMediaElement.Stop();
videoMediaElement.Close();
this.Close();
}
}
As you can see, we have tried creating a task that constantly checks to see if the video is playing, and if not it should play it. The thing is, the media state is always playing, even if the movie is stopped, and as such it does nothing.
We really don't know what is wrong, and would really appreciate some help.

How can i replay the same animation every time button pressed " WPF Animmation"

How can i replay the same animation every time button pressed 1st time i press btn animation play but nxt there is runtime error
private void Button_Click(object sender, RoutedEventArgs e)
{
int j = 0;
string[] names ={"/Assets/1.png", "/Assets/2.png", "/Assets/3.png", "/Assets/4.png", "/Assets/5.png" };
var storyboard = new Storyboard
{
};
var animation = new ObjectAnimationUsingKeyFrames();
Storyboard.SetTarget(animation,img);
Storyboard.SetTargetProperty(animation, new PropertyPath("Source"));
storyboard.Children.Add(animation);
for (int i=0 ; i <=4; i++)
{
// j = j + 1;
var keyframe = new DiscreteObjectKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300* i)),
Value = String.Format(names[i])
};
animation.KeyFrames.Add(keyframe);
}
Resources.Add("Storyboard", storyboard);
// Resources.Add("Storyboard", storyboard);
storyboard.Begin();
// storyboard.Completed += new EventHandler(Story_Completed);
// Thread.Sleep(1000);
if (j==4)
{
storyboard.Pause();
}
}
It's hard to tell where the error comes from since you don't give details about the exception, but I see at least one thing that cannot possibly work:
Resources.Add("Storyboard", storyboard);
This will work the first time but will throw an exception the second time (since the storyboard has already been added to resources).
In any case, you can re-use the same storyboard object if you take some precautions:
First, let's store the storyboard in a property, because it's easier to manipulate than resources:
private Storyboard ButtonStoryboard { get; set; }
When clicking on the button, we first check whether the storyboard exists. If not, we create it:
if (this.ButtonStoryboard == null)
{
string[] names ={"/Assets/1.png", "/Assets/2.png", "/Assets/3.png", "/Assets/4.png", "/Assets/5.png" };
var storyboard = new Storyboard();
var animation = new ObjectAnimationUsingKeyFrames();
Storyboard.SetTarget(animation,img);
Storyboard.SetTargetProperty(animation, new PropertyPath("Source"));
storyboard.Children.Add(animation);
for (int i=0 ; i <=4; i++)
{
var keyframe = new DiscreteObjectKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300* i)),
Value = String.Format(names[i])
};
animation.KeyFrames.Add(keyframe);
}
this.ButtonStoryboard = storyboard;
}
Now we must start the storyboard only if isn't already running (you can't start it twice). If it's already running, we stop it and rewind it (just like a videotape):
if (this.ButtonStoryboard.GetCurrentState() != ClockState.Stopped)
{
this.ButtonStoryboard.Stop();
this.ButtonStoryboard.Seek(TimeSpan.Zero);
}
this.ButtonStoryboard.Begin();
Putting all together:
private Storyboard ButtonStoryboard { get; set; }
private void Button_Click(object sender, RoutedEventArgs e)
{
if (this.ButtonStoryboard == null)
{
string[] names ={"/Assets/1.png", "/Assets/2.png", "/Assets/3.png", "/Assets/4.png", "/Assets/5.png" };
var storyboard = new Storyboard();
var animation = new ObjectAnimationUsingKeyFrames();
Storyboard.SetTarget(animation,img);
Storyboard.SetTargetProperty(animation, new PropertyPath("Source"));
storyboard.Children.Add(animation);
for (int i=0 ; i <=4; i++)
{
var keyframe = new DiscreteObjectKeyFrame
{
KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300* i)),
Value = String.Format(names[i])
};
animation.KeyFrames.Add(keyframe);
}
this.ButtonStoryboard = storyboard;
}
if (this.ButtonStoryboard.GetCurrentState() != ClockState.Stopped)
{
this.ButtonStoryboard.Stop();
this.ButtonStoryboard.Seek(TimeSpan.Zero);
}
this.ButtonStoryboard.Begin();
}

Play three sounds simultaneously c#

I want to play three sounds simultaneously, but second sound must play after one seconds, third sound after two seconds. I have this code:
private void Play()
{
AxWindowsMediaPlayer player1 = new AxWindowsMediaPlayer();
player1.CreateControl();
AxWindowsMediaPlayer player2 = new AxWindowsMediaPlayer();
player2.CreateControl();
AxWindowsMediaPlayer player3 = new AxWindowsMediaPlayer();
player3.CreateControl();
player1.URL = "sounds\\1.wav";
player1.Ctlcontrols.play();
System.Threading.Thread.Sleep(1000);
player2.URL = "sounds\\2.wav";
player2.Ctlcontrols.play();
System.Threading.Thread.Sleep(1000);
player3.URL = "sounds\\3.wav";
player3.Ctlcontrols.play();
Why all this sounds are playing in one time after two seconds?
I ended up using SharpDX (available via NuGet packages SharpDX
and SharpDX.XAudio2.
An example of its usage can be found in one of my GitHub projects: 2DAI
You can hear the various sounds overlapping in this screen recording as well.
Playing a sound:
var backgroundMusicSound = new AudioClip(#".\Assets\Sounds\Music\Background.wav" /*Sound path*/, 1.0 /* Volumne*/, true /*Loop Forever?*/)
backgroundMusicSound.Play();
The class that I pieced together:
public class AudioClip
{
private XAudio2 _xaudio = new XAudio2();
private WaveFormat _waveFormat;
private AudioBuffer _buffer;
private SoundStream _soundstream;
private SourceVoice _singleSourceVoice;
private bool _loopForever;
private bool _isPlaying = false; //Only applicable when _loopForever == false;
private bool _isFading;
private string _wavFilePath; //For debugging.
private float _initialVolumne;
public AudioClip(string wavFilePath, float initialVolumne = 1, bool loopForever = false)
{
_loopForever = loopForever;
_wavFilePath = wavFilePath;
_initialVolumne = initialVolumne;
var masteringsound = new MasteringVoice(_xaudio); //Yes, this is required.
var nativefilestream = new NativeFileStream(wavFilePath,
NativeFileMode.Open, NativeFileAccess.Read, NativeFileShare.Read);
_soundstream = new SoundStream(nativefilestream);
_waveFormat = _soundstream.Format;
_buffer = new AudioBuffer
{
Stream = _soundstream.ToDataStream(),
AudioBytes = (int)_soundstream.Length,
Flags = BufferFlags.EndOfStream
};
if (loopForever)
{
_buffer.LoopCount = 100;
}
}
public void Play()
{
lock (this)
{
if (_loopForever == true)
{
if (_isPlaying)
{
if (_isFading)
{
_isFading = false;
_singleSourceVoice.SetVolume(_initialVolumne);
}
return;
}
_singleSourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
_singleSourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
_singleSourceVoice.SetVolume(_initialVolumne);
_singleSourceVoice.Start();
_isPlaying = true;
return;
}
}
var sourceVoice = new SourceVoice(_xaudio, _waveFormat, true);
sourceVoice.SubmitSourceBuffer(_buffer, _soundstream.DecodedPacketsInfo);
sourceVoice.SetVolume(_initialVolumne);
sourceVoice.Start();
}
public void Fade()
{
if (_isPlaying && _isFading == false)
{
_isFading = true;
(new Thread(FadeThread)).Start();
}
}
private void FadeThread()
{
float volumne;
_singleSourceVoice.GetVolume(out volumne);
while (_isFading && volumne > 0)
{
volumne -= 0.25f;
volumne = volumne < 0 ? 0 : volumne;
_singleSourceVoice.SetVolume(volumne);
Thread.Sleep(100);
}
Stop();
}
public void Stop()
{
if (_loopForever == true)
{
if (_singleSourceVoice != null && _isPlaying)
{
_singleSourceVoice.Stop();
}
_isPlaying = false;
_isFading = false;
}
else
{
throw new Exception("Cannot stop overlapped audio.");
}
}
}
It should also be notes that loading the sounds can be a heavy process, so if you are doing it a lot then you might want to cache them as I did:
private Dictionary<string, AudioClip> _audioClips { get; set; } = new Dictionary<string, AudioClip>();
public AudioClip GetSoundCached(string wavFilePath, float initialVolumne, bool loopForever = false)
{
lock (_audioClips)
{
AudioClip result = null;
wavFilePath = wavFilePath.ToLower();
if (_audioClips.ContainsKey(wavFilePath))
{
result = _audioClips[wavFilePath];
}
else
{
result = new AudioClip(wavFilePath, initialVolumne, loopForever);
_audioClips.Add(wavFilePath, result);
}
return result;
}
}

Multi thread for joystick input

Hi there i am trying to make a question answer game. ( Whoever presses joystick button first answers the question first )
So far i ' ve used SharpDX , threading since i cant handle the button press event via SharpDX
My problem is i cant get it worked . I dont know the reason but let me explain my code.
On my page load i ' ve initialized 2 different threads ;
//Initializing the constants
private bool q = true;
private Thread th1;
private Thread th2;
private Guid joy1Guid = Guid.Empty;
private Guid joy2Guid = Guid.Empty;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var directInput = new DirectInput();
foreach (var deviceInstance in directInput.GetDevices())
{
if (deviceInstance.Subtype == 258)
{
//My joysticks connected to pc via usb.
if (joy1Guid == Guid.Empty)
joy1Guid = deviceInstance.InstanceGuid;
else if (joy2Guid == Guid.Empty)
joy2Guid = deviceInstance.InstanceGuid;
}
}
th1 = new Thread(Joy1Start);
th2 = new Thread(Joy2Start);
th1.IsBackground = true;
th2.IsBackground = true;
}
Below my Thread methods
private void Joy1Start()
{
var directInput = new DirectInput();
var joystick = new Joystick(directInput, joy1Guid);
joystick.Properties.BufferSize = 128;
joystick.Acquire();
while (q)
{
joystick.Poll();
var state = joystick.GetCurrentState();
var counter = 0;
foreach (bool isPressed in state.Buttons)
{
if (isPressed)
{
Action a1 = () => textBox1.Text = "JOY1";
textBox1.Invoke(a1);
th1.Abort();
th2.Abort();
q = false;
break;
}
counter++;
}
}
}
private void Joy2Start()
{
var directInput = new DirectInput();
var joystick = new Joystick(directInput, joy2Guid);
joystick.Properties.BufferSize = 128;
joystick.Acquire();
while (q)
{
joystick.Poll();
var state = joystick.GetCurrentState();
var counter = 0;
foreach (bool isPressed in state.Buttons)
{
if (isPressed)
{
Action a2 = () => textBox1.Text = "JOY2";
textBox1.Invoke(a2);
th1.Abort();
q = false;
break;
}
counter++;
}
}
}
I am firing thread starts with a button
private void button1_Click(object sender, EventArgs e)
{
th1.Start();
th2.Start();
}
So the problem is i can't get any response if i work with two threads.
When i only start th1 or th2 it works like a charm.
Can you please show me where is the wrong part of this algorithm ?

Categories

Resources