Autoincremental countdown timer doesn't count down unity - c#

I have this timer in my unity game that is a simple countdown timer that when certain function is completed reset the time to default and increments the time by 1 seconds. It works fine but when I increment by 3 seconds, it doesn't increment.
Here is the code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
public class GameLogic : MonoBehaviour
{
public int[] sequence; //The sequence int array will hold our sequence order
public int sequenceLength; //The sequenceLength is how long a sequence will be. Everytime the player completes a sequence it goes up one
public int sequencesPlayedCom; //The sequencesPlayedCom is to measure how many times the computer has pressed the buttons in the current sequence
public int sequencesPlayedPlayer; //The sequencesPlayedPlayer is to measure how many times the player has pressed the buttons in the current sequence
public float timeleft = 5.0f;
public float timecounter;
public int score; //Each time the player completes a sequence they get +1 onto their score
public int casualHighScore; //This variable holds the highest score that the player has ever achieved on the casual gamemode
public int randomizeHighScore; //This variable holds the highest score that the player has ever achieved on the randomize gamemode
public string gameMode; //This will tell us what game mode the player chose so we can modify the game (casual, randomize)
//Buttons
public GameObject greenButton; //This holds the GameObject of our green button, so that the script can send messages over to it
public GameObject redButton; //This holds the GameObject of our red button, so that the script can send messages over to it
public GameObject blueButton; //This holds the GameObject of our blue button, so that the script can send messages over to it
public GameObject yellowButton; //This holds the GameObject of our yellow button, so that the script can send messages over to it
//UI
public Text scoreText; //This is the text that is displayed on screen, that tells us our score
public Text highScoreText; //Just like the score text, but displaying the high score
//Sounds
public AudioSource audioSource; //This is the source of which we will play the sequence fail and complete sounds through
public AudioClip sequenceCompleteSound;
public AudioClip sequenceFailSound;
public AudioClip buttonClickSound;
void Start () //The Start function is called on the frame that the script becomes active
{
gameMode = PlayerPrefs.GetString("GameMode"); //We need to access our game mode that the player selected
casualHighScore = PlayerPrefs.GetInt("CasualHighScore"); //We need to access our saved score
randomizeHighScore = PlayerPrefs.GetInt("RandomizeHighScore");
audioSource = GameObject.Find("Camera").GetComponent<AudioSource>();
audioSource.volume = PlayerPrefs.GetFloat("Volume"); //We are setting our volume to the one that we set in the options menu
sequence = new int[50]; //Here we are defining the sequence array's size
timecounter = timeleft;
StartCoroutine(GenerateNextSequence()); //We call the GenerateNextSequence function which randomly selects the next number for the sequence
}
void Update () //The Update function is called once per frame
{
scoreText.text = "SCORE\n" + score; //Here we are setting what our on screen text will say. The '\n' basically makes a new line
if(gameMode == "casual"){
highScoreText.text = "HIGH SCORE\n" + casualHighScore; //Just like the on screen score text, but displaying the high score for the casual gamemode
}
else if(gameMode == "randomize"){
highScoreText.text = "HIGH SCORE\n" + randomizeHighScore; //Just like the on screen score text, but displaying the high score for the randomize gamemode
}
timer();
}
public void timer()
{
if (timecounter > 0)
{
timecounter -= Time.deltaTime;
Debug.Log(timecounter);
} else
{
audioSource.PlayOneShot(sequenceFailSound); //Since the player failed the sequence, we need to play the appropriate sound
SaveScore();
Application.LoadLevel(0); //Since the player we load up the menu
}
}
IEnumerator GenerateNextSequence ()
{
sequencesPlayedCom = 0; //Set the number of times that the computer has clicked a button to 0
sequencesPlayedPlayer = 0; //Set the number of times that the player has clicked a button to 0
timecounter = timeleft;
timecounter = timecounter + 3;
if (gameMode == "casual"){
sequence[sequenceLength - 1] = Random.Range(1, 5); //Since array index's start at 0, we have it randomly select a number between 1 and 5 (it rounds to the nearest int) and set it to the most current index number.
yield return new WaitForSeconds(1); //We wait 1 second after picking our next colour, before going on to playing the sequence
StartCoroutine(PlaySequence()); //Now that we have our next colour, we can go and play the array to the player
}
else if(gameMode == "randomize"){
for(int i = 0; i < sequenceLength; i ++){
sequence[i] = Random.Range(1, 5);
}
yield return new WaitForSeconds(1);
StartCoroutine(PlaySequence()); //Now that we have our random sequence, we can have the computer play it
}
}
IEnumerator PlaySequence () //Plays the sequence
{
CanClickButton(false); //We call a function that disables the buttons while the computer is playing the sequence
while(sequencesPlayedCom < sequenceLength){ //A while loop. Here we have it continuously do what is inside the brackets as long as sequencesPlayedCom < sequenceLength
GameObject buttonToPress = null; //We set this temporary GameObject variable to hold the button so its ButtonPress function can be called
if(sequence[sequencesPlayedCom] == 1){ //If the next element in the int array is 1 then it will be a green button
buttonToPress = greenButton;
}
else if(sequence[sequencesPlayedCom] == 2){
buttonToPress = redButton;
}
else if(sequence[sequencesPlayedCom] == 3){
buttonToPress = blueButton;
}
else if(sequence[sequencesPlayedCom] == 4){
buttonToPress = yellowButton;
}
buttonToPress.SendMessage("ButtonPress"); //We call the ButtonPress function on the button so the player can see and hear it
yield return new WaitForSeconds(0.7f); //Wait 0.7 seconds until we continue to the next colour in the sequence
sequencesPlayedCom++; //Adding one to the sequencesPlayedCom so we know that computer just clicked a button
}
if(sequencesPlayedCom == sequenceLength){
CanClickButton(true); //After the computer has pressed all the buttons in the sequence, the player can now click on the buttons
}
}
IEnumerator CheckSequenceButton (int id)
{
if(sequence[sequencesPlayedPlayer] == id){ //We check to see if the next color of the sequence is the one that the player pressed
sequencesPlayedPlayer ++;
}else{
yield return new WaitForSeconds(0.3f);
audioSource.PlayOneShot(sequenceFailSound); //Since the player failed the sequence, we need to play the appropriate sound
SaveScore();
yield return new WaitForSeconds(1.7f); //A delay after the player fails
Application.LoadLevel(0); //Since the player we load up the menu
}
if(sequencesPlayedPlayer == sequenceLength){ //If the player has completed the sequence
yield return new WaitForSeconds(0.3f); //We have a small delay after the player completes the sequence
audioSource.PlayOneShot(sequenceCompleteSound);
score++; //Since the player has completed the sequence, we will add 1 to the score
sequenceLength++; //The sequence length is one added to it
StartCoroutine(GenerateNextSequence()); //We continue on with this loop, increasing the sequence one colour at a time
}
}
public void GoToMenu () //Function used to get back to the main menu
{
audioSource.PlayOneShot(buttonClickSound); //Playing the button click sound
SaveScore();
Application.LoadLevel(0);
}
void CanClickButton (bool i) //Tells the buttons if they can be clicked or not
{
greenButton.SendMessage("DisableOrEnableButton", i);
redButton.SendMessage("DisableOrEnableButton", i);
blueButton.SendMessage("DisableOrEnableButton", i);
yellowButton.SendMessage("DisableOrEnableButton", i);
}
void SaveScore () //Checks if score is higher that high score then saves it to Player Prefs
{
if(gameMode == "casual"){ //If the game mode is Casual
if(score > casualHighScore){ //If the players current score is higher than their highscore then we will change it
PlayerPrefs.SetInt("CasualHighScore", score);
if (PlayGamesPlatform.Instance.localUser.authenticated)
{
// Note: make sure to add 'using GooglePlayGames'
PlayGamesPlatform.Instance.ReportScore(score,
GPGSlds.leaderboard_facil,
(bool success) =>
{
Debug.Log("(Lollygagger) Leaderboard update success: " + success);
});
}
}
}
else if(gameMode == "randomize"){
if(score > randomizeHighScore){
PlayerPrefs.SetInt("RandomizeHighScore", score);
if (PlayGamesPlatform.Instance.localUser.authenticated)
{
// Note: make sure to add 'using GooglePlayGames'
PlayGamesPlatform.Instance.ReportScore(score,
GPGSlds.leaderboard_normal,
(bool success) =>
{
Debug.Log("(Lollygagger) Leaderboard update success: " + success);
});
}
}
}
}
}
I miss some code that doesn't have to do with the timer, the timer work fine, just that I can't do the autoincrement when the function GenerateNextSequence() is run.

