I'm trying to create a timer in c# for an online game. All i really want is a timer that counts 60 seconds and then restarts. And let it go forever, then add a point for every time it resets...
What i've done so far is:
DateTime dateTime = DateTime.Now;
int sec = dateTime.Second;
if(sec = 1)
{
// stuff
}
The if does not loop, how do I do that? or anyone have a better idea? I'd really like one where i can change the seconds.
I think System.Threading.Timer might be useful, just set a callback that triggers after 60 seconds.
i found something related to my question and edited to what i wanted. it does what I want it to do, but does it create overflow or not, that im not sure of. Does anyone have a better idea of doing this?
using System;
namespace ticket
{
class Program
{
public static int x = 0;
static void LoopingFunction()
{
while (x <= 20)
{
int dwStartTime = System.Environment.TickCount;
while (true)
{
if (System.Environment.TickCount - dwStartTime > 100) break; //100 milliseconds
}
Console.WriteLine(x);
x++;
if (x == 20)
{
///add "stuff"
Console.WriteLine("Test");
x = 0;
}
}
}
static void Main()
{
LoopingFunction();
Console.Read();
}
}
}
Related
This seems very simple, but I can't seem to figure it out. Here is the code:
if(score >= 3000)
{
FindObjectOfType<GameSession>().AddLife();
}
The problem is that once I've reached and surpassed 3000, the condition is such that my score is always above 3000 and so a new life keeps getting added ad infinitum. If I just use '=' operand, however, my score could just jump above 3000 without equaling it and the life will not be added. How do I just add a single life when the score equals or is greater than 3000?
Any help would be much appreciated.
You need some sort of control for that.
For example :
bool isAdded = false; // add this outside of the method that contains if statement
if(score >= 3000)
{
if(!isAdded){
FindObjectOfType<GameSession>().AddLife();
isAdded = true;
}
}
And reset it anywhere you like. For example when the game resets. isAdded = false
Try adding a class field that is not just a static number, 3000, but that you can increase as the player passes each score to beat.
static int _lives = 1;
static int _increment = 3000;
static void Main(string[] args)
{
int scoreToBeat = 0;
for (int i = 0; i < 5000; i++)
{
var score = i;
if (score >= scoreToBeat)
{
AddLife();
scoreToBeat += _increment;
}
}
}
static void AddLife()
{
_lives += 1;
}
I am learning c# and I was trying to test my abilities by making a short game using the .net framework console. I want to make it so that if you don't type "(the thing the player needs to type)" within x amount of time, then they fail, and they go to the death screen.
I have tried looking up stuff like the System.Threading.CountdownEvent, Systen.Threading.Timer and System.Timers.Timer etc, but all the tutorials don't help.
tutorialfight:
if (fight == "Y")
{
Console.WriteLine("Goblin: 'You seem week, hit me first!'");
}
else if (fight == "N")
{
Console.WriteLine("This is the tutorial, you have no choice, Would you like to fight? (Y/N)");
fight = Console.ReadLine();
goto tutorialfight;
}
else
{
Console.WriteLine("Type Y for yes or N for no");
fight = Console.ReadLine();
goto tutorialfight;
}
int goblinhp = 5;
Console.WriteLine("Misery: 'Type what is says to do some damage. If you fail, you take some damage, and if you dont kill the enemy within the amount of time allowed, you die!'");
Console.WriteLine("Type 'x3hu' in 10 seconds to deal 1 damage");
string x3hu = Console.ReadLine();
if (x3hu != "x3hu")
{
Console.WriteLine("Your health went down 3 points!");
health = health - 3;
Console.WriteLine("Health: " + health);
Console.WriteLine("Misery: 'Dont worry, you've still got loads of health left!'");
}
else
{
goblinhp = goblinhp - 1;
Console.WriteLine("Goblin health: " + goblinhp);
Console.WriteLine("Misery: 'Great job!'");
}
It seems like you already have a grasp of what you need:
Some way of detecting Console input is available to read
Some way of setting a timeout for user input
You should be able to accomplish this by using the Console.KeyAvailable property and tracking the elapsed time of a Stopwatch.
The pseudo code would go something like this:
Console.WriteLine("You have 10 seconds to press attack (x)");
var timeout = 10;
StopWatch.Start();
while(Stopwatch.Elapsed.Seconds < timeout && !Console.KeyAvailable)
{
// wait
}
// process which event happened first
The conditions and looping logic could vary but this should be enough to get you headed in the right direction :)
KeyAvailable documentation
Stopwatch documentation
I made a simple solution based on Dawid Owens' answer.
class Program
{
static async Task Main(string[] args)
{
var timeout = 10;
var textToWrite = "Hello World!";
bool isTimeIsUp = false;
bool returnPressed = false;
StringBuilder enteredText = new StringBuilder();
Console.WriteLine($"You have {timeout} seconds to write: '{textToWrite}'");
Stopwatch stopwatch = Stopwatch.StartNew();
while (!returnPressed)
{
while (!isTimeIsUp && !Console.KeyAvailable)
{
isTimeIsUp = stopwatch.Elapsed.Seconds >= timeout;
}
if (isTimeIsUp) break;
var ch = Console.ReadKey();
returnPressed = ch.Key == ConsoleKey.Enter;
if (!returnPressed)
{
enteredText.Append(ch.KeyChar);
}
}
if (isTimeIsUp || enteredText.ToString() != textToWrite)
{
Console.WriteLine($"\nFailure!");
}
else
{
Console.WriteLine($"\nSuccess!");
}
}
}
I imagined the result would be a negative value, due to not locking and multiple threads sharing the same object. I have tested this many times with release and debug version, every time the result is correct. Why is it still correct?
Code :
static BankAccount ThisbankAccount = new BankAccount(10000);
public static void WithdrawMoney()
{
for(int i = 0; i < 1000; i++)
ThisbankAccount.WithdrawMoney(25);
}
static void Main(string[] args)
{
Thread client1 = new Thread(WithdrawMoney);
Thread client2 = new Thread(WithdrawMoney);
Thread client3 = new Thread(WithdrawMoney);
client1.Start();
client2.Start();
client3.Start();
client3.Join();
Console.WriteLine( ThisbankAccount.Balance);
Console.ReadLine();
}
}
public class BankAccount
{
object Acctlocker = new object();
public BankAccount(int initialAmount)
{
m_balance = initialAmount;
}
public void WithdrawMoney(int amnt)
{
// lock(Acctlocker)
// {
if (m_balance - amnt >= 0)
{
m_balance -= amnt;
}
// }
}
public int Balance
{
get
{
return m_balance;
}
}
private int m_balance;
}
Just because something works now doesn't mean it is guaranteed to work. Race conditions are hard to trigger and might take years to surface. And when they surface, they can be very hard to track down and diagnose.
To see your problem in action, change this code:
if (m_balance - amnt >= 0)
{
m_balance -= amnt;
}
to:
if (m_balance - amnt >= 0)
{
Thread.Sleep(10);
m_balance -= amnt;
}
That introduces a slow enough code path to highlight the problem really easily.
The reason you aren't spotting it with your current code is that the operations you are doing (subtraction and comparisons) are very fast. So the window for the race condition is very small - and you are lucky enough for it not to occur. But, over unlimited time, it definitely will occur.
I write application need check if time to checkLogin() sleep over > 30 seconds.
Then, it will break this while loop and continues the program.
My code like this:
while(!Account.checkLogin())
{
Thread.Sleep(1000);
}
How to check like:
while(!Account.checkLogin())
{
Thread.Sleep(1000);
if(Thread.Sleep like 30000)
continues;
}
If I understood the question correctly, you could sum up the iterations and and use them in the termination condition as follows.
int MAX_ITERATIONS = 30;
int NumOfIterations = 0;
while(!Account.checkLogin() && NumOfIterations < MAX_ITERATIONS)
{
Thread.Sleep(1000);
NumOfIterations++;
}
You can just sleep for 30 seconds:
Thread.Sleep(30000);
However that's holding up the thread and stops you doing anything inbetween. I prefer to use a TimeSpan, for example:
DateTime started = DateTime.UtcNow;
while (!Account.checkLogin())
{
TimeSpan ts = DateTime.UtcNow - started;
if (ts.TotalSeconds >= 30)
break;
Thread.Sleep(1000);
}
im trying to create a timer to "tick" and created this timer with a little google help.
It works perfectly in console, but when i added it in a website, it seems my computer is running at full capasity, and the site is loading slowly and not function properly.
Can i use this or do i need to start over?
namespace ticket
{
class Program
{
public static int counttick = 0;
public static int ticks = 0;
static void LoopingFunction()
{
while (counttick <= 20)
{
int dwStartTime = System.Environment.TickCount;
while (true)
{
if (System.Environment.TickCount - dwStartTime > 1000) break; //1000 milliseconds
}
counttick++;
if (counttick == 20)
{
ticks++;
counttick = 0;
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
Label2.Text = "Ticks: " + Convert.ToString(ticks);
LoopingFunction();
}
}
}`
Remove:
while (true)
{
if (System.Environment.TickCount - dwStartTime > 1000) break; //1000 milliseconds
}
And use:
System.Threading.Sleep(1000);
Try System.Threading.Timer class.
In web applications i don't recommend using static variables, because you really never know when you IIS will recycle the app pool and you static varitable will become 0. rather you should try something to persistence storage. and use to Try System.Threading.Timer class to update the value in may be a Database table or some file.
Regards.
I'll just give another approach. I needed a similar tick loop that runs at about 25 frames per second. I have a class called ApplicationLoop which, when constructed starts a thread. That thread is my application loop. (Hence the obvious class name.)
So I have a few constants, to determine my frame rate, and a frame-skip fallback value. Basically, when a task takes more time than 40ms (1000 / 25 = 40), I loop through all the tasks again to "catch-up". But I only do this a number of times.
private const int MAX_FRAMESKIP = 5;
private const int UPDATE_SKIP_TICKS = 1000 / UPDATE_TICKS_PER_SECOND;
private const int UPDATE_TICKS_PER_SECOND = 25;
My thread function:
private void UpdateLoop()
{
ulong ticks = 0UL;
_isRunning = true;
var next = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
while (_isRunning)
{
var now = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
int loops = 0;
while ((now > next) && _isRunning && (loops < MAX_FRAMESKIP))
{
ProcessTasks(ticks);
next += UPDATE_SKIP_TICKS;
loops++;
ticks++;
}
AccurateSleep(1);
}
}
My class contains a Subscribe() function which takes a delegate. I store that callback into a List and the ProcessTasks() function calls each subscribed function.
You can replace the AccurateSleep() function with a simple Thread.Sleep(1) call, but be aware that the default time-slice for a sleep is about 15ms.
[DllImport("winmm.dll")]
private static extern uint timeBeginPeriod(uint period);
[DllImport("winmm.dll")]
private static extern uint timeEndPeriod(uint period);
private static void AccurateSleep(int sleep)
{
timeBeginPeriod(1);
Thread.Sleep(sleep);
timeEndPeriod(1);
}