I started coding a simple game in Windows Form C#, but after I added the background sound (a simple .wav file) when I run the game, after a few second of playing the game crashes. (The sound can be heard).
Here is the function:
private void playAmbientSound()
{
System.Media.SoundPlayer playAmbient = new System.Media.SoundPlayer(Properties.Resources.ambient);
playAmbient.PlayLooping();
}
Then I call this function from the function resetGame() a function used in the Form constructor.
public Form1()
{
InitializeComponent();
resetGame();
}
The code that appears in the console after the crash is:
.. has exited with code -1073741819 (0xc0000005) 'Access Violation'".
As requested here is the resetGame() function:
private void resetGame()
{
btnStart.Enabled = false;
explosion.Visible = false;
award.Visible = false;
goLeft = false;
goRight = false;
score = 0;
award.Image = Properties.Resources.bronze;
roadSpeed = 12;
trafficSpeed = 15;
AI1.Top = carPosition.Next(200, 500) * -1;
AI1.Left = carPosition.Next(5, 200);
AI2.Top = carPosition.Next(200, 500) * -1;
AI2.Left = carPosition.Next(245, 422);
playAmbientSound();
gameTimer.Start();
}
Related
I want to develop an experimental program in unity. In the program, I use scripts to create a series of objects and assign values to them. I use Tobii's SDK to develop an eye movement experimental program. In order to get the line of sight feedback of these objects (actually a ray collision detection principle), I created a script and added this script for each object. But when I run, I find that only the last of the series of objects I create will give correct feedback, and the other objects will not give feedback。
My feedback script is as follow:
void Update () {
if (_gazeAwareComponent.HasGazeFocus) {
img.color = _outColor;
newText = textName.text;
MainInteraction.isEnter = true;
} else {
img.color = initinalColor;
newText = null;
MainInteraction.isEnter = false;
}
}
I use a static variable to control the state of feedback.
And in my main script, my fuction is:
void createTargetAndText (int number) {
int[] a = GetRandomSequence(10, currentTrailTime);
for (int i = 0; i < number; i++) {
GameObject image = new GameObject();
image.transform.localScale = Vector3.one;
image.name = a[i].ToString();
image.AddComponent<Image>();
image.AddComponent<SphereCollider>();
image.GetComponent<SphereCollider>().radius = targetSize / 2;
image.AddComponent<Feedback>();
image.GetComponent<Image>().sprite = sourceImage;
image.transform.SetParent(currentGameObject.transform.GetChild(3).transform);
image.layer = LayerMask.NameToLayer("UI");
GameObject textGame = new GameObject();
textGame.name = a[i].ToString();
textGame.AddComponent<Text>();
textGame.GetComponent<Text>().font = textFont;
textGame.GetComponent<Text>().text = textGame.name;
textGame.GetComponent<Text>().fontSize = 48;
textGame.GetComponent<Text>().alignment = TextAnchor.MiddleCenter;
textGame.GetComponent<Text>().color = Color.black;
textGame.transform.SetParent(image.transform);
textGame.layer = LayerMask.NameToLayer("UI");
}
}
The only problem is MainInteration.isEnter doesn't work, when I try to change the color to debug, it works.
if (_gazeAwareComponent.HasGazeFocus) {
img.color = _outColor;
newText = textName.text;
MainInteraction.isEnter = true;
if (this.name == "2") {
MainInteraction.isEnter = true;
img.color = Color.cyan;
}
}
I guess the problem may come from:
the static variables in Unity.
Can someone help me answer it? Thank you
private void GenerateAnimatedGifs()
{
UnFreezWrapper unfreezWrapper = new UnFreezWrapper();
checkBoxGetImages = false;
checkBoxGetAllImages.Checked = false;
GetImagesFiles();
for (int i = 0; i < filesSatellite.Length; i++)
{
Image img = Image.FromFile(filesSatellite[i]);
img.Save(filesSatellite[i] + "ConvertedToGif.gif", System.Drawing.Imaging.ImageFormat.Gif);
img.Dispose();
File.Delete(filesSatellite[i]);
}
GetImagesFiles();
unfreezWrapper.MakeGIF(filesRadar.ToList(), #"d:\Downloaded Images\Animates Gifs\radanim.gif", 100, true);
unfreezWrapper.MakeGIF(filesSatellite.ToList(), #"d:\Downloaded Images\Animates Gifs\satanim.gif", 100, true);
}
In the loop I convert each image to gif save it in other name and then dispose the original image and then trying to delete the original image so only the ConvertedToGif images will left.
but I'm getting the exception is being used by another process on the delete line
File.Delete(filesSatellite[i]);
but isn't the file disposed already ?
The problem is that in the constructor I'm loading the images to a pictureBox using timer that is why the images are busy with another process.
If I'm not loading the images at the constructor everything will work fine.
But I want to display the images when running the application and also to be able to convert them to other formats and making other manipulations like creating animated gif of them.
I'm stuck here.
This is the constructor code
public Form1()
{
InitializeComponent();
CheckIfImagesExist();
}
And the code of the CheckIfImagesExist method
private void CheckIfImagesExist()
{
GetImagesFiles();
if (filesRadar != null)
{
if (filesRadar.Length > 1)
{
pictureBox1.Image = new Bitmap(filesRadar[0]);
trackBar1.Enabled = true;
timer1.Enabled = true;
}
if (filesRadar.Length == 1)
{
trackBar1.Enabled = false;
pictureBox1.Image = new Bitmap(filesRadar[0]);
}
}
if (filesSatellite != null)
{
if (filesSatellite.Length > 1)
{
pictureBox2.Image = new Bitmap(filesSatellite[0]);
trackBar1.Enabled = true;
timer2.Enabled = true;
}
if (filesSatellite.Length == 1)
{
trackBar1.Enabled = false;
pictureBox2.Image = new Bitmap(filesSatellite[0]);
}
}
}
The timer tick event
int satImagesCount = 0;
private void timer2_Tick(object sender, EventArgs e)
{
satImagesCount++;
if (satImagesCount == filesSatellite.Length)
{
satImagesCount = 0;
}
pictureBox2.Image = new Bitmap(filesSatellite[satImagesCount]);
if (isInsideSat)
{
pb.Image = new Bitmap(filesSatellite[satImagesCount]);
timer2.Interval = trackBar1.Value * 100;
}
}
I'm trying to code a Simon Says game and I ran into a problem. I cannot figure out how to make my Randomizer timer (that randomizes which boxes are lit up) to run by waves. I want it to run once, then when it's referred to again - run twice and so on.
This is RandomPlace():
private PictureBox RandomPlace()
{
PictureBox p = new PictureBox();
Random rnd = new Random();
switch (rnd.Next(1, 5))
{
case 1:
p = TopRight;
break;
case 2:
p = TopLeft;
break;
case 3:
p = BottomRight;
break;
case 4:
p = BottomLeft;
break;
}
return p;
} //Gets a random PictureBox
This is RandomImage():
private void RandomImage()
{
TopLeft.Enabled = false;
TopRight.Enabled = false;
BottomLeft.Enabled = false;
BottomRight.Enabled = false;
PictureBox a = RandomPlace();
if (a == TopLeft)
{
TopLeft.Image = Resources.TopLeftLit;
label1.Text = "TopLeft";
Thread.Sleep(500);
TopLeft.Image = Resources.TopLeft;
label2.Text = "TopLeftAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 1;
patternRightNow++;
}
if (a == TopRight)
{
TopRight.Image = Resources.TopRightLit;
label1.Text = "TopRight";
Thread.Sleep(500);
TopRight.Image = Resources.TopRight;
label2.Text = "TopRightAFTERSLEEP"; //FIGURE OUT HOW TO RESET PICTURE
Thread.Sleep(500);
pattern[patternRightNow] = 2;
patternRightNow++;
}
if (a == BottomLeft)
{
this.BottomLeft.Image = Resources.BottomLeftLit;
label1.Text = "BottomLeft";
Thread.Sleep(500);
this.BottomLeft.Image = Resources.BottomLeft;
label2.Text = "BottomLeftAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 3;
patternRightNow++;
}
if (a == BottomRight)
{
this.BottomRight.Image = Resources.BottomRightLit;
label1.Text = "BottomRight";
Thread.Sleep(500);
this.BottomRight.Image = Resources.BottomRight;
label2.Text = "BottomRightAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 4;
patternRightNow++;
}
} //Lits up the random PictureBoxes and sets them back to normal
This is Randomizer_Tick():
rivate void Randomizer_Tick(object sender, EventArgs e)
{
RandomImage();
patternRightNow = 0;
tickCount++;
Randomizer.Stop();
ClickCheck();
} //Use RandomImage() to lit up random PictureBoxes on 5 waves, wave 1 - 1 PictureBox, wave 2 - 2 PictureBoxes and so on.
This is ClickCheck():
private void ClickCheck()
{
TopLeft.Enabled = true;
TopRight.Enabled = true;
BottomLeft.Enabled = true;
BottomRight.Enabled = true;
if (tickCount == clickCount)
{
CheckIfWin();
Randomizer.Start();
}
} //Enables the PictureBoxes to be pressed, after the user input reaches the current wave's amount of PictureBoxes lit up, disable PictureBoxes again and start the randomizer
Instead of using timers, I advise you to look at Tasks. It's much easier to create such statemachines.
Fill a list with colors and play it. Wait until the user pressed enough buttons and check the results.
For example: (haven't tested it, it's just for example/pseudo code)
It might contain some typo's.
private List<int> _sequence = new List<int>();
private List<int> _userInput = new List<int>();
private Random _rnd = new Random(DataTime.UtcNow.Milliseconds);
private bool _running = true;
private bool _inputEnabled = false;
private TaskCompletionSource<object> _userInputReady;
public async void ButtonStart_Click(object sender, EventArgs e)
{
if(_running)
return;
while(_running)
{
// add a color/button
_sequence.Add(_rnd.Next(4));
// play the sequence
for(int color in _sequence)
{
// light-up your image, whatever
Console.WriteLine(color);
// wait here...
await Task.Delay(300);
// turn-off your image, whatever
}
// clear userinput
_userInput.Clear();
_userInputReady = new TaskCompletionSource<object>();
_inputEnabled = true;
// wait for user input.
await _userInputReady.Task;
// compare the user input to the sequence.
for(int i=0;i<_sequence.Count;i++)
{
if(_sequence[i] != _userInput[i])
{
_running = false;
break;
}
}
}
Console.WriteLine("Not correct");
}
// one handler for all buttons. Use the .Tag property to store 0, 1, 2, 3
public void ButtonClick(object sender, EventArgs e)
{
if(!_inputEnabled)
return;
var button = (Button)sender;
// add user input to the queue
_userInput.Add((int)button.Tag);
if(_userInput.Count >= _sequence.Count)
_userInputReady.SetResult(null);
}
I'm trying out C# for Raspberry through Visual Studio and windows 10 IoT. Just took me an eternity to make everything work, but I slowly got there. I got my leds workings following their outdated 2 years old tutorials. I'm now trying to add a button to my breadboard to turn the leds on and off... Sadly, This doesn't work at all. It's like ValueChanged is never triggered.
I followed this guide: https://developer.microsoft.com/en-us/windows/iot/samples/pushbutton
My button is wired like: 1 pin directly to ground and the other one to GPIO18 (Pin 12)
Before thequestion comes, yes I did try using GPIO5 too. I just went back to GPIO18 as it was working on my python script before.
This is the code I'm trying to run, but having button problems (leds are fine):
public sealed class StartupTask : IBackgroundTask
{
private GpioController gpio = GpioController.GetDefault();
private GpioPin pinRed;
private GpioPin pinBlue;
private GpioPin pinButton;
private GpioPinValue pinValue;
private const int BLUE_PIN = 19;
private const int RED_PIN = 26;
private const int BUTTON_PIN = 18;
public void Run(IBackgroundTaskInstance taskInstance)
{
Debug.WriteLine("initialising");
InitGpio();
if (pinRed != null)
{
pinValue = GpioPinValue.High;
pinRed.Write(pinValue);
pinBlue.Write(pinValue);
}
}
private void InitGpio()
{
gpio = GpioController.GetDefault();
if (gpio == null)
{
pinRed = null;
pinBlue = null;
pinButton = null;
Debug.WriteLine("Failed starting GPIO");
return;
}
pinValue = GpioPinValue.Low;
pinRed = gpio.OpenPin(RED_PIN);
pinRed.Write(pinValue);
pinRed.SetDriveMode(GpioPinDriveMode.Output);
pinBlue = gpio.OpenPin(BLUE_PIN);
pinBlue.Write(pinValue);
pinBlue.SetDriveMode(GpioPinDriveMode.Output);
pinButton = gpio.OpenPin(BUTTON_PIN);
if (pinButton.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
{
Debug.WriteLine("Is supported");
pinButton.SetDriveMode(GpioPinDriveMode.InputPullUp);
}
else
{
Debug.WriteLine("Not supported");
pinButton.SetDriveMode(GpioPinDriveMode.Input);
}
pinButton.DebounceTimeout = TimeSpan.FromMilliseconds(50);
pinButton.ValueChanged += buttonValueChange;
Debug.WriteLine("GPIO initialised");
}
private void buttonValueChange(GpioPin sender, GpioPinValueChangedEventArgs e)
{
Debug.WriteLine("here");
if (e.Edge == GpioPinEdge.FallingEdge)
{
Debug.WriteLine("Button push");
pinValue = (pinValue == GpioPinValue.Low) ? GpioPinValue.High : GpioPinValue.Low;
pinRed.Write(pinValue);
pinBlue.Write(pinValue);
}
else
{
Debug.WriteLine("Button release");
}
}
}
Yes, lots of debug lines, as I said, trying out C# on Raspberry (InputPullUp is supported). The "here" in buttonValueChange is never triggered. I did the exact same wiring setup on Python and it worked flawlessly on the same pins.
It is suggested here ValueChanged not firing with C# Win10 Iot that "When the Run method ends, unless a deferral object is created, the Background Application ends."
As such you could try to add this line to your Run code:
var deferral = taskInstance.GetDeferral();
And see if it helps.
I have a weird problem (possibly a threading issue) that has been troubling me. I would like to have a progress bar for a task that I run in Excel/VSTO, that is started by clicking a button on the ribbon.
Since all access to the Excel Object model must occur in the main thread, I show my progress form modally on a separate thread. This works great most of the time, but odd things happen when I switch apps or windows via the Windows task bar. For example, if I am in the middle of a run and Excel is maximized, and I click Chrome on my taskbar to give it focus, then I click back to Excel and click between open Excel workbooks in the taskbar previews, sometimes the UI will partially freeze in the progress bar.
In Excel 2007/2010, I can still see the progress bar being updated but I can't drag the toolbar or click the Cancel button; this is why I say the UI partially freezes. Similar stuff happens in Excel 2013/2016 but I haven't tested as much on them.
If Excel has focus and we don't switch to another window during the execution of the task, then the progress bars work perfectly.
Does anyone have an idea what could be going wrong?
Is there another way I can go about displaying the progress bar in Excel to give consistent and reliable behavior? Note the limitation that the actual task needs to run on the main Excel UI thread and that for a progress form to be interactive and display properly, it needs to be on a secondary UI thread. Because of this, solution like using a BackgroundWorker won't work.
class RunSampleProgressTask
{
private ProgressForm _form;
internal volatile bool CancelPending;
internal volatile AutoResetEvent SignalEvent = new AutoResetEvent(false);
internal RunSampleProgressTask()
{
//create a new workbook
Globals.ThisAddIn.Application.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
int hwnd = GetHwnd();
var thread = new Thread(() => ShowProgressForm(hwnd));
thread.SetApartmentState(ApartmentState.STA);
thread.Priority = ThreadPriority.Highest;
thread.Name = "ProgressFormThread";
thread.IsBackground = true;
thread.Start();
SignalEvent.WaitOne();
//In SDI Excel a newly created workbook won't be shown until the function ends so we use a timer to show the new workbook before running Run()
if (IsSDI)
ExecuteTaskIn(200,Run);
else
Run();
}
internal static void ExecuteTaskIn(int milliseconds, Action action)
{
var timer = new System.Windows.Forms.Timer();
timer.Tick += (s, e) =>
{
((System.Windows.Forms.Timer)s).Stop(); //s is the Timer
action();
};
timer.Interval = milliseconds;
timer.Start();
}
//returns true if it is Excel 2013 or 2016 that use the new Single Document Interface
public static bool IsSDI
{
get
{
string appVersion = Globals.ThisAddIn.Application.Version;
return appVersion.StartsWith("15") || appVersion.StartsWith("16");
}
}
private void ShowProgressForm(int hwnd)
{
_form = new ProgressForm(this) {StartPosition = FormStartPosition.CenterScreen};
_form.ShowInTaskbar = false;
_form.FormBorderStyle = FormBorderStyle.FixedSingle;
_form.ShowDialog(new Win32Window(hwnd));
}
protected void ReportProgress(int percent)
{
if (_form == null || !_form.IsHandleCreated) return;
_form.BeginInvoke(new Action(() => _form.SetProgress(percent)));
}
protected void CloseForm()
{
if (_form == null || !_form.IsHandleCreated) return;
_form.BeginInvoke(new Action(() => _form.Close()));
}
internal static int GetHwnd()
{
if (IsSDI)
{
var window = Globals.ThisAddIn.Application.ActiveWindow;
int hwnd = (int)window.GetType().InvokeMember("Hwnd", BindingFlags.GetProperty, null, window, null); //late binding call to get Window.Hwnd
return hwnd;
}
else
{
return Globals.ThisAddIn.Application.Hwnd;
}
}
private const int BufRowSize = 16384; //must be a factor of RowsPerPage
private const int RowsPerPage = 1048576;
private const int BufColSize = 10;
private const int Repetitions = 80;
internal void Run()
{
ReportProgress(0);
Globals.ThisAddIn.Application.ScreenUpdating = false;
Globals.ThisAddIn.Application.EnableEvents = false;
var buf = new string[BufRowSize, BufColSize];
//fill the buffer with sample data
int cnt = 0;
for (int i = 0; i < BufRowSize; i++)
for (int j = 0; j < BufColSize; j++)
buf[i, j] = "String" + (++cnt);
var workbook = Globals.ThisAddIn.Application.ActiveWorkbook;
var sheet = workbook.ActiveSheet;
int currRow = 1;
for (int i = 0; i < Repetitions; i++)
{
if (CancelPending)
{
CloseForm();
Globals.ThisAddIn.Application.ScreenUpdating = true;
Globals.ThisAddIn.Application.EnableEvents = true;
return;
}
sheet.Range[sheet.Cells[currRow, 1], sheet.Cells[currRow + BufRowSize - 1, BufColSize]].Value2 = buf;
currRow += BufRowSize;
if (currRow > RowsPerPage)
{
currRow = 1;
sheet = workbook.Sheets.Add(Missing.Value, sheet);
}
int percent = 100 * (i + 1) / Repetitions;
ReportProgress(percent);
}
CloseForm();
Globals.ThisAddIn.Application.ScreenUpdating = true;
Globals.ThisAddIn.Application.EnableEvents = true;
}
}
public partial class ProgressForm : Form
{
private ProgressBar _progressBar;
private Label _lblStatus;
private Button _btnCancel;
private RunSampleProgressTask _task;
internal ProgressForm(RunSampleProgressTask task)
{
InitializeComponent();
this.Width = 320;
this.Height = 120;
this.ControlBox = false;
_task = task;
_progressBar = new ProgressBar(){Left=10, Top = 10, Width= 300, Height = 30};
_lblStatus = new Label(){Left = 10, Top = 50};
_btnCancel = new Button(){Text = "Cancel", Left = _lblStatus.Right + 10, Top = 50, Width = 100};
_btnCancel.Click += _btnCancel_Click;
this.Controls.Add(_progressBar);
this.Controls.Add(_lblStatus);
this.Controls.Add(_btnCancel);
this.Shown += ProgressForm_Shown;
}
void ProgressForm_Shown(object sender, EventArgs e)
{
_task.SignalEvent.Set();
}
void _btnCancel_Click(object sender, EventArgs e)
{
_task.CancelPending = true;
_lblStatus.Text = "Cancelling...";
}
internal void SetProgress(int percent)
{
_progressBar.Value = percent;
_lblStatus.Text = percent + "%";
}
}
public class Win32Window : IWin32Window
{
public Win32Window(int hwnd)
{
Handle = new IntPtr(hwnd);
}
public Win32Window(IntPtr handle)
{
Handle = handle;
}
public IntPtr Handle { get; private set; }
}