Related

How to make a combotimer in Unity

I'm making a game currently and I got stuck while I was thinking about a combotimer.
Now in my game, there are enemies that run through my character and I hit them. Yet, at some point, if I can correctly hit the enemies, I want to add a powerful combo option like hitting them without any difficulty. I thought like I can create a class or a value that keeps the correct hits and let's say it's 5. When it reaches 5, then I can change the hitting options. Yet, where I'm stuck is that how I can identify after how many hits or seconds the combo can end. And in here what came to my mind is that I can make it with time. So here's the thing. I want to detect 5 hits and then I want a combotimer which makes the value of 5 decreased. So that when the value reaches 0 then I can continue to play my game with the normal standards of it. How can I do this?
Since you didn't provide anything here is what I would do as dummy code. This does
Everytime you hit an enemy check the time since last hit
If under the maximum delay => add to combo
If not reset the combo counter and start over
If reaching enough hits => enable isSuperCombo
Over time reset the isSuperCombo
As long as you are isSuperCombo you can still add hits even if they happen after the normal maxTimeBetweenHits to enlarge the duration of isSuperCombo as a little bonus
Something like
public class ComboCounter : MonoBehaviour
{
public bool isSuperCombo;
// Maimum delay in seconds since the hit for counting the current hit as combo
[SerializeField] private float maxTimeBetweenHits = 1;
// Requried hits in one combo in order to activate power bonus
[SerializeField] private int hitsUntilSuperCombo = 5;
// Delay in seconds to reset the powerup after the last hit
[SerializeField] private float powerUpDuration = 5;
private int hitCounter;
private float lastHitTime;
private float powerUpResetTimer;
private void Update()
{
if(isSuperCombo)
{
powerUpResetTimer -= Time.deltaTime;
if(powerUpResetTimer <= 0)
{
isSuperCombo = false;
hitCounter = 0;
}
}
}
// Call when you hit an enemy
public void AddHit()
{
if(Time.time - lastHitTime < maxTimeBetweenHits)
{
// then add to the hit counter
hitCounter++;
if(hitCounter >= hitsUntilSuperCombo)
{
isSuperCombo = true;
powerUpResetTimer = powerUpDuration;
}
}
else
{
// otherwise the delay was too big => not a combo anymore
// => Reset the counter and start over with this hit as the first one
hitCounter = 1;
}
// update the lastHitTime
lastHitTime = Time.time;
}
}
Then you could e.g. in another class check something like
public void CauseDamage(Enemy enemy)
{
enemy.health -= GetComponent<ComboCounter>().isSuperCombo ? 4 : 1;
}
If you need to note 5 seconds of increased damage you can use coroutine
private float _damage = 10;
public void StartCombo(float duration = 5)
{
StartCoroutine(ComboHandler(duration));
}
private IEnumerator ComboHandler(float duration)
{
_damage *= 2; //_damage = _damage * 2;
yield return new WaitForSeconds(duration); //wait necessary amount of real time
_damage /= 2; //_damage = _damage / 2;
}
If you need to do only 5 blows with increased damage, you can use something
private float _damage = 10;
private int _increasedBlows = 0; //amount of blows with increased damage
private float _increasingCoeff = 2; //ratio of damage increase of blow
//add new increased blows after doing combo
public void AddIncreasedBlows(int amount)
{
_increasedBlows += amount;
}
//return blow damage
public float GetHitDamage()
{
if (_increasedBlows > 0)
{
_increasedBlows--;
return _damage * -_increasingCoeff; //return increased damage
}
else
{
return _damage; //return usual damage
}
}

