I have a video player which loads videos (.wav) to a playlist and scrolls through the playlist using a play queue manipulated by the playstatechange events. It works fine except for a black flicker (usually just one) that happens on the last frame of a random video (never the same spot in the play list or the same video). This also occurs on multiple computers so I am pretty sure it is not any video card settings, unless an obscure codec issue. This is for a research experiment and cannot have the flicker, it must be completely seamless. I have searched through every question and the only similar one did not involve a playlist of multiple videos, his flicker was when looping the same video, thus a totally different solution. Here is my video player creation and implementation:
public void MultipleVideos()
{
player.CreateControl();
player.Enabled = true;
player.enableContextMenu = false;
player.uiMode = "none";
player.Name = "player";
player.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
WMPLib.IWMPMedia media;
WMPLib.IWMPPlaylist playlist = player.playlistCollection.newPlaylist("myplaylist");
for (int x = 0; x < _presented.count; x++)
{
media = player.newMedia(_presented.getItem(x).video);
playlist.appendItem(media);
}
player.currentPlaylist = playlist;
}
private void player_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (!currSess.playOne)
{
if (e.newState == 8 | e.newState == 9)
{
if (e.newState == 8)
{
currSess.playQueue++;
}
}
if (currSess.playQueue+1 > player.currentPlaylist.count -1)
{
if (e.newState == 10)
{
player.uiMode = "invisible";
player.Visible = false;
displayImgs();
currSess._timer.start();
AllowControls(true);
allowItems();
player.PlayStateChange -= foo;
currSess.playQueue = 0;
}
}
}
}
Related
Im a beginner with C# I'm doing some School project using a Windows Form App, It's a simple game but I ran into some issues, I want to give a picture box control a bullet-like trajectory when the [Space] key is pressed but haven't been able to do it yet. I was instructed to do this only using Threads and NO timers.
Also I want this picture box to 'spawn' and start moving from another picture box named 'SpaceShip' but i don't know how i could do that
Of course, advice and suggestions are very welcome even if it means changing entire parts of my awful code
I tried using picturebox.Left = picturebox.Left +5; but I guess i'm doing something wrong
if (e.KeyCode == Keys.Space)
{
if(pbEnergy.Value <= 0)
{
pbEnergy.Value = 0;
System.Media.SoundPlayer SFX = new System.Media.SoundPlayer(#"C:\SFX\nolaser.wav");
SFX.Play();
}
else
{
System.Media.SoundPlayer SFX = new System.Media.SoundPlayer(#"C:\SFX\laser.wav");
SFX.Play();
pbEnergy.Value -= 10;
ThreadStart Delegate = new ThreadStart(phys);
Thread MovTh = new Thread(Delegate);
MovTh.Start();
}
}
public void phys()
{
for (int i = 0; i <= 60; i++)
{
Thread.Sleep(10);
Progress(i);
if (i == 60) //stop when value is reached
{
Thread.CurrentThread.Suspend();
}
}
}
delegate void Delegate(int n);
private void Progress(int num)
{
if (this.InvokeRequired)
{
Delegate d = new Delegate(Progress);
object[] Parameters = new object[] { num };
this.Invoke(d, Parameters);
}
else
{
picprj.Visible = true;
picprj.Left = picprj.Left + 5;
}
I expected the picture box to travel and then disappear but it finishes its trajectory and stays visible, I would appreciate some advice on this or even a better way to do it.
I have a project which consists of two forms, MainForm and CrossCorrPlotForm. On CrossCorrPlotForm, I have two charts (CrossCorrExpChart and CrossCorrRefChart) which I enabled scroll wheel zooming on, using the code described here and here.
Everything was working perfectly fine, until I added another chart (histChart), on MainForm, which is updated on each frame incoming from a camera (15-20 FPS), using a BackgroundWorker to collect and plot the data from the images. Now, both my charts on CrossCorrPlotChart are not zoomable anymore.
I presume this has something to do with the live-updating chart taking back the focus on each update. I tried adding histChart.Focus = false in the code but to no avail, as it seems "Control.Focused is read-only".
Does anyone have an idea how to make my charts zoomable again ?
Thanks
EDIT : Here is the code for the BackgroundWorker that updates chartHist :
private void OnFrameReceived(Frame frame)
{
bgw1.RunWorkerAsync(frame);
}
private void bgw1_DoWork(object s, DoWorkEventArgs e)
{
Frame frame = (Frame)e.Argument;
myBitmap = null;
try
{
frame.Fill(ref myBitmap);
mycamera.QueueFrame(frame);
SaveBitmap = myBitmap.Clone(cloneRect, myBitmap.PixelFormat);
BitmapToPrint = myBitmap.Clone(cloneRect, myBitmap.PixelFormat);
}
catch {}
}
private void bgw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (this.InvokeRequired)
{
BeginInvoke((Action)(() => bgw1_RunWorkerCompleted(sender, e)));
}
else
{
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
DataFromBitmap DataFromBitmapHist = new DataFromBitmap(SaveBitmap.Clone(cloneRect, SaveBitmap.PixelFormat));
PixelColorCount = DataFromBitmapHist.ColorCountOutput();
}).Start();
chartHist.Titles["Title2"].Visible = false;
chartHist.Series["Pixel count"].Points.Clear();
//Plotting the pixel counter, to detect saturation
for (int i = 0; i < PixelColorCount.Length; i++)
{
chartHist.Series["Pixel count"].Points.AddXY(i, PixelColorCount[i]);
}
//If there are saturated pixels : toggle a title on chartHist to warn the user
if (PixelColorCount.Last() > 1)
{
chartHist.Titles["Title1"].Visible = false;
chartHist.Titles["Title2"].Visible = true;
}
else
{
chartHist.Titles["Title1"].Visible = true;
chartHist.Titles["Title2"].Visible = false;
}
}
}
NOTES :
OnFrameReceived is a function from the API of the camera, it contains code that fires when a Frame is received from the camera.
frame.Fill puts the image contained in the Frame object in a Bitmap.
mycamera.QueueFrame sends back the Frame object to the camera, to receive a new image.
I had to use multiple threads, because using the UI thread too much resulted in blocking the reception from the camera.
I have code which loads a playlist and plays videos one after another, triggered by the PlayStateChange event of AxWindowsMediaPlayer. After reading several examples, I implemented BeginInvoke in order to delay the code while the videos play. It seems as if I need to implement EndInvoke because I am having functionality issues with my code continuing after the videos are played. How should I go about this? I could not figure it out from the posted examples and MSDN guides. Here is my code:
public void playItem(Item it)
{
player.CreateControl();
player.Enabled = true;
player.enableContextMenu = false;
player.uiMode = "none";
player.Name = "player";
player.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
WMPLib.IWMPMedia media;
WMPLib.IWMPPlaylist playlist = player.playlistCollection.newPlaylist("myplaylist");
for (int x = 0; x < _presented.count; x++)
{
media = player.newMedia(_presented.getItem(x).video);
playlist.appendItem(media);
}
player.currentPlaylist = playlist;
player.PlayStateChange += player_PlayStateChange;
}
private void player_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
{
if (e.newState == 8)
{
this.player.BeginInvoke(new Action(() =>
{
if (p_onset)
{
player.Ctlcontrols.play();
}
}));
//Maybe Implement EndInvoke here? Unsure of the proper syntax for this scenario
}
}
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.
I am back with another question. I am still new to SFML so this one seemed a bit tough. I have tried using while loops and such but to no avail.
The game I am doing at the moment is a car going back and forth on the X axis and then I guess will be able to pick up points and stuff or simply just avoid objects coming towards the car until it eventually dies.
How do I make the movement smoother? Currently the car will move 8 units first, before moving 8 units in the desired direction until I let go of the button. It's the same when I do it the other way. I would like it to just instantly move and keep moving when I press either key.
static void OnKeyPressed(object sender, EventArgs e)
{
Vector2f newPos = new Vector2f(0, car.Position.Y);
KeyEventArgs ke = (KeyEventArgs)e;
if (ke.Code.Equals(Keyboard.Key.A))
{
if (car.Position.X != 0)
{
newPos.X = car.Position.X - 8;
car.Position = newPos;
}
else if (car.Position.X < 0)
{
newPos.X = 0;
car.Position = newPos;
}
else if(car.Position.X == 0)
{
// Do nothing
}
}
else if (ke.Code.Equals(Keyboard.Key.D))
{
if (car.Position.X != window.Size.X - 32)
{
newPos.X = car.Position.X + 8;
car.Position = newPos;
}
else if (car.Position.X > window.Size.X)
{
newPos.X = window.Size.X;
car.Position = newPos;
}
else if (car.Position.X == window.Size.X)
{
// Do nothing
}
}
}
And the entire thing for reference:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SFML.Audio;
using SFML.Graphics;
using SFML.Window;
namespace SFMLCarGame
{
class Program
{
private static RenderWindow window;
private static Sprite car;
static void Main(string[] args)
{
window = new RenderWindow(new VideoMode(256,512), "Car Game");
window.Closed += new EventHandler(OnClose);
window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
Sprite bg = new Sprite(new Texture("road.png"));
car = new Sprite(new Texture("car.png"));
car.Position = new Vector2f(window.Size.X / 2, window.Size.Y - 96);
while (window.IsOpen())
{
window.DispatchEvents();
window.Clear();
window.Draw(bg);
window.Draw(car);
window.Display();
}
}
static void OnClose(object sender, EventArgs e)
{
RenderWindow window = (RenderWindow)sender;
window.Close();
}
static void OnKeyPressed(object sender, EventArgs e)
{
Vector2f newPos = new Vector2f(0, car.Position.Y);
KeyEventArgs ke = (KeyEventArgs)e;
if (ke.Code.Equals(Keyboard.Key.A))
{
if (car.Position.X != 0)
{
newPos.X = car.Position.X - 8;
car.Position = newPos;
}
else if (car.Position.X < 0)
{
newPos.X = 0;
car.Position = newPos;
}
else if(car.Position.X == 0)
{
// Do nothing
}
}
else if (ke.Code.Equals(Keyboard.Key.D))
{
if (car.Position.X != window.Size.X - 32)
{
newPos.X = car.Position.X + 8;
car.Position = newPos;
}
else if (car.Position.X > window.Size.X)
{
newPos.X = window.Size.X;
car.Position = newPos;
}
else if (car.Position.X == window.Size.X)
{
// Do nothing
}
}
}
}
}
You may want to read this short tutorial from the SFML's website.
The events are fired by the operating system, and are good for certain purposes (quit event, a key is pressed, the left mouse button is clicked) but aren't for things that need to be updated really often. Imagine that you are writing some text, and keep the 'A' key pressed. Your text will progressively grow like aaaaaaaaaaa but there is a little delay between the a spawns, imposed by the OS. You would get, say, 6 letters by second. This is the same with events. With a game running and displaying at 60 fps it is clear that your movement will not be smooth and barely manageable.
Hopefully SFML provides a way to check the instant state of the keyboard (and mouse and joystick). With the C# binding (I am assuming you are using the binding for 2.0 version, and if you don't then you should) you only have to check Keyboard.isKeyPressed(yourKey).
Doing this in the main loop will check at each frame that the key is pressed, and not wait for an OS event that is way slower.
On a side note, if your previous questions were answered correctly please mark them so by accepting an answer.
Edit : I haven't SFML for .NET installed on my computer but here is what it could look like
static void Main(string[] args)
{
window = new RenderWindow(new VideoMode(256,512), "Car Game");
window.Closed += new EventHandler(OnClose);
// Note this
// window.KeyPressed += new EventHandler<KeyEventArgs>(OnKeyPressed);
Sprite bg = new Sprite(new Texture("road.png"));
car = new Sprite(new Texture("car.png"));
car.Position = new Vector2f(window.Size.X / 2, window.Size.Y - 96);
while (window.IsOpen())
{
window.DispatchEvents();
CheckInputs(); // and this !
window.Clear();
window.Draw(bg);
window.Draw(car);
window.Display();
}
}
void CheckInputs()
{
if(Keyboard.isKeyPressed(Keyboard.key.A))
{
if(car.Position.X < 0)
car.Position.X = 0
else if(car.Position.X > 0)
car.Position.X -= 8; // shortcut for 'car.Position.X = car.Position.X - 8'
}
else if(Keyboard.isKeyPressed(Keyboard.key.D))
{
// etc
}
}
This way your transition should be much smoother, but beware, 8 pixels might be very fast !
I really recommend you to read the tutorial I have linked, because it explains the functionning of inputs in an language-agnostic way (even if the examples are in C++).
Also, you don't need your event handler anymore so I commented it. But if you are checking for other keys (like escape for pause or whatever) don't delete it, just remove the part you wrote about moving the car.