I'm new OOP student, I wrote simple clock program on Xamarin studio with C#. The format of clock is 00:00:00. It should be count up and work as a clock.
However, there must be some problems thus my clock can be draw on screen but doesn't "tick".
using SwinGameSDK;
namespace MyGame
{
public class Clock
{
private Counter counter = new Counter();
private int _seconds;
private int _minutes;
private int _hours;
public Clock ()
{
_seconds = counter.SecondsCounter;
_minutes = counter.MinutesCounter;
_hours = counter.HoursCounter;
}
public int Seconds {
get {
return _seconds;
}
set {
_seconds = value;
}
}
public int Minutes {
get {
return _minutes;
}
set {
_minutes = value;
}
}
public int Hours {
get {
return _hours;
}
set {
_hours = value;
}
}
public void DrawClock ()
{
DrawHours ();
SwinGame.DrawText (":", Color.Black, "Arial", 80, 360, 200);
DrawMinutes ();
SwinGame.DrawText (":", Color.Black, "Arial", 80, 520, 200);
DrawSeconds ();
}
public void DrawHours ()
{
SwinGame.DrawText (Hours.ToString ("D2"), Color.Black, "Arial", 80, 250, 208);
}
public void DrawMinutes ()
{
SwinGame.DrawText (Minutes.ToString ("D2"), Color.Black, "Arial", 80, 410, 208);
}
public void DrawSeconds ()
{
SwinGame.DrawText (Seconds.ToString ("D2"), Color.Black, "Arial", 80, 560, 208);
}
public void UpdateClock ()
{
counter.UpdateCounter ();
}
public void ResetClock ()
{
counter.Reset ();
}
public void SetClock ()
{
counter.SetTimer ();
}
}
}
using System.Timers;
namespace MyGame
{
public class Counter
{
private int _hoursCounter;
private int _minutesCounter;
private int _secondsCounter;
public Counter ()
{
_hoursCounter = 0;
_minutesCounter = 0;
_secondsCounter = 0;
}
public int HoursCounter {
get {
return _hoursCounter;
}
set {
_hoursCounter = value;
}
}
public int MinutesCounter {
get {
return _minutesCounter;
}
set {
_minutesCounter = value;
}
}
public int SecondsCounter {
get {
return _secondsCounter;
}
set {
_secondsCounter = value;
}
}
Timer timer = new Timer ();
public void SetTimer ()
{
timer.Interval = 1000;
timer.Elapsed += (sender, e) => UpdateCounter ();
}
public void UpdateCounter ()
{
timer.Start ();
SecondsCounter += 1;
if (SecondsCounter == 60) {
SecondsCounter = 0;
MinutesCounter += 1;
}
if (MinutesCounter == 60) {
MinutesCounter = 0;
HoursCounter += 1;
}
if (HoursCounter == 24) {
HoursCounter = 0;
MinutesCounter = 0;
SecondsCounter = 0;
}
}
public void Reset ()
{
HoursCounter = 0;
MinutesCounter = 0;
SecondsCounter = 0;
timer.Close ();
}
}
}
using SwinGameSDK;
namespace MyGame
{
public class GameMain
{
public static void Main ()
{
var myClock = new Clock ();
//Open the game window
SwinGame.OpenGraphicsWindow ("GameMain", 800, 600);
SwinGame.ShowSwinGameSplashScreen ();
//Run the game loop
while (false == SwinGame.WindowCloseRequested ()) {
//Fetch the next batch of UI interaction
SwinGame.ProcessEvents ();
//Clear the screen and draw the framerate
SwinGame.ClearScreen (Color.White);
SwinGame.DrawFramerate (0, 0);
myClock.DrawClock ();
myClock.SetClock ();
if (SwinGame.MouseClicked (MouseButton.LeftButton)) {
myClock.UpdateClock ();
}
if (SwinGame.MouseClicked (MouseButton.RightButton)) {
myClock.ResetClock ();
}
//Draw onto the screen
SwinGame.RefreshScreen (60);
}
}
}
}
The reason your clock is not ticking because you are continuously resetting it's interval using myClock.SetClock() method. This method should be only called only once outside the while loop in main method. Try following main method;
public static void Main ()
{
var myClock = new Clock ();
//Open the game window
SwinGame.OpenGraphicsWindow ("GameMain", 800, 600);
SwinGame.ShowSwinGameSplashScreen ();
myClock.SetClock (); //Set clock should be called from here.
//Run the game loop
while (false == SwinGame.WindowCloseRequested ()) {
//Fetch the next batch of UI interaction
SwinGame.ProcessEvents ();
//Clear the screen and draw the framerate
SwinGame.ClearScreen (Color.White);
SwinGame.DrawFramerate (0, 0);
myClock.DrawClock ();
if (SwinGame.MouseClicked (MouseButton.LeftButton)) {
myClock.UpdateClock ();
}
if (SwinGame.MouseClicked (MouseButton.RightButton)) {
myClock.ResetClock ();
}
//Draw onto the screen
SwinGame.RefreshScreen (60);
}
}
And SetTimer should be as follows
public void SetTimer ()
{
timer.Interval = 1000;
timer.Elapsed += (sender, e) => UpdateCounter ();
timer.Start ();
}
It seems like you dont even start the timer.
instead of calling timer.Start (); in UpdateCounter (), start the timer after timer.Elapsed += (sender, e) => UpdateCounter ();.
you should also keep your variables together.
private int _hoursCounter;
private int _minutesCounter;
private int _secondsCounter;
Timer timer;
and initialize the timer in the constructor:
..
_secondsCounter = 0;
timer = new Timer();
Related
Please go through the following code which is an oversimplification of the code I have.
I need to know how once the timer is elapsed, how to return control to the main user control class, preferably to the same case within the switch statement.
public partial class ucClass : UserControl
{
int A;
Label labelTimer = new Label();
sec secObj = new sec();
public execute()
{
switch(A)
{
case 1:
secObj.initiate(labelTimer, 10);
break:
case 2:
......
}
}
}
class sec
{
public System.Windows.Forms.Timer timer;
private Label labelTimer = new Label();
private int expectedCount = 0;
private int actualCount = 0;
public void initiate(Label labelTimer, int count)
{
this.expectedCount = count;
this.labelTimer = labelTimer;
this.timer.Interval = 1000;
startTimer();
}
private void startTimer()
{
this.timer.Start();
this.timer.Tick += this.timerElapsed;
}
private void timerElapsed(object sender, EventArgs e)
{
this.timer.Dispose();
if(expectedCount > actualCount)
{
this.actualCount += 1;
this.labelTimer.Text = this.actualCount.ToString();
this.startTimer();
}
else
{
//this is where I need to notify the main class that timer has expired and go to case 2
}
}
}
You can achieve the behavior that you want with events:
public partial class ucClass : UserControl
{
int A;
Label labelTimer = new Label();
sec secObj = new sec();
public ucClass()
{
// Listen to event from timer
secObj.TimerExpired += (sender, args) =>
{
A = args.Count;
execute();
};
}
public void execute()
{
switch(A)
{
case 1:
secObj.initiate(labelTimer, 10);
break:
case 2:
......
}
}
}
class sec
{
public System.Windows.Forms.Timer timer;
public event EventHandler<TimerExpiredEventArgs> TimerExpired;
private Label labelTimer = new Label();
private int expectedCount = 0;
private int actualCount = 0;
public void initiate(Label labelTimer, int count)
{
this.expectedCount = count;
this.labelTimer = labelTimer;
this.timer.Interval = 1000;
startTimer();
}
private void startTimer()
{
this.timer.Start();
this.timer.Tick += this.timerElapsed;
}
private void timerElapsed(object sender, EventArgs e)
{
this.timer.Dispose();
if(expectedCount > actualCount)
{
this.actualCount += 1;
this.labelTimer.Text = this.actualCount.ToString();
this.startTimer();
}
else
{
// Send event with count
TimerExpired?.Invoke(this, new TimerExpiredEventArgs
{
Count = actualCount
});
}
}
}
public class TimerExpiredEventArgs
{
public int Count { get; set; }
}
I would recommend looking into the following;
The MVVM pattern
This will allow you to seperate the UI logic (passing around labels etc) and the control logic (timers etc).
Reactive Extensions (https://github.com/dotnet/reactive)
This would allow for a very simple timer:
Observable
.Interval(TimeSpan.FromSeconds(1))
.Subscribe(count => {
labelTimer.Text = count.ToString();
if (count > actualCount) {
A = args.Count;
execute();
}
});
I've looked through this over and over again, I can't seem to figure out what the issue is. After looking it up some common issue where just people added extra braces or just forgetting one but I've looked through it and cant seem to find where I messed up. What is causing this error and why is it happening? It's showing the errors on lines 120 and 105.
using UnityEngine;
using Rocket.Core.Plugins;
using Rocket.Core.Logging;
using Rocket.Unturned.Events;
using Rocket.Unturned.Player;
using System.Collections.Generic;
using Rocket.Unturned;
using System;
using System.Timers;
namespace VipTeleport
{
public class VipTeleport : RocketPlugin
{
public static VipTeleport Instance;
public Vector3 DeathPos;
public UnturnedPlayer movePlayer;
public bool canTeleport = false;
public int timerT = 0;
public List<string> players = new List<string>();
public List<PlayerFinder> playerVars = new List<PlayerFinder>();
public PlayerFinder playerInfo;
public string steamId;
public int[] playerTimer = new int[24];
public int[] playerSteamID = new int[24];
public bool[] playersCanTeleport = new bool[24];
public int index;
protected override void Load()
{
VipTeleport.Instance = this;
//Just console logs for the plugin in RocketApi on unturneds server console
Logger.LogWarning("##################################");
Logger.LogWarning("#Vip Teleport Loaded Sucessfully!#");
Logger.LogWarning("##################################");
Logger.LogWarning("# Version V.1.0 #");
Logger.LogWarning("##################################");
}
protected override void Unload()
{
}
private void FixedUpdate()
{
U.Events.OnPlayerConnected += (UnturnedPlayer player) =>
{
int addTo = Convert.ToInt32(player.CSteamID);
foreach (int f in playerSteamID)
{
if (f == 0)
{
playerSteamID[f] = addTo;
foreach (int i in playerTimer)
{
playerTimer[f] = 0;
break;
}
foreach (bool t in playersCanTeleport)
{
playersCanTeleport[f] = false;
}
break;
}
}
};
//Listener for player Death
UnturnedPlayerEvents.OnPlayerDead += (UnturnedPlayer player, Vector3 Vector3) =>
{
int localSteamID = Convert.ToInt32(player.CSteamID);
foreach (int i in playerSteamID)
{
if (i == localSteamID)
{
index = i;
playerTimer[index] = 120;
break;
}
}
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(playerTimeVars);
aTimer.Interval = playerTimer[index];
aTimer.Enabled = true;
if ((playerTimer[index] <= 120) && (playerInfo.timerT > 0))
{
playerInfo.canTeleport = true;
}
else
{
playerInfo.canTeleport = false;
playerInfo.timerT = 0;
}
};
U.Events.OnPlayerDisconnected += (UnturnedPlayer player) =>
{
};
public int indexHolder(int i)
{
return i;
}
public void playerTimeVars(object source, ElapsedEventArgs e)
{
int localIndex = indexHolder(index);
playerTimer[localIndex] = 0;
}
}
}
}
Your last two methods need to be below a curly brace, currently they are inside the FixedUpdate() method.
private void FixedUpdate()
{
...
U.Events.OnPlayerDisconnected += (UnturnedPlayer player) =>
{
};
}
public int indexHolder(int i)
{
return i;
}
public void playerTimeVars(object source, ElapsedEventArgs e)
{
int localIndex = indexHolder(index);
playerTimer[localIndex] = 0;
}
Your FixedUpdate() method hasn't got enough brackets.
The methods public int indexHolder(int i), public void playerTimeVars(object source, ElapsedEventArgs e) are placed inside private void FixedUpdate() method which is the source of this error. Place them outside FixedUpdate and it should fix the error
I create a subclass of Forms.Timer, and I cannot stop this timer.
public class Clock : Timer
{
private int startTime;
private PictureBox one;
private PictureBox two;
private PictureBox three;
public Clock(Size _size) : base()
{ startTime = 0; initialComponent(_size); }
public Clock(int start_time, Size _size) : base()
{ startTime = start_time; initialComponent(_size); }
public Point Location
{
get { return three.Location; }
set
{
three.Location = value;
two.Location = new Point(value.X + three.Width, value.Y);
one.Location = new Point(value.X + three.Width + two.Width, value.Y);
}
}
private void initialComponent(Size _size)
{
......
}
public void Show()
{
int bits = startTime % 10;
int ten = (startTime % 100) / 10;
int hundred = (startTime % 1000) / 100;
one.Image = ImageLauncher.loadImage(bits, ImageLauncher.ImageType.Timer);
two.Image = ImageLauncher.loadImage(ten, ImageLauncher.ImageType.Timer);
three.Image = ImageLauncher.loadImage(hundred, ImageLauncher.ImageType.Timer);
}
protected override void OnTick(EventArgs e)
{
startTime++;
if (startTime > 999 || startTime < 0) return;
this.Show();
}
}
I create an object in form's constructor, the timer can start normally, but the Stop() method doesn't work. I've tried to create a method to set Timer.Enabled to false, but it is still going, more weird is I tried to reset interval with timer.Enabled in a same method, the interval has changed but timer still has not disbaled.
In constructor:
clock = new Clock(new Size(23 * 3, 38));
start:
if (!clock.Enabled) clock.Start();
method with stop:
private void gameOver(bool is_win)
{
clock.Stop();
showAll();
string winface = is_win ? "cool" : "sad";
ShortCutStart.Image = ImageLauncher.loadImage(winface, ImageLauncher.ImageType.Face);
ShortCutStart.Name = winface;
}
I am making a BCI interface, where the buttons must flicker at specific frequencies, at the moment I am using the System.Windows.Timer, however this is not very precise, and the flickering is not the frequency specified. The class I have used to make the flickering buttons are:
StateWithColor[] colors = new StateWithColor[] {
new StateWithColor(0, Color.Black),
new StateWithColor(1, Color.White)
};
public class FlickTimer<T> : IDisposable
where T : Control
{
public T Target { get; set; }
protected readonly IList<StateWithColor> possibleStates = new List<StateWithColor>();
protected int currentState = 0;
//protected int currentState_2 = 1;
protected object lockState = new object();
protected Timer timer = new Timer();
protected void Flicker(object sender, EventArgs e)
{
if (Target == null)
{
return;
}
if (Target.InvokeRequired)
{
Target.Invoke(new EventHandler(Flicker), sender, e);
return;
}
lock (lockState)
{
Target.BackColor = possibleStates[currentState].Color;
//int color = currentState + 1;
//Target.ForeColor = possibleStates[currentState_2].Color;
currentState++;
//currentState_2--;
if (currentState >= possibleStates.Count)
{
currentState = 0;
//currentState_2 = 1;
}
}
}
public FlickTimer(StateWithColor[] states, int timeout = 0, T target = null)
{
Target = target;
lock (lockState)
{
foreach (var state in states)
{
possibleStates.Add(state);
}
}
timer.Interval = timeout;
timer.Tick += Flicker;
Start();
}
public void Start()
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
public void Dispose()
{
if (timer != null)
{
Stop();
timer.Tick -= Flicker;
timer = null;
}
}
}
public struct StateWithColor
{ public int State;
public Color Color;
public StateWithColor(int state, Color color)
{
Color = color;
State = state;
}
}
This does not give the frequency I have specified when I run the Interface. The screen used for the interface is set to 120HZ, and the interface contains 9 buttons, which should be at the following frequencies: 6, 6.5, 7, 7.5, 8, 9, 10, 11, 12.5. Or nine frequencies with in the span of 6-15HZ. The frequencies can be 6.546 or 6.5 does not matter.
Is there a way to make this, and get a flivkering with the exact frequency?
I'm creating an Windowns phone 8 app(c#), its a countdown interval timer, so there is prepare time(10 sec), work time(20 sec), rest time(10 sec). I have these variables
`TimeSpan prepInterval = new TimeSpan(0, 0, 0, 10);
TimeSpan workInterval = new TimeSpan(0, 0, 0, 20);
TimeSpan restInterval = new TimeSpan(0, 0, 0, 10);`
I can't wrap my head around having them implementing them one after another when they hit 0. So when prepare time is done, the work timer is to start and when thats finised, the rest timer is to start.
If you would like to have some more broken down logic in all of this, maybe you can create some classes based on a simple interface, like the following:
interface ITimerAction
{
int Seconds { get; set; }
bool Started { get; }
bool Completed { get; }
void OnStart();
void OnComplete();
}
interface ITimerActionList
{
void Add(ITimerAction action);
void Work();
event EventHandler OnCompletedEvent;
}
This would then allow you to create an abstract TimerAction class, and TimerActionList
abstract class TimerAction : ITimerAction
{
public virtual int Seconds
{
get;
set;
}
public virtual bool Completed
{
get;
protected set;
}
public virtual bool Started
{
get;
protected set;
}
public abstract void OnStart();
public abstract void OnComplete();
}
class TimerActionList : ITimerActionList
{
public event EventHandler OnCompletedEvent;
private readonly IList<ITimerAction> actions = new List<ITimerAction>();
private bool working = false;
private Thread myThread;
public void Add(ITimerAction action)
{
if (working)
{
throw new InvalidOperationException("Cannot add new timers when work is already in progress");
}
actions.Add(action);
}
protected virtual void DoWork()
{
working = true;
int currentStep = 0, maxSteps = actions.Count;
while (currentStep < maxSteps)
{
ITimerAction action = actions[currentStep];
if (!action.Started)
{
action.OnStart();
}
if (action.Completed)
{
currentStep++;
continue;
}
if (action.Seconds == 0)
{
action.OnComplete();
continue;
}
action.Seconds--;
Thread.Sleep(1000);
}
Completed();
}
public void Work()
{
if (working)
{
throw new InvalidOperationException("Already running!");
}
working = true;
myThread = new Thread(DoWork);
myThread.Start();
}
protected virtual void Completed()
{
myThread = null;
working = false;
actions.Clear();
var local = OnCompletedEvent;
if (local != null)
{
local.Invoke(this, EventArgs.Empty);
}
}
}
You could then write the classes that inherit from the TimerAction class, that could handle an action before and after the timer ran through :)
class PrepareTimer : TimerAction
{
public override void OnStart()
{
Console.WriteLine("Preparing");
Started = true;
}
public override void OnComplete()
{
Console.WriteLine("Prepare ready");
Completed = true;
}
}
class WorkTimer : TimerAction
{
public override void OnStart()
{
Console.WriteLine("Working");
Started = true;
}
public override void OnComplete()
{
Console.WriteLine("Work ready");
Completed = true;
}
}
class CoolDownTimer : TimerAction
{
public override void OnStart()
{
Console.WriteLine("Cooling down");
Started = true;
}
public override void OnComplete()
{
Console.WriteLine("Cooldown ready");
Completed = true;
}
}
And then you could test the code as such
static void Main(string[] args)
{
bool done = false;
ITimerActionList mylist = new TimerActionList();
mylist.Add(new PrepareTimer { Seconds = 1 });
mylist.Add(new WorkTimer { Seconds = 2 });
mylist.Add(new CoolDownTimer { Seconds = 1 });
mylist.OnCompletedEvent += (sender, e) =>
{
done = true;
};
mylist.Work();
while (!done)
{
// timer is running
}
Console.WriteLine("Done!");
}
(Console program, but i guess that also goes to demonstrate?)
Here's an example based on deathismyfriend's and Hans Passant's suggestions:
var start = new DateTime();
var stage = 0;
var timer = new System.Timers.Timer(100);
timer.Elapsed += (s, e) =>
{
var elapsed = DateTime.Now - start;
int duration = stage == 1 ? 20 : 10;
if (elapsed.TotalSeconds > duration)
{
start = DateTime.Now;
stage++;
if (stage > 2)
timer.Stop();
}
};
start = DateTime.Now;
stage = 0;
timer.Start();