How can I make a smooth transition between two animations?

First animation when starting the game the character is examine or typing and then after 10 seconds I want the character to start walking and just before reaching the destination to change to idle.
The order should be : Typing , Walking , Idle
With this script the character is typing waiting 10 seconds rotating looking the target and then move to the target without the two animations Walking and Idle.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AgentControl : MonoBehaviour
{
public List<Transform> points;
public bool waitTimeToMove = false;
//notice WaitTime is a float now
public float WaitTime = 10f;
public bool randomWaitTime;
float waitMinTime = 1f;
float waitMaxTime = 10f;
public bool loop = false;
private int destPoint = 0;
private NavMeshAgent agent;
private Transform originalPos;
//two vars for handling timer
private float timer = 0;
private float originSpeed;
void Start()
{
agent = GetComponent<NavMeshAgent>();
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
agent.autoBraking = false;
originSpeed = agent.speed;
if (randomWaitTime == true)
{
WaitTime = Random.Range(waitMinTime, waitMaxTime);
}
//transforms dont exist without A GameObject and a GameObject doesn't exist without a transform
//create a new GameObject to hold our position
GameObject originalPositionObject = new GameObject();
originalPositionObject.name = "WP";
originalPositionObject.tag = "Waypoint";
originalPositionObject.transform.parent = GameObject.Find("Waypoints").transform;
//set the new gameobjects position equal to where the transform is right now
originalPositionObject.transform.position = transform.position;
//add this to the points list instead
points.Add(originalPositionObject.transform);
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Count == 0)
return;
// Set the agent to go to the currently selected destination.
agent.destination = points[destPoint].position;
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
destPoint = (destPoint + 1) % points.Count;
}
void Update()
{
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 1f)
{
//if wait to move is true
if (waitTimeToMove)
{
//if timer is less than 10
if (timer < WaitTime)
{
//add Time.deltaTime each time we hit this point
timer += Time.deltaTime;
}
//no longer waiting because timer is greater than 10
else
{
waitTimeToMove = false;
}
}
//if we hit here waitToMove is false, so go ahead as usual
else
{
if (loop == false && destPoint == points.Count - 1)
{
agent.speed = 0;
}
if (loop == true || destPoint != points.Count - 1)
{
agent.speed = originSpeed;
// Not working if setting back to loop = true in the inspector
// After it was not loop and agent in last waypoint
// When setting to loop = true it's not continue to check why
// Should continue the loop if loop true !
// Loop = true is not working when game is running only on Start
GotoNextPoint();
}
}
}
}
}
In the editor I have an animator controller for the character with 3 states : The touc/examine , walk , idle
The first animation is working fine but it's not changing to walk after 10 seconds and not changing to walk at all. It keep looping the first animation all the time. and the first animation length is more then 0 seconds.
between the first animation state and the second walk state there is a transition and exit time is disabled with one condition Walk True and a parameter I added of type bool name Walk.
between the second state walk and the last state idle also there is a transition and exit time disabled too with condition Walk True.
Screenshot of the first transition :
The main idea is to change transitions smooth between the 3 states and then stop when the last state played without looping. Each state should play once.
What I did so far :
In both transitions disabled Has Exit Time (enabled false)
Then changed the script added a line to start the Walk animation state :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AgentControl : MonoBehaviour
{
public List<Transform> points;
public bool waitTimeToMove = false;
//notice WaitTime is a float now
public float WaitTime = 10f;
public bool randomWaitTime;
float waitMinTime = 1f;
float waitMaxTime = 10f;
public bool loop = false;
public Animator anim;
private int destPoint = 0;
private NavMeshAgent agent;
private Transform originalPos;
//two vars for handling timer
private float timer = 0;
private float originSpeed;
void Start()
{
agent = GetComponent<NavMeshAgent>();
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
agent.autoBraking = false;
originSpeed = agent.speed;
if (randomWaitTime == true)
{
WaitTime = Random.Range(waitMinTime, waitMaxTime);
}
//transforms dont exist without A GameObject and a GameObject doesn't exist without a transform
//create a new GameObject to hold our position
GameObject originalPositionObject = new GameObject();
originalPositionObject.name = "WP";
originalPositionObject.tag = "Waypoint";
originalPositionObject.transform.parent = GameObject.Find("Waypoints").transform;
//set the new gameobjects position equal to where the transform is right now
originalPositionObject.transform.position = transform.position;
//add this to the points list instead
points.Add(originalPositionObject.transform);
anim = GetComponent<Animator>();
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Count == 0)
return;
// Set the agent to go to the currently selected destination.
agent.destination = points[destPoint].position;
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
destPoint = (destPoint + 1) % points.Count;
}
void Update()
{
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 1f)
{
//if wait to move is true
if (waitTimeToMove)
{
//if timer is less than 10
if (timer < WaitTime)
{
//add Time.deltaTime each time we hit this point
timer += Time.deltaTime;
}
//no longer waiting because timer is greater than 10
else
{
waitTimeToMove = false;
anim.SetBool("Walk", true);
}
}
//if we hit here waitToMove is false, so go ahead as usual
else
{
if (loop == false && destPoint == points.Count - 1)
{
agent.speed = 0;
}
if (loop == true || destPoint != points.Count - 1)
{
agent.speed = originSpeed;
// Not working if setting back to loop = true in the inspector
// After it was not loop and agent in last waypoint
// When setting to loop = true it's not continue to check why
// Should continue the loop if loop true !
// Loop = true is not working when game is running only on Start
GotoNextPoint();
}
}
}
}
}
After 10 seconds :
anim.SetBool("Walk", true);
but now I want that a bit before or when the agent get to the target destination to change it to the Idle state animation :
anim.SetBool("Idle", true);
but I'm not sure where to put it in the script. I tried in this place :
if (loop == false && destPoint == points.Count - 1)
{
agent.speed = 0;
anim.SetBool("Idle", true);
}
but it didn't work fine the agent kept walking after the target destination then moved back to the target destination then changed to idle a mess.

Not cycling through an array as expected

I'm trying to get the player to continue on after he jumps (see code), but what he does is return back to the jumpPosition transform without continuing on to the next point.
Here is what it is doing in Unity:
...
Here is my code for playerMovment:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class MovementController : MonoBehaviour
{
// public GameObject playerToMove; // not sure why I need this
public float moveSpeed; // move speed of the player going from player postion to current point, possible to use somewhere else
private Transform currentPoint; // used to determine where the next point the player has to move by cycling through 'points' array
public Transform jumpPoint; // used as a location trigger to tell the player when to jump -- will be attempting to make into an array
public Transform crouchPoint; // used as a location trigger to tell the player when to crounch -- will be attempting to make into an array
public Transform[] points; // an array of location for the 'currentPoint' to cycle through
public float maxPause = 100; // used to determine the length of time between when the player arrives at the 'currentPoint' and when to leave said point; default = 100
public float reducedPause = 2; // used to set 'maxPause' to a smaller number so that player won't keep jumping/crouching
public TestCharacterController2D controller; // acceses the TestCharacterController2D script (I didnt write this script but plan to modiify) used for basic move, jump, and crouch funtions
public Animator animator; // my attempt to find the player's animator
public bool isRight; // used to to determine which way the character is facing -- I think this can be accesed through the 'controller' variable (TestCharacterController2D script)
private bool jump; // to tell the 'controller' when to jump
private bool crouch; // to tell the 'controller' when to crouch
private bool pause = false; // used to determine when the player arrives at the 'currentPoint' and the 'maxPause' countdown begins
public int pointsSelection; // used to cycle the 'points' array when maxPause cycle is over and player is at current point
// public float jumpHeight = 100f; // not sure why used
void Start() // looking into 'onAwake' maybe? (or others)
{
currentPoint = points[pointsSelection]; // sets currentPoint to default location ('pointSelection' is 'publc' so can be modified in Unity
isRight = true; // player starts facing right -- as per character animations
}
void Update() // not sure if should have more in 'FixedUpdate' or others (maybe?)
{
jump = false;
if (Vector2.Distance(transform.position, currentPoint.position) < 0.05f)
// checks to see if player is at 'currentPoint'
{
pause = true; // starts the pause sequenece
Debug.Log("Pause = " + pause);
if (pause) // when the movement is pause do the the following
{
moveSpeed = 0;
animator.SetFloat("Speed", 0); // player stops moving -- works!
if (maxPause <= 100) // checks to see if still paused
{
Debug.Log("this is maxPause: " + maxPause);
if (maxPause < 0) // found 'maxPause' was going to far below zero
maxPause = 0;
maxPause--; // reduce pause amount (working way out of loop)
}
if (maxPause == 0) // when 'maxPause' timer has finished
{
pointsSelection++; // move to next point
maxPause = 100; // reset 'maxPause' timer
pause = false; // resume 'transform.position == currentPoint.position' process
}
}
if (pointsSelection == points.Length) // makes sure 'pointsSelection' doesn't go out of bounds
{
Debug.Log("at end of array");
pointsSelection = 0; // start the player's movement process over again
}
}
else // not sure if requried
{
Debug.Log("pause = false");
Debug.Log("this is the moveSpeed " + moveSpeed);
Debug.Log("pointsSelection: " + pointsSelection);
}
if (Vector2.Distance(transform.position, jumpPoint.position) < 0.05f && jumpPoint == currentPoint) // conditions for the jump action (automatic) -- I fell the whole thing needs to be more elaborate ** WORK IN PROGRESS **
{
jump = true;
}
else
jump = false;
currentPoint = points[pointsSelection]; // moved to line 130 -- not sure if better here
}
void FixedUpdate()
{
if (isRight && transform.position.x > currentPoint.position.x) // flipping the character -- I'm pretty sure I can use TestCharacterController2D to do this for me, this is comparing the player's 'transform'
{
moveSpeed = -0.25f; // tells controller to head in the left direction
isRight = false; // no longer facing right
}
if (!isRight && transform.position.x < currentPoint.position.x) // reverse of above
{
moveSpeed = 0.25f; // tells controller to head in the right direction
isRight = true; // no longer facing left
}
if (moveSpeed > 0 || moveSpeed < 0)
animator.SetFloat("Speed", 1); // player starts PlayerRun animation -- works!
// Move our character
controller.Move(moveSpeed, crouch, jump); // draws from the TestCharacterController2D script
}
public void OnLanding()
{
animator.SetBool("Jumped", false);
}
}

