C# WPF MVVM Controlling mediaplayer position with slider makes audio stutter - c#

For starters, as for now, everything else works perfectly. So I have a project what includes a music player part (a mediaplayer). Position is visualised by text and with a slider, and that's where my problem is. When I make the slider "draggable" (so I can set the position, not just get it) the media (.mp3) starts to stutter randomly. Here is the part of the code:
public double ElapsedSeconds
{
get
{
return mediaPlayer.Position.TotalSeconds;
}
set
{
//mediaPlayer.Position = TimeSpan.FromSeconds(value);
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ElapsedSeconds)));
}
}
private void Timer_Tick(object sender, EventArgs e)
{
ElapsedSeconds = mediaPlayer.Position.TotalSeconds;
TextContent = String.Format("{0} - {1} - {2:mm\\:ss}/{3:mm\\:ss}", playedArtist, playedTitle, TimeSpan.FromSeconds(ElapsedSeconds), TimeSpan.FromSeconds(TotalSeconds));
}
ElapsedSeconds is binded to the value of the slider.
I can only drag the slider (and create the problem) when I uncomment that 1 line
And here is what I already tried:
- I used private field to store data
- Tried to use miliseconds and ticks but it got worse
- Tried to change the dispatchertimers tick frequency (currently 100 ms) what refreshes the current value
Is there any way to make the stuttering go away? (and if yes, what is it)
p.s.: If anyone interested, here is the whole .cs file: GitHub Link

After not thinking on the problem for almost 2 weeks I found a solution. Just need a condition to when to set the Position (so I changed the commented line to these):
if (mediaPlayer.Position > TimeSpan.FromSeconds(value + 1) || mediaPlayer.Position < TimeSpan.FromSeconds(value - 1))
mediaPlayer.Position = TimeSpan.FromSeconds(value);
Although at least 1 second of change is required, this way the program ignores the milisecond rollbacks what cause stuttering, while the Slider is still draggable.

Related

Unity: Dial-like Animation Resetting

(For anyone that understands, this is a simulator for an Omnitrix from Ben10 lol)
Explanation: I am trying to create a dial-like program. When an arrow key is pressed, an animation for a dial rotating plays, but it resets to the default position right after. The animation rotates the dial 20 degrees to the right or left, depending on the key pressed. How do I make the object stay at the 20-degree angle after the animation has played, and have the next animation start at the 20-degree angle and rotate to 40 degrees?
What I tried was to have the animation play and then change the rotation angle of the object to 20 degrees directly after so that it could increase to 40 from there, but that did not work (for reasons I have not figured out).
Code:
Ignore the inner if and print statements; those work as intended for debugging other areas of the project. The transform.Rotate statement at the end is the way that I tried to have my idea work, but it was unfunctional.
void Update()
{
if (Input.GetKeyDown("d") || Input.GetKeyDown("right"))
{
anim.Play("twistRight");
if (numAliens >= 17)
{
numAliens = 0;
}
else
{
numAliens++;
}
print("right" + numAliens);
twistObject.transform.Rotate(0, 20, 0);
}
if (Input.GetKeyDown("a") || Input.GetKeyDown("left"))
{
anim.Play("twistLeft");
if (numAliens <= 0)
{
numAliens = 17;
}
else
{
numAliens--;
}
print("left" + numAliens);
twistObject.transform.Rotate(0, -20, 0);
}
}
Animator: I think that the fact that the animations transition into the default state is what is causing this, but I do not know how else to have this program work under my current (unfunctional) structure of code. Without transitioning into the default state, it does not let me play the same animation multiple times consecutively, so I felt that this was the only option.
Any and all help is greatly appreciated. Thank you in advance!
Link to demonstration: https://drive.google.com/file/d/1I5Z2lQ-R9nWzC2rQ7Z389YGldmQcaeU1/view?usp=sharing

Logic error adding 2 variables together in Unity Engine

This sounds dumb, but I can't get 2 simple variables to add to each other, I have set points to add to 100 in the inspector. Everything would seem to work fine but when I all AddPoints from another script I Always get a debug log of 5. No matter what I set pointsToAdd to it always comes out as 5. I've tried score++; and that comes out just fine, I also tried to write a Debug.log just to make sure pointsToAdd wasn't set to something weird and it always returned 0! I don't know what in the world is happening. I must have screwed something up somehow.
private float score = 0;
public float pointsToAdd; // Setting in the editor
public void AddPoints()
{
score += pointsToAdd;
Debug.Log(score);
}
And the script that's calling AddPoints contains:
public LevelManager levelManager; // I'm setting in the editor
void OnCollisionEnter2D(Collision2D other)
{
if (other.transform.CompareTag("Wall"))
{
levelManager.AddPoints();
}
Edit: I've been testing for a few days now, with every chance I get completely unpredictable results until I set my score and Text UI to static variables, what about static variables changes the way that works?
Going to need a little more information on this one.
However I don't know how you are doing it in the other script, I am assuming its not this script causing the problem, most likely the other. I would personally do:
OtherScript:
pS.AddPoints(100f);
PointsScript
private float score;
public void AddPoints(float pointsToAdd)
{
score += pointsToAdd;
}

How to count and display points in a pong game within C#?

I'm having trouble counting the points of my AI Paddle Player and the user Paddle Player each time they miss colliding the ball. I tried using a boolean method and loops to count points, but to no avail as the program keeps on stating that the label in which my points are to be displayed, is "stack overflowed" due to an infinite loop which I am unable to recognize. So can you please help me.
Here is my code:
private void resetShiruken()
{
if ((reset == false) && (AIPoints < MAXPoints))
{
picShiruken.Location = new Point(ClientSize.Width / 2 - picShiruken.Width / 2, ClientSize.Height / 2 - picShiruken.Height / 2); //puts the picShiruken Picturebox in the middle anytime the picPlayerPaddle or picAIPaddle miss and is useful for counting the points of the computer and the player.
reset = true;
}
TheWinner();
}
private void TheWinner()
{
while (reset == true)
{
AIPoints += 1;
reset = false;
}
if (AIPoints >= AIPoints)
{
lblAIPoints.Text = AIPoints.ToString();
}
resetShiruken();
}
. resetShiruken() is a method that resets the ball to the middle each time any player misses.
. TheWinner() is a method that determines the winner of the game after either one of the players reach 5 points.
Thank You very Much,
Kai
As comments says:
you have recursive call of methods which lasts forever. resetShiruken calls TheWinner which calls resetShiruken and so on....
private void resetShiruken()
{
if ((reset == false) && (AIPoints < MAXPoints))
{
picShiruken.Location = new Point(ClientSize.Width / 2 - picShiruken.Width / 2, ClientSize.Height / 2 - picShiruken.Height / 2); //puts the picShiruken Picturebox in the middle anytime the picPlayerPaddle or picAIPaddle miss and is useful for counting the points of the computer and the player.
reset = true;
}
TheWinner();
}
private void TheWinner()
{
while (reset == true)
{
AIPoints += 1;
reset = false;
}
if (AIPoints >= AIPoints)
{
lblAIPoints.Text = AIPoints.ToString();
}
//resetShiruken(); <--- if you get rid of that call, should be fine.
}
Please note if you need to do reset after show the Winner, you should add additional parameter to reset method, or create separated method for post-winning reset.
Regular answer:
Your functions keep calling each other. Thats probably where the overflow is coming from.
From the functions given I'm unable to deduce exactly what your program flow would look like so I can't provide you with a fix which will do what you expect it to do.
To get rid of the overflow however simply remove either the call to "TheWinner" from "resetShiruken" or remove the call to "resetShiruken" from "TheWineer".
I suspect you should remove the latter.
Code style:
You're mixing upercase and lowercase function names which is a bad habit.
The default case for method names is "PascalCase" in c# (as depicted by the documentation).

Windows Phone - check if MapCore.SetView doesn't zoom too much

I am using method SetView to zoom for two points in map but when they are too close I am too zoomed. So I hope I can check something like this:
myMap.SetView(bounds);
if (myMap.ZoomLevel > Constants.DefaultZoomLevel)
myMap.ZoomLevel = Constants.DefaultZoomLevel;
But method SetView isn't immediately set ZoomLevel property. What can I do to fix it? How can I set some zoom level border? Thanks
Edit:
I found that in 8.0 sdk there is ZoomLevelChanged event? This could be useful for me. So is there possible how to get it worked in 7.1?
I tried several solutions and these are my results (I needed working for WP7.1, with just targeting for WP8 there could be easier solution):
Use of TargetZoomLevel
Like this:
myMap.ZoomLevel = Math.Min(myMap.TargetZoomLevel, maxZoomLevel);
Doesn't solve my problem because SetView set ZoomLevel after this code execute. Map was just blinking between ZoomLevel from SetView and maxZoomLevel (I have timer for checking positions so that is why it was blinking and isn't good for me).
Use of MapZoom event
Like this:
private void map1_MapZoom(object sender, Microsoft.Phone.Controls.Maps.MapZoomEventArgs e)
{
if (((Map)sender).ZoomLevel > maxZoomLevel)
{
e.Handled = true;
}
}
Problem: MapZoom event handler is not fired when SetView it's used.
Check distance and set ZoomLevel if distance is little:
public static double GetDistanceBetweenPoints(LatLon firstPoint, LatLon secondPoint)
{
var sCoord = new GeoCoordinate(firstPoint.Lat, firstPoint.Lon);
var eCoord = new GeoCoordinate(secondPoint.Lat, secondPoint.Lon);
return sCoord.GetDistanceTo(eCoord);
}
usage:
var distance = LocationHelper.GetDistanceBetweenPoints(carPosition, userPosition);
if (distance < MinMetersDistance)
myMap.ZoomLevel = maxZoomLevel;
Problem: Again blinking. Sometimes I set ZoomLevel by this code. Other time it was set by SetView.
My real solution:
I just check distance between two points like in previous dot. But this time if the distance was little I just create new points from the old ones and set them in new positions (latitude and longitude) which was in min distance (one on the left side I moved more to left and second on the right side I moved more to right). Then I used SetView on new points.

