protected void OnSetVelocities(bool isRandom, double speed) { if (this.SetVelocities == null) { return; } SetVelocitiesArgs args = new SetVelocitiesArgs(); args.Asteroids = chkVelocityAsteroid.IsChecked.Value; args.Minerals = chkVelocityMineral.IsChecked.Value; args.IsRandom = isRandom; args.Speed = speed; this.SetVelocities(this, args); }
private void optionsPanel_SetVelocities(object sender, SetVelocitiesArgs e) { _setVelocityArgs = e; _hasSetVelocities = false; }
/// <summary> /// This is raised by _world once per frame (this is raised, then it requests forces for bodies) /// </summary> private void World_Updating(object sender, WorldUpdatingArgs e) { try { if (_hasSetVelocities && _setVelocityArgs != null) { _hasSetVelocities = false; _setVelocityArgs = null; } Vector3D shipPosition = _ship.PositionWorld.ToVector(); _ship.WorldUpdating(e.ElapsedTime); #region Minerals foreach (Mineral mineral in _map.GetMinerals()) { mineral.WorldUpdating(); } #endregion #region Space Stations SpaceStation currentlyOverStation = null; foreach (SpaceStation station in _spaceStations) { station.WorldUpdating(); // See if the ship is over the station Vector3D stationPosition = station.PositionWorld.ToVector(); stationPosition.Z = 0; if ((stationPosition - shipPosition).LengthSquared < station.Radius * station.Radius) { currentlyOverStation = station; } } // Store the station that the ship is over if (currentlyOverStation == null) { statusMessage.Content = ""; } else { statusMessage.Content = "Press space to enter station"; //TODO: Play a sound if this is the first time they entered the station's range } _currentlyOverStation = currentlyOverStation; #endregion // Camera UpdateCameraPosition(); #region Asteroid Gravity //TODO: It's too expensive for every small item to examine every other object each frame, and it's choppy when the calculations are // intermitent (should do threads). Set up a vector field for the minerals and bots to be attracted to // // On second thought, I don't think this will work. It would be more efficient for the map to return objects in range, but that requires // the map to store things different (I think for 2D it's a quad tree, and 3D is an oct tree?) // Only doing asteroids - the ship does gravity calculation against the asteroids in it's apply force event if (_hasGravity) { _asteroidGravityForces.Clear(); if (StaticRandom.NextDouble() < .05d) // I don't want to do this every frame { // Init my forces list for (int cntr = 0; cntr < _asteroids.Count; cntr++) { _asteroidGravityForces.Add(_asteroids[cntr].PhysicsBody, new Vector3D()); } // Apply Gravity for (int outerCntr = 0; outerCntr < _asteroids.Count - 1; outerCntr++) { Point3D centerMass1 = _asteroids[outerCntr].PositionWorld; for (int innerCntr = outerCntr + 1; innerCntr < _asteroids.Count; innerCntr++) { #region Apply Gravity Point3D centerMass2 = _asteroids[innerCntr].PositionWorld; Vector3D gravityLink = centerMass1 - centerMass2; double force = GRAVITATIONALCONSTANT * (_asteroids[outerCntr].Mass * _asteroids[innerCntr].Mass) / gravityLink.LengthSquared; gravityLink.Normalize(); gravityLink *= force; _asteroidGravityForces[_asteroids[innerCntr].PhysicsBody] += gravityLink; _asteroidGravityForces[_asteroids[outerCntr].PhysicsBody] -= gravityLink; #endregion } } // I also need to attract to the ship, because it's attracted to the asteroids // I can't because the ship is attracted every frame, so the forces are unbalanced Point3D shipPos = _ship.PositionWorld; double shipMass = _ship.PhysicsBody.Mass; for (int cntr = 0; cntr < _asteroids.Count; cntr++) { #region Apply Gravity Vector3D gravityLink = shipPos - _asteroids[cntr].PositionWorld; double force = GRAVITATIONALCONSTANT * (_asteroids[cntr].Mass * shipMass) / gravityLink.LengthSquared; gravityLink.Normalize(); gravityLink *= force; _asteroidGravityForces[_asteroids[cntr].PhysicsBody] -= gravityLink; #endregion } } } #endregion _map.WorldUpdating(); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }