Compare commits
8 Commits
tiles_movi
...
master
Author | SHA1 | Date |
---|---|---|
BraydonKains | 531ffbf531 | 3 years ago |
BraydonKains | ff84687bc9 | 5 years ago |
BraydonKains | d7cc841ad8 | 5 years ago |
BraydonKains | 51f5d963cd | 5 years ago |
BraydonKains | 0229f9f055 | 5 years ago |
BraydonKains | 4be05cff2d | 5 years ago |
BraydonKains | 830891a71e | 5 years ago |
BraydonKains | 15612f660a | 5 years ago |
File diff suppressed because one or more lines are too long
@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../SeeNoEvil/SeeNoEvil.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,18 +0,0 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace SeeNoEvil.Tests
|
||||
{
|
||||
public class Tests
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test1()
|
||||
{
|
||||
Assert.Pass();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
{
|
||||
"name": "cat",
|
||||
"image": "Master-no-background-01",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"animations": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Walk Left",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 32,
|
||||
"y": 64,
|
||||
"timer": 8
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 64,
|
||||
"y": 64,
|
||||
"timer": 8
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"x": 0,
|
||||
"y": 64,
|
||||
"timer": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Walk Right",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 32,
|
||||
"y": 96,
|
||||
"timer": 8
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 64,
|
||||
"y": 96,
|
||||
"timer": 8
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"x": 0,
|
||||
"y": 96,
|
||||
"timer": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Walk Up",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 32,
|
||||
"y": 128,
|
||||
"timer": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 0,
|
||||
"y": 128,
|
||||
"timer": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Walk Down",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 32,
|
||||
"y": 160,
|
||||
"timer": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 0,
|
||||
"y": 160,
|
||||
"timer": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Scared Left",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 96,
|
||||
"y": 64,
|
||||
"timer": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Scared Right",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 96,
|
||||
"y": 96,
|
||||
"timer": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Scared Up",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 64,
|
||||
"y": 128,
|
||||
"timer": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Scared Down",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 64,
|
||||
"y": 160,
|
||||
"timer": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
{
|
||||
"name": "ghost",
|
||||
"image": "Master-no-background-01",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"animations": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Walk Left",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 0,
|
||||
"y": 32,
|
||||
"timer": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 32,
|
||||
"y": 32,
|
||||
"timer": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Walk Right",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"timer": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 32,
|
||||
"y": 0,
|
||||
"timer": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Walk Up",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 64,
|
||||
"y": 0,
|
||||
"timer": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 64,
|
||||
"y": 32,
|
||||
"timer": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Walk Down",
|
||||
"frames": [
|
||||
{
|
||||
"id": 1,
|
||||
"x": 96,
|
||||
"y": 0,
|
||||
"timer": 6
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"x": 96,
|
||||
"y": 32,
|
||||
"timer": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SeeNoEvil.Character {
|
||||
public class AnimationController {
|
||||
public string Name {get; private set;}
|
||||
public string Image {get; private set;}
|
||||
public int Width {get; private set;}
|
||||
public int Height {get; private set;}
|
||||
public bool Idle;
|
||||
public Dictionary<int, Animation> Animations {get; private set;}
|
||||
private Animation CurrentAnimation;
|
||||
|
||||
public Frame CurrentFrame {
|
||||
get {
|
||||
if(Idle) return CurrentAnimation.CurrentFrame;
|
||||
else return CurrentAnimation.GetFrame();
|
||||
}
|
||||
}
|
||||
|
||||
public AnimationController(AnimationSetModel model) {
|
||||
Name = model.Name;
|
||||
Image = model.Image;
|
||||
Width = model.Width;
|
||||
Height = model.Height;
|
||||
Animations = model.Animations.Aggregate(new Dictionary<int, Animation>(),
|
||||
(animations, animation) => {
|
||||
animations.Add(animation.Id, new Animation(animation));
|
||||
return animations;
|
||||
});
|
||||
ChangeAnimation(1);
|
||||
Idle = true;
|
||||
}
|
||||
|
||||
public void ChangeAnimation(int animationId) {
|
||||
if(Animations.TryGetValue(animationId, out CurrentAnimation))
|
||||
CurrentAnimation.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public class Animation {
|
||||
public int Id {get; set;}
|
||||
public string Name {get; set;}
|
||||
public FrameCollection Frames {get; set;}
|
||||
public Frame CurrentFrame;
|
||||
private int TotalFrames;
|
||||
private int CurrentFrameId;
|
||||
|
||||
public Animation(AnimationModel model) {
|
||||
Id = model.Id;
|
||||
Name = model.Name;
|
||||
Frames = new FrameCollection(model.Frames);
|
||||
TotalFrames = model.Frames.Count();
|
||||
}
|
||||
|
||||
public void Reset() {
|
||||
CurrentFrameId = 1;
|
||||
CurrentFrame = Frames[CurrentFrameId];
|
||||
}
|
||||
|
||||
// TODO Is this super fuckin ugly? Seems like it
|
||||
public Frame GetFrame() {
|
||||
Frame result = CurrentFrame;
|
||||
if(CurrentFrame.Timer == 1) {
|
||||
CurrentFrameId = CurrentFrameId == TotalFrames ? 1 : CurrentFrameId + 1;
|
||||
CurrentFrame = Frames[CurrentFrameId];
|
||||
} else if(CurrentFrame.Timer > 1) CurrentFrame.Timer--;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public class FrameCollection {
|
||||
private IEnumerable<Frame> Frames;
|
||||
|
||||
public Frame this[int i] {
|
||||
get {
|
||||
return Frames.Where(item => item.Id == i).First();
|
||||
}
|
||||
}
|
||||
|
||||
public FrameCollection(IEnumerable<Frame> frames) {
|
||||
Frames = frames;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SeeNoEvil.Character {
|
||||
public struct AnimationSetModel {
|
||||
public string Name {get; set;}
|
||||
public string Image {get; set;}
|
||||
public int Width {get; set;}
|
||||
public int Height {get; set;}
|
||||
public IEnumerable<AnimationModel> Animations {get; set;}
|
||||
}
|
||||
|
||||
public struct AnimationModel {
|
||||
public int Id {get; set;}
|
||||
public string Name {get; set;}
|
||||
public IEnumerable<Frame> Frames{get; set;}
|
||||
}
|
||||
|
||||
public struct Frame {
|
||||
public int Id {get; set;}
|
||||
public int X {get; set;}
|
||||
public int Y {get; set;}
|
||||
public int Timer {get; set;}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SeeNoEvil.Character {
|
||||
public static class AnimationParser {
|
||||
public static AnimationSetModel ReadAnimationJson(string fileName) {
|
||||
StreamReader streamReader = File.OpenText(fileName);
|
||||
string text = streamReader.ReadToEnd();
|
||||
var options = new JsonSerializerOptions {
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
return JsonSerializer.Deserialize<AnimationSetModel>(text, options);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SeeNoEvil.Character {
|
||||
public class Cat : Character {
|
||||
public Cat(Vector2 position, Direction facing) : base(position) {
|
||||
AnimationController = new AnimationController(AnimationParser.ReadAnimationJson("SeeNoEvil/Animation/cat.json"));
|
||||
Width = AnimationController.Width;
|
||||
Height = AnimationController.Height;
|
||||
Facing = facing;
|
||||
ChooseAnimation(Facing);
|
||||
}
|
||||
|
||||
public override void Move(Direction direction) {
|
||||
if(!Moving) {
|
||||
ChooseAnimation(direction);
|
||||
base.Move(direction);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 GetSight() {
|
||||
Vector2 sight = Position;
|
||||
for(int i = 0; i <= 9; i++) {
|
||||
switch(Facing) {
|
||||
case Direction.Up:
|
||||
sight.Y -= Height;
|
||||
break;
|
||||
case Direction.Down:
|
||||
sight.Y += Height;
|
||||
break;
|
||||
case Direction.Left:
|
||||
sight.X -= Width;
|
||||
break;
|
||||
case Direction.Right:
|
||||
sight.X += Width;
|
||||
break;
|
||||
}
|
||||
if(!Field.TryWalk(sight)) break;
|
||||
}
|
||||
return sight;
|
||||
}
|
||||
|
||||
public void ChooseAnimation(Direction direction) {
|
||||
switch(direction) {
|
||||
case Direction.Up:
|
||||
AnimationController.ChangeAnimation(3);
|
||||
break;
|
||||
case Direction.Down:
|
||||
AnimationController.ChangeAnimation(4);
|
||||
break;
|
||||
case Direction.Left:
|
||||
AnimationController.ChangeAnimation(1);
|
||||
break;
|
||||
case Direction.Right:
|
||||
AnimationController.ChangeAnimation(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Scared() {
|
||||
switch(Facing) {
|
||||
case Direction.Up:
|
||||
AnimationController.ChangeAnimation(7);
|
||||
break;
|
||||
case Direction.Down:
|
||||
AnimationController.ChangeAnimation(8);
|
||||
break;
|
||||
case Direction.Left:
|
||||
AnimationController.ChangeAnimation(5);
|
||||
break;
|
||||
case Direction.Right:
|
||||
AnimationController.ChangeAnimation(6);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using SeeNoEvil.Level;
|
||||
|
||||
namespace SeeNoEvil.Character {
|
||||
public class Character {
|
||||
private Vector2 Destination {get; set;}
|
||||
private Vector2 Velocity {get; set;}
|
||||
public Vector2 Position {get; private set;}
|
||||
private Texture2D SpriteSheet;
|
||||
|
||||
protected Vector2 StartingPosition;
|
||||
protected AnimationController AnimationController;
|
||||
protected int Width;
|
||||
protected int Height;
|
||||
protected PlayField Field;
|
||||
|
||||
public Direction Facing;
|
||||
public bool Moving =>
|
||||
!Destination.Equals(Vector2.Zero) &&
|
||||
!Velocity.Equals(Vector2.Zero) &&
|
||||
!Position.Equals(Destination);
|
||||
|
||||
public Character(Vector2 position) {
|
||||
Position = position;
|
||||
StartingPosition = position;
|
||||
Destination = Vector2.Zero;
|
||||
Velocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
public void Load(ContentManager content, PlayField playField) {
|
||||
SpriteSheet = content.Load<Texture2D>(AnimationController.Image);
|
||||
Field = playField;
|
||||
}
|
||||
|
||||
// TODO Do I want to move every frame?
|
||||
public void Update() {
|
||||
if(Moving) {
|
||||
Position = Vector2.Add(Position, Velocity);
|
||||
AnimationController.Idle = false;
|
||||
}
|
||||
else AnimationController.Idle = true;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch) {
|
||||
Frame currentFrame = AnimationController.CurrentFrame;
|
||||
Rectangle srcRectangle = new Rectangle(currentFrame.X,
|
||||
currentFrame.Y,
|
||||
AnimationController.Width,
|
||||
AnimationController.Height);
|
||||
spriteBatch.Draw(SpriteSheet, Position, srcRectangle, Color.White);
|
||||
}
|
||||
|
||||
public virtual void Move(Direction direction) {
|
||||
if(!Moving) {
|
||||
int velocity = 16;
|
||||
int x = 0, y = 0;
|
||||
switch(direction) {
|
||||
case Direction.Up:
|
||||
y = -1;
|
||||
break;
|
||||
case Direction.Down:
|
||||
y = 1;
|
||||
break;
|
||||
case Direction.Left:
|
||||
x = -1;
|
||||
break;
|
||||
case Direction.Right:
|
||||
x = 1;
|
||||
break;
|
||||
}
|
||||
var tryPosition = Vector2.Add(Position, new Vector2(Width*x, Height*y));
|
||||
if(Field.TryWalk(tryPosition)) {
|
||||
Destination = Vector2.Add(Position, new Vector2(Width*x, Height*y));
|
||||
Velocity = new Vector2(x*velocity, y*velocity);
|
||||
Facing = direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset() {
|
||||
Position = StartingPosition;
|
||||
Destination = Vector2.Zero;
|
||||
Velocity = Vector2.Zero;
|
||||
}
|
||||
}
|
||||
public enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using SeeNoEvil.Level;
|
||||
using SeeNoEvil.Tiled;
|
||||
|
||||
namespace SeeNoEvil.Character {
|
||||
public class GhostController {
|
||||
public List<Ghost> Ghosts {get; set;}
|
||||
public GhostController(IEnumerable<ObjectCoordinate> coordinates) {
|
||||
Ghosts = coordinates.Select(
|
||||
coord => new Ghost(new Vector2(coord.X, coord.Y))
|
||||
).ToList();
|
||||
}
|
||||
|
||||
public void LoadAll(ContentManager content, PlayField playField) =>
|
||||
Ghosts.ForEach(ghost => ghost.Load(content, playField));
|
||||
|
||||
public void DrawAll(SpriteBatch spriteBatch) =>
|
||||
Ghosts.ForEach(ghost => ghost.Draw(spriteBatch));
|
||||
|
||||
public void UpdateAll() =>
|
||||
Ghosts.ForEach(ghost => ghost.Update());
|
||||
|
||||
public void MoveGhosts() =>
|
||||
Ghosts.ForEach(ghost => ghost.DecideMove());
|
||||
|
||||
public bool AreGhostsHere(Vector2 playerPosition, Vector2 playerSight, Direction direction) =>
|
||||
Ghosts.Any(ghost => ghost.IsInSight(playerPosition, playerSight, direction));
|
||||
}
|
||||
|
||||
public class Ghost : Character {
|
||||
public Ghost(Vector2 position) : base(position) {
|
||||
AnimationController = new AnimationController(AnimationParser.ReadAnimationJson("SeeNoEvil/Animation/ghost.json"));
|
||||
Width = AnimationController.Width;
|
||||
Height = AnimationController.Height;
|
||||
Facing = Direction.Down;
|
||||
}
|
||||
|
||||
public void DecideMove() {
|
||||
Array values = Enum.GetValues(typeof(Direction));
|
||||
Random random = new Random();
|
||||
Direction randomDirection = (Direction)values.GetValue(random.Next(values.Length));
|
||||
switch(randomDirection) {
|
||||
case Direction.Up:
|
||||
AnimationController.ChangeAnimation(3);
|
||||
break;
|
||||
case Direction.Down:
|
||||
AnimationController.ChangeAnimation(4);
|
||||
break;
|
||||
case Direction.Left:
|
||||
AnimationController.ChangeAnimation(1);
|
||||
break;
|
||||
case Direction.Right:
|
||||
AnimationController.ChangeAnimation(2);
|
||||
break;
|
||||
}
|
||||
|
||||
base.Move(randomDirection);
|
||||
}
|
||||
|
||||
// FIXME it's a bit better now but still
|
||||
public bool IsInSight(Vector2 playerPosition, Vector2 playerSight, Direction direction) {
|
||||
if(direction == Direction.Up)
|
||||
return playerPosition.X == Position.X &&
|
||||
(playerPosition.Y > Position.Y) && (Position.Y > playerSight.Y);
|
||||
else if(direction == Direction.Down)
|
||||
return playerPosition.X == Position.X &&
|
||||
(playerPosition.Y < Position.Y) && (Position.Y < playerSight.Y);
|
||||
else if(direction == Direction.Left)
|
||||
return playerPosition.Y == Position.Y &&
|
||||
(playerPosition.X > Position.X) && (Position.X > playerSight.X);
|
||||
else
|
||||
return playerPosition.Y == Position.Y &&
|
||||
(playerPosition.X < Position.X) && (Position.X < playerSight.X);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,27 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace SeeNoEvil.Level {
|
||||
public struct Camera {
|
||||
public int width;
|
||||
public int height;
|
||||
public int x;
|
||||
public int y;
|
||||
}
|
||||
public class Camera {
|
||||
public Matrix Transform {get; private set;}
|
||||
public Viewport Viewport {get; private set;}
|
||||
public Vector2 Centre {get; set;}
|
||||
|
||||
// public class Camera {
|
||||
// private Viewport m_dimension;
|
||||
private Vector3 TranslationVector =>
|
||||
new Vector3(-Centre.X + (Viewport.Width / 2),
|
||||
-Centre.Y + (Viewport.Height / 2),
|
||||
1);
|
||||
|
||||
// public Camera(int x, int y) {
|
||||
// m_dimension.x = x;
|
||||
// m_dimension.y = x;
|
||||
// }
|
||||
public Camera(Viewport _viewport) {
|
||||
Viewport = _viewport;
|
||||
//TODO This is to experiment
|
||||
Centre = new Vector2(Viewport.Width / 2, Viewport.Height / 2);
|
||||
}
|
||||
|
||||
// public Viewport GetDimension() {
|
||||
// return m_dimension;
|
||||
// }
|
||||
// }
|
||||
//FIXME Don't need velocity anymore?
|
||||
public void Update(Vector2 position) {
|
||||
Centre = position;
|
||||
Transform = Matrix.CreateTranslation(TranslationVector);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +1,62 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SeeNoEvil.Tiled;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
using SeeNoEvil.Tiled;
|
||||
|
||||
namespace SeeNoEvil.Level {
|
||||
public class TilemapLevel {
|
||||
private readonly string MapName;
|
||||
private TiledMap Map;
|
||||
private Dictionary<string, Texture2D> TilesetTextures;
|
||||
|
||||
public TilemapLevel(string tilemapName) {
|
||||
MapName = tilemapName;
|
||||
}
|
||||
|
||||
public void LoadMap() {
|
||||
Map = TiledParser.ReadMapJson(MapName);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetTilesetNames() {
|
||||
return Map.GetTilesetNames();
|
||||
}
|
||||
|
||||
public void Draw(Camera viewport, SpriteBatch spritebatch, IDictionary<string, Texture2D> this_sucks) {
|
||||
IEnumerable<TileLocation> locations = Map.DrawView(viewport);
|
||||
locations.ToList().ForEach(tile => {
|
||||
Texture2D this_one;
|
||||
if(tile.tile.gid > 0 && this_sucks.TryGetValue(tile.tile.setName, out this_one)) {
|
||||
spritebatch.Draw(this_one, tile.location, tile.tile.srcRectangle, Color.White);
|
||||
}
|
||||
});
|
||||
}
|
||||
public void LoadMap(ContentManager content) {
|
||||
Map = new TiledMap(TiledParser.ReadMapJson(MapName));
|
||||
Map.LoadView();
|
||||
Map.LoadObjects();
|
||||
TilesetTextures = Map.GetTilesetNames().Aggregate(new Dictionary<string, Texture2D>(),
|
||||
(textures, contentName) => {
|
||||
textures.Add(contentName, content.Load<Texture2D>(contentName));
|
||||
return textures;
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetTilesetNames() => Map.GetTilesetNames();
|
||||
|
||||
public Vector2 GetPlayerPosition() {
|
||||
//FIXME This fuckin sucks
|
||||
Map.Objects.TryGetValue("Cat", out List<ObjectCoordinate> catCoords);
|
||||
ObjectCoordinate catCoord = catCoords.First();
|
||||
return new Vector2(catCoord.X, catCoord.Y);
|
||||
}
|
||||
|
||||
public PlayField GetPlayField() {
|
||||
Map.View.TryGetValue("Ground", out List<TileLocation> ground);
|
||||
return new PlayField(ground);
|
||||
}
|
||||
|
||||
public IEnumerable<ObjectCoordinate> GetGhostCoordinates() {
|
||||
// FIXME this fuckin sucks too I think?
|
||||
Map.Objects.TryGetValue("Ghosts", out List<ObjectCoordinate> ghosts);
|
||||
return ghosts;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, string layer) {
|
||||
List<TileLocation> locations;
|
||||
if(Map.View.TryGetValue(layer, out locations))
|
||||
locations.ForEach(tile => {
|
||||
Texture2D layerTexture;
|
||||
if(tile.tile.gid > 0 && TilesetTextures.TryGetValue(tile.tile.setName, out layerTexture)) {
|
||||
spriteBatch.Draw(layerTexture, tile.location, tile.tile.srcRectangle, Color.White);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using SeeNoEvil.Tiled;
|
||||
|
||||
namespace SeeNoEvil.Level {
|
||||
public class PlayField {
|
||||
private IEnumerable<TileLocation> Tiles {get; set;}
|
||||
|
||||
public PlayField(IEnumerable<TileLocation> tiles) {
|
||||
Tiles = tiles;
|
||||
}
|
||||
|
||||
public bool TryWalk(Vector2 newLocation) =>
|
||||
Tiles.Any(tile => tile.location.Equals(newLocation) && tile.tile.gid != 0);
|
||||
|
||||
private bool Between(float pos1, float pos2, float bound) =>
|
||||
(bound - pos1) >= (pos2 - pos1);
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
// TODO Handle flipped tiles!
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SeeNoEvil.Level;
|
||||
|
||||
namespace SeeNoEvil.Tiled {
|
||||
public class TileLayer {
|
||||
|
||||
public string Type {get; private set;}
|
||||
public string Name {get; private set;}
|
||||
public readonly List<DataCoordinate> DataCoordinates = new List<DataCoordinate>();
|
||||
|
||||
private int Width;
|
||||
private int Height;
|
||||
private List<uint> Data;
|
||||
|
||||
public TileLayer(MapLayerModel model) {
|
||||
Name = model.Name;
|
||||
Width = model.Width;
|
||||
Height = model.Height;
|
||||
Type = model.Type;
|
||||
if(model.Type == "tilelayer") {
|
||||
Data = model.Data.ToList();
|
||||
BuildCoordinates();
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildCoordinates() {
|
||||
int row = 0;
|
||||
int column = 0;
|
||||
Data.ForEach(gid => {
|
||||
DataCoordinates.Add(new DataCoordinate(column, row, gid));
|
||||
if(column == Width-1) {
|
||||
row++;
|
||||
column = 0;
|
||||
} else column++;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
//TODO Do all these need to be public?
|
||||
namespace SeeNoEvil.Tiled {
|
||||
//TODO Can probably be a struct?
|
||||
public class ObjectLayer {
|
||||
public IEnumerable<ObjectCoordinate> Objects {get; private set;}
|
||||
public string Name {get; private set;}
|
||||
public ObjectLayer(MapLayerModel model) {
|
||||
Name = model.Name;
|
||||
Objects = model.Objects.Select(o => new ObjectCoordinate(o.Id,
|
||||
o.X,
|
||||
o.Y));
|
||||
}
|
||||
}
|
||||
|
||||
public struct ObjectCoordinate {
|
||||
public ObjectCoordinate(int id, float x, float y) {
|
||||
X = (int)Math.Round(x / 32)*32;
|
||||
Y = (int)Math.Round(y / 32)*32;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public int X {get; set;}
|
||||
public int Y {get; set;}
|
||||
public int Id {get; set;}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SeeNoEvil.Tiled {
|
||||
public class TileSet {
|
||||
private string Image {get; set;}
|
||||
private string Name {get; set;}
|
||||
private int ImageHeight {get; set;}
|
||||
private int ImageWidth {get; set;}
|
||||
private int TileHeight {get; set;}
|
||||
private int TileWidth {get; set;}
|
||||
private int Spacing {get; set;}
|
||||
private int Columns {get; set;}
|
||||
private int FirstGid {get; set;}
|
||||
private int TileCount {get; set;}
|
||||
private Dictionary<uint, Tile> Tiles {get; set;}
|
||||
private bool TilesLoaded {get; set;}
|
||||
|
||||
public TileSet(TileSetModel model) {
|
||||
Image = model.Image;
|
||||
Name = model.Name;
|
||||
ImageHeight = model.ImageHeight;
|
||||
ImageWidth = model.ImageWidth;
|
||||
TileHeight = model.TileHeight;
|
||||
TileWidth = model.TileWidth;
|
||||
Spacing = model.Spacing;
|
||||
Columns = model.Columns;
|
||||
FirstGid = model.FirstGid;
|
||||
TileCount = model.TileCount;
|
||||
Tiles = new Dictionary<uint, Tile>();
|
||||
TilesLoaded = false;
|
||||
}
|
||||
|
||||
public bool ContainsTile(uint gid) =>
|
||||
!(gid < FirstGid || gid > (FirstGid + TileCount - 1));
|
||||
|
||||
public Tile GetTile(uint gid) {
|
||||
if(!TilesLoaded) LoadTiles();
|
||||
Tile result;
|
||||
Tiles.TryGetValue(gid, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public string GetContentName() {
|
||||
return Name;
|
||||
}
|
||||
|
||||
private void LoadTiles() {
|
||||
Tiles = new Dictionary<uint, Tile>();
|
||||
int row = 0;
|
||||
int rowPx = 0;
|
||||
int column = 0;
|
||||
int columnPx = 0;
|
||||
for(int i = 0; i < TileCount; i++) {
|
||||
Rectangle rectangle = new Rectangle(
|
||||
columnPx,
|
||||
rowPx,
|
||||
TileWidth,
|
||||
TileHeight
|
||||
);
|
||||
uint gid = (uint)(i + FirstGid);
|
||||
Tiles.Add(gid, new Tile(gid, rectangle, Name));
|
||||
if(column == Columns-1) {
|
||||
row++;
|
||||
rowPx += Spacing + TileHeight;
|
||||
column = 0;
|
||||
columnPx = 0;
|
||||
} else {
|
||||
column++;
|
||||
columnPx += Spacing + TileWidth;
|
||||
}
|
||||
}
|
||||
|
||||
TilesLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SeeNoEvil.Tiled {
|
||||
public struct TiledModel {
|
||||
public bool Infinite {get; set;}
|
||||
public IEnumerable<MapLayerModel> Layers {get; set;}
|
||||
public IEnumerable<TileSetModel> TileSets {get; set;}
|
||||
public int TileHeight {get; set;}
|
||||
public int TileWidth {get; set;}
|
||||
public int Height {get; set;}
|
||||
public int Width {get; set;}
|
||||
}
|
||||
|
||||
public struct TileSetModel {
|
||||
public string Image {get; set;}
|
||||
public string Name {get; set;}
|
||||
public int ImageHeight {get; set;}
|
||||
public int ImageWidth {get; set;}
|
||||
public int TileHeight {get; set;}
|
||||
public int TileWidth {get; set;}
|
||||
public int Spacing {get; set;}
|
||||
public int Columns {get; set;}
|
||||
public int FirstGid {get; set;}
|
||||
public int TileCount {get; set;}
|
||||
}
|
||||
|
||||
public struct MapLayerModel {
|
||||
public string Name {get; set;}
|
||||
public int Width {get; set;}
|
||||
public int Height {get; set;}
|
||||
public IEnumerable<uint> Data {get; set;}
|
||||
public string Type {get; set;}
|
||||
public IEnumerable<TiledObjectModel> Objects {get; set;}
|
||||
}
|
||||
|
||||
public struct TiledObjectModel {
|
||||
public int Id {get; set;}
|
||||
public float X {get; set;}
|
||||
public float Y {get; set;}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace SeeNoEvil.Tiled {
|
||||
public struct Tile {
|
||||
public Tile(long _gid, Rectangle _srcRectangle, string _setName) {
|
||||
gid = (uint)_gid;
|
||||
srcRectangle = _srcRectangle;
|
||||
setName = _setName;
|
||||
}
|
||||
public uint gid;
|
||||
public Rectangle srcRectangle;
|
||||
public string setName;
|
||||
}
|
||||
|
||||
public struct TileLocation {
|
||||
public TileLocation(Tile tile, Vector2 location) {
|
||||
this.tile = tile;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Tile tile;
|
||||
public Vector2 location;
|
||||
}
|
||||
|
||||
public struct DataCoordinate {
|
||||
public DataCoordinate(int _x, int _y, uint _gid) {
|
||||
x = _x;
|
||||
y = _y;
|
||||
gid = _gid;
|
||||
}
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public uint gid;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue