private static void DownloadTiles(String OutDirectory, IndexRect r) { Directory.CreateDirectory(OutDirectory); var c = new WebClient(); Console.WriteLine("Идёт загрузка:"); for (int x = r.Left; x <= r.Right; x++) { for (int y = r.Top; y <= r.Bottom; y++) { String from = String.Format("http://c.tile.openstreetmap.org/13/{0}/{1}.png", x, y); String to = Path.Combine(OutDirectory, String.Format("{0}-{1}.png", x, y)); int AttemptsCount = 3; while (AttemptsCount > 0) { try { c.DownloadFile(from, to); Console.Write('.'); break; } catch (WebException wexc) { AttemptsCount--; if (AttemptsCount < 0) throw new Exception(String.Format("Не удалось загрузить тайл [{0} {1}]", x, y), wexc); } } } Console.WriteLine(); } }
// @todo stoppedに入った点が持っていたエネルギーを外側に逃がす public void AddCircleMovement(Vector3 fromLocal, Vector3 toLocal, float strength, float radius, int objectMask) { Vector2 p1 = new Vector2(toLocal.x, toLocal.z); Vector2 p0 = new Vector2(fromLocal.x, fromLocal.z); Vector2 v = p1 - p0; float d = v.magnitude; if (d < 1e-6) { return; } // 移動先の円内のオフセット総計 float totalOffset = 0f; IndexRect rect1 = localRectToIndex(p1.x, p1.y, p1.x, p1.y, radius); for (int i = rect1.i0; i <= rect1.i1; i++) { int k = rect1.j0 + i * countX; for (int j = rect1.j0; j <= rect1.j1; j++, k++) { Vector3 p3 = particlesData[k].position; Vector2 p = new Vector2(p3.x, p3.z); float lFrom1 = (p - p1).magnitude; if (lFrom1 < radius) { totalOffset += particlesData[k].force; particlesData[k].position.Set(p3.x, 0f, p3.z); particlesData[k].velocity = 0f; particlesData[k].force = 0f; particlesData[k].stopped |= objectMask; } } } // float strengthInner = strength; float minDistance = new Vector2(sizeX / divisionX, sizeZ / divisionZ).magnitude *minDistanceCoef; if (d < minDistance) { strengthInner *= d / minDistance; d = minDistance; v = v.normalized * d; p0 = p1 - v; } Vector2 vForward = v.normalized / d; Vector2 vSide = (new Vector2(-v.y, v.x)).normalized / radius; totalOffset /= strengthInner; // 押し出された水の量を計算 float piR_d = Mathf.PI * radius + d; float s = piR_d * piR_d + 2f * Mathf.PI * (2 * radius * d + totalOffset); s = (Mathf.Sqrt(s) - piR_d) / Mathf.PI; float strengthOuter = strength; if (s < minDistance) { strengthOuter *= s / minDistance; s = minDistance; } float radiusOuter = radius + s; Vector2 vSideOuter = vSide.normalized / radiusOuter; // float z0 = Mathf.Min(p0.y, p1.y); float z1 = Mathf.Max(p0.y, p1.y); float x0 = Mathf.Min(p0.x, p1.x); float x1 = Mathf.Max(p0.x, p1.x); IndexRect rect = localRectToIndex(x0, z0, x1, z1, radiusOuter); for (int i = rect.i0; i <= rect.i1; i++) { int k = rect.j0 + i * countX; for (int j = rect.j0; j <= rect.j1; j++, k++) { Vector3 p3 = particlesData[k].position; Vector2 p = new Vector2(p3.x, p3.z); Vector2 pFrom0 = p - p0; Vector2 pFrom1 = p - p1; float lFrom0 = pFrom0.magnitude; float lFrom1 = pFrom1.magnitude; if (lFrom1 < radius) { continue; } // 移動先の円外 int stopped = particlesData[k].stopped &= ~objectMask; if (stopped != 0) { continue; } float forward = Vector2.Dot(pFrom0, vForward); float side = Mathf.Abs(Vector2.Dot(pFrom0, vSide)); bool forwardIn = 0 < forward && forward < 1; if (lFrom0 < radius || forwardIn && side < 1) { // 移動元の円より内側 or 軌跡の内側 particlesData[k].force -= strengthInner; } else { float sideOuter = Mathf.Abs(Vector2.Dot(pFrom0, vSideOuter)); if (lFrom1 < radius + s || forwardIn && sideOuter < forward) { // 移動先から押し出し半径の内側 or 軌跡の側面 particlesData[k].force += strengthOuter; } } } } }