How to increase my score gradually with a timer?

I am currently creating a hidden object game and I have been stuck on how to add a timer and countdown to my game. I have currently a score which generates after all of the objects have been clicked however I would love if the score went up gradually once the user clicked on each one. here is my code below so far.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class trackingclicks : MonoBehaviour {
//static variable added to count users clicks
public static int totalclicks=0;
//"mouseclick" keycode variable to look for mouse click
public KeyCode mouseclick;
public Transform scoreObj;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//checks the change in time, aka how much time has passed- bonus time starts at 90
clickcontrol.timeBonus -= Time.deltaTime;
if (clickcontrol.remainItems == 0)
{
clickcontrol.totalScore += (70 + (Mathf.RoundToInt(clickcontrol.timeBonus)));
scoreObj.GetComponent<TextMesh>().text = "Score : " + clickcontrol.totalScore;
clickcontrol.remainItems = -1;
}
//Check for mouse click
if (Input.GetKeyDown (mouseclick))
{
totalclicks += 1;
}
if (totalclicks >= 5)
{
Debug.Log ("FAIL!!!");
totalclicks = 0;
}
}
}
You can use coroutines for timers (coroutines execute code after a certain amount of time). If you want your score to increment gradually once the player clicks on an object (I think that's what you're asking), then something like this should work:
public int score;
IEnumerator IncrementScore(int amount, int interval) { //amount is the amount of score to add over the time, interval is the time IN SECONDS between adds
for (int i = 0; i < amount; i++) {
yield return new WaitForSeconds(interval);
score++;
}
}
I wasn't sure where the score variable was so I made a new one; you can set it to your own, wherever it is. If you need more help, feel free to ask.

