//标记元器件 public override void stamp() { if (isOpen) { CirSim.stampVoltageSource(nodes[0], nodes[1], voltSource[0], 0); } }
//标记矩阵 public override void stamp() { //标记两个结点矩阵的非线性 CirSim.stampNonLinear(nodes[0]); CirSim.stampNonLinear(nodes[1]); //doStep(); }
//标记矩阵 public override void stamp() { CirSim.stampNonLinear(nodes[0]); CirSim.stampNonLinear(nodes[1]); CirSim.stampNonLinear(nodes[2]); doStep(); }
//标记元器件 public override void stamp() { for (int i = 0; i < getPostCount() - 1; i++) { CirSim.stampResistor(nodes[i], nodes[8], resistance); //每个端点都与正极之间有一个电阻 } }
//进行下一步 public override void doStep() { float vbc = volts[0] - volts[1]; // typically negative float vbe = volts[0] - volts[2]; // typically positive if (Mathf.Abs(vbc - lastvbc) > .01 || // .01 Mathf.Abs(vbe - lastvbe) > .01) { gmin = 0; } //System.out.print("T " + vbc + " " + vbe + "\n"); vbc = pnp * limitStep(pnp * vbc, pnp * lastvbc); vbe = pnp * limitStep(pnp * vbe, pnp * lastvbe); lastvbc = vbc; lastvbe = vbe; float pcoef = vdcoef * pnp; float expbc = Mathf.Exp(vbc * pcoef); /*if (expbc > 1e13 || Double.isInfinite(expbc)) * expbc = 1e13;*/ double expbe = Mathf.Exp(vbe * pcoef); if (expbe < 1) { expbe = 1; } /*if (expbe > 1e13 || Double.isInfinite(expbe)) * expbe = 1e13;*/ ie = (float)(pnp * leakage * (-(expbe - 1) + rgain * (expbc - 1))); ic = (float)(pnp * leakage * (fgain * (expbe - 1) - (expbc - 1))); ib = -(ie + ic); //System.out.println("gain " + ic/ib); //System.out.print("T " + vbc + " " + vbe + " " + ie + " " + ic + "\n"); float gee = (float)(-leakage * vdcoef * expbe); float gec = rgain * leakage * vdcoef * expbc; float gce = -gee * fgain; float gcc = -gec * (1 / rgain); // stamps from page 302 of Pillage. Node 0 is the base, // node 1 the collector, node 2 the emitter. Also stamp // minimum conductance (gmin) between b,e and b,c CirSim.stampMatrix(nodes[0], nodes[0], -gee - gec - gce - gcc + gmin * 2); CirSim.stampMatrix(nodes[0], nodes[1], gec + gcc - gmin); CirSim.stampMatrix(nodes[0], nodes[2], gee + gce - gmin); CirSim.stampMatrix(nodes[1], nodes[0], gce + gcc - gmin); CirSim.stampMatrix(nodes[1], nodes[1], -gcc + gmin); CirSim.stampMatrix(nodes[1], nodes[2], -gce); CirSim.stampMatrix(nodes[2], nodes[0], gee + gec - gmin); CirSim.stampMatrix(nodes[2], nodes[1], -gec); CirSim.stampMatrix(nodes[2], nodes[2], -gee + gmin); // we are solving for v(k+1), not delta v, so we use formula // 10.5.13, multiplying J by v(k) CirSim.stampRightSide(nodes[0], -ib - (gec + gcc) * vbc - (gee + gce) * vbe); CirSim.stampRightSide(nodes[1], -ic + gce * vbe + gcc * vbc); CirSim.stampRightSide(nodes[2], -ie + gee * vbe + gec * vbc); }
//标记元器件 public override void stamp() { if (isRun) { CirSim.stampVoltageSource(0, nodes[1], voltSource[0], 999); //输出电压为999 isRun = false; //运行标志位置false } else { CirSim.stampVoltageSource(0, nodes[1], voltSource[0], 0); //输出电压为0 } CirSim.stampResistor(nodes[0], nodes[3], 10); //0 3结点间为10欧姆的电阻 }
//灯泡损坏协程 IEnumerator Damage(float delayTime) { yield return(new WaitForSeconds(delayTime)); //等待delayTime秒 Flash.SetActive(true); //闪光效果 Utils.audioManager.playAudio(2); //播放烧毁音效 stop(); //小灯泡停止工作 isDamaged = true; //元器件破损 CirSim.damageList.Add(transform.GetComponent <CircuitElm>()); //添加进损坏列表 CirSim.analyzeCircuit(); //重新分析电路 yield return(new WaitForSeconds(0.5f)); //等待音效播放完 smoke.Play(); //触发粒子系统 Utils.menuListener.PopTipUI("灯泡烧毁"); //弹出提示界面 }
//进行下一步 public override void doStep() { setUp(); float voltdiff = volts[0] - volts[1]; //电势 voltdiff = limitStep(voltdiff, lastvoltdiff); lastvoltdiff = voltdiff; if (voltdiff >= 0 || zvoltage == 0) { // regular diode or forward-biased zener float eval = Mathf.Exp(voltdiff * vdcoef); // make diode linear with negative voltages; aids convergence if (voltdiff < 0) { eval = 1; } float geq = vdcoef * leakage * eval; float nc = (eval - 1) * leakage - geq * voltdiff; CirSim.stampConductance(nodes[0], nodes[1], geq); CirSim.stampCurrentSource(nodes[0], nodes[1], nc); } else { // Zener diode /* * I(Vd) = Is * (exp[Vd*C] - exp[(-Vd-Vz)*C] - 1 ) * * geq is I'(Vd) * nc is I(Vd) + I'(Vd)*(-Vd) */ float geq = leakage * vdcoef * ( Mathf.Exp(voltdiff * vdcoef) + Mathf.Exp((-voltdiff - zoffset) * vdcoef)); float nc = leakage * ( Mathf.Exp(voltdiff * vdcoef) - Mathf.Exp((-voltdiff - zoffset) * vdcoef) - 1 ) + geq * (-voltdiff); CirSim.stampConductance(nodes[0], nodes[1], geq); CirSim.stampCurrentSource(nodes[0], nodes[1], nc); } }
void Update() { value = transform.GetComponent <Scrollbar> ().value; if (value == oldValue) { return; } for (int i = 0; i < PhotosensitiveResistorElm.Length; i++) { Debug.Log(PhotosensitiveResistorElm.Length); PhotosensitiveResistorElm[i].GetComponent <PhotosensitiveResistorElm> ().resistance = 100.0f * (1 - value); PhotosensitiveResistorElm[i].transform.FindChild("Spotlight").GetComponent <Light> ().intensity = 8.0f * value; if (PhotosensitiveResistorElm[i].GetComponent <PhotosensitiveResistorElm> ().resistance < 5.0f) { PhotosensitiveResistorElm[i].GetComponent <PhotosensitiveResistorElm> ().resistance = 5.0f; } } CirSim.analyzeCircuit(); //分析电路 oldValue = transform.GetComponent <Scrollbar> ().value; }
//标记元器件 public override void stamp() { if (ICState == -1) //开始录音,在连接话筒的两个端口施加电压 { CirSim.stampVoltageSource(nodes[3], nodes[5], voltSource[0], 0.0555f); //标记两个连接话筒的端点 0.0555位话筒接收的电压值 Debug.Log("ICState状态为-1"); } if (ICState == 1) //播放录音,在输出端口施加电压 { CirSim.stampVoltageSource(0, nodes[4], voltSource[0], 998f); //输出电压为998 Debug.Log("ICState状态为1"); } Debug.Log("ICState状态为0"); //标记电阻 CirSim.stampResistor(nodes[6], nodes[0], resistance); //6 0结点间为5欧姆的电阻 CirSim.stampResistor(nodes[6], nodes[1], resistance); //6 1结点间为5欧姆的电阻 CirSim.stampResistor(nodes[6], nodes[2], resistance); //6 2结点间为5欧姆的电阻 }
//标记元器件 public override void stamp() { CirSim.stampResistor(nodes [0], nodes [1], resistance); }
// 移动平台触屏操作 void MobileInput() { if (Utils.isIntroduction) { return; } if (Utils.gestureLayer) //电路连通好后的手势触摸层 { if (Input.touchCount == 1) { Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position); LayerMask unitmask = 1 << LayerMask.NameToLayer("unit"); //规定触摸层数 if (Physics.Raycast(ray, out hit, 100, unitmask.value) && Input.touches[0].phase == TouchPhase.Began) { Utils.audioManager.playAudio(1); //播放音效 temp = hit.collider.transform.GetComponent <CircuitElm>(); //获取元器件脚本 if (temp.type == CirSim.TYPES.SwitchElm) { setUICamera(temp, UICamera); //设置UI摄像机位置 ((SwitchElm)temp).convert(); //转换开关状态 } else if (temp.type == CirSim.TYPES.SlidingResistanceElm || temp.type == CirSim.TYPES.AmmeterElm) { setUICamera(temp, UICamera); //设置UI摄像机位置 } gameObjGesture = hit.collider.gameObject; //获取触摸物体引用 CirSim.analyzeCircuit(); //分析电路 } else if (Input.touches[0].phase == TouchPhase.Moved) { if (gameObjGesture == null) { return; } CircuitElm elm = gameObjGesture.transform.GetComponent <CircuitElm>(); //获取元器件脚本 if (elm.type == CirSim.TYPES.SlidingResistanceElm) //若为滑动变阻器 { ((SlidingResistanceElm)(elm)).slideSwitch(Input.touches[0].deltaPosition); //滑动滑块 CirSim.analyzeCircuit(); //分析电路 } } else if (Input.touches[0].phase == TouchPhase.Ended) { gameObjGesture = null; //手持物体引用置null } } return; } if (gameObj != null) // 如果触控物体不为空 { if (!gameObj.tag.Equals("plate") && Input.touchCount <= 0) // 如果触控物体不为地板并且此时没有手指触控事件 { return; // 直接返回 } else if (gameObj.tag.Equals("plate") && Input.touchCount <= 0) // 如果触控物体为地板并且此时没有手指触控事件 { RotatePlate(gameObj); // 校正旋转地板 } } // 1个手指触摸屏幕 if (Input.touchCount == 1) { Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position); // 定义从摄像机出发的射线 LayerMask uimask = 1 << LayerMask.NameToLayer("UI"); //定义UI层 LayerMask unitmask = 1 << LayerMask.NameToLayer("unit"); // 获取unit层 LayerMask platemask = 1 << LayerMask.NameToLayer("plate"); // 获取plate层 LayerMask originalmask = 1 << LayerMask.NameToLayer("original"); // 获取放置初始元器件层 if (Input.GetMouseButtonDown(0)) { if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) //触摸在UI上 //Debug.Log("触摸在UI上"); { gameObj = null; return; } } if (Input.touches [0].phase == TouchPhase.Began) // 单指触控 { m_screenpos = Input.touches [0].position; // 记录手指触屏的位置 if (Physics.Raycast(ray, out hit, 100, uimask.value)) //如果触碰到了UI按钮 { gameObj = null; return; } else if (Physics.Raycast(ray, out hit, 100, originalmask.value)) //如果触摸到原始元器件 { isHoldUnit = true; //表示持有元件 GameObject gb = Instantiate(hit.collider.gameObject); gb.GetComponent <CircuitElm> ().originalPos = new Vector3(hit.collider.transform.position.x, 0.0f, hit.collider.transform.position.z); gb.transform.SetParent(hit.collider.gameObject.transform.parent); //初始化一个元器件 gameObj = hit.collider.gameObject; gameObj.tag = "unit"; //unit层 gameObj.layer = 8; //unit层 gameObj.GetComponent <CircuitElm>().convertState(true); //转变为透明 Utils.holdingName = gameObj.name; //获取手持元器件的名字 Vector2 tempPos = Camera.main.WorldToScreenPoint(gameObj.transform.position); // 将元件的世界坐标转换为屏幕坐标 offSet = new Vector2(m_screenpos.x - tempPos.x, m_screenpos.y - tempPos.y); // 触控时考虑偏移 } else if (Physics.Raycast(ray, out hit, 100, unitmask.value)) // 如果触控到元件 { isHoldUnit = true; // 表示持有元件 //若元器件被压在底下,则不能动 CircuitElm tempCE = hit.collider.transform.GetComponent <CircuitElm>(); if (tempCE.interfaceList[0] != null || tempCE.interfaceList[2] != null) { gameObj = null; return; } gameObj = hit.collider.gameObject; // 保存持有元件的对象 gameObj.GetComponent <CircuitElm>().convertState(true); //变为透明显示元器件 CirSim.elmList.Remove(gameObj.GetComponent <CircuitElm>()); //在元器件列表中删除该元器件 Utils.holdingName = gameObj.name; // 获取手持元器件的名字 Vector2 tempPos = Camera.main.WorldToScreenPoint(gameObj.transform.position); // 将元件的世界坐标转换为屏幕坐标 offSet = new Vector2(m_screenpos.x - tempPos.x, m_screenpos.y - tempPos.y); // 触控时考虑偏移 //gameObj.transform.SetParent(null); // 设置父物体为空 } else // 如果没有触控到元件 { Utils.holdingName = "null"; // 手持物体名称 isHoldUnit = false; // 表示未持有元件 gameObj = Utils.plate; // 保存地板对象 } } else if (Input.touches [0].phase == TouchPhase.Moved) // 手指移动 { if (gameObj == null) { return; // 若手持物体为空,则返回 } Touch touch = Input.touches [0]; // 获取touch对象 switch (gameObj.tag) // 区别操作对象的便签 { case "unit": // 元件 gameObj.transform.GetComponent <CircuitElm>().state = 2; //切换元器件的状态 Vector3 unitPosition = gameObj.transform.position; // 获取元件世界坐标 Vector3 screenPosition = Camera.main.WorldToScreenPoint(unitPosition); // 将元件的世界坐标转为屏幕坐标 // 计算时考虑偏移量 Vector3 fingerPosition = new Vector3(touch.position.x - offSet.x, touch.position.y - offSet.y, screenPosition.z); Vector3 worldPosition = Camera.main.ScreenToWorldPoint(fingerPosition); // 获取触屏点世界坐标 gameObj.transform.position = new Vector3(worldPosition.x, gameObj.transform.GetComponent <CircuitElm>().getHeight(), worldPosition.z); // 更新元件世界坐标 break; case "plate": // 底板 Vector2 deltaPos = touch.deltaPosition; // 获取滑屏当前帧改变值 gameObj.transform.Rotate(Vector3.down * deltaPos.x * 0.6f, Space.World); // 根据滑屏距离的水平值旋转底板 break; default: //Debug.Log ("touch error!"); // 打印错误信息 break; } } else if (Input.touches[0].phase == TouchPhase.Ended) { //Utils.holdingName = null;//手持元起价置空 if (gameObj != null && gameObj.tag == "unit") { //恢复为不透明 gameObj.GetComponent <CircuitElm>().convertState(false); gameObj.transform.GetComponent <CircuitElm>().putUnit();//将元器件放到指定位置 } } } else if (Input.touchCount > 1) // 如果是多点触控 // 记录两个手指的位置 { Vector2 finger1 = new Vector2(); Vector2 finger2 = new Vector2(); // 记录两个手指的移动 Vector2 mov1 = new Vector2(); Vector2 mov2 = new Vector2(); for (int i = 0; i < 2; i++) // 遍历触控点 { Touch touch = Input.touches [i]; // 获取touch对象 if (touch.phase == TouchPhase.Ended) // 如果有一只手指松开 { break; // 直接跳出循环 } if (touch.phase == TouchPhase.Moved) // 如果行为是移动 { float mov = 0; // 定义记录移动距离的变量 if (i == 0) // 如果是第一支手指 { finger1 = touch.position; // 记录触屏位置 mov1 = touch.deltaPosition; // 记录移动距离 } else // 如果是第二支手指 { finger2 = touch.position; // 记录触屏位置 mov2 = touch.deltaPosition; // 记录移动距离 // Debug.Log (" asd " + Vector2.Angle (mov1, mov2)); // 双指运动方向相同 if (Vector2.Angle(mov1, mov2) <= 90 && (mov1.magnitude > 0.8f || mov2.magnitude > 0.8f)) { if (Vector2.Angle(mov1, new Vector2(1, 0)) < 10) // 滑动方向向量如果和x正轴向量夹角小于10度 // 水平向右旋转 { transform.RotateAround(Utils.plate.transform.position, new Vector3(0, -1, 0), RotateHSpeed * Time.deltaTime); } else if (Vector2.Angle(mov1, new Vector2(-1, 0)) < 10) // 滑动方向向量如果和x负轴向量夹角小于10度 // 水平向左旋转 { transform.RotateAround(Utils.plate.transform.position, new Vector3(0, 1, 0), RotateHSpeed * Time.deltaTime); } else if (Vector2.Angle(mov1, new Vector2(0, 1)) < 10) // 滑动方向向量如果和y负轴向量夹角小于10度 //垂直向上旋转 { transform.FindChild("Main Camera").Rotate(-RotateVSpeed * Time.deltaTime, 0, 0); } else if (Vector2.Angle(mov1, new Vector2(0, -1)) < 10) // 滑动方向向量如果和y负轴向量夹角小于10度 // 垂直向下旋转 { transform.FindChild("Main Camera").Rotate(RotateVSpeed * Time.deltaTime, 0, 0); } } else // 缩放 { if (finger1.x > finger2.x) // 如果第一根手指的x坐标大于第二根 { mov = mov1.x; // 总的移动距离为第一根手指的x方向移动距离 } else // 如果第二根手指的x坐标大于第一根 { mov = mov2.x; // 总的移动距离为第二根手指的x方向移动距离 } if (finger1.y > finger2.y) // 如果第一根手指的y坐标大于第二根 { mov += mov1.y; // 总的移动距离为第一根手指的y方向移动距离 } else // 如果第二根手指的y坐标大于第一根 { mov += mov2.y; // 总的移动距离为第二根手指的y方向移动距离 } transform.Translate(0, -mov * Time.deltaTime, 0); // 移动摄像机父物体的y坐标 if (transform.position.y <= MaxZoomRatio) // 如果y坐标小于等于最大放大率 { transform.position = new Vector3(transform.position.x, MaxZoomRatio, transform.position.z); } else if (transform.position.y >= MinZoomRatio) // 如果y坐标大于等于最小放大率 { transform.position = new Vector3(transform.position.x, MinZoomRatio, transform.position.z); } //Debug.Log (transform.position + "asd" + transform.FindChild("Main Camera").transform.position); } } } } } }
//标记元器件 public override void stamp() { CirSim.stampResistor(nodes[0], nodes[2], maxResistance * ratio); CirSim.stampResistor(nodes[1], nodes[2], maxResistance * (1 - ratio)); }
//标记元器件 public override void stamp() { CirSim.stampVoltageSource(nodes[0], nodes[1], voltSource[0], 0); //标记元器件 }
//标记元器件 public override void stamp() { CirSim.stampVoltageSource(nodes[0], nodes[1], voltSource[0], getVoltage()); }