I am trying to prevent a click if a move is invalid based on an the int lastClickedValuex and o respectively
Not sure how to do the check. Last thing I have to do before my code is complete and driving me insane.
Basically
if (lastclickedvaluex >= boardsquarevalue || boardsquarevalue == 0){
allow move;
} else {
dont show the sprite;
dont switch turns;
restart the players turn;
dont change the value of lastclickedvaluex;
make like player never clicked I suppose;
}
Im at hour 20 so its probably something immensely stupid.
using UnityEngine;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
public int playerTurn; //0 = X && 1 = O
public int turnCountX; //Tally Player X Turns
public int turnCountO; //Tally Player O Turns
public GameObject[] bigTurnIcons; //Player Icons Array
public Sprite[] playerGamePieces; //GamePieces Array
public Button[] gameBoardSquares; //GameBoard Array
public int lastPlayedSquareValueX; //Store Value of Last Clicked Square
public int lastPlayedSquareValueO; // ""
public bool gameOver; // End Game
public bool isValidMove; // Check For Valid Move
public int boardSquareValue; //Value of Each Square from Value Script
public int[] markedSquare; //Win Check Array
void Awake()
{
GameSetup();
}
public void GameSetup()
{
isValidMove = true;
playerTurn = 0; //Set Player Turn To X Goes First
turnCountX = 0; //Set X Turn Count to 0
turnCountO = 0; //Set O Turn COunt to 0
bigTurnIcons[0].SetActive(true); //Set X Turn Icon to Active
bigTurnIcons[1].SetActive(false); //Set O Turn Icon to Inactive
for (int i = 0; i < gameBoardSquares.Length; i++) //Initialize Squares (GameBoard) Array
{
gameBoardSquares[i].interactable = true; //Make All Squares Clickable
gameBoardSquares[i].GetComponent<Image>().sprite = null; //Set TurnIcons To Off
}
for (int j = 0; j < markedSquare.Length; j++) //Initialize MarkedSquare Array
{
markedSquare[j] = -100; //Set Value To Wacky Number So It Doesn't Interfere With Formula FOr Win Check
}
}
public void PlaySquareButton(int WhichNumber) //OnClick Function
{
markedSquare[WhichNumber] = playerTurn + 1; //OnClick Store Which PLayer Clicked Which Square
gameBoardSquares[WhichNumber].image.sprite = playerGamePieces[playerTurn]; //OnClick Check To Place Correct Symbol (GamePiece)
gameBoardSquares[WhichNumber].interactable = false; //OnClick Set Button.Interactable To False So It Cannot Be CLicked Again
boardSquareValue = gameBoardSquares[WhichNumber].GetComponent<Value>().boardSquareValue; //OnClick Set The Square's Value To The BoardSquareValue Variable in the Value Script
if (turnCountO > 3 || turnCountX > 3) //Check For Wins After 3 Turns
{
CheckForWinner(); //Iterate Through The MarkedSpaces Array To Check For A Winner
}
if (playerTurn == 0)
{
playerTurn = 1; //Player O Turn
bigTurnIcons[0].SetActive(false);
bigTurnIcons[1].SetActive(true);
Debug.Log(boardSquareValue); //Show Value of Clicked Square in Console
lastPlayedSquareValueX = boardSquareValue; //Set Last CLicked Value to Current Clicked Square
turnCountX++; //Increment Player Turn Count
}
else
{
playerTurn = 0;
bigTurnIcons[0].SetActive(true);
bigTurnIcons[1].SetActive(false);
Debug.Log(boardSquareValue);
lastPlayedSquareValueO = boardSquareValue;
turnCountO++;
}
}
Thank you for any help
GameBoard
As per your comments, you may be missing:
public PlaySquareButton(int WhichNumber){
if(playerTurn)
{
if(WhichNumber > lastPlayedSquareValueX){
markedSquare[WhichNumber] = playerTurn + 1; //OnClick Store Which PLayer Clicked Which Square
gameBoardSquares[WhichNumber].image.sprite = playerGamePieces[playerTurn]; //OnClick Check To Place Correct Symbol (GamePiece)
gameBoardSquares[WhichNumber].interactable = false; //OnClick Set Button.Interactable To False So It Cannot Be CLicked Again
...
}
}else{
if(WhichNumber > lastPlayedSquareValueO){
markedSquare[WhichNumber] = playerTurn + 1; //OnClick Store Which PLayer Clicked Which Square
gameBoardSquares[WhichNumber].image.sprite = playerGamePieces[playerTurn]; //OnClick Check To Place Correct Symbol (GamePiece)
gameBoardSquares[WhichNumber].interactable = false; //OnClick Set Button.Interactable To False So It Cannot Be CLicked Again
...
}
}
}
Basically before you start your functionality you check if the WhichNumber, that I guess comes from the square once clicked, is greater than the lastPlayedSquareValueX
Related
The script:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LightsEffects : MonoBehaviour
{
private Renderer[] renderers;
private float lastChangeTime;
private int greenIndex = 0;
public void LightsEffect(List<GameObject> objects, Color instantiateColor, Color colorEffect)
{
renderers = new Renderer[objects.Count];
for (int i = 0; i < renderers.Length; i++)
{
renderers[i] = objects[i].GetComponent<Renderer>();
renderers[i].material.color = Color.red;
}
// Set green color to the first one
greenIndex = 0;
renderers[greenIndex].material.color = Color.green;
}
/// <summary>
/// Running the effect
/// </summary>
/// <param name="changeDirection">Changing the lights movement directions - false = forward, true = backward.</param>
public void LightsEffectCore(float delay, bool changeDirection)
{
// Change color each `delay` seconds
if (Time.time > lastChangeTime + delay)
{
lastChangeTime = Time.time;
// Set color of the last renderer to red
// and the color of the current one to green
renderers[greenIndex].material.color = Color.red;
if (changeDirection == true)
{
Array.Reverse(renderers);
changeDirection = false;
}
greenIndex = (greenIndex + 1) % renderers.Length;
renderers[greenIndex].material.color = Color.green;
}
}
}
The part of the direction change:
if (changeDirection == true)
{
Array.Reverse(renderers);
changeDirection = false;
}
The problem is that now it will be true all the time and next time it will be changed to false i will need to reverse the array again but then since it's false it will reverse the array all the time:
if (changeDirection == true)
{
Array.Reverse(renderers);
changeDirection = false;
}
else
{
Array.Reverse(renderers);
changeDirection = true;
}
But now when it will be change back to false or if the game start as false it will change right back to true and will reverse the array and so on.
I want that when it's true keep it true and once changing it to false keep it false until changing again.
I got messed the flag states and the reversing.
thanks for reading.
I'm currently building a small memory card game in Unity using C#. I have the main portion of code finished but when I press the play button on a certain scene Unity freezes.
I believe it is due to an infinite While loop, but I can not find the issue. I would really appreciate any help anyone can offer. I will leave my code below. Thanks in advance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine;
public class Pairs : MonoBehaviour {
public Sprite[] face; //array of card faces
public Sprite back;
public GameObject[] deck; //array of deck
public Text pairsCount;
private bool deckSetUp = false;
private int pairsLeft = 13;
// Update is called once per frame
void Update () {
if (!deckSetUp)
{
SetUpDeck();
}
if (Input.GetMouseButtonUp(0)) //detects left click
{
CheckDeck();
}
}//Update
void SetUpDeck()
{
for (int ix = 0; ix < 2; ix++)
{
for(int i = 1; i < 14; i++)//sets up card value (2-10 JQKA)
{
bool test = false;
int val = 0;
while (!test)
{
val = Random.Range(0, deck.Length);
test = !(deck[val].GetComponent<Card>().SetUp);
}//while
//sets up cards
deck[val].GetComponent<Card>().Number = i;
deck[val].GetComponent<Card>().SetUp = true;
}//nested for
}//for
foreach (GameObject crd in deck)
{
crd.GetComponent<Card>().setUpArt();
}
if (!deckSetUp)
{
deckSetUp = true;
}
}//SetUpDeck
public Sprite getBack()
{
return back;
}//getBack
public Sprite getFace(int i)
{
return face[i - 1];
}//getFace
void CheckDeck()
{
List < int > crd = new List<int>();
for(int i = 0; i < deck.Length; i++)
{
if(deck[i].GetComponent<Card>().State == 1)
{
crd.Add(i);
}
}
if(crd.Count == 2)
{
CompareCards(crd);
}
}//CheckDeck
void CompareCards(List<int> crd)
{
Card.NO_TURN = true; //stops cards turning
int x = 0;
if(deck[crd[0]].GetComponent<Card>().Number ==
deck[crd[1]].GetComponent<Card>().Number)
{
x = 2;
pairsLeft--;
pairsCount.text = "PAIRS REMAINING: " + pairsLeft;
if(pairsLeft == 0) // goes to home screen when game has been won
{
SceneManager.LoadScene("Home");
}
}
for(int j = 0; j < crd.Count; j++)
{
deck[crd[j]].GetComponent<Card>().State = x;
deck[crd[j]].GetComponent<Card>().PairCheck();
}
}//CompareCards
}
I believe the issue lies in the while(!test) but i do not know why test never become true.
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class Card : MonoBehaviour {
public static bool NO_TURN = false;
[SerializeField]
private int cardState; //state of card
[SerializeField]
private int cardNumber; //Card value (1-13)
[SerializeField]
private bool _setUp = false;
private Sprite back; //card back (Green square)
private Sprite face; //card face (1-10 JQKA)
private GameObject pairsManager;
void Begin()
{
cardState = 1; //cards face down
pairsManager = GameObject.FindGameObjectWithTag("PairsManager");
}
public void setUpArt()
{
back = pairsManager.GetComponent<Pairs>().getBack();
face = pairsManager.GetComponent<Pairs>().getFace(cardNumber);
turnCard();//turns the card
}
public void turnCard() //handles turning of card
{
if (cardState == 0)
{
cardState = 1;
}
else if(cardState == 1)
{
cardState = 0;
}
if (cardState == 0 && !NO_TURN)
{
GetComponent<Image>().sprite = back; // shows card back
}
else if (cardState == 1 && !NO_TURN)
{
GetComponent<Image>().sprite = face; // shows card front
}
}
//setters and getters
public int Number
{
get {return cardNumber;}
set { cardNumber = value;}
}
public int State
{
get { return cardState; }
set { cardState = value; }
}
public bool SetUp
{
get { return _setUp; }
set { _setUp = value; }
}
public void PairCheck()
{
StartCoroutine(pause ());
}
IEnumerator pause()
{
yield return new WaitForSeconds(1);
if (cardState == 0)
{
GetComponent<Image>().sprite = back;
}
else if (cardState == 1)
{
GetComponent<Image>().sprite = face;
}
}
}
Thank you for reading, I will post a link to the github repository if that helps.
github repository
Your deck array has at least one card in it that has _setUp set to true which would make it go in a infinite loop.
The reason it goes in a infinite loop is because it will have set all available _setUp to true and it would keep looking for _setUp that are set to false and it will never find any.
The reason you need at least 26 object that have _setUp to false is because in the nested for loop you loop 13 times and then you do that twice which gives a total of 26 loops. So you need at least 26 objects.
What you can do to make sure that they're all false is to set them all to false before entering the for loop
for(int i = 0; i < deck.Length; i++)
{
deck[i].GetComponent<Card>().SetUp = false;
}
I have 4 objects each located in a corner of a square. I wish to move these objects clockwise, 1 position per method call.
With the code I have atm, they all just complete the entire loop on 1 method call instead of moving only one position...
My code so far:
void SwitchPositions()
{
tempPosition1 = parent.transform.GetChild(0).GetComponent<Transform>().position;
tempPosition2 = parent.transform.GetChild(1).GetComponent<Transform>().position;
tempPosition3 = parent.transform.GetChild(2).GetComponent<Transform>().position;
tempPosition4 = parent.transform.GetChild(3).GetComponent<Transform>().position;
parent.transform.GetChild (0).GetComponent<Transform> ().position = tempPosition2;
parent.transform.GetChild (1).GetComponent<Transform> ().position = tempPosition3;
parent.transform.GetChild (2).GetComponent<Transform> ().position = tempPosition4;
parent.transform.GetChild (3).GetComponent<Transform> ().position = tempPosition1;
Debug.Log (tempPosition1);
}
If anyone has any ideas how to fix this or at least explain to me why it-s completing the entire loop in 1 method call...
Thank you!
I am really not sure how your timer works or for that matter anything wrong with your code. But I have used the coroutine where after every two seconds the blocks get switched and it happens continuously. I think this should be somewhere close to what you need.
//Predefined positions where objects to place
public Transform[] Position;
//The objects that will will be swapped in coroutines
public Transform[] ObjectsToMove;
private int ObjectIndex = 0;
private bool startupdate = true;
void Update () {
if(startupdate)
StartCoroutine(SwitchBlocks());
}
IEnumerator SwitchBlocks() {
startupdate = false;
int tempIndex = ObjectIndex;
for(int i = 0; i < ObjectsToMove.Length; i++) {
tempIndex = ObjectIndex + i;
if(tempIndex > ObjectsToMove.Length - 1)
tempIndex -= ObjectsToMove.Length;
ObjectsToMove[i].position = Position[tempIndex].position;
}
ObjectIndex++;
if(ObjectIndex > ObjectsToMove.Length - 1) {
ObjectIndex = 0;
}
yield return new WaitForSeconds(2.0f);
startupdate = true;
yield return null;
}
Hope this helps.
I got some trouble with my unity cardboard app. May some of you guys can help me.
I have build a little Island with Animations and A second island as a main menu.
So when the apps starts, you see the Island from above and the Logo of the App.
When the user pull down the magnet button on side the app will starts another level.
I used this scripts:
http://www.andrewnoske.com/wiki/Unity_-_Detecting_Google_Cardboard_Click
Detecting Google Cardboard Magnetic Button Click - Singleton Implementation
CardboardMagnetSensor.cs and CardboardTriggerControlMono.cs
I created a script in my asset folder(CardboardMagnetSensor.cs) like in the description from Link. Than I created a second script(CardboardTriggerControlMono.cs) like in the discription an dragged it onto my CardboardMain in may Projekt.
The CardboardTriggerControlMono.cs looks like:
using UnityEngine;
using System.Collections;
public class CardboardTriggerControlMono : MonoBehaviour {
public bool magnetDetectionEnabled = true;
void Start() {
CardboardMagnetSensor.SetEnabled(magnetDetectionEnabled);
// Disable screen dimming:
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
void Update () {
if (!magnetDetectionEnabled) return;
if (CardboardMagnetSensor.CheckIfWasClicked()) {
Debug.Log("Cardboard trigger was just clicked");
Application.LoadLevel(1);
CardboardMagnetSensor.ResetClick();
}
}
}
The CarboardMagnetSensor:
using UnityEngine;
using System.Collections.Generic;
public class CardboardMagnetSensor {
// Constants:
private const int WINDOW_SIZE = 40;
private const int NUM_SEGMENTS = 2;
private const int SEGMENT_SIZE = WINDOW_SIZE / NUM_SEGMENTS;
private const int T1 = 30, T2 = 130;
// Variables:
private static bool wasClicked; // Flips to true once set off.
private static bool sensorEnabled; // Is sensor active.
private static List<Vector3> sensorData; // Keeps magnetic sensor data.
private static float[] offsets; // Offsets used to detect click.
// Call this once at beginning to enable detection.
public static void SetEnabled(bool enabled) {
Reset();
sensorEnabled = enabled;
Input.compass.enabled = sensorEnabled;
}
// Reset variables.
public static void Reset() {
sensorData = new List<Vector3>(WINDOW_SIZE);
offsets = new float[SEGMENT_SIZE];
wasClicked = false;
sensorEnabled = false;
}
// Poll this once every frame to detect when the magnet button was clicked
// and if it was clicked make sure to call "ResetClick()"
// after you've dealt with the action, or it will continue to return true.
public static bool CheckIfWasClicked() {
UpdateData();
return wasClicked;
}
// Call this after you've dealt with a click operation.
public static void ResetClick() {
wasClicked = false;
}
// Updates 'sensorData' and determines if magnet was clicked.
private static void UpdateData() {
Vector3 currentVector = Input.compass.rawVector;
if (currentVector.x == 0 && currentVector.y == 0 && currentVector.z == 0) {
return;
}
if(sensorData.Count >= WINDOW_SIZE) sensorData.RemoveAt(0);
sensorData.Add(currentVector);
// Evaluate model:
if(sensorData.Count < WINDOW_SIZE) return;
float[] means = new float[2];
float[] maximums = new float[2];
float[] minimums = new float[2];
Vector3 baseline = sensorData[sensorData.Count - 1];
for(int i = 0; i < NUM_SEGMENTS; i++) {
int segmentStart = 20 * i;
offsets = ComputeOffsets(segmentStart, baseline);
means[i] = ComputeMean(offsets);
maximums[i] = ComputeMaximum(offsets);
minimums[i] = ComputeMinimum(offsets);
}
float min1 = minimums[0];
float max2 = maximums[1];
// Determine if button was clicked.
if(min1 < T1 && max2 > T2) {
sensorData.Clear();
wasClicked = true; // Set button clicked to true.
// NOTE: 'wasClicked' will now remain true until "ResetClick()" is called.
}
}
private static float[] ComputeOffsets(int start, Vector3 baseline) {
for(int i = 0; i < SEGMENT_SIZE; i++) {
Vector3 point = sensorData[start + i];
Vector3 o = new Vector3(point.x - baseline.x, point.y - baseline.y, point.z - baseline.z);
offsets[i] = o.magnitude;
}
return offsets;
}
private static float ComputeMean(float[] offsets) {
float sum = 0;
foreach(float o in offsets) {
sum += o;
}
return sum / offsets.Length;
}
private static float ComputeMaximum(float[] offsets) {
float max = float.MinValue;
foreach(float o in offsets) {
max = Mathf.Max(o, max);
}
return max;
}
private static float ComputeMinimum(float[] offsets) {
float min = float.MaxValue;
foreach(float o in offsets) {
min = Mathf.Min(o, min);
}
return min;
}
}
And my steps:
http://www.directupload.net/file/d/3887/mtjygjan_jpg.htm
(sorry I´m not able to upload pictures here)
How ever, it wont work. When I start the app and pull down the magnet, nothing happens. May I did something wrong with switching the level over level index?
I use a nexus 4 and 5 for testing the app
Thanks allot and greetz to you!
Phillip
If you are using the Google Cardboard SDK for Unity, it currently has a bug that prevents Unity from seeing the magnet (and gyro, and accelerometer). That is probably why your script is not working. Until the bug is fixed, there is no good workaround, but you can instead use the property Cardboard.CardboardTriggered to detect if the magnet was pulled.
Update for Unity 5: The sensor bug is gone. Cardboard SDK does not block the sensors.
I am trying to make touch buttons in WP8 with all the states (Pressed, Released, Moved), but the TouchLocationState.Released is not working.
Here's my code:
Class variables:
bool touching = false;
int touchID;
Button tempButton;
Button is a separate class with a method to switch states when touched.
The Update method contains the following code:
TouchCollection touchCollection = TouchPanel.GetState();
if (!touching && touchCollection.Count > 0)
{
touching = true;
foreach (TouchLocation location in touchCollection)
{
for (int i = 0; i < menuButtons.Count; i++)
{
touchID = location.Id; // store the ID of current touch
Point touchLocation = new Point((int)location.Position.X, (int)location.Position.Y); // create a point
Button button = menuButtons[i];
if (GetMenuEntryHitBounds(button).Contains(touchLocation)) // a method which returns a rectangle.
{
button.SwitchState(true); // change the button state
tempButton = button; // store the pressed button for accessing later
}
}
}
}
else if (touchCollection.Count == 0) // clears the state of all buttons if no touch is detected
{
touching = false;
for (int i = 0; i < menuButtons.Count; i++)
{
Button button = menuButtons[i];
button.SwitchState(false);
}
}
menuButtons is a list of buttons on the menu.
A separate loop (within the Update method) after the touched variable is true
if (touching)
{
TouchLocation location;
TouchLocation prevLocation;
if (touchCollection.FindById(touchID, out location))
{
if (location.TryGetPreviousLocation(out prevLocation))
{
Point point = new Point((int)location.Position.X, (int)location.Position.Y);
if (prevLocation.State == TouchLocationState.Pressed && location.State == TouchLocationState.Released)
{
if (GetMenuEntryHitBounds(tempButton).Contains(point))
// Execute the button action. I removed the excess
}
}
}
}
The code for switching the button state is working fine but the code where I want to trigger the action is not.
location.State == TouchLocationState.Released mostly ends up being false.
(Even after I release the touch, it has a value of TouchLocationState.Moved)
And what is more irritating that it sometimes works!
I am really confused and stuck for days now. Is this the right way? If yes then where am I going wrong? Or is there some other more effective way to do this?
I finally found the solution myself. It does not need the released state of the TouchLocationState
Posting it here. Hopefully it'll help others.
Thanks if anyone was trying.
The class variables are renamed:
private Point _touchPoint;
private TouchLocation _touchLocation;
private int _touchID;
private Button _selectedButton;
private bool _touched;
private bool _launchEvent;
The update method now has the following code
TouchCollection touchCollection = TouchPanel.GetState();
if (!_touched && touchCollection.Count > 0)
{
_touched = false;
_launchEvent = false;
foreach (TouchLocation location in touchCollection)
{
for (int i = 0; i < menuButtons.Count; i++)
{
Button button = menuButtons[i];
_touchID = location.Id;
_touchPoint = new Point((int)location.Position.X, (int)location.Position.Y);
if (GetButtonHitBounds(button).Contains(_touchPoint))
{
button.SwitchState(true);
_selectedButton = button;
}
}
}
}
else if (touchCollection.Count == 0)
{
_touched = false;
for (int i = 0; i < menuButtons.Count; i++)
{
Button button = menuButtons[i];
button.SwitchState(false);
if (GetButtonHitBounds(button).Contains(_touchPoint) && _launchEvent)
{
OnReleased(i, PlayerIndex.One);
_launchEvent = false;
}
}
}
///
// This if statement checks whether the touch is still inside the button area.
// Then assigns a value of true to the _launchEvent variable.
//
// The 'try' block is used because if the first touch is not on button, then the
// value of the _selectedButton is null and it will throw an exception.
///
if (touchCollection.FindById(_touchID, out _touchLocation))
{
if (_touchLocation.State == TouchLocationState.Moved)
{
try
{
if (GetButtonHitBounds(_selectedButton).Contains((int)_touchLocation.Position.X, (int)_touchLocation.Position.Y))
_launchEvent = true;
else
_launchEvent = false;
}
catch { }
}
}