Unity: Quiz game multiple choice button colors - c#

I'm doing a multiple choice quiz game, and im tryinng to highlight the correct answer in green if the wrong answer is clicked. for example if i have A , B , C and D and "A" is the correct answer. i want if i choose "B" to turn B to red color and display the correct answer to green which is in this case "A". Right now i have if i click the right answer it displays green, as i want it. and if i press wrong answer it displays red. what im missing is when i click wrong answer i want to also highlight the correct answer.
Here's my functions:
In the Game controller:
public bool theAnswerIsCorrect;
public bool IsCorrected()
{
return theAnswerIsCorrect;
}
public void AnswerButtonClick(bool isCorrect)
{
if (isCorrect)
{
Debug.Log("I'm Correct");
theAnswerIsCorrect = true;
playerScore += currentRoundData.pointAddedForCorrectAnswer;
scoreDisplayText.text = "Score: " + playerScore.ToString();
}
else
theAnswerIsCorrect = false;
// Do we still have questions?
if (questionPool.Length > questionIndex + 1)
{
//questionIndex++;
UpdateQuestionIndex();
StartCoroutine(DelayTime(3));
// ShowQuestion();
}
else
{
EndRound();
}
}
And this is an a class that just holdes my data
public class answerData {
public string answerTxt;
public bool isCorrect;
}
This is being used in the ButtonClick function (the code in the begging of the question) -> this line
gameController.AnswerButtonClick (AnswerData.isCorrect);
And in the inspector i specify by the bool what is the correct answer
*** NEW SCRIPT HERE "Picking up the Correct button"
// store reference to btn text
public Text answerText;
private answerData AnswerData;
private GameController gameController;
public static AnswerButton _instace;
private void Awake()
{
_instace = this;
}
// Use this for initialization
void Start ()
{
gameController = FindObjectOfType<GameController> ();
}
public void Setup(answerData data)
{
AnswerData = data;
answerText.text = AnswerData.answerTxt;
}
IEnumerator ReturnButtonColor()
{
yield return new WaitForSeconds(2.9f);
GetComponent<Button>().image.color = Color.white;
Debug.Log("HiB");
}
public void HandleClick()
{
gameController.AnswerButtonClick (AnswerData.isCorrect);
if (gameController.IsCorrected())
{
GetComponent<Button>().image.color = Color.green;
Debug.Log("im true");
StartCoroutine(ReturnButtonColor());
}
else
{
GetComponent<Button>().image.color = Color.red;
// gameController.IsCorrected().image.color = Color.green;
StartCoroutine(ReturnButtonColor());
}
}
Thank you

I am assuming that all option button have same script attached.
Create one delegate and register this in your script which is attached to your option button.
Like this
Create delegate and event
#region DELEGATES
public delegate void OnQuestionOptionClicked ();
public static event OnQuestionOptionClicked onQuestionOptionClicked;
#endregion
#region DELEGATE_CALLS
private void RaiseOnQuestionOptionClicked ()
{
if (onQuestionOptionClicked != null)
onQuestionOptionClicked ();
}
#endregion
Register it
void OnEnable ()
{
onQuestionOptionClicked += OnQuestionOptionClicked;
}
void OnDisable ()
{
onQuestionOptionClicked -= OnQuestionOptionClicked;
}
#region DELEGATE_EVENT_LISTENER
void OnQuestionOptionClicked ()
{
GetComponent<Button>().interactable = false;
if (AnswerData.isCorrect){
GetComponent<Button>().image.color = Color.green;
Debug.Log("im true");
}
}
#endregion
Your setup method
public void Setup(answerData data)
{
AnswerData = data;
answerText.text = AnswerData.answerTxt;
GetComponent<Button>().interactable = true;
GetComponent<Button>().image.color = Color.white;
}
And on button click event
#region BUTTON_CLICK_LISTENER
public void ButtonClick()
{
gameController.AnswerButtonClick (AnswerData.isCorrect);
if (!gameController.IsCorrected())
{
GetComponent<Button>().image.color = Color.red;
Debug.Log("im true");
// StartCoroutine(ReturnButtonColor());
}
RaiseOnQuestionOptionClicked ();
}
#endregion
Hope this solution helps you.;)

Like using GetComponent<Button>().image.color = Color.green; in the if statement , you could simply add in /*Button A*/.image.color = Color.green; in the else statement.

What #BadWolf in the comments is saying is the correct answer. If you need more coding help you have to include more information. How do you determine the Correct Button? Does it have a special name in the Scene? Does the gameController know which button is the correct? It seems gameController knows which Button is the correct one so you should create a method which will look something like:
public Button GetCorrectButton(){
return theCorrectButton;
}
I don't know the code for how you see if it is the correct button but I'm guessing you have some way where you use the Correct Button. Find the Correct Button and return it in the method GetCorrectButton.
which you will then use in your code like:
public void ButtonClick()
{
gameController.AnswerButtonClick (AnswerData.isCorrect);
if (gameController.IsCorrected())
{
GetComponent<Button>().image.color = Color.green;
Debug.Log("im true");
// StartCoroutine(ReturnButtonColor());
}
else
{
GetComponent<Button>().image.color = Color.red;
// Like this:
gameController.GetCorrectButton().image.color = Color.green;
}
}
I can be more specific if I get some more information/code to see!

Related

How to get selected toggle from toggle group?

I have created one toggle group and now I want to retrieve selected toggle item with some easiest way possible.
Share your side suggestions with me...
EDIT:
Here you have ToggleGroup details:
I was using this code to check:
public class RandomMatchMakerPanelController : MonoBehaviour
{
public Sprite defaultPlayerPhoto;
//
[Header ("Player-1")]
public Image player1Photo;
public Text player1NameText;
public Text player1CountryText;
public ToggleGroup player1BallGroup;
[Header ("Player-2")]
public Image player2Photo;
public Text player2NameText;
public Text player2CountryText;
public ToggleGroup player2BallGroup;
void OnEnable ()
{
// StartCoroutine (CreateRandomMatches ());
GetSelectedToggle ();
ShowLocalPlayerDetails ();
}
private void ShowLocalPlayerDetails ()
{
if (DataCollection.localPlayer.ProfilePhoto == null)
player1Photo.sprite = defaultPlayerPhoto;
else
player1Photo.sprite = DataCollection.localPlayer.ProfilePhoto;
player1NameText.text = DataCollection.localPlayer.PlayerName;
player1CountryText.text = DataCollection.localPlayer.Country;
}
private void GetSelectedToggle ()
{
// Toggle[] ballToggles = player1BallGroup.GetComponentsInChildren<Toggle> ();
foreach (Toggle toggle in player1BallGroup.ActiveToggles()) {
Debug.Log ("toggle: "+ toggle.isOn);
}
// May have several selected toggles
// foreach (Toggle toggle in ballToggles) {
// if(toggle.isOn)
// }
}
IEnumerator CreateRandomMatches ()
{
yield return new WaitForSeconds (0.25f);
RandomMatchMaker matchMaker = GameObject.FindGameObjectWithTag (GameConstants.TAG_NETWORK_MANAGER).GetComponent<RandomMatchMaker> ();
matchMaker.FindInternetMatch ("Dodgels-");
}
public void OnBackButtonClick ()
{
SoundManager.Instance.PlayButtonClickSound ();
Camera.main.SendMessage (GameConstants.ACTIVATE_RANDOM_MATCH_MAKER_PANEL, false, SendMessageOptions.DontRequireReceiver);
Camera.main.SendMessage (GameConstants.ACTIVATE_RANDOM_PLAYER_GAMEPLAY, false, SendMessageOptions.DontRequireReceiver);
Camera.main.SendMessage (GameConstants.ACTIVATE_MAIN_MENU_PANEL, true, SendMessageOptions.DontRequireReceiver);
}
}
At present nothing get displayed in Console though one toggle at a time remain always active.
You can get all active toggles with the ActiveToggles() function which selects the set of active toggles in the group. Usually, this set is composed of a unique Toggle.
using System.Linq;
// ...
public UnityEngine.UI.ToggleGroup ToggleGroup ; // Drag & drop the desired ToggleGroup in the inspector
private void Start()
{
if( ToggleGroup == null ) ToggleGroup = GetComponent<ToggleGroup>();
}
public void LogSelectedToggle()
{
// May have several selected toggles
foreach( Toggle toggle in ToggleGroup.ActiveToggles() )
{
Debug.Log( toggle, toggle ) ;
}
// OR
Toggle selectedToggle = ToggleGroup.ActiveToggles().FirstOrDefault();
if( selectedToggle != null )
Debug.Log( selectedToggle, selectedToggle ) ;
}
Execute following method from the parent of your toggles
Toggle GetSelectedToggle()
{
Toggle[] toggles=GetComponentsInChildren<Toggle>();
foreach (var t in toggles)
if (t.isOn) return t; //returns selected toggle
return null; // if nothing is selected return null
}

Running a async function in my INotifyPropertyChanged-class and the code doesnt run

I am trying to make each listcell in a listview different depending what they clicked previously and I am doing this with a INotifyPropertyChanged.
I have a if/else code in my class but it doesn't run.. i get no color.
If i for example us a color = Color.Green; inside my Public Current then it works. But not when I do this if/else statement it doesnt run.
This is my class:
public class Current : INotifyPropertyChanged
{
Color color;
public event PropertyChangedEventHandler PropertyChanged;
public Current()
{
RunThis ();
}
async void RunThis ()
{
var checkWhatOption = await parseAPI.WhatOption ();
if ((checkWhatOption ["results"] as JArray).Count > 0) {
color = Color.Black;
}
else {
color = Color.Red;
}
}
public Color Color
{
set
{
if (color != value)
{
color = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("Color"));
}
}
}
get
{
return color;
}
}
}
And in my XAML on the page where I use it I have this code :
<Label BackgroundColor="{Binding Color}" >
<Label.BindingContext>
<local:Current />
</Label.BindingContext>
UPDATED:
public static async Task RunThis()
{
if ((Stringone ["results"] as JArray).Count > 0) {
Color = Color.Black; //An object reference is required to access non-static member.
}
else {
color = Color.Red; //An object reference is required to access non-static member.
}
}
protected override async void OnAppearing()
{
await Current.RunThis ();
}
Chances are it is being blocked.
Your call to your async RunThis function from the constructor isn't using await, which of course you can't within the constructor.
Also try to change the RunThis function to something along the lines:-
public async Task RunThis()
{
..
}
And then find and appropriate place to call this using await, but not via a constructor. Be sure that the caller has async specified also.

need a button to change its text when clicked

I am trying to do a simple toggle silent mode app. I got the for dummies book and no luck so far.
What I want to do is when the audio is on I want to change my text on my button to Turn off (using a string). and when pressed I want it to change to another string. But I can't get this thing down right. I have tried several ways so far. Any suggestions ?
package com.example.silentmodetoggle;
import android.os.Bundle;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class TSMMainActivity extends Activity {
//Instantiate an AudioManager to manage the ringer state
private AudioManager mAudioManager;
private boolean mPhoneIsSilent;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tsmmain);
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
checkIfPhoneIsSilent();
setButtonClickListener();
//does this even work?
TextView textView=(TextView)findViewById(R.string.silence_phone);
}//onCreate
private void setButtonClickListener()
{
Button toggleButton = (Button) findViewById(R.id.toggleButton);
toggleButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (mPhoneIsSilent)
{ //set to normal mode
mAudioManager
.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
mPhoneIsSilent = false;
}
else
{
mAudioManager
.setRingerMode(AudioManager.RINGER_MODE_SILENT);
mPhoneIsSilent = true;
}
//now toggle the UI again
toggleUi();
}
});
}
private void checkIfPhoneIsSilent()
{
int ringerMode = mAudioManager.getRingerMode();
if (ringerMode == AudioManager.RINGER_MODE_SILENT)
{
mPhoneIsSilent = true;
}
else
{
mPhoneIsSilent = false;
}
}
private void toggleUi()
{
ImageView imageView = (ImageView) findViewById(R.id.phone_icon);
Drawable newPhoneImage;
if (mPhoneIsSilent)
{
//i think i should put it here.
newPhoneImage = getResources().getDrawable(R.drawable.phone_silent);
}
else
{
newPhoneImage = getResources().getDrawable(R.drawable.phone_on);
}
imageView.setImageDrawable(newPhoneImage);
}
private void textView(int silencePhone) {
// TODO Auto-generated method stub
}
#Override
protected void onResume()
{
super.onResume();
checkIfPhoneIsSilent();
toggleUi();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.tsmmain, menu);
return true;
}
}
Try this:
#Override
public void onClick(View v)
{
if (mPhoneIsSilent)
{ //set to normal mode
mAudioManager
.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
mPhoneIsSilent = false;
((Button)v).setText("Turn On");
}
else
{
mAudioManager
.setRingerMode(AudioManager.RINGER_MODE_SILENT);
mPhoneIsSilent = true;
((Button)v).setText("Turn Off");
}
Hope this helps :)
In the OnClickListener(View v) the argument v is the button you clicked on. Therefore you can call the method setText(String s) and change the text.
It should be explicitly cast to its type as v is a generic type of View.

Extension Method Solution

I've got some code to indicate when a field on my WinForm has changed.
If the Control is a TextBox, I alter the ForeColor and BackColor depending on if the Text of the Control is equal to the default (or initial) value.
private void LastName_Changed(object sender, EventArgs e) {
if (sender.Equals(txtLastName)) {
if (emp0.LastName != txtLastName.Text) {
txtLastName.ForeColor = changedTxtFont;
txtLastName.BackColor = changedTxtBack;
btnOK.Enabled = true;
} else {
txtLastName.ForeColor = systemTxtFont;
txtLastName.BackColor = systemTxtBack;
}
AuthenticationReset();
}
}
If the Control is a DateTimePicker or ComboBox, I can't really do this (there is no visible ForeColor or BackColor), so I alter the Label that is associated with the Control.
private void TrainDate_Changed(object sender, EventArgs e) {
if (sender.Equals(dtTrainDate)) {
DateTime trainDate = Global.SqlDate(emp0.TrainDate);
if (trainDate != dtTrainDate.Value) {
lblTrainDate.ForeColor = changedLblFont;
lblTrainDate.BackColor = changedLblBack;
btnOK.Enabled = true;
} else {
lblTrainDate.ForeColor = systemLblFont;
lblTrainDate.BackColor = systemLblBack;
}
AuthenticationReset();
}
}
I'd like to create some sort of Extension Method that could change the ForeColor and BackColor of a Control dependent upon what that Control is and if the value had changed.
Here is an attempt, but the use of this in the code is not valid and the extension methods do not show up for any of the Controls I want to use them on.
public static class ColorChange {
public static Color ForeColorChange(this Color owned, bool changed) {
if (this is TextBox) {
return changed ? Color.Red : SystemColors.WindowText;
} else {
return changed ? Color.Red : SystemColors.ControlText;
}
}
public static Color BackColorChange(this Color owned, bool changed) {
if (this is TextBox) {
return changed ? Color.Yellow : SystemColors.Window;
} else {
return SystemColors.Control;
}
}
}
Is there a way to approach what I'm trying to do or is this not what Extension Methods are for?
I'd like to end up with something like this:
private void TrainDate_Changed(object sender, EventArgs e) {
if (sender.Equals(dtTrainDate)) {
DateTime trainDate = Global.SqlDate(emp0.TrainDate);
if (trainDate != dtTrainDate.Value) {
lblTrainDate.ForeColorChange(true);
lblTrainDate.BackColorChange(true);
btnOK.Enabled = true;
} else {
lblTrainDate.ForeColorChange(false);
lblTrainDate.BackColorChange(false);
}
AuthenticationReset();
}
}
Solution:
Using the answer checked below, I wrote the following Extension Method:
public static class ColorChange {
public static void AlteredText(this Control owned, bool changed) {
if (owned is TextBox) {
owned.ForeColor = changed ? Color.Red : SystemColors.WindowText;
owned.BackColor = changed ? Color.Yellow : SystemColors.Window;
} else {
owned.ForeColor = changed ? Color.Red : SystemColors.ControlText;
owned.BackColor = SystemColors.Control;
}
}
}
Here is how I will be using it:
private void TrainDate_Changed(object sender, EventArgs e) {
if (sender.Equals(dtTrainDate)) {
DateTime trainDate = Global.SqlDate(emp0.TrainDate);
if (trainDate != dtTrainDate.Value) {
lblTrainDate.AlteredText(true);
btnOK.Enabled = true;
} else {
lblTrainDate.AlteredText(false);
}
AuthenticationReset();
}
}
I hope others get use out of this as well. ~Joe.
You've defined extension methods for the Color class, not Control, which is why it won;t show for controls. In addition, your methods probably want to inspect the owned control that you'll need to pass in.
This extends Control instead of Color (needs to be defined in a static class):
public static void ForeColorChange(this Control owned, bool changed) {
if (owned is TextBox) {
owned.ForeColor = changed ? Color.Red : SystemColors.WindowText;
} else {
owned.ForeColor = changed ? Color.Red : SystemColors.ControlText;
}
}
public static void BackColorChange(this Control owned, bool changed) {
if (owned is TextBox) {
owned.BackColor = changed ? Color.Yellow : SystemColors.Window;
} else {
owned.BackColor = SystemColors.Control;
}
}
Usage:
TextBox box = ...;
box.ForeColorChange(true);
If you want to call your extension method on your textbox, you have to do this in the toplevel of your namespace:
public static class Extensions
{
public static void myExtensionMethod(this Textbox textbox)
{
//Do what you want to do
}
}
And then it is accessible over your textbox:
Textbox myTextbox = new Textbox();
myTextbox.myExtensionMethod();
If you want, you can also pass parameters to your extension method.
Use your owned instead of this.. oh and as Rowland Shaw says, Control instead of Color.
So your code should finally be
public static Color ForeColorChange(this Control owned, bool changed) {
if (owned is TextBox) {
return changed ? Color.Red : SystemColors.WindowText;
} else {
return changed ? Color.Red : SystemColors.ControlText;
}
}
public static Color BackColorChange(this Control owned, bool changed) {
if (owned is TextBox) {
return changed ? Color.Yellow : SystemColors.Window;
} else {
return SystemColors.Control;
}
}

