bool VectorIntersectPlane(Vector3 v, Vector3 p, CollisionPlane wall) { //regarder si intersection entre rayon et plane float d = Vector3.Dot(wall.getPlanePoints()[0], wall.getPlaneNormal()); Vector3 n = wall.getPlaneNormal(); //resoudre system equation entre droite du vector et plane de la face float alpha = (d - Vector3.Dot(n, p)) / Vector3.Dot(n, v); //regarder si intersection est dans vecteur if (alpha > 1 || alpha <= 0) { return(false); } //regarder si intersection est dans polygon Vector3 planeIntersection = p + v * alpha; planeIntersection = wall.transform.InverseTransformPoint(planeIntersection); if (VerifyIfWithinPolygon(wall.getPlanePointsLocal(), planeIntersection)) { Debug.Log("COLLISION at point:" + p); CalculateRebound(n); return(true); } return(false); }
internal void SetWaypoint(CollisionIndex WP, CollisionPlane p) { LastPlane = p; if (this.button1 == null) { InitializeComponent(); } Current = WP; this.Text = WP.ToString();// +" matrix=" + WP.GetMatrix((float)WP.Position.Z); this.button1.Text = WP.ExtraInfoString(LastPlane); int i = 0; foreach (Button B in CurrentButtons) { Controls.Remove(B); } CurrentButtons.Clear(); foreach (IMeshedObject O in WP.GetOccupiedObjects(p.MinZ, p.MaxZ)) { i++; Button B = new Button(); B.Location = new System.Drawing.Point(24, 28 + i * 20); B.Name = "o" + i; B.Size = new System.Drawing.Size(715, 23); B.TabIndex = i; B.Text = O.DebugString(); B.TextAlign = ContentAlignment.MiddleLeft; B.UseVisualStyleBackColor = true; B.Click += new System.EventHandler(this.object_click); this.Controls.Add(B); CurrentButtons.Add(B); } }
public static List <Box3Fill> Simplify(List <Box3Fill> simpl) { try { return(Simplify1(simpl)); } catch (Exception) { return(simpl); } int bc = simpl.Count; int t0 = Environment.TickCount; List <Box3Fill> s0 = Simplify0(new List <Box3Fill>(simpl)); int t1 = Environment.TickCount; List <Box3Fill> s1 = Simplify1(new List <Box3Fill>(simpl)); int t2 = Environment.TickCount; int c0 = s0.Count; int c1 = s1.Count; CollisionPlane.Debug("Simplify {0} S0={1}/{2} S1={3}/{4} ", bc, t1 - t0, c0, t2 - t1, c1); if (c1 < c0) { return(s1); } return(s0); }
internal void OnNewCollisionPlane(CollisionPlane found) { if (CurrentPlane == null) { CurrentPlane = found; } }
public PlanesManager() { ListOfPlanes = new List <CollisionPlane>(); //// Bottom //int offset1 = StaticData.PlaneOffsetBottom; //Vector3 direction1 = new Vector3(0, 1, 0); //direction1.Normalize(); //Rectangle rect1 = new Rectangle(0, // offset1, // StaticData.LevelFarWidth, // 10); //CollisionPlane plane1 = new CollisionPlane(-(offset1), direction1, Material.Wood, // TextureType.DefaultBox, // rect1); //// Right //int offset2 = StaticData.PlaneOffsetRight; //Vector3 direction2 = new Vector3(-1, 0, 0); //direction2.Normalize(); //Rectangle rect2 = new Rectangle(offset2, // 0, // 10, // StaticData.LevelFarWidth); //CollisionPlane plane2 = new CollisionPlane(-offset2, direction2, Material.Steel, // TextureType.DefaultBox, // rect2); ////Left //int offset3 = StaticData.PlaneOffsetLeft; //Vector3 direction3 = new Vector3(1, 0, 0); //direction3.Normalize(); //Rectangle rect3 = new Rectangle(offset3 - 10, // 0, // 10, // StaticData.LevelFarWidth); //CollisionPlane plane3 = new CollisionPlane(-offset3, direction3, Material.Steel, // TextureType.DefaultBox, // rect3); // Up int offset4 = StaticData.PlaneOffsetUp; Vector3 direction4 = new Vector3(0, -1, 0); direction4.Normalize(); Rectangle rect4 = new Rectangle(0, offset4 - 10, StaticData.LevelFarWidth, 10); CollisionPlane plane4 = new CollisionPlane(-offset4, direction4, Material.Steel, TextureType.DefaultBox, rect4); //this.ListOfPlanes.Add(plane1); //this.ListOfPlanes.Add(plane2); //this.ListOfPlanes.Add(plane3); this.ListOfPlanes.Add(plane4); }
public void LineIntersection_GetCollisionPointsReturnsEmptyListWhenThereIsNoCollidingPlanes() { Line line1 = new Line(new PointD(0, 3), new PointD(4, 7)); LineIntersections li = new LineIntersections(line1); CollisionPlane plane1 = new CollisionPlane(new PointD(3, 0), new PointD(3, 4)); CollisionPlane plane2 = new CollisionPlane(new PointD(0, 2), new PointD(4, 2)); List <CollisionPlane> collisionPlanes = new List <CollisionPlane> { plane1, plane2 }; var collisionPoints = li.GetCollisionPoints(collisionPlanes); Assert.AreEqual(0, collisionPoints.Count()); }
public void LineIntersection_GetCollisionPointsReturnsTwoCollisionPointsForTwoPlaneColliding() { Line line1 = new Line(new PointD(0, 0), new PointD(4, 4)); LineIntersections li = new LineIntersections(line1); CollisionPlane plane1 = new CollisionPlane(new PointD(3, 0), new PointD(3, 4)); CollisionPlane plane2 = new CollisionPlane(new PointD(0, 2), new PointD(4, 2)); List <CollisionPlane> collisionPlanes = new List <CollisionPlane> { plane1, plane2 }; var collisionPoints = li.GetCollisionPoints(collisionPlanes); Assert.AreEqual(2, collisionPoints.Count()); }
public void LineIntersections_GetCollisionPointsReturnsIntersectionPointOnCollisionPlaneForLineEndingOnIt() { Line line1 = new Line(new PointD(0, 0), new PointD(200, 200)); LineIntersections li = new LineIntersections(line1); CollisionPlane plane1 = new CollisionPlane(new PointD(200, 0), new PointD(200, 400)); var collisionPoints = li.GetCollisionPoints(new List <CollisionPlane> { plane1 }); Assert.AreEqual(1, collisionPoints.Count()); Assert.AreEqual(200, collisionPoints.First().Point.X, 1e-5); Assert.AreEqual(200, collisionPoints.First().Point.Y, 1e-5); }
public void SetOccupied(CallbackXY p, SimZMinMaxLevel MinMaxZ, float detail) { if (InnerBoxes.Count == 0) { CollisionPlane.Debug("using outerbox for " + this); OuterBox.SetOccupied(p, MinMaxZ, detail); return; } foreach (CollisionObject box in InnerBoxes) { box.SetOccupied(p, MinMaxZ, detail); } }
public void LineIntersection_GetCollisionPointsReturnsOneCollisionForProperCollisionPlane() { Line line1 = new Line(new PointD(0, 0), new PointD(4, 4)); LineIntersections li = new LineIntersections(line1); CollisionPlane plane1 = new CollisionPlane(new PointD(3, 0), new PointD(3, 4)); List <CollisionPlane> collisionPlanes = new List <CollisionPlane> { plane1 }; var collisionPoints = li.GetCollisionPoints(collisionPlanes); Assert.AreEqual(1, collisionPoints.Count()); Assert.AreEqual(3, collisionPoints.First().Point.X, 1e-5); Assert.AreEqual(3, collisionPoints.First().Point.Y, 1e-5); }
public void LineIntersection_GetClosestCollisionPointsReturnsTwoCollisionPointsForTwoPlanesIntersectingInThePointOfCollision() { Line line1 = new Line(new PointD(0, 0), new PointD(4, 4)); LineIntersections li = new LineIntersections(line1); CollisionPlane plane1 = new CollisionPlane(new PointD(3, 0), new PointD(3, 4)); CollisionPlane plane2 = new CollisionPlane(new PointD(0, 3), new PointD(4, 3)); List <CollisionPlane> collisionPlanes = new List <CollisionPlane> { plane1, plane2 }; var collisionPoints = li.GetClosestCollisionPoints(collisionPlanes); Assert.AreEqual(2, collisionPoints.Count()); Assert.IsNotNull(collisionPoints.FirstOrDefault(cp => cp.HittableObject == plane1)); Assert.IsNotNull(collisionPoints.FirstOrDefault(cp => cp.HittableObject == plane2)); }
public void LineIntersection_GetClosestCollisionPointsReturnsOneCollisionPointsForTwoPlanesWithDifferentPointsOfCollision() { Line line1 = new Line(new PointD(0, 0), new PointD(4, 4)); LineIntersections li = new LineIntersections(line1); CollisionPlane plane1 = new CollisionPlane(new PointD(3, 0), new PointD(3, 4)); CollisionPlane plane2 = new CollisionPlane(new PointD(0, 2), new PointD(4, 2)); List <CollisionPlane> collisionPlanes = new List <CollisionPlane> { plane1, plane2 }; var collisionPoints = li.GetClosestCollisionPoints(collisionPlanes); Assert.AreEqual(1, collisionPoints.Count()); Assert.AreEqual(plane2, collisionPoints.First().HittableObject); Assert.AreEqual(2, collisionPoints.First().Point.X); Assert.AreEqual(2, collisionPoints.First().Point.Y); }
bool Intersect(CollisionPlane wall) { float d = Vector3.Dot(wall.getPlanePoints()[0], wall.getPlaneNormal()); Vector3 n = wall.getPlaneNormal(); float distance = Mathf.Abs(Vector3.Dot(n, center) + d); if (Mathf.Abs(Vector3.Dot(n, center) + d) <= radius) { Vector3 intersectPoint = center + distance * n / n.magnitude; intersectPoint = wall.transform.InverseTransformPoint(intersectPoint); if (VerifyIfWithinPolygon(wall.getPlanePointsLocal(), intersectPoint)) { Debug.Log("COLLISION AT POINT: " + wall.transform.TransformPoint(intersectPoint)); CalculateRebound(n); return(true); } } return(false); }
public bool IsInside(float x, float y, float z) { // Offset position if (OuterBox.IsInside(x, y, z)) // Is possible? { if (InnerBoxes.Count == 0) { CollisionPlane.Debug("using outerbox for " + this); return(true); } foreach (CollisionObject box in InnerBoxes) { if (box.IsInside(x, y, z)) { return(true); } } } return(false); }
private void object_click(object sender, EventArgs e) { IList <CollisionObject> occs = (IList <CollisionObject>)Current.GetOccupiedObjects(LastPlane.MinZ, LastPlane.MaxZ); try { if (sender is Button) { Button B = (Button)sender; string name = B.Name.Substring(1); int i = int.Parse(name) - 1; CollisionObject O = occs[i]; if (O is IMeshedObject) { ((IMeshedObject)O).RemeshObject(); } } } catch (Exception ex) { CollisionPlane.Debug(ex); } }
private void SetCurrentPlane(CollisionPlane value) { if (InvokeRequired) { this.Invoke(new SetCurrentPlaneDelegate(SetCurrentPlane), new object[] { value }); return; } if (value != null && _CurrentPlane != value) { _CurrentPlane = value; if (_CurrentPlane != null) { PathStore = _CurrentPlane.PathStore; PathFinderDemo pfd = PathStore.PanelGUI; if (pfd != null) { pfd.SetPlane(_CurrentPlane); pfd.Text = String.Format("{0} {1}", PathStore.RegionName, _CurrentPlane); } _Matrix = _CurrentPlane.ByteMatrix; } Invalidate(); } }
internal void SetWaypoint(CollisionIndex WP,CollisionPlane p) { LastPlane = p; if (this.button1 == null) { InitializeComponent(); } Current = WP; this.Text = WP.ToString();// +" matrix=" + WP.GetMatrix((float)WP.Position.Z); this.button1.Text = WP.ExtraInfoString(LastPlane); int i = 0; foreach (Button B in CurrentButtons) { Controls.Remove(B); } CurrentButtons.Clear(); foreach (IMeshedObject O in WP.GetOccupiedObjects(p.MinZ, p.MaxZ)) { i++; Button B = new Button(); B.Location = new System.Drawing.Point(24, 28+i*20); B.Name = "o"+i; B.Size = new System.Drawing.Size(715, 23); B.TabIndex = i; B.Text = O.DebugString(); B.TextAlign = ContentAlignment.MiddleLeft; B.UseVisualStyleBackColor = true; B.Click += new System.EventHandler(this.object_click); this.Controls.Add(B); CurrentButtons.Add(B); } }
/// <summary> /// Berechnet die Geschwindigkeit einer <see cref="Entity"/> nach der Kollision mit der Welt. (Original Lassi) /// </summary> /// <param name="gameTime">Simulation time</param> /// <param name="position">Position der <see cref="Entity"/></param> /// <param name="cache"><see cref="ILocalChunkCache"/> as workspace</param> /// <param name="radius">Radius der <see cref="Entity"/></param> /// <param name="height">Höhe der <see cref="Entity"/></param> /// <param name="deltaPosition">Positionsänderung zwischen zwei Simulationsdurchläufen</param> /// <param name="velocity">Berechnete Geschwindigkeit</param> /// <exception cref="ArgumentNullException">Cache</exception> /// <returns>Geschwindigkeit der <see cref="Entity"/> nach der Killisionsprüfung</returns> public Vector3 WorldCollision(GameTime gameTime, Coordinate position, ILocalChunkCache cache, float radius, float height, Vector3 deltaPosition, Vector3 velocity) { if (cache == null) { throw new ArgumentNullException(nameof(cache)); } Vector3 move = deltaPosition; //Blocks finden die eine Kollision verursachen könnten int minx = (int)Math.Floor(Math.Min( position.BlockPosition.X - radius, position.BlockPosition.X - radius + deltaPosition.X)); int maxx = (int)Math.Ceiling(Math.Max( position.BlockPosition.X + radius, position.BlockPosition.X + radius + deltaPosition.X)); int miny = (int)Math.Floor(Math.Min( position.BlockPosition.Y - radius, position.BlockPosition.Y - radius + deltaPosition.Y)); int maxy = (int)Math.Ceiling(Math.Max( position.BlockPosition.Y + radius, position.BlockPosition.Y + radius + deltaPosition.Y)); int minz = (int)Math.Floor(Math.Min( position.BlockPosition.Z, position.BlockPosition.Z + deltaPosition.Z)); int maxz = (int)Math.Ceiling(Math.Max( position.BlockPosition.Z + height, position.BlockPosition.Z + height + deltaPosition.Z)); //Beteiligte Flächen des Spielers var playerplanes = CollisionPlane.GetEntityCollisionPlanes(radius, height, velocity, position); for (int z = minz; z <= maxz; z++) { for (int y = miny; y <= maxy; y++) { for (int x = minx; x <= maxx; x++) { move = velocity * (float)gameTime.ElapsedGameTime.TotalSeconds; Index3 pos = new Index3(x, y, z); Index3 blockPos = pos + position.GlobalBlockIndex; ushort block = cache.GetBlock(blockPos); if (block == 0) { continue; } var blockplanes = CollisionPlane.GetBlockCollisionPlanes(pos, velocity); foreach (var playerPlane in playerplanes) { foreach (var blockPlane in blockplanes) { if (!CollisionPlane.Intersect(blockPlane, playerPlane)) { continue; } var distance = CollisionPlane.GetDistance(blockPlane, playerPlane); if (!CollisionPlane.CheckDistance(distance, move)) { continue; } var subvelocity = (distance / (float)gameTime.ElapsedGameTime.TotalSeconds); var diff = velocity - subvelocity; float vx; float vy; float vz; if (blockPlane.normal.X != 0 && (velocity.X > 0 && diff.X >= 0 && subvelocity.X >= 0 || velocity.X < 0 && diff.X <= 0 && subvelocity.X <= 0)) { vx = subvelocity.X; } else { vx = velocity.X; } if (blockPlane.normal.Y != 0 && (velocity.Y > 0 && diff.Y >= 0 && subvelocity.Y >= 0 || velocity.Y < 0 && diff.Y <= 0 && subvelocity.Y <= 0)) { vy = subvelocity.Y; } else { vy = velocity.Y; } if (blockPlane.normal.Z != 0 && (velocity.Z > 0 && diff.Z >= 0 && subvelocity.Z >= 0 || velocity.Z < 0 && diff.Z <= 0 && subvelocity.Z <= 0)) { vz = subvelocity.Z; } else { vz = velocity.Z; } velocity = new Vector3(vx, vy, vz); if (vx == 0 && vy == 0 && vz == 0) { return(velocity); } } } } } } return(velocity); }
public void AddPlane(CollisionPlane plane) { ListOfPlanes.Add(plane); }
protected override void UpdatePropPanels() { _updating = true; if (pnlPlaneProps.Visible) { if (_selectedPlanes.Count <= 0) { pnlPlaneProps.Visible = false; return; } CollisionPlane p = _selectedPlanes[0]; //Material cboMaterial.SelectedItem = cboMaterial.Items[p._material]; //Type chkTypeFloor.Checked = p.IsFloor; chkTypeCeiling.Checked = p.IsCeiling; chkTypeLeftWall.Checked = p.IsLeftWall; chkTypeRightWall.Checked = p.IsRightWall; //Flags chkFallThrough.Checked = p.IsFallThrough; chkLeftLedge.Checked = p.IsLeftLedge; chkRightLedge.Checked = p.IsRightLedge; chkNoWalljump.Checked = p.IsNoWalljump; chkTypeCharacters.Checked = p.IsCharacters; chkTypeItems.Checked = p.IsItems; chkTypePokemonTrainer.Checked = p.IsPokemonTrainer; chkTypeRotating.Checked = p.IsRotating; //UnknownFlags chkFlagUnknown1.Checked = p.IsUnknownSSE; chkFlagUnknown2.Checked = p.IsUnknownFlag1; chkFlagSuperSoft.Checked = p.IsSuperSoft; chkFlagUnknown4.Checked = p.IsUnknownFlag4; } else if (pnlPointProps.Visible) { if (_selectedLinks.Count <= 0) { pnlPointProps.Visible = false; return; } numX.Value = _selectedLinks[0].Value._x; numY.Value = _selectedLinks[0].Value._y; } else if (pnlObjProps.Visible) { if (_selectedObject == null) { pnlObjProps.Visible = false; return; } txtModel.Text = _selectedObject._modelName; txtBone.Text = _selectedObject._boneName; chkObjUnk.Checked = _selectedObject.UnknownFlag; chkObjModule.Checked = _selectedObject.ModuleControlled; chkObjSSEUnk.Checked = _selectedObject.UnknownSSEFlag; } _updating = false; }
private void CheckBoxCollision(GameTime gameTime, Entity entity, MoveableComponent movecomp, PositionComponent poscomp) { if (!entity.Components.ContainsComponent <BodyComponent>()) { return; } BodyComponent bc = entity.Components.GetComponent <BodyComponent>(); Coordinate position = poscomp.Position; Vector3 move = movecomp.PositionMove; //Blocks finden die eine Kollision verursachen könnten int minx = (int)Math.Floor(Math.Min( position.BlockPosition.X - bc.Radius, position.BlockPosition.X - bc.Radius + movecomp.PositionMove.X)); int maxx = (int)Math.Ceiling(Math.Max( position.BlockPosition.X + bc.Radius, position.BlockPosition.X + bc.Radius + movecomp.PositionMove.X)); int miny = (int)Math.Floor(Math.Min( position.BlockPosition.Y - bc.Radius, position.BlockPosition.Y - bc.Radius + movecomp.PositionMove.Y)); int maxy = (int)Math.Ceiling(Math.Max( position.BlockPosition.Y + bc.Radius, position.BlockPosition.Y + bc.Radius + movecomp.PositionMove.Y)); int minz = (int)Math.Floor(Math.Min( position.BlockPosition.Z, position.BlockPosition.Z + movecomp.PositionMove.Z)); int maxz = (int)Math.Ceiling(Math.Max( position.BlockPosition.Z + bc.Height, position.BlockPosition.Z + bc.Height + movecomp.PositionMove.Z)); //Beteiligte Flächen des Spielers var playerplanes = CollisionPlane.GetEntityCollisionPlanes(bc.Radius, bc.Height, movecomp.Velocity, poscomp.Position); bool abort = false; var cache = entity.Components.GetComponent <LocalChunkCacheComponent>().LocalChunkCache; for (int z = minz; z <= maxz && !abort; z++) { for (int y = miny; y <= maxy && !abort; y++) { for (int x = minx; x <= maxx && !abort; x++) { move = movecomp.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds; Index3 pos = new Index3(x, y, z); Index3 blockPos = pos + position.GlobalBlockIndex; ushort block = cache.GetBlock(blockPos); if (block == 0) { continue; } var blockplane = CollisionPlane.GetBlockCollisionPlanes(pos, movecomp.Velocity).ToList(); var planes = from pp in playerplanes from bp in blockplane where CollisionPlane.Intersect(bp, pp) let distance = CollisionPlane.GetDistance(bp, pp) where CollisionPlane.CheckDistance(distance, move) select new { BlockPlane = bp, PlayerPlane = pp, Distance = distance }; foreach (var plane in planes) { var subvelocity = (plane.Distance / (float)gameTime.ElapsedGameTime.TotalSeconds); var diff = movecomp.Velocity - subvelocity; float vx; float vy; float vz; if (plane.BlockPlane.normal.X != 0 && (movecomp.Velocity.X > 0 && diff.X >= 0 && subvelocity.X >= 0 || movecomp.Velocity.X < 0 && diff.X <= 0 && subvelocity.X <= 0)) { vx = subvelocity.X; } else { vx = movecomp.Velocity.X; } if (plane.BlockPlane.normal.Y != 0 && (movecomp.Velocity.Y > 0 && diff.Y >= 0 && subvelocity.Y >= 0 || movecomp.Velocity.Y < 0 && diff.Y <= 0 && subvelocity.Y <= 0)) { vy = subvelocity.Y; } else { vy = movecomp.Velocity.Y; } if (plane.BlockPlane.normal.Z != 0 && (movecomp.Velocity.Z > 0 && diff.Z >= 0 && subvelocity.Z >= 0 || movecomp.Velocity.Z < 0 && diff.Z <= 0 && subvelocity.Z <= 0)) { vz = subvelocity.Z; } else { vz = movecomp.Velocity.Z; } movecomp.Velocity = new Vector3(vx, vy, vz); if (vx == 0 && vy == 0 && vz == 0) { abort = true; break; } } } } } // TODO: Was ist für den Fall Gravitation = 0 oder im Scheitelpunkt des Sprungs? //movecomp.OnGround = Player.Velocity.Z == 0f; movecomp.PositionMove = movecomp.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds; }
public virtual bool UpdateOccupied(SimPathStore pathStore) { if (pathStore == null) { CollisionPlane.Debug("Cant UpdatePathOccupied for {0}", this);// + " pos " + RootObject.DistanceVectorString(RootObject)); return(false); } if (!UpdateMeshPaths) { return(false); } if (MeshOnlySolids && !IsSolid) { return(false); } if (InnerBoxes == null) { return(false); } if (InnerBoxes.Count == 0) { return(false); } if (!IsRegionAttached()) { return(false); } // int t1; try { //lock (PathStore) { if (PathStore == pathStore) { return(false); } PathStore = pathStore;//.Add(pathStore); if (tryFastVersion) { // UpdatePathOccupiedFast(PathStore); // int tc = Environment.TickCount; UpdatePathOccupiedVeryFast(pathStore); // t1 = Environment.TickCount - tc; InnerBoxes = null; PathStore.AddedCount++; // CollisionPlane.Debug("t1 vs t2 = " + t1 ); return(true); } } ForceUpdatePathOccupied(pathStore); return(true); } catch (Exception e) { // lock (PathStore) { PathStore = null;//.Remove(pathStore); } return(false); }; }
/// <summary> /// Aktualisiert den Spieler (Bewegung, Interaktion) /// </summary> /// <param name="frameTime">Die aktuelle Zeit.</param> public void Update(GameTime frameTime) { #region Inputverarbeitung // Input verarbeiten Player.Angle += (float)frameTime.ElapsedGameTime.TotalSeconds * Head.X; Player.Tilt += (float)frameTime.ElapsedGameTime.TotalSeconds * Head.Y; Player.Tilt = Math.Min(1.5f, Math.Max(-1.5f, Player.Tilt)); #endregion #region Physik float lookX = (float)Math.Cos(Player.Angle); float lookY = -(float)Math.Sin(Player.Angle); var velocitydirection = new Vector3(lookX, lookY, 0) * Move.Y; float stafeX = (float)Math.Cos(Player.Angle + MathHelper.PiOver2); float stafeY = -(float)Math.Sin(Player.Angle + MathHelper.PiOver2); velocitydirection += new Vector3(stafeX, stafeY, 0) * Move.X; Player.Velocity += PhysicalUpdate(velocitydirection, frameTime.ElapsedGameTime, !Player.FlyMode, Player.FlyMode); #endregion #region Playerbewegung /Kollision Vector3 move = Player.Velocity * (float)frameTime.ElapsedGameTime.TotalSeconds; Player.OnGround = false; //Blocks finden die eine Kollision verursachen könnten int minx = (int)Math.Floor(Math.Min( Player.Position.BlockPosition.X - Player.Radius, Player.Position.BlockPosition.X - Player.Radius + move.X)); int maxx = (int)Math.Ceiling(Math.Max( Player.Position.BlockPosition.X + Player.Radius, Player.Position.BlockPosition.X + Player.Radius + move.X)); int miny = (int)Math.Floor(Math.Min( Player.Position.BlockPosition.Y - Player.Radius, Player.Position.BlockPosition.Y - Player.Radius + move.Y)); int maxy = (int)Math.Ceiling(Math.Max( Player.Position.BlockPosition.Y + Player.Radius, Player.Position.BlockPosition.Y + Player.Radius + move.Y)); int minz = (int)Math.Floor(Math.Min( Player.Position.BlockPosition.Z, Player.Position.BlockPosition.Z + move.Z)); int maxz = (int)Math.Ceiling(Math.Max( Player.Position.BlockPosition.Z + Player.Height, Player.Position.BlockPosition.Z + Player.Height + move.Z)); //Beteiligte Flächen des Spielers var playerplanes = CollisionPlane.GetPlayerCollisionPlanes(Player).ToList(); bool abort = false; for (int z = minz; z <= maxz && !abort; z++) { for (int y = miny; y <= maxy && !abort; y++) { for (int x = minx; x <= maxx && !abort; x++) { move = Player.Velocity * (float)frameTime.ElapsedGameTime.TotalSeconds; Index3 pos = new Index3(x, y, z); Index3 blockPos = pos + Player.Position.GlobalBlockIndex; ushort block = localChunkCache.GetBlock(blockPos); if (block == 0) { continue; } var blockplane = CollisionPlane.GetBlockCollisionPlanes(pos, Player.Velocity).ToList(); var planes = from pp in playerplanes from bp in blockplane where CollisionPlane.Intersect(bp, pp) let distance = CollisionPlane.GetDistance(bp, pp) where CollisionPlane.CheckDistance(distance, move) select new { BlockPlane = bp, PlayerPlane = pp, Distance = distance }; foreach (var plane in planes) { var subvelocity = (plane.Distance / (float)frameTime.ElapsedGameTime.TotalSeconds); var diff = Player.Velocity - subvelocity; float vx; float vy; float vz; if (plane.BlockPlane.normal.X != 0 && (Player.Velocity.X > 0 && diff.X >= 0 && subvelocity.X >= 0 || Player.Velocity.X < 0 && diff.X <= 0 && subvelocity.X <= 0)) { vx = subvelocity.X; } else { vx = Player.Velocity.X; } if (plane.BlockPlane.normal.Y != 0 && (Player.Velocity.Y > 0 && diff.Y >= 0 && subvelocity.Y >= 0 || Player.Velocity.Y < 0 && diff.Y <= 0 && subvelocity.Y <= 0)) { vy = subvelocity.Y; } else { vy = Player.Velocity.Y; } if (plane.BlockPlane.normal.Z != 0 && (Player.Velocity.Z > 0 && diff.Z >= 0 && subvelocity.Z >= 0 || Player.Velocity.Z < 0 && diff.Z <= 0 && subvelocity.Z <= 0)) { vz = subvelocity.Z; } else { vz = Player.Velocity.Z; } Player.Velocity = new Vector3(vx, vy, vz); if (vx == 0 && vy == 0 && vz == 0) { abort = true; break; } } } } } // TODO: Was ist für den Fall Gravitation = 0 oder im Scheitelpunkt des Sprungs? Player.OnGround = Player.Velocity.Z == 0f; Coordinate position = Player.Position + Player.Velocity * (float)frameTime.ElapsedGameTime.TotalSeconds; position.NormalizeChunkIndexXY(planet.Size); Player.Position = position; //Beam me up KeyboardState ks = Keyboard.GetState(); if (ks.IsKeyDown(Keys.P)) { Player.Position += new Vector3(0, 0, 10); } if (Player.Position.ChunkIndex != _oldIndex) { _oldIndex = Player.Position.ChunkIndex; ReadyState = false; localChunkCache.SetCenter(planet, new Index2(Player.Position.ChunkIndex), (success) => { ReadyState = success; }); } #endregion #region Block Interaction if (lastInteract.HasValue) { ushort lastBlock = localChunkCache.GetBlock(lastInteract.Value); localChunkCache.SetBlock(lastInteract.Value, 0); if (lastBlock != 0) { var blockDefinition = DefinitionManager.Instance.GetBlockDefinitionByIndex(lastBlock); var slot = Player.Inventory.FirstOrDefault(s => s.Definition == blockDefinition); // Wenn noch kein Slot da ist oder der vorhandene voll, dann neuen Slot if (slot == null) { slot = new InventorySlot() { Definition = blockDefinition, Amount = 0 }; Player.Inventory.Add(slot); for (int i = 0; i < Player.Tools.Length; i++) { if (Player.Tools[i] == null) { Player.Tools[i] = slot; break; } } } slot.Amount += 125; } lastInteract = null; } if (lastApply.HasValue) { if (ActiveTool != null) { Index3 add = new Index3(); switch (lastOrientation) { case OrientationFlags.SideWest: add = new Index3(-1, 0, 0); break; case OrientationFlags.SideEast: add = new Index3(1, 0, 0); break; case OrientationFlags.SideSouth: add = new Index3(0, -1, 0); break; case OrientationFlags.SideNorth: add = new Index3(0, 1, 0); break; case OrientationFlags.SideBottom: add = new Index3(0, 0, -1); break; case OrientationFlags.SideTop: add = new Index3(0, 0, 1); break; } if (ActiveTool.Definition is IBlockDefinition) { IBlockDefinition definition = ActiveTool.Definition as IBlockDefinition; Index3 idx = lastApply.Value + add; var boxes = definition.GetCollisionBoxes(localChunkCache, idx.X, idx.Y, idx.Z); float gap = 0.01f; var playerBox = new BoundingBox( new Vector3( Player.Position.GlobalBlockIndex.X + Player.Position.BlockPosition.X - Player.Radius + gap, Player.Position.GlobalBlockIndex.Y + Player.Position.BlockPosition.Y - Player.Radius + gap, Player.Position.GlobalBlockIndex.Z + Player.Position.BlockPosition.Z + gap), new Vector3( Player.Position.GlobalBlockIndex.X + Player.Position.BlockPosition.X + Player.Radius - gap, Player.Position.GlobalBlockIndex.Y + Player.Position.BlockPosition.Y + Player.Radius - gap, Player.Position.GlobalBlockIndex.Z + Player.Position.BlockPosition.Z + Player.Height - gap) ); // Nicht in sich selbst reinbauen bool intersects = false; foreach (var box in boxes) { var newBox = new BoundingBox(idx + box.Min, idx + box.Max); if (newBox.Min.X < playerBox.Max.X && newBox.Max.X > playerBox.Min.X && newBox.Min.Y < playerBox.Max.Y && newBox.Max.X > playerBox.Min.Y && newBox.Min.Z < playerBox.Max.Z && newBox.Max.X > playerBox.Min.Z) { intersects = true; } } if (!intersects) { localChunkCache.SetBlock(idx, DefinitionManager.Instance.GetBlockDefinitionIndex(definition)); ActiveTool.Amount -= 125; if (ActiveTool.Amount <= 0) { Player.Inventory.Remove(ActiveTool); for (int i = 0; i < Player.Tools.Length; i++) { if (Player.Tools[i] == ActiveTool) { Player.Tools[i] = null; } } ActiveTool = null; } } } // TODO: Fix Interaction ;) //ushort block = _manager.GetBlock(lastApply.Value); //IBlockDefinition blockDefinition = BlockDefinitionManager.GetForType(block); //IItemDefinition itemDefinition = ActiveTool.Definition; //blockDefinition.Hit(blockDefinition, itemDefinition.GetProperties(null)); //itemDefinition.Hit(null, blockDefinition.GetProperties(block)); } lastApply = null; } #endregion }