Denna serie är gjorde med MonoGame 3.8.1. Du hittar källkod och övrigt material länkat.
Worms Content
Ladda ned
31,39 KB
MapGenerator.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;
namespace WormsGame
{
internal class MapGenerator
{
public int Width { get; set; }
public int Height { get; set; }
public Texture2D LevelTexture { get; set; }
private Random rnd = new Random();
private Color[] colorData;
public MapGenerator(int width, int height)
{
Width = width;
Height = height;
}
public void Generate(GraphicsDevice device)
{
colorData = new Color[Width * Height];
List<double> HeightMap = new List<double> { 0, 0 };
LevelTexture = new Texture2D(device, Width, Height);
double Max = 1.0;
double Roughness = ((double)100 / 100.0);
for (int j = 0; j < 10; j++)
{
int count = HeightMap.Count;
for (int i = 0; i < count - 1; i++)
{
double tmp = (HeightMap[i * 2] + HeightMap[i * 2 + 1]) / 2.0;
double offset = (rnd.NextDouble() * 2.0 - 1.0) * Max;
HeightMap.Insert(i * 2 + 1, tmp + offset);
}
Max = Max * Math.Pow(2, -Roughness);
}
for(int x = 0; x < Width; x++)
{
double index = (x / (double)Width) * (HeightMap.Count - 1);
int start = (int)Math.Floor(index);
double r2 = index - Math.Floor(index);
double r1 = 1.0 - r2;
double height = HeightMap[start] * r1 + HeightMap[start + 1] * r2;
var yStart = (int)(300 + 250.0 * height);
for (int y = yStart; y < Height; y++)
colorData[y * Width + x] = Color.Chocolate;
}
LevelTexture.SetData(colorData);
}
public bool IsLand(Vector2 pos)
{
int x = (int)pos.X;
int y = (int)pos.Y;
if (x < 0 || x >= Width || y >= Height)
return true;
if (y < 0)
return false;
return (colorData[x + y * Width] != Color.Transparent);
}
public static Rectangle Intersection(Rectangle r1, Rectangle r2)
{
int x1 = Math.Max(r1.Left, r2.Left);
int y1 = Math.Max(r1.Top, r2.Top);
int x2 = Math.Min(r1.Right, r2.Right);
int y2 = Math.Min(r1.Bottom, r2.Bottom);
if ((x2 >= x1) && (y2 >= y1))
{
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
return Rectangle.Empty;
}
public void Explode(Vector2 pos, Texture2D circle)
{
var area =
Intersection(
new Rectangle((int)pos.X - circle.Width / 2, (int)pos.Y - circle.Height / 2, circle.Width, circle.Height),
new Rectangle(0, 0, Width, Height));
Color[] explosion = new Color[circle.Width * circle.Height];
circle.GetData(explosion);
int offset = (area.X == 0 && area.Width < circle.Width) ? circle.Width - area.Width : 0;
for (int y = 0; y < area.Height; y++)
{
for (int x = 0; x < area.Width; x++)
{
if (explosion[x + offset + y * circle.Width] != Color.Transparent)
{
colorData[area.X + x + (area.Y + y) * Width] = Color.Transparent;
}
}
}
LevelTexture.SetData(colorData);
}
public int FindLand(Vector2 pos)
{
int x = (int)MathHelper.Clamp(pos.X, 0, Width - 1);
int y = (int)MathHelper.Clamp(pos.Y, 0, Height - 1);
if (colorData[x + y * Width] == Color.Transparent)
{
for (int i = y; i < Height; i++)
if (colorData[x + i * Width] != Color.Transparent)
return i;
return Height;
}
else
{
for (int i = y; i >= 0; i--)
if (colorData[x + i * Width] == Color.Transparent)
return i;
return 0;
}
}
}
}
TankManager.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WormsGame
{
internal class TankManager
{
private Texture2D tankTexture2D;
private Texture2D tankCannonTexture2D;
private Texture2D explosionTexture2D;
private Texture2D shotTexture2D;
private List<Tank> tanks = new List<Tank>();
private List<GameObj> shots = new List<GameObj>();
private KeyboardState prevState;
private MapGenerator mapGenerator;
public TankManager(MapGenerator mapGenerator)
{
this.mapGenerator = mapGenerator;
}
public void LoadContent(ContentManager content)
{
tankTexture2D = content.Load<Texture2D>("Tank");
tankCannonTexture2D = content.Load<Texture2D>("Tank_Cannon");
shotTexture2D = content.Load<Texture2D>("Projectile");
explosionTexture2D = content.Load<Texture2D>("Circle");
tanks.Add(new Tank()
{
Position = new Vector2(300, 0),
Width = tankTexture2D.Width,
Height = tankTexture2D.Height
});
}
public void Update()
{
var kbState = Keyboard.GetState();
var player1 = tanks.First();
if (kbState.IsKeyDown(Keys.Left))
player1.Speed = new Vector2(-1, player1.Speed.Y);
if (kbState.IsKeyDown(Keys.Right))
player1.Speed = new Vector2(1, player1.Speed.Y);
if (kbState.IsKeyDown(Keys.Q))
player1.CanonAngle -= 0.07f;
if (kbState.IsKeyDown(Keys.E))
player1.CanonAngle += 0.07f;
if (kbState.IsKeyDown(Keys.Space) && !prevState.IsKeyDown(Keys.Space))
{
shots.Add(new GameObj()
{
Position = player1.CannonPosition,
Speed = new Vector2((float)Math.Cos(player1.ShotAngle), (float)Math.Sin(player1.ShotAngle)) * 8
});
}
foreach (var tank in tanks)
{
var oldPos = player1.Position;
var oldSpeed = player1.Speed;
var oldAngle = player1.Angle;
tank.Speed += new Vector2(0, 0.1f);
tank.Position += tank.Speed;
// kollision med kartan?
var landPosition = FindLandPosition(tank.Position);
if(landPosition.Item1.Y <= tank.Position.Y)
{
tank.Speed = Vector2.Zero;
tank.Angle = landPosition.Item2;
tank.Position = landPosition.Item1;
}
if ((tank.Angle > 1.0f && oldSpeed.X < 0) || (tank.Angle < -1.0f && oldSpeed.X > 0))
{
tank.Position = oldPos;
tank.Angle = oldAngle;
}
}
foreach(var shot in shots)
{
shot.Speed += new Vector2(0, 0.1f);
var oldPos = shot.Position;
var normSpeed = shot.Speed;
normSpeed.Normalize();
shot.Position += shot.Speed;
for (int i = 0; i < (int)shot.Speed.Length(); i++)
{
oldPos += normSpeed;
if (mapGenerator.IsLand(oldPos))
{
shot.FlaggedForRemoval= true;
mapGenerator.Explode(oldPos, explosionTexture2D);
}
}
}
shots.RemoveAll(s => s.FlaggedForRemoval);
prevState = kbState;
}
public void Draw(SpriteBatch spriteBatch)
{
foreach(var tank in tanks)
{
spriteBatch.Draw(tankCannonTexture2D, tank.CannonPosition, null, Color.White, tank.CannonTransformedAngle,
new Vector2(tankCannonTexture2D.Width / 2, tankCannonTexture2D.Height), 1.0f, SpriteEffects.None, 0);
spriteBatch.Draw(tankTexture2D, tank.Position, null, Color.White, tank.Angle,
new Vector2(tankTexture2D.Width / 2, tankTexture2D.Height), 1.0f, SpriteEffects.None, 0);
}
foreach(var shot in shots)
{
spriteBatch.Draw(shotTexture2D, shot.Position, null, Color.White, 0,
new Vector2(shotTexture2D.Width / 2, shotTexture2D.Height / 2), 1.0f, SpriteEffects.None, 0);
}
}
private Tuple<Vector2, float> FindLandPosition(Vector2 position)
{
int x1 = (int)position.X - tankTexture2D.Width / 2 + 4;
int x2 = (int)position.X + tankTexture2D.Width / 2 - 4;
int y1 = mapGenerator.FindLand(new Vector2(x1, position.Y));
int y2 = mapGenerator.FindLand(new Vector2(x2, position.Y));
var angle = (float)Math.Atan2(y2 - y1, x2 - x1);
var pos = new Vector2(position.X, (y1 + y2) / 2);
return new Tuple<Vector2, float>(pos, angle);
}
}
}
Senaste kommentarer