I'am building a game in XNA, and I'am very new to XNA as well, but I got to start somewhere. Almost everything in my games works perfect. It is an topview racing game. The only problem is that I want to last the bonuses, that I pickup from the map last for a given time, like 3 seconds, I know that I need to use a timer, but I don't know how I should use it.
this is a part of code, I use when the car collides with a tile of my map:
if (map[x][y] == 0)
{
if (speedBonus)
{
car.speed = 450;
}
else
{
car.speed = 200;
}
I hope one of you guys can help me with this problem, because I have spent like 2 hours fixing it, but my code didn't help me out. Thanks in advance!
You'll want to record the time the bonus was picked up, which you can save into a DateTime object. Then, during each iteration of your main loop, check to see if the TimeSpan is greater than 3 seconds. If so, remove the bonus.
Thanks for the help, I fixed my code this way:
With 2 variables on top:
float timer = 3;
const float TIMER = 3;
And in the update:
if (map[x][y] == 0)
{
if (speedBonus)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
timer -= elapsed;
car.speed = 450;
if (timer <= 0)
{
speedBonus = false;
timer = TIMER; //Reset Timer
}
}
else
{
car.speed = 200;
}
it now works like a charm, thanks for the help!
Related
Using yield return new WaitForSeconds(waitTime);
within an IEnumerator, what is the shortest wait time other than 0? I have tried using a float number and have tried as low as 0.00001f for the waitTime, however i'm not sure if there is a limit or not?
The purpose is that I am having a player's coins added one unit at a time, so the meter is 'filling up' rather than instant. I have tried searching but I cannot seem to find the answer to what the shortest limit is for WaitForSeconds, so if anyone knows I'd greatly appreciate the answer.
Additionally, my code is as follows if anyone has any input on how I can speed up the process without making it instant, as it's just not quite quick enough and the player is having to sit for a while waiting for the coins to be added to the meter at the end of the game.
IEnumerator AddCoins()
{
yield return new WaitForSeconds(1);
while (userGainedCoins > 0)
{
if (addingSoundPlaying == false)
{
addingSound.Play();
addingSoundPlaying = true;
}
if (userGainedCoins == 1)
{
addingSound.Stop();
}
userCoins += 1;
userGainedCoins -= 1;
PlayerPrefs.SetInt("User Coins", userCoins);
yield return new WaitForSeconds(waitTime);
}
addingSoundPlaying = false;
}
I think it doesn't have a minimum time, it just waits until it reaches a certain amount before waiting. If you want, you can just add multiple coins at a time. I usually try not to mess with these kinds of things, and instead of messing with the coins, I would just mess with the value it displays. You could have a script that holds the number of coins and increases/decreases it based on the timestep. Something like this:
public int coins = 100;
public int displayedCoins = 0;
private void Update() {
int change = Mathf.CeilToInt(300 * Time.deltaTime);
if (displayedCoins < coins)
displayedCoins = Math.Min(displayedCoins + change, coins);
else
displayedCoins = Math.Max(displayedCoins - change, coins);
}
and with this you can just set the amount and forget about it, and it works with gaining and losing coins. You can also change the change value to something like int change = Mathf.CeilToInt(Mathf.Abs(coins - displayCoins) * Time.deltaTime) to make it have an ease-out effect, or whatever you want. (I didn't test this code.)
I want to make countdown timer that will return value of bool when he is active , so I can check on other script if is active give double points if is not then you need to give normal points..
I want to make it more complicated and I want to add time on timer if the timer is active, if is not then we use default time on countdown...
I don't know how to use courutine specially when I need to add time if the timer is not over..
Lets say like a example:
I pick up power up and timer starts for 5 seconds counting to 0.
If i pick up again powerup and timer is on lets say 3 , Power up need to have now 8 seconds. When powerup is over he must go from 5 seconds when player pick up new one..
Here is my code that doesn't work how I want also my code doesn't have a function to add time to power up when power up is active.. In other words I don't know how i can check if powerup is active and if yes just to add to counter 5 more seconds..
Here is code that doesn't contain adding time it only contains working counter..
void startDoublePoints()
{
StartCoroutine("doublePoints");
Time.timeScale = 1;
}
//Simple courutine
IEnumerator doublePoints()
{
while (true)
{
yield return new WaitForSeconds(1);
timeLeft--;
}
}
I hope someone will explain me more about how I can achieve my goal.. I hope I explained what I need to achieve.. If you do not understand something please ask on comment and I will try to explain it again..
Thank you so much community I don't know how would I learn anything without this great place :)
float powerUpTimer;
bool isDoublePoints = false;
void Update()
{
// Check timer only when Power up time
if(isDoublePoints)
{
// Countdown the timer with update time
powerUpTimer -= Time.deltaTime;
if(powerUpTimer <= 0)
{
// End of power up time
isDoublePoints = false;
powerUpTimer = 0;
}
}
}
// Add any time player picks to timer
public void OnPickPowerUp(float buffTime)
{
isDoublePoints = true;
powerUpTimer += buffTime;
}
So when my character gets hit by the enemies fire breath, I want to create the feel of the character being set on fire. So while the character is on fire I want him to lose a specific amount of health for a specific amount of time.
For example; lets say he is on fire for 3 seconds and I want to make him lose 30 health for being on fire, how would I evenly distribute losing 30 health for 3 seconds? I dont want the 30 damage to be applied instantly to the health, I want it to slowly tick away at the players health so that at the 3 second mark 30 damage has been dealt.
The game is being made with c#.
Thanks.
This is just like moving Gameobject over time or doing something over time. The only difference is that you have to use Mathf.Lerp instead of Vector3.Lerp. You also need to calculate the end value by subtracting the value you want to lose over time from the current value of the player's life. You pass this into the b or second parameter of the Mathf.Lerp function.
bool isRunning = false;
IEnumerator loseLifeOvertime(float currentLife, float lifeToLose, float duration)
{
//Make sure there is only one instance of this function running
if (isRunning)
{
yield break; ///exit if this is still running
}
isRunning = true;
float counter = 0;
//Get the current life of the player
float startLife = currentLife;
//Calculate how much to lose
float endLife = currentLife - lifeToLose;
//Stores the new player life
float newPlayerLife = currentLife;
while (counter < duration)
{
counter += Time.deltaTime;
newPlayerLife = Mathf.Lerp(startLife, endLife, counter / duration);
Debug.Log("Current Life: " + newPlayerLife);
yield return null;
}
//The latest life is stored in newPlayerLife variable
//yourLife = newPlayerLife; //????
isRunning = false;
}
Usage:
Let's say that player's life is 50 and we want to remove 2 from it within 3 seconds. The new player's life should be 48 after 3 seconds.
StartCoroutine(loseLifeOvertime(50, 2, 3));
Note that the player's life is stored in the newPlayerLife variable. At the end of the coroutine function, you will have to manually assign your player's life with the value from the newPlayerLife variable.
I suppose, what you are looking for is a Coroutine. Check out here and here for the documentation. It will allow you to do your custom health reducing actions separately from update function. Using coroutines you can make something happening by ticks, and you can determine how much time the tick is.
You could use couroutines. Something like this:
void OnHitByFire()
{
StartCoroutine(DoFireDamage(5f, 4, 10f));
}
IEnumerator DoFireDamage(float damageDuration, int damageCount, float damageAmount)
{
int currentCount = 0;
while (currentCount < damageCount)
{
HP -= damageAmount;
yield return new WaitForSeconds(damageDuration);
currentCount++;
}
}
So this is what I ended up doing. It causes the character on fire to lose 30 health and you can see the health ticking down instead of it happening over intervals.
IEnumerator OnFire()
{
bool burning = true;
float timer = 0;
while (burning)
{
yield return new WaitForSeconds(0.1f);
hp -= 1;
timer += 0.1f;
if (timer >= 3)
{
burning = false;
}
}
}
I am trying to figure out how to count 10 times each second and display it.
I have an int called countpoints which is what the user starts with points. Lets say 800.
I would like to drop 10 points each second but showing each point falling instead of every 10 points like my script below does.
here is how I have done so far:
if(miliseconds <= 0){
if(seconds <= 0){
minutes--;
seconds = 59;
}
else if(seconds >= 0){
seconds--;
countpoints = countpoints-10;
}
miliseconds = 100;
}
miliseconds -= Time.deltaTime * 100;
This runs in void update and here countpoints falls by 10 each second. but i would like to be able to show the numbers drop down like a stopwatch each second. How do i do that?
Any help is appreciated and thanks in advance :-)
You should use coroutine for that calculation instead of in Update(). It can be very easy with the coroutine. You just need to start croutine and then wait for 0.1 seconds and decrease counterpoints by 1. Again call that coroutine inside that to keep it running. Just add condition whenever you want to keep on calling it.
private int countpoints=800;
private float t=0.1f;
private int noOfSeconds=90;
private int min;
private int sec;
private int temp=0;
void Start ()
{
StartCoroutine(StartTimer());
}
IEnumerator StartTimer ()
{
yield return new WaitForSeconds(t);
countpoints--;
temp++;
if(temp==10)
{
temp=0;
noOfSeconds--;
}
min = noOfSeconds/60;
sec = noOfSeconds%60;
if(noOfSeconds>0)
{
StartCoroutine(StartTimer());
}
}
void OnGUI ()
{
GUI.Label(new Rect(100f,100f,100f,50f),countpoints.ToString());
GUI.Label(new Rect(100f,160f,100f,50f),"Time : "+min.ToString("00")+":"+sec.ToString("00"));
}
You could just do it in the Update method and decrement the points once every 100ms, you need to take care of not rounding things up or down as the error would be systematic and you'll get choppy results.
Using coroutines won't work as expected as the interval is not guaranteed.
private float _milliseconds = 0;
private int points = 800;
void Update()
{
_milliseconds += Time.delta * 1000;
if( _milliseconds > 100 )
{
points--;
//add updating GUI code here for points
_milliseconds -= 100;
}
}
You won't get choppy decrements as the _milliseconds are decremented by 100, so even if there are differences in the duration of the frames in the long run you'll get a proper handling.
One problem with the script is if frames take a lot more than 100ms consistenly , but if it takes that long you probably have bigger problems:D
i am developing a mobile game using XNA and have an on and off switch which changes the state whenever tapped on. My problem is that it changes rapidly and multiple times from a single tap. How do i stop this?
Store a time the in-game switch was last used and calculate the timespan passed
if(buttonPressed && (Datetime.Now - timeLastInGameSwitchActivated).Milliseconds > 1000)
{
ToggleIngameSwitch();
timeLastInGameSwitchActivated = Datetime.Now;
}
add a previous value variable to check the last state of the button, if its different to the current one then do the desired code
ButtonState prev = state
if(currentstate != prev)
{
dothis
}
I use this simple technique to deal with 'delay' stuff.
float elapsed = (float)gameTime.ElapsedGameTime.Milliseconds;
timeCounter += elapsed;
if (timeCounter > yourMinimumDelayTime)
{
//your code here
timeCounter = 0;
}