public void Initialize(World world, PhysicsControl physics) { _physics = physics; var particles = new List<Vector2>(); var velocities = new List<Vector2>(); Particles = new Vector2[ParticleCount]; Velocities = new Vector2[ParticleCount]; _velocityBuffer = new Vector2[ParticleCount]; const float initGridSize = 0.4f; for (var x = 0.0f; x < _width; x += initGridSize) for (var y = 0.0f; y < _height; y += initGridSize) { if (!world.StaticGeometry.IsWaterSpawn(x, y)) continue; particles.Add(new Vector2(x, y)); velocities.Add(new Vector2(0,0)); _grid[(int)(particles.Last().X * GridMultiplier), (int)(particles.Last().Y * GridMultiplier)].Add(particles.Count-1); } Particles = particles.ToArray(); Velocities = velocities.ToArray(); _velocityBuffer = Velocities.ToArray(); ParticleCount = particles.Count; _w = new float[ParticleCount, ParticleCount]; }
public Session(Ballz _game, World.World world, MatchSettings settings) { World = world; Terrain = World.StaticGeometry; GameSettings = settings; Physics = new Physics.PhysicsControl(_game); Physics.Enabled = false; _game.Components.Add(Physics); GameRenderer = new Renderer.GameRenderer(_game); GameRenderer.Enabled = false; GameRenderer.Visible = false; _game.Components.Add(GameRenderer); DebugRenderer = new Renderer.DebugRenderer(_game); DebugRenderer.Enabled = false; DebugRenderer.Visible = false; _game.Components.Add(DebugRenderer); SessionLogic = new Logic.GameLogic(_game, this); SessionLogic.Enabled = false; _game.Components.Add(SessionLogic); Logic = _game.Services.GetService <LogicControl>(); Logic.Message += Physics.HandleMessage; Logic.Message += GameRenderer.HandleMessage; Logic.Message += SessionLogic.HandleMessage; Logic.Message += DebugRenderer.HandleMessage; Input = _game.Services.GetService <Input.InputTranslator>(); Game = _game; }
public void DrawWaterDebug(World.World world) { if (NOWATER || world.Water?.ParticleCount == 0) return; var blending = new BlendState(); blending.AlphaSourceBlend = Blend.SourceAlpha; blending.AlphaDestinationBlend = Blend.InverseSourceAlpha; blending.ColorSourceBlend = Blend.SourceAlpha; blending.ColorDestinationBlend = Blend.InverseSourceAlpha; var water = world.Water; var particles = water.Particles; VertexPositionColor[] lines = new VertexPositionColor[particles.Length * 6]; for(int i = 0; i < particles.Length; i++) { var bottom = particles[i] + new Vector2(0, -DebugParticleSize); var right = particles[i] + new Vector2(-DebugParticleSize, DebugParticleSize); var left = particles[i] + new Vector2(DebugParticleSize, DebugParticleSize); lines[i * 6 + 0].Position = new Vector3(bottom, 0f); lines[i * 6 + 1].Position = new Vector3(right, 0f); lines[i * 6 + 2].Position = new Vector3(right, 0f); lines[i * 6 + 3].Position = new Vector3(left, 0f); lines[i * 6 + 4].Position = new Vector3(left, 0f); lines[i * 6 + 5].Position = new Vector3(bottom, 0f); lines[i * 6 + 0].Color = Color.White; lines[i * 6 + 1].Color = Color.White; lines[i * 6 + 2].Color = Color.White; lines[i * 6 + 3].Color = Color.White; lines[i * 6 + 4].Color = Color.White; lines[i * 6 + 5].Color = Color.White; } Game.GraphicsDevice.RasterizerState = new RasterizerState { CullMode = CullMode.None }; Game.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, lines, 0, particles.Length * 3); }
public void DrawWater(World.World world) { if (NOWATER) return; var waterDomainScreenPos = WorldToScreen(Vector2.Zero); WaterEffect.Parameters["WaterTexture"].SetValue(WaterRenderTarget); WaterEffect.Techniques[0].Passes[0].Apply(); var oldRasterizerState = Game.GraphicsDevice.RasterizerState; Game.GraphicsDevice.RasterizerState = new RasterizerState { CullMode = CullMode.None, }; var oldDepthState = Game.GraphicsDevice.DepthStencilState; Game.GraphicsDevice.DepthStencilState = new DepthStencilState { DepthBufferEnable = false, DepthBufferWriteEnable = false }; Game.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, FullscreenQuad, 0, 2); Game.GraphicsDevice.DepthStencilState = oldDepthState; Game.GraphicsDevice.RasterizerState = oldRasterizerState; }
public void PrepareDrawWater(World.World world) { if (NOWATER) return; var blending = BlendState.Additive; var water = world.Water; var particles = water.Particles; Game.GraphicsDevice.SetRenderTarget(WaterRenderTarget); Game.GraphicsDevice.Clear(Color.Transparent); spriteBatch.Begin(SpriteSortMode.Deferred, blending); for (int i = 0; i < particles.Length; i++) { var pos = WorldToScreen(particles[i]); spriteBatch.Draw(MetaBallTexture, position: pos, origin: new Vector2(MetaBallRadius, MetaBallRadius)); } spriteBatch.End(); Game.GraphicsDevice.SetRenderTarget(null); }
public void Step(World worldState, float elapsedSeconds) { if (GameSession.Renderer.WaterRenderer.NOWATER) return; if (++seldomCtr < 2) return; //Collision(elapsedSeconds); Viscosity(elapsedSeconds); Avoidance(elapsedSeconds); for (var i = 0; i < ParticleCount; ++i) { Velocities[i].Y += -9.81f*elapsedSeconds; } WorldCollision(elapsedSeconds); for (var i = 0; i < ParticleCount; ++i) { Particles[i] = Particles[i] + Velocities[i]*elapsedSeconds; var x = Math.Max(0, Math.Min(Particles[i].X,_width-1)); var y = Math.Max(0, Math.Min(Particles[i].Y,_height-1)); if (x != Particles[i].X) Velocities[i].X = -Velocities[i].X*0.5f; if (y != Particles[i].Y) Velocities[i].Y = -Velocities[i].Y*0.5f; Particles[i].X = x; Particles[i].Y = y; } for (var x = 0; x < _width*GridMultiplier; ++x) for (var y = 0; y < _height * GridMultiplier; ++y) _grid[x,y].Clear(); for (var i = 0; i < ParticleCount; ++i) _grid[(int)(Particles[i].X * GridMultiplier), (int)(Particles[i].Y * GridMultiplier)].Add(i); }
public void Update(float elapsedSeconds, World.World worldState) { if (!IsAlive) { Ball.IsAiming = false; } else { if (KeyPressed[InputMessage.MessageType.ControlsLeft]) { Ball.Velocity = new Vector2(-2f, Ball.Velocity.Y); Ball.AimDirection = new Vector2(-Math.Abs(Ball.AimDirection.X), Ball.AimDirection.Y); } if (KeyPressed[InputMessage.MessageType.ControlsRight]) { Ball.Velocity = new Vector2(2f, Ball.Velocity.Y); Ball.AimDirection = new Vector2(Math.Abs(Ball.AimDirection.X), Ball.AimDirection.Y); } // Up/Down keys rotate the aim vector if (KeyPressed[InputMessage.MessageType.ControlsUp]) { var v = Ball.AimDirection; // Rotate at 60°/s. Use sign of v.x to determine the direction, so that the up key always moves the crosshair upwards. var radians = (v.X > 0 ? 1 : -1) * elapsedSeconds * 2 * (float)Math.PI * 60f / 360f; Ball.AimDirection = v.Rotate(radians); } if (KeyPressed[InputMessage.MessageType.ControlsDown]) { var v = Ball.AimDirection; // Rotate at 60°/s. Use sign of v.x to determine the direction, so that the up key always moves the crosshair upwards. var radians = (v.X > 0 ? -1 : 1) * elapsedSeconds * 2 * (float)Math.PI * 60f / 360f; Ball.AimDirection = v.Rotate(radians); } if(KeyPressed[InputMessage.MessageType.ControlsAction]) { Ball.ShootCharge += elapsedSeconds * 0.7f; if (Ball.ShootCharge > 1f) Ball.ShootCharge = 1f; } else if(Ball.ShootCharge > 0 ) { Game.Services.GetService<SoundControl>().playSound(SoundControl.shotSound); worldState.Entities.Add(new Shot { ExplosionRadius = 1.0f, HealthImpactAtDirectHit = 25, IsInstantShot = false, Position = Ball.Position + Ball.AimDirection * (Ball.Radius + 0.2f), Velocity = Ball.AimDirection * Ball.ShootCharge * 30f, }); Ball.ShootCharge = 0f; } // Handle single-shot input events switch (controlInput) { case InputMessage.MessageType.ControlsJump: Ball.Velocity = new Vector2(Ball.Velocity.X, 5f); break; default: break; } } controlInput = null; }
public override bool Update(float elapsedSeconds, World.World worldState) { bool ballMadeAction = base.Update(elapsedSeconds, worldState); if(Ball.IsAlive) { Vector2 upDir = Vector2.Normalize(Ball.Position - worldState.StaticGeometry.gravityPoint); Vector2 leftDir = new Vector2(-upDir.Y, upDir.X); if (KeyPressed[InputMessage.MessageType.ControlsLeft]) { var speed = WalkingTime < SlowWalkTime ? WalkingSpeedSlow : WalkingSpeedNormal; Ball.Velocity = new Vector2(Min(-speed, Ball.Velocity.X), Ball.Velocity.Y); WalkingTime += elapsedSeconds; } else if (KeyPressed[InputMessage.MessageType.ControlsRight]) { var speed = WalkingTime < SlowWalkTime ? WalkingSpeedSlow : WalkingSpeedNormal; Ball.Velocity = new Vector2(Max(speed, Ball.Velocity.X), Ball.Velocity.Y); WalkingTime += elapsedSeconds; } else { WalkingTime = 0; } if (Ball.Velocity.X > 0.01 && Ball.ViewRotation < 0.99) Ball.ViewRotation += ViewRotationSpeed * elapsedSeconds; else if (Ball.Velocity.X < -0.01 && Ball.ViewRotation > -0.99) Ball.ViewRotation -= ViewRotationSpeed * elapsedSeconds; else if (Abs(Ball.Velocity.X) < 0.01 && Abs(Ball.ViewRotation) > 0.01) Ball.ViewRotation -= Math.Sign(Ball.ViewRotation) * ViewRotationSpeed * elapsedSeconds; Ball.ViewRotation = Max(-1, Min(Ball.ViewRotation, 1)); // Up/Down keys rotate the aim vector if (KeyPressed[InputMessage.MessageType.ControlsUp]) { var v = Ball.AimDirection; // Rotate at 60°/s. Use sign of v.x to determine the direction, so that the up key always moves the crosshair upwards. var radians = (v.X > 0 ? 1 : -1) * elapsedSeconds * 2 * (float)Math.PI * 60f / 360f; Ball.AimDirection = v.Rotate(radians); } if (KeyPressed[InputMessage.MessageType.ControlsDown]) { var v = Ball.AimDirection; // Rotate at 60°/s. Use sign of v.x to determine the direction, so that the up key always moves the crosshair upwards. var radians = (v.X > 0 ? -1 : 1) * elapsedSeconds * 2 * (float)Math.PI * 60f / 360f; Ball.AimDirection = v.Rotate(radians); } if(KeyPressed[InputMessage.MessageType.ControlsLeft]) Ball.AimDirection = new Vector2(-Math.Abs(Ball.AimDirection.X), Ball.AimDirection.Y); else if(KeyPressed[InputMessage.MessageType.ControlsRight]) Ball.AimDirection = new Vector2(Math.Abs(Ball.AimDirection.X), Ball.AimDirection.Y); // Handle single-shot input events ProcessInput(controlInput); } controlInput = null; return ballMadeAction; }
public override bool Update(float elapsedSeconds, World.World worldState) { base.Update(elapsedSeconds, worldState); if (Ball.IsAlive) { _shootCooldown -= elapsedSeconds; if (_shootCooldown <= 0f) { if (_currentTarget == null || _currentTarget.Disposed || _currentTarget.Health <= 0) { _currentTarget = (Ball)worldState.Entities .FirstOrDefault(e => e is Ball && ((Ball)e).Player != Ball.Player && ((Ball)e).Health > 0); _currentTarget = worldState.Entities.Aggregate( (curMin, x) => (x as Ball)?.Player != Ball.Player && (curMin == null || (Ball.Position - x.Position).LengthSquared() < (Ball.Position - curMin.Position).LengthSquared()) ? x : curMin) as Ball; } if (_currentTarget != null) { Ball.IsAiming = false; Ball.IsCharging = false; var curCharge = 0.01f; float o = 0; while (curCharge < 0.5f) { var g = 9.81f; // gravity var v = curCharge * 25f; // velocity var x = _currentTarget.Position.X - Ball.Position.X; // target x var y = _currentTarget.Position.Y - Ball.Position.Y; // target y var s = v * v * v * v - g * (g * (x * x) + 2 * y * (v * v)); //substitution if (s < 0) { curCharge += 0.01f; continue; } o = (float)Math.Atan2(v * v + Math.Sqrt(s), g * x); // launch angle Ball.IsAiming = true; Ball.IsCharging = true; break; } if (!Ball.IsAiming) { Ball.HoldingWeapon = "HandGun"; Ball.AimDirection = Vector2.Normalize(_currentTarget.Position - Ball.Position); var muzzle = SpriteGraphicsEffect.CreateMuzzle( Game.Match.GameTime, Ball.Position + 2f * Ball.AimDirection, Ball.AimDirection.RotationFromDirection() ); Game.Match.World.GraphicsEvents.Add(muzzle); var rayHit = Game.Match.Physics.Raycast(Ball.Position, Ball.Position + Ball.AimDirection * 1000f); if (rayHit.HasHit) { const float explosionRadius = 0.3f; const float damage = 25f; Game.Match.World.StaticGeometry.SubtractCircle(rayHit.Position.X, rayHit.Position.Y, explosionRadius); Ballz.The().Match.World.GraphicsEvents.Add(SpriteGraphicsEffect.CreateExplosion(Ballz.The().Match.GameTime, rayHit.Position, 0, 0.2f)); var theBall = rayHit.Entity as Ball; if (theBall?.Health > 0) theBall.ChangeHealth(-damage); } _shootCooldown = PauseBetweenShots; return true; } Ball.HoldingWeapon = "Bazooka"; Ball.AimDirection = Vector2.UnitX.Rotate(o); if (Ball.ShootCharge > curCharge) { Shot newShot = new Shot { ExplosionRadius = 3.0f, HealthDecreaseFromExplosionImpact = 25, HealthDecreaseFromProjectileHit = 10, ShotType = Shot.ShotType_T.Normal, ExplosionDelay = 0.0f, Recoil = 1.0f, Position = Ball.Position + Ball.AimDirection * (Ball.Radius + 0.101f), Velocity = Ball.AimDirection * curCharge * 25f, }; Game.Match.World.AddEntity(newShot); Ball.PhysicsBody.ApplyForce(-10000 * Ball.ShootCharge * newShot.Recoil * Ball.AimDirection); Ball.ShootCharge = 0f; _shootCooldown = PauseBetweenShots; return true; } } else { Ball.IsAiming = false; } } else { Ball.IsCharging = false; } } return false; }