예제 #1
0
        /// <summary>
        /// Handle the collision of two molecules
        /// </summary>
        /// <param name="m1">molecule 1</param>
        /// <param name="m2">molecule 2</param>
        public void Collision(Molecule m1, Molecule m2)
        {
            // check if ReactionPrep of both molecules is not null and if the ReactionPrep equals
            if ((m1.ReactionPrep != null) && (m1.ReactionPrep == m2.ReactionPrep))
            {
                // both molecules have the same ReactionPrep assigned and therefore
                // belong to the same reaction

                ReactionPrep reactionPrep = m1.ReactionPrep;

                // make the molecules ready for reacting
                reactionPrep.Ready(m1);
                reactionPrep.Ready(m2);
            }
        }
예제 #2
0
        /// <summary>
        /// Performs a reaction.
        /// Called by the ReactionPrep when all molecules are ready.
        /// </summary>
        /// <param name="reactionPrep">Reaction prep.</param>
        public void PerformReaction(ReactionPrep reactionPrep)
        {
            bool selectedInvolved = false;

            // calculate center

            Vector3 center    = Vector3.zero;
            float   centerSum = 0;

            foreach (Molecule m in reactionPrep.Molecules)
            {
                selectedInvolved |= (m == SelectedMolecule);

                m.ClearReactionPrep();

                center    += m.Position * m.Species.Size;
                centerSum += m.Species.Size;

                GameObject.Destroy(m.gameObject);
            }

            if (centerSum > float.Epsilon)             // avoid division by 0
            {
                center = center / centerSum;
            }

            // momentum conservation

            Vector3 momentum = Vector3.zero;

            foreach (Molecule m in reactionPrep.Molecules)
            {
                momentum += m.rigidbody.velocity;                 //* m.Species.Mass;  // ignore mass (because it doesnt work properly when a very big and a very small molecule collide
            }

            float productMassSum = 0;
            float productSizeSum = 0;

            MoleculeSpecies[] productSpecies = reactionPrep.ReactionType.Products;

            foreach (MoleculeSpecies productS in productSpecies)
            {
                productMassSum += productS.Mass;
                productSizeSum += productS.Size;
            }

            Vector3 productVelocity = momentum;             // / productMassSum; // ignore mass (because it doesnt work properly when a very big and a very small molecule collide

            // create products

            Vector3 productPosition = center;

            foreach (MoleculeSpecies productS in productSpecies)
            {
                Molecule product = productS.CreateMolecule(productPosition);
                product.rigidbody.velocity = productVelocity;

                productPosition += new Vector3(product.Species.Size * 1.2f, 0, 0);                 // so products don't touch

                if (selectedInvolved)
                {
                    selectedInvolved = false;

                    SelectedMolecule = product;
                }
            }

            if (selectedInvolved)
            {
                selectedInvolved = false;
                SelectedMolecule = null;
            }

            // flash

            GameObject flash = (GameObject)GameObject.Instantiate(LightFlash.GetPrefabObject(), Vector3.Lerp(center, Camera.main.gameObject.transform.position, 0.5f), Quaternion.identity);

            float intensity = 2f * (float)System.Math.Sqrt(productSizeSum);

            flash.GetComponent <LightFlash>().FinalIntensity = intensity;

            TryInitiateOpenReactions();
        }
예제 #3
0
        /// <summary>
        /// Initiates a reaction.
        /// </summary>
        /// <returns><c>true</c>, if the reaction was initiated, <c>false</c> otherwise.</returns>
        /// <param name="reaction">Reaction.</param>
        /// <param name="queueIfNotPossible">If set to <c>true</c>, the reaction is queued and performed later if the reaction is not possible at the moment.</param>
        public bool InitiateReaction(ReactionType reaction, bool queueIfNotPossible)
        {
            CUE cue = CUE.GetInstance();

            ReactionPrep reactionPrep = new ReactionPrep(reaction);

            bool moleculesFound;

            // Select molecules

            // Prefer selected molecule if suitable
            if (
                selectedMolecule != null && selectedReaction != null &&                 // molecule and reaction must be selected
                selectedReaction == reaction &&                                         // selected reaction must match current reaction
                selectedMolecule.ReactionPrep == null                                   // selected molecule must not be already involved in a reaction
                )
            {
                moleculesFound = cue.Molecules.FindMolecuelsForReaction(reactionPrep, selectedMolecule);
            }
            else
            {
                // select random molecules
                moleculesFound = cue.Molecules.FindMolecuelsForReaction(reactionPrep);
            }

            if (moleculesFound)
            {
                // Ready reactions for 0 to 1 reagents because Collision is never called for these molecules

                if (reactionPrep.MoleculeCount == 0)
                {
                    reactionPrep.Ready(null);
                }
                if (reactionPrep.MoleculeCount == 1)
                {
                    reactionPrep.Ready(reactionPrep.Molecules[0]);                     // necessary if only one reagent in reaction
                }

                return(true);
            }
            else
            {
                // not sufficient molecules for reaction

                reactionPrep.Release();                 // remove ReactonPrep from Molecules

                if (queueIfNotPossible)
                {
                    // --> queue Reaction for later

                    ShortKeyDict <ReactionType, int> .Entry entry;
                    if (!openReactions.Find(reaction, out entry))
                    {
                        entry = openReactions.Set(reaction, 0);
                    }

                    entry.Value++;
                }

                return(false);
            }
        }