I have tried nutting this issue out, and failed multiple times.
I tried searching existing posts, and understand why this is occuring.
However still being new to Unity (Particularly scripting) I am unable to find a solution to my issue.
I am learning from a book "Unity 3.x Game Development by example"by Ryan Creighton. (Excellent book btw)
Specific Error:
Assets/Scripts/GameScript.js(97,36): BCE0024: The type ‘Card’ does not have a visible constructor that matches the argument list ‘(String)’.
Entire Code from Script:
I believe the issue will be found in the last function “BuildDeck” but could be wrong.
var cols:int = 4; // the number of columns in the card grid
var rows:int = 4; // the number of rows in the card grid
var totalCards:int = 16;
var matchesNeededToWin:int = totalCards * 0.5; //If there are 16 cards the player needs to find 8 matches to clear the board
var matchesMade:int = 0; //At the outset, the player has not made any matches
var cardW:int = 100; //Each card's width and height is 100 pixels
var cardH:int = 100;
var aCards:Array; //We'll store all the cards we create int this array
var aGrid:Array; //This array will keep track of the shuffled, dealt cards
var aCardsFlipped:ArrayList; //This array will store the two cards that the player flips over
var playerCanClick:boolean; // We'll use this to flag to prevent the player from clicking buttons when we don't want him to
var playerHasWon:boolean=false; //Store whether or not the player has won. This should probably stat out false.
class Card extends System.Object
{
var isFaceUp:boolean = false;
var isMatched:boolean = false;
var img:String;
function Card()
{
this.img = img;
}
}
function Start () {
playerCanClick = true; //Lets the player play.
//Initialise the arrays as empty lists:
aCards = new Array();
aGrid = new Array();
aCardsFlipped = new ArrayList();
//Calls the Build Deck Function
BuildDeck();
for (i=0; i<rows; i++)
{
aGrid[i] = new Array(); //Create a new, empty array at index i
for (j=0; j < cols; j++)
{
var someNum:int = Random.Range(0,aCards.length);
aGrid[i][j] = aCards[someNum];
aCards.RemoveAt(someNum);
}
}
}
function OnGUI(){
GUILayout.BeginArea (Rect(0,0,Screen.width,Screen.height));
BuildGrid();
GUILayout.EndArea();
print("building grid!");
}
function BuildGrid(){
GUILayout.BeginVertical();
GUILayout.FlexibleSpace();
for (i=0; i<rows; i++)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
for (j=0; j<cols; j++)
{
var card:Object = aGrid[i][j];
if(GUILayout.Button(Resources.Load(card.img),
GUILayout.Width(cardW)))
{
Debug.Log(card.img);
}
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
GUILayout.FlexibleSpace();
GUILayout.EndVertical();
}
function BuildDeck()
{
var totalRobots:int = 4; //we've got four robots to work with
//this stores a reference to a card
for (i=0; i<totalRobots;i++)
{
var aRobotParts:Array = ["Head", "Arm", "leg"];
for (j=0; j<2; j++)
{
var someNum:int = Random.Range(0, aRobotParts.Length);
var theMissingPart:String = aRobotParts[someNum];
aRobotParts.RemoveAt(someNum);
var card:Object;
card = new Card ("robot" + "Missing" + theMissingPart);
aCards.Add(card);
//card = new Card ("robot" + (i + 1) + theMissingPart);
//aCards.Add(card);
}
}
}
Thankyou in advance if anybody is able to assist or point me in the correct direction.
You are trying to use a constructor for the Card class that takes a string as a parameter but you only have one constructor defined with no parameters so you need a constructor like this:
Here’s my whole script in case I did anything stupid:
//#pragma strict
var cols:int = 4; // the number of columns in the card grid
var rows:int = 4; // the number of rows in the card grid
var totalCards:int = 16;
var matchesNeededToWin:int = totalCards * 0.5; // If there are 16 cards, the player needs to find 8 matches to clear the board
var matchesMade:int = 0; // At the outset, the player has not made any matches
var cardW:int = 100; // Each card's width and height is 100 pixels
var cardH:int = 100;
var aCards:Array; // We'll store all the cards we create in this array
var aGrid:Array; // This array will keep track of the shuffled, dealt cards
var aCardsFlipped:ArrayList; // This array will store the two cards that the player flips over
var playerCanClick:boolean; // We'll use this flag to prevent the player from clicking buttons when we don't want him to
var playerHasWon:boolean = false; // Store whether or not the player has won. This should probably start out false :)
function Start ()
{
playerCanClick = true; // We should let the player play, don't you think?
// Initialize the arrays as empty lists:
aCards = new Array();
aGrid = new Array();
aCardsFlipped = new ArrayList();
BuildDeck();
for(var i=0; i<rows; i++)
{
aGrid[i] = new Array(); // Create a new, empty array at index i
for(var j=0; j<cols; j++)
{
var someNum:int = Random.Range(0,aCards.length);
aGrid[i][j] = aCards[someNum];
aCards.RemoveAt(someNum);
}
}
}
function OnGUI ()
{
GUILayout.BeginArea (Rect (0,0,Screen.width,Screen.height));
BuildGrid();
GUILayout.EndArea();
// print("building grid with ");
}
class Card extends System.Object
{
var isFaceUp:boolean = false;
var isMatched:boolean = false;
var img:String;
var id:int;
function Card (img, id:int)
{
this.img = img;
this.id = id;
}
}
function BuildGrid()
{
GUILayout.BeginVertical();
GUILayout.FlexibleSpace();
for(var i=0; i<rows; i++)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
for(var j=0; j<cols; j++)
{
var card:Object = aGrid[i][j];
var img;
if(card.isMatched)
{
img = "blank";
}
else
{
if (card.isFaceUp)
{
img = card.img;
}
else
{
img = "wrench";
}
}
GUI.enabled = !card.isMatched;
if(GUILayout.Button(Resources.Load(img), GUILayout.Width(cardW)))
{
if(playerCanClick)
{
FlipCardFaceUp(card);
}
Debug.Log(card.img);
}
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
}
GUILayout.FlexibleSpace();
GUILayout.EndVertical();
}
function BuildDeck()
{
var totalRobots:int = 4; //we have four robots in total
var card:Object; //this stores a reference to a card
var id:int = 0;
for(var i=0;i<totalRobots; i++)
{
var aRobotParts:Array = ["Head", "Arm", "Leg"];
for(var j=0;j<2; j++)
{
var someNum:int = Random.Range(0, aRobotParts.length);
var theMissingPart = aRobotParts[someNum];
aRobotParts.RemoveAt(someNum);
card = new Card("robot" + (i+1) + "Missing" + theMissingPart, id);
aCards.Add(card);
//this one causes problems
card = new Card("robot" + (i+1) + theMissingPart);
aCards.Add(card);
id++;
}
}
}
function FlipCardFaceUp(card:Card)
{
card.isFaceUp = true;
if(aCardsFlipped.IndexOf(card) < 0)
{
aCardsFlipped.Add(card);
if(aCardsFlipped.Count == 2)
{
playerCanClick = false;
yield WaitForSeconds(1);
if(aCardsFlipped[0].id == aCardsFlipped[1].id)
{
//match!
aCardsFlipped[0].isMatched = true;
aCardsFlipped[1].isMatched = true;
}
else
{
aCardsFlipped[0].isFaceUp = false;
aCardsFlipped[1].isFaceUp = false;
}
aCardsFlipped = new ArrayList();
playerCanClick = true;
}
}
}
Still one tiny problem… Everything is working fine now, but when the game has been won it puts a box on the screen with a button to play again. I tried making sure the player can click but the button is still ghosted. If I artificially set the Player has Won status to true I can click the button, otherwise no.
function BuildWinPrompt()
{
var winPromptW:int = 100;
var winPromptH:int = 90;
var halfScreenW:int = Screen.width/2;
var halfScreenH:int = Screen.height/2;
var halfPromptW:int = winPromptW/2;
var halfPromptH:int = winPromptH/2;
playerCanClick = true;
// GUI.BeginGroup(Rect(halfScreenW-halfPromptW, halfScreenH-halfPromptH, winPromptW, winPromptH));
GUI.BeginGroup(Rect(0, 100, winPromptW, winPromptH));
playerCanClick = true;
GUI.Box (Rect (0, 0, winPromptW, winPromptH), winner);
// GUI.skin = customSkin;
if(GUI.Button(Rect(10,40,80,20),"Play again?"))
{
Application.LoadLevel("Title");
}
GUI.EndGroup();
}
Added a Debug.Log line in below the if and the game jumps straight to the title screen, comment it out and the button is ghosted and I can’t get anywhere…