Unity Project

reference
https://cardgames.io/yahtzee/
This commit is contained in:
mcutegs2
2020-07-21 15:43:56 +09:00
commit 42edc18e4e
4081 changed files with 189452 additions and 0 deletions

387
Assets/Dice/Plugins/Dice.cs Normal file
View File

@@ -0,0 +1,387 @@
/**
* Copyright (c) 2010-2015, WyrmTale Games and Game Components
* All rights reserved.
* http://www.wyrmtale.com
*
* THIS SOFTWARE IS PROVIDED BY WYRMTALE GAMES AND GAME COMPONENTS 'AS IS' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL WYRMTALE GAMES AND GAME COMPONENTS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using UnityEngine;
using System.Collections;
/// <summary>
/// This dice dupporting class has some 'static' methods to help you throwning dice
/// and getting the rolling dice count, value or rolling state (asString)
/// </summary>
public class Dice : MonoBehaviour {
//------------------------------------------------------------------------------------------------------------------------------
// public attributes
//------------------------------------------------------------------------------------------------------------------------------
// constants for checking mouse button input
public const int MOUSE_LEFT_BUTTON = 0;
public const int MOUSE_RIGHT_BUTTON = 1;
public const int MOUSE_MIDDLE_BUTTON = 2;
// rollSpeed determines how many seconds pass between rolling the single dice
public float rollSpeed = 0.25F;
// rolling = true when there are dice still rolling, rolling is checked using rigidBody.velocity and rigidBody.angularVelocity
public static bool rolling = true;
//------------------------------------------------------------------------------------------------------------------------------
// protected and private attributes
//------------------------------------------------------------------------------------------------------------------------------
// keep rolling time to determine when dice to be rolled, have to be instantiated
protected float rollTime = 0;
// material cache
private static ArrayList matNames = new ArrayList();
private static ArrayList materials = new ArrayList();
// reference to the dice that have to be rolled
private static ArrayList rollQueue = new ArrayList();
// reference to all dice, created by Dice.Roll
private static ArrayList allDice = new ArrayList();
// reference to the dice that are rolling
private static ArrayList rollingDice = new ArrayList();
//------------------------------------------------------------------------------------------------------------------------------
// public methods
//------------------------------------------------------------------------------------------------------------------------------
/// <summary>
/// This method will create/instance a prefab at a specific position with a specific rotation and a specific scale and assign a material
/// </summary>
public static GameObject prefab(string name, Vector3 position, Vector3 rotation, Vector3 scale, string mat)
{
// load the prefab from Resources
Object pf = Resources.Load("Prefabs/" + name);
if (pf!=null)
{
// the prefab was found so create an instance for it.
GameObject inst = (GameObject) GameObject.Instantiate( pf , Vector3.zero, Quaternion.identity);
if (inst!=null)
{
// the instance could be created so set material, position, rotation and scale.
if (mat!="") inst.GetComponent<Renderer>().material = material(mat);
inst.transform.position = position;
inst.transform.Rotate(rotation);
inst.transform.localScale = scale;
// return the created instance (GameObject)
return inst;
}
}
else
Debug.Log("Prefab "+name+" not found!");
return null;
}
/// <summary>
/// This method will perform a quick lookup for a 'cached' material. If not found, the material will be loaded from the Resources
/// </summary>
public static Material material(string matName)
{
Material mat = null;
// check if material is cached
int idx = matNames.IndexOf(matName);
if (idx<0)
{
// not cached so load it from Resources
string[] a = matName.Split('-');
if (a.Length>1)
{
a[0] = a[0].ToLower();
if (a[0].IndexOf("d")==0)
mat = (Material) Resources.Load("Materials/"+a[0]+"/"+matName);
}
if (mat==null) mat = (Material) Resources.Load("Materials/"+matName);
if (mat!=null)
{
// add material to cache
matNames.Add(matName);
materials.Add(mat);
}
}
else
mat = (Material) materials[idx];
// return material - null if not found
return mat;
}
/// <summary>
/// Log a text to the console
/// </summary>
public static void debug(string txt)
{
Debug.Log(txt);
}
/// <summary>
/// Roll one or more dice with a specific material from a spawnPoint and give it a specific force.
/// format dice : ({count}){die type} , exmpl. d6, 4d4, 12d8 , 1d20
/// possible die types : d4, d6, d8 , d10, d12, d20
/// </summary>
public static void Roll(string dice, string mat, Vector3 spawnPoint, Vector3 force)
{
rolling = true;
// sotring dice to lowercase for comparing purposes
dice = dice.ToLower();
int count = 1;
string dieType = "d6";
// 'd' must be present for a valid 'dice' specification
int p = dice.IndexOf("d");
if (p>=0)
{
// check if dice starts with d, if true a single die is rolled.
// dice must have a count because dice does not start with 'd'
if (p>0)
{
// extract count
string[] a = dice.Split('d');
count = System.Convert.ToInt32(a[0]);
// get die type
if (a.Length>1)
dieType = "d"+a[1];
else
dieType = "d6";
}
else
dieType = dice;
// instantiate the dice
for (int d=0; d<count; d++)
{
// randomize spawnPoint variation
spawnPoint.x = spawnPoint.x - 1 + Random.value * 2;
spawnPoint.y = spawnPoint.y - 1 + Random.value * 2;
spawnPoint.y = spawnPoint.y - 1 + Random.value * 2;
// create the die prefab/gameObject
GameObject die = prefab(dieType, spawnPoint, Vector3.zero, Vector3.one, mat);
// give it a random rotation
die.transform.Rotate(new Vector3(Random.value * 360, Random.value * 360, Random.value * 360));
// inactivate this gameObject because activating it will be handeled using the rollQueue and at the apropriate time
die.active = false;
// create RollingDie class that will hold things like spawnpoint and force, to be used when activating the die at a later stage
RollingDie rDie = new RollingDie(die, dieType, mat, spawnPoint, force);
// add RollingDie to allDices
allDice.Add(rDie);
// add RollingDie to the rolling queue
rollQueue.Add(rDie);
}
}
}
/// <summary>
/// Get value of all ( dieType = "" ) dice or dieType specific dice.
/// </summary>
public static int Value(string dieType)
{
int v = 0;
// loop all dice
for (int d = 0; d < allDice.Count; d++)
{
RollingDie rDie = (RollingDie) allDice[d];
// check the type
if (rDie.name == dieType || dieType == "")
v += rDie.die.value;
}
return v;
}
/// <summary>
/// Get number of all ( dieType = "" ) dice or dieType specific dice.
/// </summary>
public static int Count(string dieType)
{
int v = 0;
// loop all dice
for (int d = 0; d < allDice.Count; d++)
{
RollingDie rDie = (RollingDie)allDice[d];
// check the type
if (rDie.name == dieType || dieType == "")
v++;
}
return v;
}
/// <summary>
/// Get rolling status of all ( dieType = "" ) dice or dieType specific dice.
/// </summary>
public static string AsString(string dieType)
{
// count the dice
string v = ""+Count(dieType);
if (dieType == "")
v += " dice | ";
else
v += dieType + " : ";
if (dieType == "")
{
// no dieType specified to cumulate values per dieType ( if they are available )
if (Count("d6") > 0) v += AsString("d6") + " | ";
if (Count("d10") > 0) v += AsString("d10") + " | ";
}
else
{
// assemble status of specific dieType
bool hasValue = false;
for (int d = 0; d < allDice.Count; d++)
{
RollingDie rDie = (RollingDie)allDice[d];
// check type
if (rDie.name == dieType || dieType == "")
{
if (hasValue) v += " + ";
// if the value of the die is 0 , no value could be determined
// this could be because the die is rolling or is in a invalid position
v += "" + ((rDie.die.value == 0) ? "?" : "" + rDie.die.value);
hasValue = true;
}
}
v += " = " + Value(dieType);
}
return v;
}
/// <summary>
/// Clears all currently rolling dice
/// </summary>
public static void Clear()
{
for (int d=0; d<allDice.Count; d++)
GameObject.Destroy(((RollingDie)allDice[d]).gameObject);
allDice.Clear();
rollingDice.Clear();
rollQueue.Clear();
rolling = false;
}
/// <summary>
/// Update is called once per frame
/// </summary>
void Update()
{
if (rolling)
{
// there are dice rolling so increment rolling time
rollTime += Time.deltaTime;
// check rollTime against rollSpeed to determine if a die should be activated ( if one available in the rolling queue )
if (rollQueue.Count > 0 && rollTime > rollSpeed)
{
// get die from rolling queue
RollingDie rDie = (RollingDie)rollQueue[0];
GameObject die = rDie.gameObject;
// activate the gameObject
die.active = true;
// apply the force impuls
die.GetComponent<Rigidbody>().AddForce((Vector3) rDie.force, ForceMode.Impulse);
// apply a random torque
die.GetComponent<Rigidbody>().AddTorque(new Vector3(-50 * Random.value * die.transform.localScale.magnitude, -50 * Random.value * die.transform.localScale.magnitude, -50 * Random.value * die.transform.localScale.magnitude), ForceMode.Impulse);
// add die to rollingDice
rollingDice.Add(rDie);
// remove the die from the queue
rollQueue.RemoveAt(0);
// reset rollTime so we can check when the next die has to be rolled
rollTime = 0;
}
else
if (rollQueue.Count == 0)
{
// roll queue is empty so if no dice are rolling we can set the rolling attribute to false
if (!IsRolling())
rolling = false;
}
}
}
/// <summary>
/// Check if there all dice have stopped rolling
/// </summary>
private bool IsRolling()
{
int d = 0;
// loop rollingDice
while (d < rollingDice.Count)
{
// if rolling die no longer rolling , remove it from rollingDice
RollingDie rDie = (RollingDie)rollingDice[d];
if (!rDie.rolling)
rollingDice.Remove(rDie);
else
d++;
}
// return false if we have no rolling dice
return (rollingDice.Count > 0);
}
}
/// <summary>
/// Supporting rolling die class to keep die information
/// </summary>
class RollingDie
{
public GameObject gameObject; // associated gameObject
public Die die; // associated Die (value calculation) script
public string name = ""; // dieType
public string mat; // die material (asString)
public Vector3 spawnPoint; // die spawnPoiunt
public Vector3 force; // die initial force impuls
// rolling attribute specifies if this die is still rolling
public bool rolling
{
get
{
return die.rolling;
}
}
public int value
{
get
{
return die.value;
}
}
// constructor
public RollingDie(GameObject gameObject, string name, string mat, Vector3 spawnPoint, Vector3 force)
{
this.gameObject = gameObject;
this.name = name;
this.mat = mat;
this.spawnPoint = spawnPoint;
this.force = force;
// get Die script of current gameObject
die = (Die)gameObject.GetComponent(typeof(Die));
}
// ReRoll this specific die
public void ReRoll()
{
if (name != "")
{
GameObject.Destroy(gameObject);
Dice.Roll(name, mat, spawnPoint, force);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6b4036603d212e4eae18e23b556ca9f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

133
Assets/Dice/Plugins/Die.cs Normal file
View File

@@ -0,0 +1,133 @@
/**
* Copyright (c) 2010-2015, WyrmTale Games and Game Components
* All rights reserved.
* http://www.wyrmtale.com
*
* THIS SOFTWARE IS PROVIDED BY WYRMTALE GAMES AND GAME COMPONENTS 'AS IS' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL WYRMTALE GAMES AND GAME COMPONENTS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using UnityEngine;
using System.Collections;
/// <summary>
/// Die base class to determine if a die is rolling and to calculate it's current value
/// </summary>
public class Die : MonoBehaviour {
//------------------------------------------------------------------------------------------------------------------------------
// public attributes
//------------------------------------------------------------------------------------------------------------------------------
// current value, 0 is undetermined (die is rolling) or invalid.
public int value = 0;
//------------------------------------------------------------------------------------------------------------------------------
// protected and private attributes
//------------------------------------------------------------------------------------------------------------------------------
// normalized (hit)vector from die center to upper side in local space is used to determine what side of a specific die is up/down = value
protected Vector3 localHitNormalized;
// hitVector check margin
protected float validMargin = 0.45F;
// true is die is still rolling
public bool rolling
{
get
{
return !(GetComponent<Rigidbody>().velocity.sqrMagnitude < .1F && GetComponent<Rigidbody>().angularVelocity.sqrMagnitude < .1F);
}
}
// calculate the normalized hit vector and should always return true
protected bool localHit
{
get
{
// create a Ray from straight above this Die , moving downwards
Ray ray = new Ray(transform.position + (new Vector3(0, 2, 0) * transform.localScale.magnitude), Vector3.up * -1);
RaycastHit hit = new RaycastHit();
// cast the ray and validate it against this die's collider
if (GetComponent<Collider>().Raycast(ray, out hit, 3 * transform.localScale.magnitude))
{
// we got a hit so we determine the local normalized vector from the die center to the face that was hit.
// because we are using local space, each die side will have its own local hit vector coordinates that will always be the same.
localHitNormalized = transform.InverseTransformPoint(hit.point.x, hit.point.y, hit.point.z).normalized;
return true;
}
// in theory we should not get at this position!
return false;
}
}
// calculate this die's value
void GetValue()
{
// value = 0 -> undetermined or invalid
value = 0;
float delta = 1;
// start with side 1 going up.
int side = 1;
Vector3 testHitVector;
// check all sides of this die, the side that has a valid hitVector and smallest x,y,z delta (if more sides are valid) will be the closest and this die's value
do
{
// get testHitVector from current side, HitVector is a overriden method in the dieType specific Die subclass
// eacht dieType subclass will expose all hitVectors for its sides,
testHitVector = HitVector(side);
if (testHitVector != Vector3.zero)
{
// this side has a hitVector so validate the x,y and z value against the local normalized hitVector using the margin.
if (valid(localHitNormalized.x, testHitVector.x) &&
valid(localHitNormalized.y, testHitVector.y) &&
valid(localHitNormalized.z, testHitVector.z))
{
// this side is valid within the margin, check the x,y, and z delta to see if we can set this side as this die's value
// if more than one side is within the margin (especially with d10, d12, d20 ) we have to use the closest as the right side
float nDelta = Mathf.Abs(localHitNormalized.x - testHitVector.x) + Mathf.Abs(localHitNormalized.y - testHitVector.y) + Mathf.Abs(localHitNormalized.z - testHitVector.z);
if (nDelta < delta)
{
value = side;
delta = nDelta;
}
}
}
// increment side
side++;
// if we got a Vector.zero as the testHitVector we have checked all sides of this die
} while (testHitVector != Vector3.zero);
}
void Update()
{
// determine the value is the die is not rolling
if (!rolling && localHit)
GetValue();
}
// validate a test value against a value within a specific margin.
protected bool valid(float t, float v)
{
if (t > (v - validMargin) && t < (v + validMargin))
return true;
else
return false;
}
// virtual method that to get a die side hitVector.
// this has to be overridden in the dieType specific subclass
protected virtual Vector3 HitVector(int side)
{
return Vector3.zero;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a7ca1acb51470bb44bd5b0c932c809a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: