FreeTrainの進化系を目指す
マウスポインタ位置の地形ポリゴンを検出、バグ修正済み
| @@ -128,11 +128,15 @@ | ||
| 128 | 128 | } |
| 129 | 129 | |
| 130 | 130 | static public bool IsInnerPoint2D(Point[] triangle_vertex, Point testpos) { |
| 131 | + double c,c2=0.0; | |
| 131 | 132 | for (int i=0; i<3; i++) { |
| 132 | 133 | Point p = triangle_vertex[i]; |
| 133 | 134 | Point v1 = SubVector(testpos, p); |
| 134 | 135 | Point v2 = SubVector(p, triangle_vertex[(i + 2) % 3]); |
| 135 | - if (GetOuterProduct2D(v1, v2) < 0) return false; | |
| 136 | + c = GetOuterProduct2D(v1, v2); | |
| 137 | + if (c == 0) return true; // On the line | |
| 138 | + if (c2 != 0 && c2 * c < 0) return false; // Out of triangle | |
| 139 | + c2 = c; | |
| 136 | 140 | } |
| 137 | 141 | return true; |
| 138 | 142 | } |
| @@ -34,7 +34,7 @@ | ||
| 34 | 34 | |
| 35 | 35 | public SceneBuilder(GameImpl g) { |
| 36 | 36 | this.game = g; |
| 37 | - SetViewFactor(new ViewFactor(InterCardinalDirection.NORTHEAST, ZoomScale.x2)); | |
| 37 | + SetViewFactor(new ViewFactor(InterCardinalDirection.NORTHEAST)); | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | public SceneBuilder(GameImpl g, ISurface s) : this(g){ |
| @@ -274,8 +274,8 @@ | ||
| 274 | 274 | } |
| 275 | 275 | |
| 276 | 276 | protected Point WorldPosToGrid(PointF3D p3d) { |
| 277 | - int isx = (int)Math.Floor(p3d.X / Geocon.UnitWidthPixel); | |
| 278 | - int isy = (int)Math.Floor(p3d.Y / Geocon.UnitWidthPixel); | |
| 277 | + int isx = (int)Math.Round(p3d.X / Geocon.UnitWidthPixel); | |
| 278 | + int isy = (int)Math.Round(p3d.Y / Geocon.UnitWidthPixel); | |
| 279 | 279 | int d = (int)Math.Ceiling(p3d.Z / Geocon.HalfOf_UnitWidthPixel); |
| 280 | 280 | return new Point(isx - d, isy - d); |
| 281 | 281 | } |
| @@ -283,6 +283,7 @@ | ||
| 283 | 283 | public object GetObjectAt(Point spos) { |
| 284 | 284 | ITerrainPolygon pol; |
| 285 | 285 | PointF3D p3dv; |
| 286 | + marker0 = null; | |
| 286 | 287 | if (DrawIndexUtil.ResolveTerrain(this, spos, out pol, out p3dv)) { |
| 287 | 288 | |
| 288 | 289 | return pol; |
| @@ -290,14 +291,14 @@ | ||
| 290 | 291 | return null; |
| 291 | 292 | } |
| 292 | 293 | |
| 293 | - public object GetObjectAt_old(Point spos) { | |
| 294 | + public object GetGroundAt(Point spos) { | |
| 294 | 295 | PointF3D p3d = surface.ToWorldPosition(spos); |
| 295 | 296 | #if DEBUG |
| 296 | 297 | Debug.Write("mouse(" + spos.X + "," + spos.Y + ")"); |
| 297 | 298 | //Debug.Write("world(" + (int)p3d.X + "," + (int)p3d.Y + "," + (int)p3d.Z + ")"); |
| 298 | 299 | #endif |
| 299 | - int isx = (int)Math.Floor(p3d.X / Geocon.UnitWidthPixel); | |
| 300 | - int isy = (int)Math.Floor(p3d.Y / Geocon.UnitWidthPixel); | |
| 300 | + int isx = (int)Math.Round(p3d.X / Geocon.UnitWidthPixel); | |
| 301 | + int isy = (int)Math.Round(p3d.Y / Geocon.UnitWidthPixel); | |
| 301 | 302 | object ret = null; |
| 302 | 303 | TerrainMapImpl map = game.TerrainMap; |
| 303 | 304 | // 標高の高い地表セルは画面上方に表示される。 |
| @@ -323,15 +324,15 @@ | ||
| 323 | 324 | #endif |
| 324 | 325 | marker0 = null; |
| 325 | 326 | while(true){ |
| 326 | - //Debug.Write("(" + l1.X + "," + l1.Y + ")"); | |
| 327 | 327 | if (l2.X >= 0 && l2.Y >= 0 && l2.X < sz.sx && l2.Y < sz.sy) { |
| 328 | + //Debug.Write("l2(" + l2.X + "," + l2.Y + ")"); | |
| 328 | 329 | HitTest(l2, spos, out ret); |
| 329 | 330 | if (ret != null) break; |
| 330 | 331 | } |
| 331 | 332 | if (l1.X >= 0 && l1.Y >= 0 && l1.X < sz.sx && l1.Y < sz.sy) { |
| 332 | - if (HitTest(l1, spos, out ret)) { | |
| 333 | - break; | |
| 334 | - } | |
| 333 | + //Debug.Write("l1(" + l1.X + "," + l1.Y + ")"); | |
| 334 | + HitTest(l1, spos, out ret); | |
| 335 | + if (ret != null) break; | |
| 335 | 336 | } |
| 336 | 337 | if (isx < l1.X) { |
| 337 | 338 | //Debug.Write("exit3"); |
| @@ -379,22 +380,21 @@ | ||
| 379 | 380 | Point rep = surface.ToScreenPosition(p3d); |
| 380 | 381 | //Debug.Write(":rep(" + rep.X + "," + rep.Y + ")"); |
| 381 | 382 | // ビューのY座標は上に行くほど小さくなることに注意 |
| 382 | - //Debug.Write(":h="+h); | |
| 383 | 383 | if (rep.Y < vw_p.Y) { // 指定ポイントより上=絶対ヒットしない |
| 384 | 384 | //Debug.Write("HitTest at=" + iso_p); |
| 385 | 385 | //Debug.WriteLine(":e1=" + (rep.Y - vw_p.Y)); |
| 386 | 386 | return true; |
| 387 | 387 | } |
| 388 | - int xoff = rep.X - vw_p.X; | |
| 388 | + int xoff = vw_p.X - rep.X; | |
| 389 | 389 | int yoff = 0; |
| 390 | 390 | //Debug.WriteLine("HitTest at=" + iso_p); |
| 391 | 391 | bool cliff = false; |
| 392 | - //rep.Y -= (Geocon.TerrainMaxHeightInPixel + Geocon.HalfOf_UnitWidthPixel); | |
| 393 | - foreach (ITerrainPiece p in map[iso_p.X, iso_p.Y, upperDir]) { | |
| 392 | + //rep.Y += (Geocon.TerrainMaxHeightInPixel + Geocon.HalfOf_UnitWidthPixel); | |
| 393 | + Location l = cdUtil.IsometricGridToLocation(iso_p.X, iso_p.Y, 0); | |
| 394 | + foreach (ITerrainPiece p in map[l.X, l.Y, upperDir]) { | |
| 394 | 395 | int h1 = p.BaseHeight * Geocon.UnitHeightPixel; |
| 395 | 396 | yoff = vw_p.Y - rep.Y + h1; |
| 396 | 397 | //Debug.Write(",off(" + xoff + "," + yoff + ")"); |
| 397 | - //Debug.Write(",h1="+h1); | |
| 398 | 398 | if (yoff > 0 ) { |
| 399 | 399 | cliff = true; //おそらく手前の崖を差している |
| 400 | 400 | continue; |
| @@ -404,10 +404,20 @@ | ||
| 404 | 404 | TerrainPieceTemplate.TerrainPolygonSet tpset = p.Template.GetPolygons(upperDir); |
| 405 | 405 | if (tpset.Ground.IsVisible) { |
| 406 | 406 | //Debug.Write("!"); |
| 407 | - if (TerrainUtil.IsInnerPoint2D(tpset.Ground.GetVerticis(scaler), new Point(xoff,yoff))) { | |
| 407 | + Debug.Write("["+iso_p.X+","+iso_p.Y+"]+(" + xoff + "," + yoff + ")"); | |
| 408 | + if (TerrainUtil.IsInnerPoint2D(tpset.Ground.GetVerticis(scaler), new Point(xoff, yoff))) { | |
| 409 | +#if false //DEBUG | |
| 410 | + Debug.Write("%"); | |
| 411 | + foreach (Point bp in tpset.Ground.GetVerticis(scaler)) { | |
| 412 | + Debug.Write("<"+bp.X+","+bp.Y+">"); | |
| 413 | + } | |
| 414 | + Debug.Write("%"); | |
| 415 | +#endif | |
| 408 | 416 | ret = tpset.Ground; |
| 417 | + //Debug.Write("vw.Y=" + vw_p.Y + ", rp.Y=" + rep.Y + ", h1=" + h1); | |
| 409 | 418 | //Debug.WriteLine(""); |
| 410 | - marker0 = new TerrainMarker(iso_p, tpset, true); | |
| 419 | + //marker0 = new TerrainMarker(iso_p, tpset, true); | |
| 420 | + CreateMarker(iso_p.X, iso_p.Y, TrMk_Ground); | |
| 411 | 421 | return true; |
| 412 | 422 | } |
| 413 | 423 | } |
| @@ -59,53 +59,57 @@ | ||
| 59 | 59 | if (AdjustPointForGround(ref p3dv, idx)) { |
| 60 | 60 | int gx = (int)Math.Round(p3dv.X / Geocon.UnitWidthPixel); |
| 61 | 61 | int gy = (int)Math.Round(p3dv.Y / Geocon.UnitWidthPixel); |
| 62 | - Debug.Write("->(" + p3dv.X + "," + p3dv.Y + ") : grid[" + gx + "," + gy + "]"); | |
| 63 | - foreach (ITerrainPiece p in map[gx, gy, sb.upperDir]) { | |
| 62 | + Debug.Write(":Ground->(" + p3dv.X + "," + p3dv.Y + ") : grid[" + gx + "," + gy + "]"); | |
| 63 | + Location l = sb.cdUtil.IsometricGridToLocation(gx, gy, 0); | |
| 64 | + foreach (ITerrainPiece p in map[l.X, l.Y, sb.upperDir]) { | |
| 64 | 65 | TerrainPieceTemplate.TerrainPolygonSet tpset = p.Template.GetPolygons(sb.upperDir); |
| 65 | 66 | if (tpset.Ground.IsVisible) { |
| 66 | - Point rep = sb.surface.ToScreenPosition(p3dv); | |
| 67 | + PointF3D p3d = new PointF3D(gx * Geocon.UnitWidthPixel, gy * Geocon.UnitWidthPixel, 0); | |
| 68 | + Point rep = sb.surface.ToScreenPosition(p3d); | |
| 67 | 69 | int xoff = mousePos.X - rep.X; |
| 68 | 70 | int yoff = mousePos.Y - rep.Y; |
| 71 | + int h1 = p.BaseHeight * Geocon.UnitHeightPixel; | |
| 72 | + yoff += h1; | |
| 69 | 73 | //Debug.Write("!"); |
| 70 | 74 | if (TerrainUtil.IsInnerPoint2D(tpset.Ground.GetVerticis(sb.scaler), new Point(xoff, yoff))) { |
| 75 | + Debug.WriteLine("+(" + xoff + "," + yoff + ")"); | |
| 71 | 76 | pol = tpset.Ground; |
| 72 | - Debug.WriteLine(": Ground hit 1 off(" + xoff + ", yoff=" + yoff + ")"); | |
| 77 | + sb.CreateMarker(gx, gy, SceneBuilder.TrMk_Ground); | |
| 73 | 78 | break; |
| 74 | - } else if (pol == null) { | |
| 75 | - Debug.WriteLine(": Ground hit 2 off(" + xoff + ", yoff=" + yoff + ")"); | |
| 76 | - pol = tpset.Ground; | |
| 79 | + //} else if (pol == null) { | |
| 80 | + // pol = tpset.Ground; | |
| 77 | 81 | } |
| 78 | 82 | } |
| 79 | - sb.CreateMarker(gx, gy, SceneBuilder.TrMk_Ground); | |
| 80 | 83 | } |
| 81 | - Debug.WriteLineIf(pol == null, "WTF!?"); | |
| 84 | + //Debug.WriteLineIf(pol == null, "WTF!?"); | |
| 82 | 85 | return pol != null; |
| 83 | 86 | } else if (AdjustPointForCliff(ref p3dv, idx)) { |
| 84 | 87 | int gx = (int)Math.Round(p3dv.X / Geocon.UnitWidthPixel); |
| 85 | 88 | int gy = (int)Math.Round(p3dv.Y / Geocon.UnitWidthPixel); |
| 86 | - Debug.Write("->(" + p3dv.X + "," + p3dv.Y + ") : grid[" + gx + "," + gy + "]"); | |
| 87 | - foreach (ITerrainPiece p in map[gx, gy, sb.upperDir]) { | |
| 89 | + Debug.Write(":Cliff->(" + p3dv.X + "," + p3dv.Y + ") : grid[" + gx + "," + gy + "]"); | |
| 90 | + Location l = sb.cdUtil.IsometricGridToLocation(gx, gy, 0); | |
| 91 | + foreach (ITerrainPiece p in map[l.X, l.Y, sb.upperDir]) { | |
| 88 | 92 | //if (p.BaseHeight < p3dv.Z) continue; |
| 89 | 93 | TerrainPieceTemplate.TerrainPolygonSet tpset = p.Template.GetPolygons(sb.upperDir); |
| 90 | 94 | UInt32 testval = (idx & Mask_CliffPolygon_D); |
| 91 | 95 | if (testval == Mask_CliffPolygon_D) { |
| 92 | - Debug.WriteLine(": Cliff(Diagonal)"); | |
| 96 | + Debug.WriteLine(":Diagonal"); | |
| 93 | 97 | pol = tpset.CliffDiagonal; |
| 94 | 98 | sb.CreateMarker(gx, gy, SceneBuilder.TrMk_CliffDiag); |
| 95 | 99 | } else if (testval == Mask_CliffPolygon_R) { |
| 96 | - Debug.WriteLine(": Cliff(Right)"); | |
| 100 | + Debug.WriteLine(":Right"); | |
| 97 | 101 | pol = tpset.CliffRight; |
| 98 | 102 | sb.CreateMarker(gx, gy, SceneBuilder.TrMk_CliffRight); |
| 99 | 103 | } else { |
| 100 | - Debug.WriteLine(": Cliff(Left)"); | |
| 104 | + Debug.WriteLine(":Left"); | |
| 101 | 105 | pol = tpset.CliffLeft; |
| 102 | 106 | sb.CreateMarker(gx, gy, SceneBuilder.TrMk_CliffLeft); |
| 103 | 107 | } |
| 104 | 108 | } |
| 105 | - Debug.WriteLineIf(pol == null, "WTF2!?"); | |
| 109 | + //Debug.WriteLineIf(pol == null, "WTF2!?"); | |
| 106 | 110 | return pol != null; |
| 107 | 111 | } |
| 108 | - Debug.WriteLine("--"); | |
| 112 | + //Debug.WriteLine("--"); | |
| 109 | 113 | return false; |
| 110 | 114 | } |
| 111 | 115 |
| @@ -26,7 +26,7 @@ | ||
| 26 | 26 | Point minP = new Point(int.MaxValue, int.MaxValue); |
| 27 | 27 | Point maxP = new Point(int.MinValue, int.MinValue); |
| 28 | 28 | for (int i = 0; i < n; i++) { |
| 29 | - int x = locs[i].Y - locs[i].X; | |
| 29 | + int x = locs[i].X - locs[i].Y; | |
| 30 | 30 | int y = -locs[i].Z - (locs[i].X + locs[i].Y) / 2; |
| 31 | 31 | minP.X = Math.Min(minP.X, x); |
| 32 | 32 | maxP.X = Math.Max(maxP.X, x); |