How can i stop AxWindowsMediaPlayer from accepting any user commands in C#

In my democode an embeded windows media player starts to load and play a video. The player shows no controls, all other options are the default options. So far this works.
What does not work is that not all userinteraction is stopped. For instance it is possible to change the mode to fullscreen with a doubleclick and it also is possible to get a full context with a right click.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
axWindowsMediaPlayer1.uiMode = "none";
}
private void button1_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.URL = #"C:\stackoverflow.mp4";
}
}
How can i isolate the player from the user and only control the player via code?
A friend just helped me to solve this.
Disabling the context menĂ¼ was rather easy
axWindowsMediaPlayer1.enableContextMenu = false;
Disabling the doubleclick requires a message filter - there is already a solution on the web.
Application.AddMessageFilter((IMessageFilter)CustomFilter(this/*Form*/, axWMP));
I have rewritten my example and i am now using this code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
axWindowsMediaPlayer1.uiMode = "none";
axWindowsMediaPlayer1.enableContextMenu = false;
Application.AddMessageFilter(new IgnoreMouseClickMessageFilter(this, axWindowsMediaPlayer1));
}
private void button1_Click(object sender, EventArgs e)
{
axWindowsMediaPlayer1.URL = #"C:\stackoverflow.mp4";
}
}
class IgnoreMouseClickMessageFilter : IMessageFilter
{
private Control parent { get; set; }
private Control target { get; set; }
public IgnoreMouseClickMessageFilter(Control parent, Control target)
{
this.parent = parent;
this.target = target;
}
public bool PreFilterMessage(ref Message messageBeforeFiltering)
{
const Boolean FilterTheMessageOut = true;
const Boolean LetTheMessageThrough = false;
if (IsNull(parent)) return LetTheMessageThrough;
if (IsNull(target)) return LetTheMessageThrough;
if (WasNotClickedOnTarget(parent, target)) return LetTheMessageThrough;
if (MessageContainsAnyMousebutton(messageBeforeFiltering)) return FilterTheMessageOut;
return LetTheMessageThrough;
}
private bool MessageContainsAnyMousebutton(Message message)
{
if (message.Msg == 0x202) return true; /* WM_LBUTTONUP*/
if (message.Msg == 0x203) return true; /* WM_LBUTTONDBLCLK*/
if (message.Msg == 0x204) return true; /* WM_RBUTTONDOWN */
if (message.Msg == 0x205) return true; /* WM_RBUTTONUP */
return false;
}
private bool WasNotClickedOnTarget(Control parent, Control target)
{
Control clickedOn = parent.GetChildAtPoint(Cursor.Position);
if (IsNull(clickedOn)) return true;
if (AreEqual(clickedOn, target)) return false;
return true;
}
private bool AreEqual(Control controlA, Control controlB)
{
if (controlA == controlB) return true;
return false;
}
private bool IsNull(Control control)
{
if (control == null) return true;
return false;
}
}
Special thanks to my unnamed friend and to "remarkpk11" from the Microsoft Developer Network Frorums.
There are some smaller issues with the code - i dont like that the Messages are hidden from me in the first place and i also would love to get rid of the two global dependencies Cursor and Application. But as far as this question goes i consider it answered.
try axWindowsMediaPlayer1.Ctlenabled = False
EDIT: sorry, this is for vb..
axWindowsMediaPlayer1.Ctlcontrols.stop();

Categories