move to github
This commit is contained in:
197
SpacePew/Models/EntityBase.cs
Normal file
197
SpacePew/Models/EntityBase.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public abstract class EntityBase : IEntity
|
||||
{
|
||||
public const float OneRound = (float)Math.PI * 2;
|
||||
public const float VelocityModifier = .1f;
|
||||
public const float GravityModifier = 100f;
|
||||
|
||||
public Rectangle BoundingRectangle
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Rectangle((int)this.Position.X - (int)this.Origin.X, (int)this.Position.Y - (int)this.Origin.Y, this.Texture.Width, this.Texture.Height);
|
||||
}
|
||||
}
|
||||
|
||||
private Color[] _textureData;
|
||||
public Color[] GetTextureData()
|
||||
{
|
||||
if (_textureData == null)
|
||||
{
|
||||
this._textureData = new Color[this.Texture.Width * this.Texture.Height];
|
||||
this.Texture.GetData(this._textureData);
|
||||
}
|
||||
|
||||
return _textureData;
|
||||
}
|
||||
|
||||
// These should be settings in the start menu GUI later on
|
||||
|
||||
public bool IsCollisionWith(IEntity entity)
|
||||
{
|
||||
// never collide with oneself
|
||||
if (ReferenceEquals(entity, this))
|
||||
return false;
|
||||
|
||||
return entity.Collide(this);
|
||||
}
|
||||
|
||||
public virtual bool Collide(IEntity entity)
|
||||
{
|
||||
Matrix transform = Matrix.CreateTranslation(new Vector3(this.Position - this.Origin, 0.0f));
|
||||
|
||||
Matrix entityTransform =
|
||||
Matrix.CreateTranslation(new Vector3(-entity.Origin, 0.0f)) *
|
||||
Matrix.CreateRotationZ(entity.Angle) *
|
||||
Matrix.CreateTranslation(new Vector3(entity.Position, 0.0f));
|
||||
|
||||
Rectangle entityRectangle = CalculateBoundingRectangle(
|
||||
new Rectangle(0, 0, entity.Texture.Width, entity.Texture.Height),
|
||||
entityTransform);
|
||||
|
||||
if (entityRectangle.Intersects(this.BoundingRectangle))
|
||||
{
|
||||
if (IntersectPixels(transform, this.Texture.Width,
|
||||
this.Texture.Height, this.GetTextureData(),
|
||||
entityTransform, entity.Texture.Width,
|
||||
entity.Texture.Height, entity.GetTextureData()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IntersectPixels(Matrix transformA, int widthA, int heightA, Color[] dataA,
|
||||
Matrix transformB, int widthB, int heightB, Color[] dataB)
|
||||
{
|
||||
Matrix transformAtoB = transformA * Matrix.Invert(transformB);
|
||||
|
||||
Vector2 stepX = Vector2.TransformNormal(Vector2.UnitX, transformAtoB);
|
||||
Vector2 stepY = Vector2.TransformNormal(Vector2.UnitY, transformAtoB);
|
||||
|
||||
Vector2 yPosInB = Vector2.Transform(Vector2.Zero, transformAtoB);
|
||||
|
||||
for (int yA = 0; yA < heightA; yA++)
|
||||
{
|
||||
Vector2 posInB = yPosInB;
|
||||
|
||||
for (int xA = 0; xA < widthA; xA++)
|
||||
{
|
||||
var xB = (int)Math.Round(posInB.X);
|
||||
var yB = (int)Math.Round(posInB.Y);
|
||||
|
||||
if (0 <= xB && xB < widthB &&
|
||||
0 <= yB && yB < heightB)
|
||||
{
|
||||
Color colorA = dataA[xA + yA * widthA];
|
||||
Color colorB = dataB[xB + yB * widthB];
|
||||
|
||||
if (colorA.A != 0 && colorB.A != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
posInB += stepX;
|
||||
}
|
||||
|
||||
yPosInB += stepY;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Rectangle CalculateBoundingRectangle(Rectangle rectangle, Matrix transform)
|
||||
{
|
||||
var leftTop = new Vector2(rectangle.Left, rectangle.Top);
|
||||
var rightTop = new Vector2(rectangle.Right, rectangle.Top);
|
||||
var leftBottom = new Vector2(rectangle.Left, rectangle.Bottom);
|
||||
var rightBottom = new Vector2(rectangle.Right, rectangle.Bottom);
|
||||
|
||||
Vector2.Transform(ref leftTop, ref transform, out leftTop);
|
||||
Vector2.Transform(ref rightTop, ref transform, out rightTop);
|
||||
Vector2.Transform(ref leftBottom, ref transform, out leftBottom);
|
||||
Vector2.Transform(ref rightBottom, ref transform, out rightBottom);
|
||||
|
||||
Vector2 min = Vector2.Min(Vector2.Min(leftTop, rightTop), Vector2.Min(leftBottom, rightBottom));
|
||||
Vector2 max = Vector2.Max(Vector2.Max(leftTop, rightTop), Vector2.Max(leftBottom, rightBottom));
|
||||
|
||||
return new Rectangle((int)min.X, (int)min.Y, (int)(max.X - min.X), (int)(max.Y - min.Y));
|
||||
}
|
||||
|
||||
#region IEntity Members
|
||||
|
||||
public virtual string Owner
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public abstract int Health { get; set; }
|
||||
public abstract string TextureName { get; }
|
||||
|
||||
public virtual void CollideWithLevel(Level level) { }
|
||||
|
||||
public Texture2D Texture { get; set; }
|
||||
public virtual Color Color { get; set; }
|
||||
public Vector2 Position { get; set; }
|
||||
public Vector2 Velocity { get; set; }
|
||||
|
||||
public virtual Vector2 Origin
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Vector2(this.Texture.Width / 2, this.Texture.Height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private float _angle;
|
||||
public float Angle
|
||||
{
|
||||
get
|
||||
{
|
||||
return _angle;
|
||||
}
|
||||
set
|
||||
{
|
||||
_angle = value;
|
||||
|
||||
if (_angle > OneRound)
|
||||
{
|
||||
_angle -= OneRound;
|
||||
}
|
||||
else if (_angle < 0)
|
||||
{
|
||||
_angle += OneRound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Created() { }
|
||||
|
||||
public virtual void ApplyGravity(GameTime time)
|
||||
{
|
||||
float timeSeconds = time.ElapsedGameTime.Milliseconds * .001f;
|
||||
Velocity = new Vector2(
|
||||
Velocity.X,
|
||||
Velocity.Y + (timeSeconds * GravityModifier));
|
||||
}
|
||||
|
||||
public virtual void Update(GameTime time)
|
||||
{
|
||||
ApplyGravity(time);
|
||||
|
||||
float timeSeconds = time.ElapsedGameTime.Milliseconds * .001f;
|
||||
Position += Velocity * timeSeconds;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
28
SpacePew/Models/Explosion.cs
Normal file
28
SpacePew/Models/Explosion.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public class Explosion : EntityBase
|
||||
{
|
||||
public Explosion()
|
||||
{
|
||||
_health = 10;
|
||||
}
|
||||
|
||||
private int _health;
|
||||
public override int Health
|
||||
{
|
||||
get
|
||||
{
|
||||
return _health;
|
||||
}
|
||||
set
|
||||
{
|
||||
_health = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string TextureName
|
||||
{
|
||||
get { return "explosion_small"; }
|
||||
}
|
||||
}
|
||||
}
|
28
SpacePew/Models/IEntity.cs
Normal file
28
SpacePew/Models/IEntity.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public interface IEntity
|
||||
{
|
||||
string TextureName { get; }
|
||||
Texture2D Texture { get; set; }
|
||||
Color[] GetTextureData();
|
||||
Color Color { get; set; }
|
||||
|
||||
string Owner { get; set; }
|
||||
|
||||
int Health { get; set; }
|
||||
|
||||
Vector2 Origin { get; }
|
||||
Vector2 Position { get; set; }
|
||||
Vector2 Velocity { get; set; }
|
||||
float Angle { get; set; }
|
||||
|
||||
bool Collide(IEntity entity);
|
||||
void CollideWithLevel(Level level);
|
||||
void ApplyGravity(GameTime time);
|
||||
void Update(GameTime time);
|
||||
void Created();
|
||||
}
|
||||
}
|
12
SpacePew/Models/IKillable.cs
Normal file
12
SpacePew/Models/IKillable.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public interface IKillable
|
||||
{
|
||||
void Kill();
|
||||
}
|
||||
}
|
301
SpacePew/Models/Level.cs
Normal file
301
SpacePew/Models/Level.cs
Normal file
@@ -0,0 +1,301 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections;
|
||||
using Microsoft.Xna.Framework.Media;
|
||||
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public class Tile
|
||||
{
|
||||
public Point Position { get; set; }
|
||||
public Texture2D Texture { get; set; }
|
||||
public Tile(Texture2D texure, Point position)
|
||||
{
|
||||
Texture = texure;
|
||||
Position = position;
|
||||
}
|
||||
}
|
||||
|
||||
public class TiledTexture : List<Tile>
|
||||
{
|
||||
public int TileWidth { get; set; }
|
||||
public int TileHeight { get; set; }
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
public int XTiles { get; set; }
|
||||
public int YTiles { get; set; }
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public void GetData(Color[] textureData)
|
||||
{
|
||||
var buffer = new Color[TileWidth * TileHeight];
|
||||
for (var j = 0; j < XTiles; j++)
|
||||
{
|
||||
for (var i = 0; i < YTiles; i++)
|
||||
{
|
||||
var tile = this[i * XTiles + j];
|
||||
tile.Texture.GetData(buffer);
|
||||
|
||||
for (var x = 0; x < TileWidth; x++)
|
||||
{
|
||||
for (var y = 0; y < TileHeight; y++)
|
||||
{
|
||||
var xpos = tile.Position.X + x;
|
||||
var ypos = tile.Position.Y + y;
|
||||
textureData[ypos * Width + xpos] = buffer[y * TileWidth + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(Color[] textureData)
|
||||
{
|
||||
var buffer = new Color[TileWidth * TileHeight];
|
||||
for (var j = 0; j < XTiles; j++)
|
||||
{
|
||||
for (var i = 0; i < YTiles; i++)
|
||||
{
|
||||
var tile = this[i * XTiles + j];
|
||||
for (var x = 0; x < TileWidth; x++)
|
||||
{
|
||||
for (var y = 0; y < TileHeight; y++)
|
||||
{
|
||||
var xpos = tile.Position.X + x;
|
||||
var ypos = tile.Position.Y + y;
|
||||
buffer[y * TileWidth + x] = textureData[ypos * Width + xpos];
|
||||
}
|
||||
}
|
||||
|
||||
tile.Texture.SetData(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveAsPng(Stream s, int width, int height)
|
||||
{
|
||||
throw new NotImplementedException("Har inte hunnit med.. borde gå att kopiera nån av Get/Set ovan och skapa upp en bild.");
|
||||
}
|
||||
}
|
||||
|
||||
public class Level
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public byte[] OggVorbisSong { get; set; }
|
||||
public TiledTexture Texture { get; set; }
|
||||
public TiledTexture IndestructibleTexture { get; set; }
|
||||
public TiledTexture DeformedTexture { get; set; }
|
||||
private Color[] _deformedTextureData;
|
||||
|
||||
public Queue<MapHit> Hits { get; set; }
|
||||
|
||||
public bool[] CollisionData
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool[] IndestructibleCollisionData
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private int _width;
|
||||
private int _height;
|
||||
|
||||
public Level(GraphicsDevice device)
|
||||
{
|
||||
}
|
||||
|
||||
public Level()
|
||||
{ }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_width = Texture.Width;
|
||||
_height = Texture.Height;
|
||||
|
||||
Hits = new Queue<MapHit>();
|
||||
|
||||
var textureData = new Color[Texture.Width * Texture.Height];
|
||||
Texture.GetData(textureData);
|
||||
|
||||
var indestructibleTextureData = new Color[IndestructibleTexture.Width * IndestructibleTexture.Height];
|
||||
IndestructibleTexture.GetData(indestructibleTextureData);
|
||||
|
||||
CollisionData = new bool[Texture.Width * Texture.Height];
|
||||
|
||||
_deformedTextureData = new Color[DeformedTexture.Width * DeformedTexture.Height];
|
||||
for (int i = _deformedTextureData.Length - 1; i >= 0; i--)
|
||||
{
|
||||
_deformedTextureData[i] = textureData[i].A > 0 ? textureData[i] : Color.Transparent;
|
||||
}
|
||||
|
||||
DeformedTexture.SetData(_deformedTextureData);
|
||||
|
||||
IndestructibleCollisionData = new bool[IndestructibleTexture.Width * IndestructibleTexture.Height];
|
||||
for (int i = 0; i < indestructibleTextureData.Length; i++)
|
||||
{
|
||||
if (indestructibleTextureData[i].A == 0)
|
||||
{
|
||||
IndestructibleCollisionData[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildLevelFromCollisionData()
|
||||
{
|
||||
for (int i = 0; i < CollisionData.Length; i++)
|
||||
{
|
||||
if (CollisionData[i])
|
||||
{
|
||||
_deformedTextureData[i] = Color.Transparent;
|
||||
}
|
||||
}
|
||||
|
||||
DeformedTexture.SetData(_deformedTextureData);
|
||||
}
|
||||
|
||||
public void BuildCollisionDataFromLevel()
|
||||
{
|
||||
for (int i = 0; i < _deformedTextureData.Length; i++)
|
||||
{
|
||||
if (_deformedTextureData[i] == Color.Transparent)
|
||||
{
|
||||
CollisionData[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of pixels of the entity that collides with the background
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="centerX"></param>
|
||||
/// <param name="centerY"></param>
|
||||
/// <returns></returns>
|
||||
public int Collide(IEntity entity, int centerX, int centerY)
|
||||
{
|
||||
int entityWidth = entity.Texture.Width;
|
||||
int entityHeight = entity.Texture.Height;
|
||||
|
||||
int posX = (int)entity.Position.X - (int)entity.Origin.X + centerX;
|
||||
int posY = (int)entity.Position.Y - (int)entity.Origin.Y + centerY;
|
||||
|
||||
if (posX < 1 || posY < 1 || posX > Texture.Width - entityWidth - 1 || posY > Texture.Height - entityHeight - 1)
|
||||
return 1000000000;
|
||||
|
||||
int hit = 0;
|
||||
|
||||
Color[] data = entity.GetTextureData();
|
||||
|
||||
var player = entity as Player;
|
||||
bool isLandingAngle = player != null && (MathHelper.ToDegrees(player.Angle) >= 345 || MathHelper.ToDegrees(player.Angle) <= 15) && player.Velocity.Y > 0;
|
||||
|
||||
for (int y = 0; y < entityHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < entityWidth; x++)
|
||||
{
|
||||
Color colorInPixel = data[(x - entity.Texture.Bounds.X) + (y - entity.Texture.Bounds.Y) * entity.Texture.Bounds.Width];
|
||||
if(colorInPixel.A != 0)
|
||||
{
|
||||
if (CollisionData[(posX + x) + (posY + y) * _width] == false)
|
||||
{
|
||||
if (isLandingAngle)
|
||||
{
|
||||
if (CollisionData[(posX + x) + (posY + y + 1) * _width] == false &&
|
||||
CollisionData[(posX + x + player.Texture.Width) + (posY + y + 1) * _width] == false)
|
||||
{
|
||||
if (player.Velocity.Y > 200f)
|
||||
{
|
||||
var yVelocity = (int)player.Velocity.Y;
|
||||
SoundManager.Play("Audio/Waves/thump", player.Position);
|
||||
player.Velocity = new Vector2(player.Velocity.X / 3, -player.Velocity.Y / 3);
|
||||
return (yVelocity - 200) / 50;
|
||||
}
|
||||
|
||||
player.Land();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
entity.CollideWithLevel(this);
|
||||
|
||||
CollisionData[(posX + x) + (posY + y) * _width] = true;
|
||||
|
||||
Hits.Enqueue(new MapHit(entity));
|
||||
|
||||
hit++;
|
||||
}
|
||||
else if (IndestructibleCollisionData[(posX + x) + (posY + y) * _width] == false)
|
||||
{
|
||||
if (isLandingAngle)
|
||||
{
|
||||
if (IndestructibleCollisionData[(posX + x) + (posY + y + 1) * _width] == false &&
|
||||
IndestructibleCollisionData[(posX + x + player.Texture.Width) + (posY + y + 1) * _width] == false)
|
||||
{
|
||||
if (player.Velocity.Y > 200f)
|
||||
{
|
||||
var yVelocity = (int)player.Velocity.Y;
|
||||
SoundManager.Play("Audio/Waves/thump", player.Position);
|
||||
player.Velocity = new Vector2(player.Velocity.X / 3, -player.Velocity.Y / 3);
|
||||
return (yVelocity - 200) / 50;
|
||||
}
|
||||
|
||||
player.Land();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
entity.CollideWithLevel(this);
|
||||
|
||||
hit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
return hit / 20;
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
public void StopLevelSong()
|
||||
{
|
||||
_stopMusic = true;
|
||||
}
|
||||
|
||||
private bool _stopMusic;
|
||||
public void PlayLevelSong()
|
||||
{
|
||||
using (var ms = new MemoryStream(this.OggVorbisSong))
|
||||
{
|
||||
using (var vorbis = new NVorbis.NAudioSupport.VorbisWaveReader(ms))
|
||||
{
|
||||
using (var waveOut = new NAudio.Wave.WaveOut())
|
||||
{
|
||||
waveOut.Init(vorbis);
|
||||
waveOut.Play();
|
||||
|
||||
while (!_stopMusic)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
SpacePew/Models/MapHit.cs
Normal file
21
SpacePew/Models/MapHit.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public class MapHit
|
||||
{
|
||||
public Texture2D Texture { get; private set; }
|
||||
public Vector2 Position { get; private set; }
|
||||
public Vector2 Origin { get; private set; }
|
||||
public float Angle { get; private set; }
|
||||
|
||||
public MapHit(IEntity entity)
|
||||
{
|
||||
Texture = entity.Texture;
|
||||
Position = entity.Position;
|
||||
Origin = entity.Origin;
|
||||
Angle = entity.Angle;
|
||||
}
|
||||
}
|
||||
}
|
295
SpacePew/Models/Player.cs
Normal file
295
SpacePew/Models/Player.cs
Normal file
@@ -0,0 +1,295 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using SpacePew.Networking;
|
||||
using SpacePew.Camera;
|
||||
using SpacePew.Models.Projectiles;
|
||||
using SpacePew.Models.Weapons;
|
||||
|
||||
namespace SpacePew.Models
|
||||
{
|
||||
public class Player : EntityBase, IFocusable
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
private SoundEffectInstance _thrustSound;
|
||||
public Player()
|
||||
{
|
||||
_weapon = new Cannon();
|
||||
_projectile = new Bullet();
|
||||
|
||||
_secondaryWeapon = new ClusterLauncher();
|
||||
_secondaryProjectile = new ClusterBomb();
|
||||
|
||||
Health = 100;
|
||||
|
||||
Fuel = 50000;
|
||||
|
||||
_lastCollide = DateTime.Now;
|
||||
|
||||
_thrustSound = SoundManager.GetSoundEffectInstance("Audio/Waves/engine");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly Vector2 _up = new Vector2(0, -1);
|
||||
private Matrix _rotationMatrix;
|
||||
|
||||
private Vector2 _direction;
|
||||
|
||||
private readonly IProjectile _projectile;
|
||||
private readonly IProjectile _secondaryProjectile;
|
||||
|
||||
private IWeapon _secondaryWeapon;
|
||||
public IWeapon SecondaryWeapon
|
||||
{
|
||||
get { return _secondaryWeapon; }
|
||||
set { _secondaryWeapon = value; }
|
||||
}
|
||||
|
||||
private IWeapon _weapon;
|
||||
public IWeapon Weapon
|
||||
{
|
||||
get { return _weapon; }
|
||||
set { _weapon = value; }
|
||||
}
|
||||
|
||||
public bool IsRemotePlayer { get; set; }
|
||||
public bool Landed { get; set; }
|
||||
public double Fuel { get; private set; }
|
||||
|
||||
#region Input handling
|
||||
|
||||
private bool _isThrusting;
|
||||
public void HandleKeyboard(KeyboardState state)
|
||||
{
|
||||
if (!MainGame.IsKeyboardInUse)
|
||||
{
|
||||
if (state.IsKeyDown(Keys.Right))
|
||||
{
|
||||
if (Landed)
|
||||
{
|
||||
Landed = false;
|
||||
}
|
||||
|
||||
this.MoveRight();
|
||||
}
|
||||
|
||||
if (state.IsKeyDown(Keys.Left))
|
||||
{
|
||||
if (Landed)
|
||||
{
|
||||
Landed = false;
|
||||
}
|
||||
|
||||
this.MoveLeft();
|
||||
}
|
||||
|
||||
if (state.IsKeyDown(Keys.Up))
|
||||
{
|
||||
if (Landed)
|
||||
{
|
||||
Landed = false;
|
||||
}
|
||||
|
||||
_isThrusting = true;
|
||||
|
||||
this.Thrust();
|
||||
}
|
||||
else
|
||||
{
|
||||
_isThrusting = false;
|
||||
}
|
||||
|
||||
if (state.IsKeyDown(Keys.Space))
|
||||
{
|
||||
this.Fire();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.Weapon.Heat > 0)
|
||||
{
|
||||
this.Weapon.Heat -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.IsKeyDown(Keys.LeftControl))
|
||||
{
|
||||
this._secondaryWeapon.Fire(this._secondaryProjectile, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this._secondaryWeapon.Heat > 0)
|
||||
{
|
||||
this._secondaryWeapon.Heat -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.IsKeyDown(Keys.R))
|
||||
{
|
||||
this.Health = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Fire()
|
||||
{
|
||||
this._weapon.Fire(_projectile, this);
|
||||
}
|
||||
|
||||
private void MoveRight()
|
||||
{
|
||||
Angle += 0.1f;
|
||||
}
|
||||
|
||||
private void MoveLeft()
|
||||
{
|
||||
Angle -= 0.1f;
|
||||
}
|
||||
|
||||
private void Thrust()
|
||||
{
|
||||
Fuel -= 1;
|
||||
|
||||
_rotationMatrix = Matrix.CreateRotationZ(Angle);
|
||||
_direction = Vector2.Transform(_up, _rotationMatrix);
|
||||
|
||||
Velocity += _direction / VelocityModifier;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEntity Members
|
||||
|
||||
public override string Owner { get; set; }
|
||||
public override sealed int Health { get; set; }
|
||||
|
||||
public override void ApplyGravity(GameTime time)
|
||||
{
|
||||
if (!Landed)
|
||||
{
|
||||
base.ApplyGravity(time);
|
||||
}
|
||||
}
|
||||
|
||||
public override Vector2 Origin
|
||||
{
|
||||
get { return new Vector2(Texture.Width / 2, Texture.Height / 2); }
|
||||
}
|
||||
|
||||
public override string TextureName
|
||||
{
|
||||
get { return "player"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private DateTime _lastCollide;
|
||||
public void CollideWith(IEntity entity)
|
||||
{
|
||||
var projectile = entity as IProjectile;
|
||||
if (projectile != null)
|
||||
{
|
||||
this.Health -= projectile.Damage;
|
||||
return;
|
||||
}
|
||||
var player = entity as Player;
|
||||
if (player != null)
|
||||
{
|
||||
if (_lastCollide <= DateTime.Now.AddMilliseconds(-80))
|
||||
{
|
||||
_lastCollide = DateTime.Now;
|
||||
|
||||
if (Math.Abs(this.Velocity.Length()) > Math.Abs(entity.Velocity.Length()))
|
||||
{
|
||||
entity.Velocity += this.Velocity / 2;
|
||||
this.Velocity /= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Velocity += entity.Velocity / 2;
|
||||
entity.Velocity /= 4;
|
||||
}
|
||||
}
|
||||
|
||||
this.Landed = false;
|
||||
player.Landed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CollideWithLevel(Level level)
|
||||
{
|
||||
Velocity -= (Velocity / 300);
|
||||
}
|
||||
|
||||
public static Player CreatePlayer(Vector2 startPosition)
|
||||
{
|
||||
return CreatePlayer(startPosition, string.Empty);
|
||||
}
|
||||
|
||||
public static Player CreatePlayer(Vector2 startPosition, string name)
|
||||
{
|
||||
return EntityFactory.Instance.CreateEntity<Player>(
|
||||
name,
|
||||
startPosition,
|
||||
new Vector2(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
public void Land()
|
||||
{
|
||||
if (!Landed)
|
||||
{
|
||||
this.Velocity = new Vector2(0, 0);
|
||||
this.Position = new Vector2(this.Position.X, this.Position.Y - 1); // Need to adjust because per pixel collision
|
||||
// sometimes can't catch up with frame rate
|
||||
this.Angle = 0;
|
||||
|
||||
Landed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Kill()
|
||||
{
|
||||
SoundManager.Play("Audio/Waves/explosion", this.Position);
|
||||
this.Position = new Vector2(25, 25);
|
||||
this.Velocity = new Vector2(0, 0);
|
||||
this.Angle = 0;
|
||||
this.Health = 100;
|
||||
this.Landed = false;
|
||||
}
|
||||
|
||||
public override void Update(GameTime time)
|
||||
{
|
||||
if (_isThrusting)
|
||||
{
|
||||
if (_thrustSound.State != SoundState.Playing)
|
||||
{
|
||||
_thrustSound.Play();
|
||||
}
|
||||
|
||||
this.Texture = TextureManager.LoadTexture("player_thrusting");
|
||||
}
|
||||
else
|
||||
{
|
||||
_thrustSound.Pause();
|
||||
this.Texture = TextureManager.LoadTexture("player");
|
||||
}
|
||||
|
||||
base.Update(time);
|
||||
}
|
||||
|
||||
#region IFocusable Members
|
||||
|
||||
Vector2 IFocusable.Position
|
||||
{
|
||||
get { return this.Position; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
18
SpacePew/Models/Projectiles/BouncingBullet.cs
Normal file
18
SpacePew/Models/Projectiles/BouncingBullet.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public sealed class BouncingBullet : Bullet
|
||||
{
|
||||
public BouncingBullet()
|
||||
{
|
||||
Health = 30;
|
||||
}
|
||||
|
||||
public override CollisionType CollisionType
|
||||
{
|
||||
get
|
||||
{
|
||||
return CollisionType.Bounce;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
70
SpacePew/Models/Projectiles/Bullet.cs
Normal file
70
SpacePew/Models/Projectiles/Bullet.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public class Bullet : ProjectileBase
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public Bullet()
|
||||
{
|
||||
this.Color = Color.White;
|
||||
this.Velocity = new Vector2();
|
||||
this.Angle = 0;
|
||||
this.Health = 15;
|
||||
}
|
||||
|
||||
public Bullet(Vector2 position)
|
||||
: this()
|
||||
{
|
||||
this.Position = position;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEntity Members
|
||||
|
||||
public override sealed int Health
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override string TextureName
|
||||
{
|
||||
get { return "bullet"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IProjectile Members
|
||||
|
||||
public override string FireSoundAssetName
|
||||
{
|
||||
get { return "Audio/Waves/bullet_sound"; }
|
||||
}
|
||||
|
||||
public override string HitSoundAssetName
|
||||
{
|
||||
get { return "Audio/Waves/bullet_hit"; }
|
||||
}
|
||||
|
||||
public override int Damage
|
||||
{
|
||||
get { return 5; }
|
||||
}
|
||||
|
||||
public override float Speed
|
||||
{
|
||||
get { return 400f; }
|
||||
}
|
||||
|
||||
public override CollisionType CollisionType
|
||||
{
|
||||
get { return CollisionType.Explode; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
93
SpacePew/Models/Projectiles/ClusterBomb.cs
Normal file
93
SpacePew/Models/Projectiles/ClusterBomb.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using SpacePew.Models.Weapons;
|
||||
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
class ClusterBomb : Bullet, IKillable
|
||||
{
|
||||
private const int FuseTime = 7000; //time in milliseconds before it explodes
|
||||
private double _elapsed = 0;
|
||||
readonly DateTime _startTick;
|
||||
|
||||
public override int Damage
|
||||
{
|
||||
get { return 10; }
|
||||
}
|
||||
|
||||
public override float Speed
|
||||
{
|
||||
get { return 100; }
|
||||
}
|
||||
|
||||
public ClusterBomb()
|
||||
{
|
||||
_startTick = DateTime.Now;
|
||||
}
|
||||
|
||||
public override Color Color
|
||||
{
|
||||
get
|
||||
{
|
||||
var r = (byte)((_elapsed / FuseTime) * 255f);
|
||||
var g = (byte)(128 + Math.Sin(_elapsed / 150f) * 127f);
|
||||
var b = (byte)(255 - g);
|
||||
return new Color(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(Microsoft.Xna.Framework.GameTime time)
|
||||
{
|
||||
_elapsed = (DateTime.Now - _startTick).TotalMilliseconds;
|
||||
|
||||
if (_elapsed >= FuseTime)
|
||||
{
|
||||
this.Health = 0;
|
||||
}
|
||||
|
||||
base.Update(time);
|
||||
}
|
||||
|
||||
private void CreateCluster(float angle, string owner)
|
||||
{
|
||||
var entity = EntityFactory.Instance.CreateEntity<ProjectileBase>(
|
||||
typeof(Bullet),
|
||||
owner,
|
||||
Position,
|
||||
Vector2.Zero,
|
||||
angle);
|
||||
|
||||
Matrix m = Matrix.CreateRotationZ(angle + (float)(WeaponBase.Randomizer.NextDouble() * .2f - .1f));
|
||||
Vector2 velocity = Vector2.Transform(-Vector2.UnitY, m);
|
||||
|
||||
entity.Position += velocity * 10;
|
||||
entity.Velocity = velocity * entity.Speed * (float)(WeaponBase.Randomizer.NextDouble() + 0.5f);
|
||||
|
||||
//TODO.. fix
|
||||
//FiredShots.Enqueue(entity);
|
||||
}
|
||||
|
||||
public override void ApplyGravity(GameTime time)
|
||||
{
|
||||
float timeSeconds = time.ElapsedGameTime.Milliseconds * .001f;
|
||||
Velocity = new Vector2(
|
||||
Velocity.X,
|
||||
Velocity.Y + (timeSeconds * GravityModifier * 0.5f));
|
||||
}
|
||||
|
||||
#region IKillable Members
|
||||
|
||||
public void Kill()
|
||||
{
|
||||
//TODO: make sure the clusters are only created on the client that created the cluster, and then let the server send them to all klients
|
||||
for (float i = 0; i < 45; i += .5f)
|
||||
CreateCluster(i, this.Owner);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
8
SpacePew/Models/Projectiles/CollisionType.cs
Normal file
8
SpacePew/Models/Projectiles/CollisionType.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public enum CollisionType
|
||||
{
|
||||
Explode,
|
||||
Bounce
|
||||
}
|
||||
}
|
91
SpacePew/Models/Projectiles/HomingBullet.cs
Normal file
91
SpacePew/Models/Projectiles/HomingBullet.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public class HomingBullet : Bullet
|
||||
{
|
||||
public HomingBullet()
|
||||
{
|
||||
this.Color = Color.PowderBlue;
|
||||
}
|
||||
|
||||
public override float Speed
|
||||
{
|
||||
get
|
||||
{
|
||||
return 200f;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Damage
|
||||
{
|
||||
get
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
private Player _target;
|
||||
|
||||
const float TimeIncrementSpeed = 5;
|
||||
|
||||
public override void Update(GameTime time)
|
||||
{
|
||||
base.Update(time);
|
||||
|
||||
if (_target == null)
|
||||
{
|
||||
GetTarget();
|
||||
}
|
||||
|
||||
if (_target != null)
|
||||
{
|
||||
var delta = new Vector2(_target.Position.X - this.Position.X, _target.Position.Y - this.Position.Y);
|
||||
|
||||
if (delta.Length() > TimeIncrementSpeed)
|
||||
{
|
||||
delta.Normalize();
|
||||
delta.X *= TimeIncrementSpeed;
|
||||
delta.Y *= TimeIncrementSpeed;
|
||||
}
|
||||
|
||||
this.Position = new Vector2(Position.X + (int)delta.X, Position.Y + (int)delta.Y);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetTarget()
|
||||
{
|
||||
var players = EntityFactory.Instance.Entities.OfType<Player>().Where(player => player.Owner != this.Owner).ToList();
|
||||
|
||||
if (players.Count > 0)
|
||||
{
|
||||
_target = FindClosestPlayer(players, this.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private static Player FindClosestPlayer(IEnumerable<Player> list, Vector2 pointToCompare)
|
||||
{
|
||||
Player closestPlayer = list.ToList()[0];
|
||||
|
||||
float distance = float.PositiveInfinity;
|
||||
foreach (var player in list)
|
||||
{
|
||||
float dx = pointToCompare.X - player.Position.X;
|
||||
float dy = pointToCompare.Y - player.Position.Y;
|
||||
|
||||
float d = dx * dx - dy * dy;
|
||||
|
||||
if (d < distance)
|
||||
{
|
||||
distance = d;
|
||||
closestPlayer = player;
|
||||
}
|
||||
}
|
||||
|
||||
return closestPlayer;
|
||||
}
|
||||
}
|
||||
}
|
12
SpacePew/Models/Projectiles/IProjectile.cs
Normal file
12
SpacePew/Models/Projectiles/IProjectile.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public interface IProjectile : IEntity
|
||||
{
|
||||
string HitSoundAssetName { get; }
|
||||
string FireSoundAssetName { get; }
|
||||
|
||||
int Damage { get; }
|
||||
float Speed { get; }
|
||||
CollisionType CollisionType { get; }
|
||||
}
|
||||
}
|
29
SpacePew/Models/Projectiles/LongShot.cs
Normal file
29
SpacePew/Models/Projectiles/LongShot.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public class LongShot : Bullet
|
||||
{
|
||||
public override Vector2 Origin
|
||||
{
|
||||
get { return new Vector2(5, 12); }
|
||||
}
|
||||
|
||||
public override string TextureName
|
||||
{
|
||||
get { return "longshot"; }
|
||||
}
|
||||
|
||||
public override void ApplyGravity(GameTime time)
|
||||
{
|
||||
base.ApplyGravity(time);
|
||||
|
||||
//Sätt rotationen till lika som riktningen som pilen åker
|
||||
Vector2 vNormal = Velocity;
|
||||
vNormal.Normalize();
|
||||
Angle = (vNormal.X > 0 ? 1f : -1f) * (float)(Math.Acos(Vector2.Dot(-Vector2.UnitY, vNormal)));
|
||||
}
|
||||
}
|
||||
}
|
75
SpacePew/Models/Projectiles/Missile.cs
Normal file
75
SpacePew/Models/Projectiles/Missile.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public sealed class Missile : ProjectileBase
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public Missile()
|
||||
{
|
||||
this.Color = Color.Red;
|
||||
this.Velocity = new Vector2();
|
||||
this.Angle = 0;
|
||||
this.Health = 10;
|
||||
}
|
||||
|
||||
public Missile(Vector2 position)
|
||||
: this()
|
||||
{
|
||||
this.Position = position;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEntity Members
|
||||
|
||||
public override void CollideWithLevel(Level level)
|
||||
{
|
||||
// blow stuff
|
||||
}
|
||||
|
||||
public override int Health
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override string TextureName
|
||||
{
|
||||
get { return "bullet"; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IProjectile Members
|
||||
|
||||
public override string FireSoundAssetName
|
||||
{
|
||||
get { return "Audio/Waves/bullet_sound"; }
|
||||
}
|
||||
|
||||
public override string HitSoundAssetName
|
||||
{
|
||||
get { return "Audio/Waves/bullet_hit"; }
|
||||
}
|
||||
|
||||
public override int Damage
|
||||
{
|
||||
get { return 50; }
|
||||
}
|
||||
|
||||
public override float Speed
|
||||
{
|
||||
get { return 600f; }
|
||||
}
|
||||
|
||||
public override CollisionType CollisionType
|
||||
{
|
||||
get { return CollisionType.Explode; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
48
SpacePew/Models/Projectiles/ProjectileBase.cs
Normal file
48
SpacePew/Models/Projectiles/ProjectileBase.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace SpacePew.Models.Projectiles
|
||||
{
|
||||
public abstract class ProjectileBase : EntityBase, IProjectile
|
||||
{
|
||||
#region IEntity Members
|
||||
|
||||
public override bool Collide(IEntity entity)
|
||||
{
|
||||
bool collided = base.Collide(entity);
|
||||
|
||||
if (collided)
|
||||
{
|
||||
SoundManager.Play(HitSoundAssetName, this.Position);
|
||||
}
|
||||
|
||||
return collided;
|
||||
}
|
||||
|
||||
public override void CollideWithLevel(Level level)
|
||||
{
|
||||
if (this.CollisionType == CollisionType.Explode)
|
||||
{
|
||||
// blow up somehow (particle system is there, but needs to trash the level a little more too)
|
||||
}
|
||||
else if (this.CollisionType == CollisionType.Bounce)
|
||||
{
|
||||
this.Velocity -= (this.Velocity * 1.9f);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Created()
|
||||
{
|
||||
SoundManager.Play(FireSoundAssetName, this.Position);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IProjectile Members
|
||||
|
||||
public abstract string HitSoundAssetName { get; }
|
||||
public abstract string FireSoundAssetName { get; }
|
||||
public abstract int Damage { get; }
|
||||
public abstract float Speed { get; }
|
||||
public abstract CollisionType CollisionType { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
20
SpacePew/Models/Weapons/Cannon.cs
Normal file
20
SpacePew/Models/Weapons/Cannon.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
public class Cannon : WeaponBase
|
||||
{
|
||||
public override float HeatGeneration
|
||||
{
|
||||
get { return 0.4f; }
|
||||
}
|
||||
|
||||
public override int Delay
|
||||
{
|
||||
get { return 35; }
|
||||
}
|
||||
|
||||
public override int Spread
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
}
|
||||
}
|
20
SpacePew/Models/Weapons/ClusterLauncher.cs
Normal file
20
SpacePew/Models/Weapons/ClusterLauncher.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
public class ClusterLauncher : WeaponBase
|
||||
{
|
||||
public override float HeatGeneration
|
||||
{
|
||||
get { return 100f; }
|
||||
}
|
||||
|
||||
public override int Delay
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public override int Spread
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
}
|
||||
}
|
13
SpacePew/Models/Weapons/IWeapon.cs
Normal file
13
SpacePew/Models/Weapons/IWeapon.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using SpacePew.Models.Projectiles;
|
||||
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
public interface IWeapon
|
||||
{
|
||||
int Delay { get; }
|
||||
int Spread { get; }
|
||||
float Heat { get; set; }
|
||||
float HeatGeneration { get; }
|
||||
void Fire(IProjectile projectile, Player player);
|
||||
}
|
||||
}
|
20
SpacePew/Models/Weapons/Launcher.cs
Normal file
20
SpacePew/Models/Weapons/Launcher.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
public class Launcher : WeaponBase
|
||||
{
|
||||
public override float HeatGeneration
|
||||
{
|
||||
get { return 100f; }
|
||||
}
|
||||
|
||||
public override int Delay
|
||||
{
|
||||
get { return 200; }
|
||||
}
|
||||
|
||||
public override int Spread
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
}
|
||||
}
|
24
SpacePew/Models/Weapons/SecondaryCannon.cs
Normal file
24
SpacePew/Models/Weapons/SecondaryCannon.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
/// <summary>
|
||||
/// A slower version of the cannon, should be used for powerful projectiles like the homing bullets to even things out
|
||||
/// </summary>
|
||||
public class SecondaryCannon : Cannon
|
||||
{
|
||||
public override float HeatGeneration
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Delay
|
||||
{
|
||||
get
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
64
SpacePew/Models/Weapons/TriCannon.cs
Normal file
64
SpacePew/Models/Weapons/TriCannon.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using SpacePew.Models.Projectiles;
|
||||
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
public class TriCannon : WeaponBase
|
||||
{
|
||||
public override float HeatGeneration
|
||||
{
|
||||
get { return 0.8f; }
|
||||
}
|
||||
|
||||
public override int Delay
|
||||
{
|
||||
get { return 40; }
|
||||
}
|
||||
|
||||
public override int Spread
|
||||
{
|
||||
get { return 3; }
|
||||
}
|
||||
|
||||
public override void Fire(IProjectile projectile, Player player)
|
||||
{
|
||||
if (Heat + this.HeatGeneration > MaxHeat)
|
||||
return;
|
||||
|
||||
Heat += 1f * this.HeatGeneration;
|
||||
|
||||
if (_lastShot <= DateTime.Now.AddMilliseconds(-this.Delay - (Heat >= HeatStartAffectAt ? Heat : 0)))
|
||||
{
|
||||
float angle = player.Angle + (float)(Randomizer.Next(-Spread * 100, Spread * 100) / 9000.0);
|
||||
|
||||
InternalFire(projectile, player, angle - 0.15f);
|
||||
InternalFire(projectile, player, angle);
|
||||
InternalFire(projectile, player, angle + 0.15f);
|
||||
|
||||
_lastShot = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
private static void InternalFire(IProjectile projectile, IEntity player, float angle)
|
||||
{
|
||||
var entity = EntityFactory.Instance.CreateEntity<ProjectileBase>(
|
||||
projectile.GetType(),
|
||||
player.Owner,
|
||||
player.Position,
|
||||
new Vector2(),
|
||||
angle);
|
||||
|
||||
Matrix m = Matrix.CreateRotationZ(angle);
|
||||
Vector2 velocity = Vector2.Transform(-Vector2.UnitY, m);
|
||||
|
||||
entity.Position += velocity * (player.Origin.Y + entity.Origin.Y);
|
||||
entity.Velocity = velocity * projectile.Speed;
|
||||
|
||||
entity.Velocity = player.Velocity + entity.Velocity;
|
||||
|
||||
FiredShots.Enqueue(entity);
|
||||
}
|
||||
}
|
||||
}
|
82
SpacePew/Models/Weapons/WeaponBase.cs
Normal file
82
SpacePew/Models/Weapons/WeaponBase.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using SpacePew.Models.Projectiles;
|
||||
|
||||
namespace SpacePew.Models.Weapons
|
||||
{
|
||||
public abstract class WeaponBase : IWeapon
|
||||
{
|
||||
protected const int MaxHeat = 100;
|
||||
protected const int HeatStartAffectAt = MaxHeat / 2;
|
||||
|
||||
static WeaponBase()
|
||||
{
|
||||
FiredShots = new Queue<IProjectile>();
|
||||
}
|
||||
|
||||
public static Queue<IProjectile> FiredShots;
|
||||
|
||||
protected DateTime _lastShot;
|
||||
|
||||
private static Random _randomizer;
|
||||
|
||||
public static Random Randomizer
|
||||
{
|
||||
get { return _randomizer ?? (_randomizer = new Random()); }
|
||||
}
|
||||
|
||||
private float _heat;
|
||||
|
||||
protected WeaponBase()
|
||||
{
|
||||
_lastShot = DateTime.Now;
|
||||
}
|
||||
|
||||
public virtual float Heat
|
||||
{
|
||||
get { return _heat; }
|
||||
set { _heat = value; }
|
||||
}
|
||||
|
||||
#region IWeapon Members
|
||||
|
||||
public abstract float HeatGeneration { get; }
|
||||
public abstract int Delay { get; }
|
||||
public abstract int Spread { get; }
|
||||
|
||||
public virtual void Fire(IProjectile projectile, Player player)
|
||||
{
|
||||
if (_heat + this.HeatGeneration > MaxHeat)
|
||||
return;
|
||||
|
||||
_heat += 1f * this.HeatGeneration;
|
||||
|
||||
if (_lastShot <= DateTime.Now.AddMilliseconds(-this.Delay - (_heat >= HeatStartAffectAt ? _heat : 0)))
|
||||
{
|
||||
float angle = player.Angle + (float)(Randomizer.Next(-Spread * 100, Spread * 100) / 9000.0);
|
||||
|
||||
var entity = EntityFactory.Instance.CreateEntity<ProjectileBase>(
|
||||
projectile.GetType(),
|
||||
player.Owner,
|
||||
player.Position,
|
||||
new Vector2(),
|
||||
angle);
|
||||
|
||||
Matrix m = Matrix.CreateRotationZ(angle);
|
||||
Vector2 velocity = Vector2.Transform(-Vector2.UnitY, m);
|
||||
|
||||
entity.Position += velocity * (player.Origin.Y + entity.Origin.Y);
|
||||
entity.Velocity = velocity * projectile.Speed;
|
||||
|
||||
entity.Velocity = player.Velocity + entity.Velocity;
|
||||
FiredShots.Enqueue(entity);
|
||||
|
||||
_lastShot = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user