How to make a TextBlock work like a score counter in C# XAML

<Canvas x:Name="LayoutRoot" Background="white">
<Image Source="level1.jpg" Name="bg" Width="640" Height="480"
Canvas.Top="10" Canvas.Left="50"/>
<TextBlock Name="score">Scorehere</TextBlock>
</Canvas>
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (DetectCollisionLeft(myCat, myZero))
{
LayoutRoot.Children.Remove(myZero);
}
}
What I basically have is when my cat in the game collides with the number zero the number disappears. How can I get the TextBlock in the XAML to display a number that increases every time the number is collected.
Thank you
As I understand your problem statement, you want to update the score every time a collision is detected. If so then simply update the TextBlock.Text property to update the score.
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (DetectCollisionLeft(myCat, myZero))
{
if(LayoutRoot.Children.Contains(myZero))
{
LayoutRoot.Children.Remove(myZero);
//Update the score as score = previousScore + 1
int scoreAsInt;
if(Int32.TryParse(score.Text, NumberStyles.Integer, CultureInfo.CurrentCulture, out scoreAsInt) != null)
{
scoreAsInt = scoreAsInt + 1;
score.Text = scoreAsInt.ToString(CultureInfo.CurrentCulture);
}
}
}
}
Note that you have to consider the scenario in which the score becomes too large for the integer range. In that case you can either reset the score or use a larger type like long for the score.
My first suggestion is that you need to separate your logic from the visuals. This can be done either by using the MVVM pattern, or by writing data model classes for the score and cat and moving the logic there. MVVM is probably a little overboard for a simple project like this, but there can quickly arise unnecessary problems and complexity when the visual data and the logic is mixed.
Having said that, here's a simple answer to your problem. If you want to keep the score on the screen and just update it, there is no reason to remove it at all. Just update the text value and move it to a new random location in the canvas. Something like this:
if (DetectCollisionLeft(myCat, myZero))
{
Random rand = new Random();
score.Text = int.Parse(score.Text) + 1;
// Measure text for new random position
score.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
// Set the position of the text
Canvas.SetLeft(score, rand.Next(640 + 10 - score.DesiredSize.Width));
Canvas.SetTop(score, rand.Next(480 + 10 - score.DesiredSize.Height));
}
There could be better ways to randomize the position of the score. For example, it would be better to pass in the width of the screen / parent container instead of using the hard coded values 640 and 480. Hopefully this points you in the right direction.

Categories