Trying to perform an action whilst a variable is above zero in XNA

I am creating a basic 2D space shooter game in XNA 4.0.
I have a player class and in its Update method it calls a shoot function if the space bar is pressed. It checks this every frame. In my main game class I have a check on whether the player intersects with a ammo boost item. When the player intersects with this item it should set the players bullet delay to 1 (instead of 10) and sets the variable ammoBoost to 500 which reduces by 1 every frame.
So now when the player presses space bar it should fire the bullets with only 1 delay for 500 frames.
So far I have everything working and it fires with only the small delay, but I can't get it to reset the bullet delay to 10 when the ammoBoost variable has reached 0 after the 500 frames.
I've including relevant code snippets:
main game class
// Update boosts and check for collisions
foreach (Boost b in boostList)
{
b.Update(gameTime);
if(b.boundingBox.Intersects(p.boundingBox))
{
// if life boost
if(b.boost == 1)
{
// add life to player lives
hud.playerLives += 1;
// make boost invisible
b.isVisible = false;
}
// if bullet boost
else if(b.boost == 2)
{
b.isVisible = false;
// set ammo for gun
hud.boostAmmo = 500;
p.boostAmmo = 500;
}
}
}
player class update method:
// fire bullets
if (keyboard.IsKeyDown(Keys.Space))
{
shoot(boostAmmo);
}
// shoot (used to set starting position of bullets)
public void shoot(int boostAmmo)
{
// if boostammo is above zero boost is active and there should be no delay on bullets firing
if (boostAmmo > 0)
{
bulletDelay = 1;
Bullet newBullet = new Bullet(bulletTexture);
newBullet.position = new Vector2(playerPosition.X + 32 - newBullet.texture.Width / 2, playerPosition.Y + 30);
if (playSounds)
{
sm.playerShootSound.Play();
}
newBullet.isVisible = true;
if (bulletList.Count() < 20)
{
bulletList.Add(newBullet);
}
boostAmmo = boostAmmo -1;
}
else if (boostAmmo <= 0)
{
// shoot only if the bullet delay resets
if (bulletDelay > 0)
{
bulletDelay--;
}
// if bullet delay is at zero then create a new bullet at player position and make it visible on the screen, then ad that bullet to the list
if (bulletDelay <= 0)
{
Bullet newBullet = new Bullet(bulletTexture);
newBullet.position = new Vector2(playerPosition.X + 32 - newBullet.texture.Width / 2, playerPosition.Y + 30);
if (playSounds)
{
sm.playerShootSound.Play();
}
newBullet.isVisible = true;
if (bulletList.Count() < 20)
{
bulletList.Add(newBullet);
}
}
// reset bullet delay
if (bulletDelay == 0)
{
bulletDelay = 10;
}
}
Why is the bullet delay not reseting back to 10 after the 500 frames have passed?
I think what you are doing is setting bulletDelay back to 10 ... repeatedly.
Right now, when boostAmmo <= 0 you set bulletDelay back to 10, then you do some more checks. Then, repeat, you set bulletDelay back to 10. bulletDelay never reaches 0!
Also, you're never firing a bullet if boostAmmo > 0. I'll let you see if you can figure the rest out on your own, but I'll edit this answer if you need me to give you a full solution~

Categories