Imported existing sources
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
public class AnimationClip
|
||||
{
|
||||
public class Bone
|
||||
{
|
||||
public class Keyframe
|
||||
{
|
||||
public double Time;
|
||||
public Quaternion Rotation;
|
||||
public Vector3 Translation;
|
||||
|
||||
public Matrix Transform
|
||||
{
|
||||
get
|
||||
{
|
||||
return Matrix.CreateFromQuaternion(Rotation) * Matrix.CreateTranslation(Translation);
|
||||
}
|
||||
set
|
||||
{
|
||||
Matrix transform = value;
|
||||
transform.Right = Vector3.Normalize(transform.Right);
|
||||
transform.Up = Vector3.Normalize(transform.Up);
|
||||
transform.Backward = Vector3.Normalize(transform.Backward);
|
||||
Rotation = Quaternion.CreateFromRotationMatrix(transform);
|
||||
Translation = transform.Translation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string name = "";
|
||||
private List<Keyframe> keyframes = new List<Keyframe>();
|
||||
public string Name { get { return name; } set { name = value; } }
|
||||
public List<Keyframe> Keyframes { get { return keyframes; } }
|
||||
}
|
||||
|
||||
private List<Bone> bones = new List<Bone>();
|
||||
public string Name;
|
||||
public double Duration;
|
||||
public List<Bone> Bones { get { return bones; } }
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
public class AnimationClipReader : ContentTypeReader<AnimationClip>
|
||||
{
|
||||
protected override AnimationClip Read(ContentReader input, AnimationClip existingInstance)
|
||||
{
|
||||
var clip = new AnimationClip();
|
||||
clip.Name = input.ReadString();
|
||||
clip.Duration = input.ReadDouble();
|
||||
|
||||
int boneCnt = input.ReadInt32();
|
||||
for (int i = 0; i < boneCnt; i++)
|
||||
{
|
||||
var bone = new AnimationClip.Bone();
|
||||
clip.Bones.Add(bone);
|
||||
|
||||
bone.Name = input.ReadString();
|
||||
|
||||
int keyframeCnt = input.ReadInt32();
|
||||
for (int j = 0; j < keyframeCnt; j++)
|
||||
{
|
||||
var keyframe = new AnimationClip.Bone.Keyframe();
|
||||
keyframe.Time = input.ReadDouble();
|
||||
keyframe.Rotation = input.ReadQuaternion();
|
||||
keyframe.Translation = input.ReadVector3();
|
||||
|
||||
bone.Keyframes.Add(keyframe);
|
||||
}
|
||||
}
|
||||
|
||||
return clip;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
public class AnimationClipWriter : ContentTypeWriter<AnimationClip>
|
||||
{
|
||||
protected override void Write(ContentWriter output, AnimationClip clip)
|
||||
{
|
||||
output.Write(clip.Name);
|
||||
output.Write(clip.Duration);
|
||||
output.Write(clip.Bones.Count);
|
||||
|
||||
foreach (var bone in clip.Bones)
|
||||
{
|
||||
output.Write(bone.Name);
|
||||
output.Write(bone.Keyframes.Count);
|
||||
|
||||
foreach (var keyframe in bone.Keyframes)
|
||||
{
|
||||
output.Write(keyframe.Time);
|
||||
output.Write(keyframe.Rotation);
|
||||
output.Write(keyframe.Translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
return typeof(AnimationClipReader).AssemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,315 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
[ContentProcessor(DisplayName = "Animation Processor")]
|
||||
public class AnimationProcessor : ModelProcessor
|
||||
{
|
||||
private ModelContent model;
|
||||
private ModelExtra modelExtra = new ModelExtra();
|
||||
private Dictionary<MaterialContent, SkinnedMaterialContent> toSkinnedMaterial = new Dictionary<MaterialContent, SkinnedMaterialContent>();
|
||||
private Dictionary<string, int> bones = new Dictionary<string, int>();
|
||||
private Matrix[] boneTransforms;
|
||||
private Dictionary<string, AnimationClip> clips = new Dictionary<string, AnimationClip>();
|
||||
|
||||
public override ModelContent Process(NodeContent input, ContentProcessorContext context)
|
||||
{
|
||||
var skeleton = ProcessSkeleton(input);
|
||||
SwapSkinnedMaterial(input);
|
||||
model = base.Process(input, context);
|
||||
ProcessAnimations(model, input, context);
|
||||
model.Tag = modelExtra;
|
||||
return model;
|
||||
}
|
||||
|
||||
private BoneContent ProcessSkeleton(NodeContent input)
|
||||
{
|
||||
var skeleton = MeshHelper.FindSkeleton(input);
|
||||
|
||||
if (skeleton == null)
|
||||
return null;
|
||||
|
||||
FlattenTransforms(input, skeleton);
|
||||
TrimSkeleton(skeleton);
|
||||
|
||||
var nodes = FlattenHeirarchy(input);
|
||||
var bones = MeshHelper.FlattenSkeleton(skeleton);
|
||||
|
||||
var nodeToIndex = new Dictionary<NodeContent, int>();
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
nodeToIndex[nodes[i]] = i;
|
||||
|
||||
foreach (var bone in bones)
|
||||
modelExtra.Skeleton.Add(nodeToIndex[bone]);
|
||||
|
||||
return skeleton;
|
||||
}
|
||||
|
||||
private List<NodeContent> FlattenHeirarchy(NodeContent item)
|
||||
{
|
||||
var nodes = new List<NodeContent>();
|
||||
nodes.Add(item);
|
||||
|
||||
foreach (var child in item.Children)
|
||||
FlattenHeirarchy(nodes, child);
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private void FlattenHeirarchy(List<NodeContent> nodes, NodeContent item)
|
||||
{
|
||||
nodes.Add(item);
|
||||
foreach (var child in item.Children)
|
||||
FlattenHeirarchy(nodes, child);
|
||||
}
|
||||
|
||||
void FlattenTransforms(NodeContent node, BoneContent skeleton)
|
||||
{
|
||||
foreach (var child in node.Children)
|
||||
{
|
||||
if (child == skeleton)
|
||||
continue;
|
||||
|
||||
if(IsSkinned(child))
|
||||
FlattenAllTransforms(child);
|
||||
}
|
||||
}
|
||||
|
||||
void FlattenAllTransforms(NodeContent node)
|
||||
{
|
||||
MeshHelper.TransformScene(node, node.Transform);
|
||||
|
||||
node.Transform = Matrix.Identity;
|
||||
|
||||
foreach (var child in node.Children)
|
||||
FlattenAllTransforms(child);
|
||||
}
|
||||
|
||||
void TrimSkeleton(NodeContent skeleton)
|
||||
{
|
||||
var todelete = new List<NodeContent>();
|
||||
|
||||
foreach (var child in skeleton.Children)
|
||||
if (child.Name.EndsWith("Nub") || child.Name.EndsWith("Footsteps"))
|
||||
todelete.Add(child);
|
||||
else
|
||||
TrimSkeleton(child);
|
||||
|
||||
foreach (var child in todelete)
|
||||
skeleton.Children.Remove(child);
|
||||
}
|
||||
|
||||
bool IsSkinned(NodeContent node)
|
||||
{
|
||||
var mesh = node as MeshContent;
|
||||
if (mesh != null)
|
||||
foreach (var geometry in mesh.Geometry)
|
||||
foreach (var vchannel in geometry.Vertices.Channels)
|
||||
if (vchannel is VertexChannel<BoneWeightCollection>)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SwapSkinnedMaterial(NodeContent node)
|
||||
{
|
||||
var mesh = node as MeshContent;
|
||||
if (mesh != null)
|
||||
{
|
||||
foreach (var geometry in mesh.Geometry)
|
||||
{
|
||||
bool swap = false;
|
||||
foreach (var vchannel in geometry.Vertices.Channels)
|
||||
{
|
||||
if (vchannel is VertexChannel<BoneWeightCollection>)
|
||||
{
|
||||
swap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (swap)
|
||||
{
|
||||
if (toSkinnedMaterial.ContainsKey(geometry.Material))
|
||||
geometry.Material = toSkinnedMaterial[geometry.Material];
|
||||
else
|
||||
{
|
||||
var smaterial = new SkinnedMaterialContent();
|
||||
var bmaterial = geometry.Material as BasicMaterialContent;
|
||||
|
||||
smaterial.Alpha = bmaterial.Alpha;
|
||||
smaterial.DiffuseColor = bmaterial.DiffuseColor;
|
||||
smaterial.EmissiveColor = bmaterial.EmissiveColor;
|
||||
smaterial.SpecularColor = bmaterial.SpecularColor;
|
||||
smaterial.SpecularPower = bmaterial.SpecularPower;
|
||||
smaterial.Texture = bmaterial.Texture;
|
||||
smaterial.WeightsPerVertex = 4;
|
||||
|
||||
toSkinnedMaterial[geometry.Material] = smaterial;
|
||||
geometry.Material = smaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var child in node.Children)
|
||||
SwapSkinnedMaterial(child);
|
||||
}
|
||||
|
||||
private void ProcessAnimations(ModelContent model, NodeContent input, ContentProcessorContext context)
|
||||
{
|
||||
for (int i = 0; i < model.Bones.Count; i++)
|
||||
bones[model.Bones[i].Name] = i;
|
||||
|
||||
boneTransforms = new Matrix[model.Bones.Count];
|
||||
|
||||
ProcessAnimationsRecursive(input);
|
||||
|
||||
if (modelExtra.Clips.Count == 0)
|
||||
{
|
||||
var clip = new AnimationClip();
|
||||
modelExtra.Clips.Add(clip);
|
||||
|
||||
var clipName = "Take 001";
|
||||
|
||||
clips[clipName] = clip;
|
||||
|
||||
clip.Name = clipName;
|
||||
foreach (var bone in model.Bones)
|
||||
{
|
||||
var clipBone = new AnimationClip.Bone();
|
||||
clipBone.Name = bone.Name;
|
||||
|
||||
clip.Bones.Add(clipBone);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var clip in modelExtra.Clips)
|
||||
{
|
||||
for (int b = 0; b < bones.Count; b++)
|
||||
{
|
||||
var keyframes = clip.Bones[b].Keyframes;
|
||||
if (keyframes.Count == 0 || keyframes[0].Time > 0)
|
||||
{
|
||||
var keyframe = new AnimationClip.Bone.Keyframe();
|
||||
keyframe.Time = 0;
|
||||
keyframe.Transform = boneTransforms[b];
|
||||
keyframes.Insert(0, keyframe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessAnimationsRecursive(NodeContent input)
|
||||
{
|
||||
int inputBoneIndex;
|
||||
if (bones.TryGetValue(input.Name, out inputBoneIndex))
|
||||
boneTransforms[inputBoneIndex] = input.Transform;
|
||||
|
||||
foreach (var animation in input.Animations)
|
||||
{
|
||||
AnimationClip clip;
|
||||
string clipName = animation.Key;
|
||||
|
||||
if (!clips.TryGetValue(clipName, out clip))
|
||||
{
|
||||
clip = new AnimationClip();
|
||||
modelExtra.Clips.Add(clip);
|
||||
|
||||
clips[clipName] = clip;
|
||||
|
||||
clip.Name = clipName;
|
||||
foreach (var bone in model.Bones)
|
||||
{
|
||||
var clipBone = new AnimationClip.Bone();
|
||||
clipBone.Name = bone.Name;
|
||||
|
||||
clip.Bones.Add(clipBone);
|
||||
}
|
||||
}
|
||||
|
||||
if (animation.Value.Duration.TotalSeconds > clip.Duration)
|
||||
clip.Duration = animation.Value.Duration.TotalSeconds;
|
||||
|
||||
foreach (var channel in animation.Value.Channels)
|
||||
{
|
||||
int boneIndex;
|
||||
if (!bones.TryGetValue(channel.Key, out boneIndex))
|
||||
continue;
|
||||
|
||||
if (UselessAnimationTest(boneIndex))
|
||||
continue;
|
||||
|
||||
var keyframes = new LinkedList<AnimationClip.Bone.Keyframe>();
|
||||
foreach (var keyframe in channel.Value)
|
||||
{
|
||||
var transform = keyframe.Transform;
|
||||
|
||||
var newKeyframe = new AnimationClip.Bone.Keyframe();
|
||||
newKeyframe.Time = keyframe.Time.TotalSeconds;
|
||||
newKeyframe.Transform = transform;
|
||||
|
||||
keyframes.AddLast(newKeyframe);
|
||||
}
|
||||
|
||||
LinearKeyframeReduction(keyframes);
|
||||
foreach (var keyframe in keyframes)
|
||||
clip.Bones[boneIndex].Keyframes.Add(keyframe);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var child in input.Children)
|
||||
ProcessAnimationsRecursive(child);
|
||||
}
|
||||
|
||||
private const float TinyLength = 1e-8f;
|
||||
private const float TinyCosAngle = 0.9999999f;
|
||||
|
||||
private void LinearKeyframeReduction(LinkedList<AnimationClip.Bone.Keyframe> keyframes)
|
||||
{
|
||||
if (keyframes.Count < 3)
|
||||
return;
|
||||
|
||||
for (var node = keyframes.First.Next; ; )
|
||||
{
|
||||
var next = node.Next;
|
||||
if (next == null)
|
||||
break;
|
||||
|
||||
// Determine nodes before and after the current node.
|
||||
var a = node.Previous.Value;
|
||||
var b = node.Value;
|
||||
var c = next.Value;
|
||||
|
||||
var t = (float)((node.Value.Time - node.Previous.Value.Time) / (next.Value.Time - node.Previous.Value.Time));
|
||||
|
||||
var translation = Vector3.Lerp(a.Translation, c.Translation, t);
|
||||
var rotation = Quaternion.Slerp(a.Rotation, c.Rotation, t);
|
||||
|
||||
if ((translation - b.Translation).LengthSquared() < TinyLength && Quaternion.Dot(rotation, b.Rotation) > TinyCosAngle)
|
||||
keyframes.Remove(node);
|
||||
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
bool UselessAnimationTest(int boneId)
|
||||
{
|
||||
foreach (var mesh in model.Meshes)
|
||||
if (mesh.ParentBone.Index == boneId)
|
||||
return false;
|
||||
|
||||
foreach (int b in modelExtra.Skeleton)
|
||||
if (boneId == b)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{9975ED45-7A21-4F8A-9EC3-12F5845F681F}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FluckyGame.Client.Pipeline.Animation</RootNamespace>
|
||||
<AssemblyName>FluckyGame.Client.Pipeline.Animation</AssemblyName>
|
||||
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
|
||||
<XnaPlatform>Windows</XnaPlatform>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\x86\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\x86\Release</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<SpecificVersion>True</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86">
|
||||
<SpecificVersion>true</SpecificVersion>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AnimationClip.cs" />
|
||||
<Compile Include="AnimationClipReader.cs" />
|
||||
<Compile Include="AnimationClipWriter.cs" />
|
||||
<Compile Include="AnimationProcessor.cs" />
|
||||
<Compile Include="ModelExtra.cs" />
|
||||
<Compile Include="ModelExtraReader.cs" />
|
||||
<Compile Include="ModelExtraWriter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.ContentPipelineExtensions.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
public class ModelExtra
|
||||
{
|
||||
private List<int> skeleton = new List<int>();
|
||||
private List<AnimationClip> clips = new List<AnimationClip>();
|
||||
|
||||
public List<int> Skeleton { get { return skeleton; } set { skeleton = value; } }
|
||||
public List<AnimationClip> Clips { get { return clips; } set { clips = value; } }
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
public class ModelExtraReader : ContentTypeReader<ModelExtra>
|
||||
{
|
||||
protected override ModelExtra Read(ContentReader input, ModelExtra existingInstance)
|
||||
{
|
||||
var extra = new ModelExtra();
|
||||
extra.Skeleton = input.ReadObject<List<int>>();
|
||||
extra.Clips = input.ReadObject<List<AnimationClip>>();
|
||||
return extra;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline;
|
||||
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
|
||||
|
||||
namespace FluckyGame.Client.Pipeline.Animation
|
||||
{
|
||||
[ContentTypeWriter]
|
||||
public class ModelExtraWriter : ContentTypeWriter<ModelExtra>
|
||||
{
|
||||
protected override void Write(ContentWriter output, ModelExtra extra)
|
||||
{
|
||||
output.WriteObject(extra.Skeleton);
|
||||
output.WriteObject(extra.Clips);
|
||||
}
|
||||
|
||||
public override string GetRuntimeReader(TargetPlatform targetPlatform)
|
||||
{
|
||||
return typeof(ModelExtraReader).AssemblyQualifiedName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("FluckyGame.Client.Pipeline.Animation")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FluckyGame.Client.Pipeline.Animation")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("9975ed45-7a21-4f8a-9ec3-12f5845f681f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
68
src/FluckyGame.Client/FluckyGame.Client/Bone.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FluckyGame.Client
|
||||
{
|
||||
public class Bone
|
||||
{
|
||||
private Bone parent = null;
|
||||
private List<Bone> children = new List<Bone>();
|
||||
private Matrix bindTransform = Matrix.Identity;
|
||||
private Vector3 bindScale = Vector3.One;
|
||||
private Vector3 translation = Vector3.Zero;
|
||||
private Quaternion rotation = Quaternion.Identity;
|
||||
private Vector3 scale = Vector3.One;
|
||||
|
||||
public string Name = "";
|
||||
public Matrix BindTransform { get { return bindTransform; } }
|
||||
public Matrix SkinTransform { get; set; }
|
||||
public Quaternion Rotation { get { return rotation; } set { rotation = value; } }
|
||||
public Vector3 Translation { get { return translation; } set { translation = value; } }
|
||||
public Vector3 Scale { get { return scale; } set { scale = value; } }
|
||||
public Bone Parent { get { return parent; } }
|
||||
public List<Bone> Children { get { return children; } }
|
||||
public Matrix AbsoluteTransform = Matrix.Identity;
|
||||
|
||||
public Bone(string name, Matrix bindTransform, Bone parent)
|
||||
{
|
||||
this.Name = name;
|
||||
this.parent = parent;
|
||||
if (parent != null)
|
||||
parent.children.Add(this);
|
||||
|
||||
this.bindScale = new Vector3(bindTransform.Right.Length(),
|
||||
bindTransform.Up.Length(), bindTransform.Backward.Length());
|
||||
|
||||
bindTransform.Right = bindTransform.Right / bindScale.X;
|
||||
bindTransform.Up = bindTransform.Up / bindScale.Y;
|
||||
bindTransform.Backward = bindTransform.Backward / bindScale.Y;
|
||||
this.bindTransform = bindTransform;
|
||||
|
||||
ComputeAbsoluteTransform();
|
||||
SkinTransform = Matrix.Invert(AbsoluteTransform);
|
||||
}
|
||||
|
||||
public void ComputeAbsoluteTransform()
|
||||
{
|
||||
var transform =
|
||||
Matrix.CreateScale(Scale * bindScale) *
|
||||
Matrix.CreateFromQuaternion(Rotation) *
|
||||
Matrix.CreateTranslation(Translation) *
|
||||
BindTransform;
|
||||
|
||||
if (Parent != null)
|
||||
AbsoluteTransform = transform * Parent.AbsoluteTransform;
|
||||
else
|
||||
AbsoluteTransform = transform;
|
||||
}
|
||||
|
||||
public void SetCompleteTransform(Matrix m)
|
||||
{
|
||||
var setTo = m * Matrix.Invert(BindTransform);
|
||||
|
||||
Translation = setTo.Translation;
|
||||
Rotation = Quaternion.CreateFromRotationMatrix(setTo);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace FluckyGame.Client.Entities
|
||||
{
|
||||
class BouncingEntity : ModelEntity
|
||||
{
|
||||
float ySpeed;
|
||||
|
||||
const float randomMin = 1;
|
||||
const float randomMax = 5;
|
||||
|
||||
public BouncingEntity(Model model) :
|
||||
base(model)
|
||||
{
|
||||
ySpeed = ((float)Game1.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
}
|
||||
|
||||
public BouncingEntity(Model model, Vector3 position) :
|
||||
base(model, position)
|
||||
{
|
||||
ySpeed = ((float)Game1.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
}
|
||||
|
||||
public BouncingEntity(Model model, Vector3 position, Vector3 rotation) :
|
||||
base(model, position, rotation)
|
||||
{
|
||||
ySpeed = ((float)Game1.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
}
|
||||
|
||||
public BouncingEntity(Model model, Vector3 position, Vector3 rotation, Vector3 scalation) :
|
||||
base(model, position, rotation, scalation)
|
||||
{
|
||||
ySpeed = ((float)Game1.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
}
|
||||
|
||||
public override void Update(GameTime gameTime, KeyboardState keyboardState, MouseState mouseState)
|
||||
{
|
||||
base.Update(gameTime, keyboardState, mouseState);
|
||||
|
||||
if (Position.Y > 0)
|
||||
ySpeed -= 0.1f / 17 * gameTime.ElapsedGameTime.Milliseconds;
|
||||
else
|
||||
ySpeed = ((float)Game1.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
|
||||
Position.Y += ySpeed / 17 * gameTime.ElapsedGameTime.Milliseconds;
|
||||
|
||||
UpdateWorld();
|
||||
}
|
||||
}
|
||||
}
|
15
src/FluckyGame.Client/FluckyGame.Client/Entities/Entity.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace FluckyGame.Client
|
||||
{
|
||||
public class Entity
|
||||
{
|
||||
public virtual void Update(GameTime gameTime, KeyboardState keyboardState, MouseState mouseState)
|
||||
{ }
|
||||
|
||||
public virtual void Draw(GameTime gameTime)
|
||||
{ }
|
||||
}
|
||||
}
|
288
src/FluckyGame.Client/FluckyGame.Client/Entities/ModelEntity.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using FluckyGame.Client.Pipeline.Animation;
|
||||
|
||||
namespace FluckyGame.Client.Entities
|
||||
{
|
||||
public class ModelEntity : Entity
|
||||
{
|
||||
public Vector3 Position;
|
||||
public Vector3 Rotation;
|
||||
public Vector3 Scalation;
|
||||
|
||||
Model model;
|
||||
public Model Model { get { return model; } }
|
||||
|
||||
AnimationClip animationClip;
|
||||
public AnimationClip AnimationClip
|
||||
{
|
||||
get { return animationClip; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
if (animationClip == null)
|
||||
throw new Exception("No clip playing!");
|
||||
|
||||
animationClip = value;
|
||||
boneInfos = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animationClip != null)
|
||||
throw new Exception("Another clip playing!");
|
||||
|
||||
animationClip = value;
|
||||
animationPlaying = false;
|
||||
animationLooping = false;
|
||||
animationDuration = (float)animationClip.Duration;
|
||||
animationSpeed = 1;
|
||||
boneInfos = new BoneInfo[animationClip.Bones.Count];
|
||||
for (int i = 0; i < boneInfos.Length; i++)
|
||||
boneInfos[i] = new BoneInfo(model, animationClip.Bones[i]);
|
||||
animationPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool animationPlaying;
|
||||
public bool AnimationPlaying
|
||||
{
|
||||
get { if (animationClip == null) throw new Exception("No clip playing!"); else return animationPlaying; }
|
||||
set { if (animationClip == null) throw new Exception("No clip playing!"); else animationPlaying = value; }
|
||||
}
|
||||
|
||||
bool animationLooping;
|
||||
public bool AnimationLooping
|
||||
{
|
||||
get { if (animationClip == null) throw new Exception("No clip playing!"); else return animationLooping; }
|
||||
set { if (animationClip == null) throw new Exception("No clip playing!"); else animationLooping = value; }
|
||||
}
|
||||
|
||||
float animationDuration;
|
||||
public float AnimationDuration
|
||||
{
|
||||
get { if (animationClip == null) throw new Exception("No clip playing!"); else return animationDuration; }
|
||||
}
|
||||
|
||||
float animationSpeed;
|
||||
public float AnimationSpeed
|
||||
{
|
||||
get { if (animationClip == null) throw new Exception("No clip playing!"); else return animationSpeed; }
|
||||
set { if (animationClip == null) throw new Exception("No clip playing!"); else animationSpeed = value; }
|
||||
}
|
||||
|
||||
float animationPosition;
|
||||
public float AnimationPosition
|
||||
{
|
||||
get { if (animationClip == null) throw new Exception("No clip playing!"); else return animationPosition; }
|
||||
set
|
||||
{
|
||||
if (animationClip == null)
|
||||
throw new Exception("No clip playing!");
|
||||
else
|
||||
{
|
||||
animationPosition = value;
|
||||
|
||||
while (animationPosition < 0)
|
||||
animationPosition += animationDuration;
|
||||
|
||||
while (animationPosition > animationDuration)
|
||||
animationPosition -= animationDuration;
|
||||
|
||||
foreach (var bone in boneInfos)
|
||||
bone.SetPosition(animationPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BoneInfo[] boneInfos;
|
||||
|
||||
Matrix world;
|
||||
|
||||
public ModelEntity(Model model)
|
||||
{
|
||||
this.model = model;
|
||||
|
||||
Position = Vector3.Zero;
|
||||
Rotation = Vector3.Zero;
|
||||
Scalation = new Vector3(1, 1, 1);
|
||||
|
||||
UpdateWorld();
|
||||
}
|
||||
|
||||
public ModelEntity(Model model, Vector3 position)
|
||||
{
|
||||
this.model = model;
|
||||
|
||||
this.Position = position;
|
||||
Rotation = Vector3.Zero;
|
||||
Scalation = new Vector3(1, 1, 1);
|
||||
|
||||
UpdateWorld();
|
||||
}
|
||||
|
||||
public ModelEntity(Model model, Vector3 position, Vector3 rotation)
|
||||
{
|
||||
this.model = model;
|
||||
|
||||
this.Position = position;
|
||||
this.Rotation = rotation;
|
||||
Scalation = new Vector3(1, 1, 1);
|
||||
|
||||
UpdateWorld();
|
||||
}
|
||||
|
||||
public ModelEntity(Model model, Vector3 position, Vector3 rotation, Vector3 scalation)
|
||||
{
|
||||
this.model = model;
|
||||
|
||||
this.Position = position;
|
||||
this.Rotation = rotation;
|
||||
this.Scalation = scalation;
|
||||
|
||||
UpdateWorld();
|
||||
}
|
||||
|
||||
public void UpdateWorld()
|
||||
{
|
||||
world = Matrix.CreateScale(Scalation) * Matrix.CreateFromYawPitchRoll(Rotation.X, Rotation.Y, Rotation.Z) * Matrix.CreateTranslation(Position);
|
||||
}
|
||||
|
||||
public override void Draw(GameTime gameTime)
|
||||
{
|
||||
if (animationClip == null)
|
||||
{
|
||||
foreach (var mesh in model.Meshes)
|
||||
{
|
||||
foreach (var effect in mesh.Effects)
|
||||
if (effect is IEffectMatrices)
|
||||
(effect as IEffectMatrices).World = world;
|
||||
|
||||
mesh.Draw();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animationPlaying)
|
||||
{
|
||||
AnimationPosition += (float)gameTime.ElapsedGameTime.TotalSeconds * animationSpeed;
|
||||
if (AnimationLooping && AnimationPosition >= AnimationDuration)
|
||||
AnimationPosition -= AnimationDuration;
|
||||
}
|
||||
|
||||
var modelExtra = Game1.currentInstance.modelExtras[model];
|
||||
var bones = Game1.currentInstance.modelBones[model];
|
||||
|
||||
var boneTransforms = new Matrix[bones.Count];
|
||||
for (int i = 0; i < bones.Count; i++)
|
||||
{
|
||||
var bone = bones[i];
|
||||
bone.ComputeAbsoluteTransform();
|
||||
boneTransforms[i] = bone.AbsoluteTransform;
|
||||
}
|
||||
|
||||
var skeleton = new Matrix[modelExtra.Skeleton.Count];
|
||||
for (int s = 0; s < modelExtra.Skeleton.Count; s++)
|
||||
{
|
||||
var bone = bones[modelExtra.Skeleton[s]];
|
||||
skeleton[s] = bone.SkinTransform * bone.AbsoluteTransform;
|
||||
}
|
||||
|
||||
foreach (var modelMesh in model.Meshes)
|
||||
{
|
||||
foreach (var effect in modelMesh.Effects)
|
||||
{
|
||||
if (effect is IEffectMatrices)
|
||||
(effect as IEffectMatrices).World = boneTransforms[modelMesh.ParentBone.Index] * world;
|
||||
|
||||
if (effect is SkinnedEffect)
|
||||
(effect as SkinnedEffect).SetBoneTransforms(skeleton);
|
||||
|
||||
modelMesh.Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BoneInfo
|
||||
{
|
||||
private int currentKeyframe = 0;
|
||||
private Bone assignedBone = null;
|
||||
public bool valid = false;
|
||||
private Quaternion rotation;
|
||||
public Vector3 translation;
|
||||
public AnimationClip.Bone.Keyframe Keyframe1;
|
||||
public AnimationClip.Bone.Keyframe Keyframe2;
|
||||
|
||||
public AnimationClip.Bone ClipBone { get; set; }
|
||||
public Bone ModelBone { get { return assignedBone; } }
|
||||
|
||||
public BoneInfo(Model model, AnimationClip.Bone bone)
|
||||
{
|
||||
this.ClipBone = bone;
|
||||
SetKeyframes();
|
||||
SetPosition(0);
|
||||
assignedBone = Game1.currentInstance.modelBones[model].FirstOrDefault(o => o.Name == ClipBone.Name);
|
||||
}
|
||||
|
||||
public void SetPosition(float position)
|
||||
{
|
||||
var keyframes = ClipBone.Keyframes;
|
||||
if (keyframes.Count == 0)
|
||||
return;
|
||||
|
||||
while (position < Keyframe1.Time && currentKeyframe > 0)
|
||||
{
|
||||
currentKeyframe--;
|
||||
SetKeyframes();
|
||||
}
|
||||
|
||||
while (position >= Keyframe2.Time && currentKeyframe < ClipBone.Keyframes.Count - 2)
|
||||
{
|
||||
currentKeyframe++;
|
||||
SetKeyframes();
|
||||
}
|
||||
|
||||
if (Keyframe1 == Keyframe2)
|
||||
{
|
||||
rotation = Keyframe1.Rotation;
|
||||
translation = Keyframe1.Translation;
|
||||
}
|
||||
else
|
||||
{
|
||||
var t = (float)((position - Keyframe1.Time) / (Keyframe2.Time - Keyframe1.Time));
|
||||
rotation = Quaternion.Slerp(Keyframe1.Rotation, Keyframe2.Rotation, t);
|
||||
translation = Vector3.Lerp(Keyframe1.Translation, Keyframe2.Translation, t);
|
||||
}
|
||||
|
||||
valid = true;
|
||||
if (assignedBone != null)
|
||||
{
|
||||
var m = Matrix.CreateFromQuaternion(rotation);
|
||||
m.Translation = translation;
|
||||
assignedBone.SetCompleteTransform(m);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetKeyframes()
|
||||
{
|
||||
if (ClipBone.Keyframes.Count > 0)
|
||||
{
|
||||
Keyframe1 = ClipBone.Keyframes[currentKeyframe];
|
||||
if (currentKeyframe == ClipBone.Keyframes.Count - 1)
|
||||
Keyframe2 = Keyframe1;
|
||||
else
|
||||
Keyframe2 = ClipBone.Keyframes[currentKeyframe + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
Keyframe1 = null;
|
||||
Keyframe2 = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
src/FluckyGame.Client/FluckyGame.Client/Entities/PlayerEntity.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using FluckyGame.Library;
|
||||
|
||||
namespace FluckyGame.Client.Entities
|
||||
{
|
||||
public class PlayerEntity : ModelEntity
|
||||
{
|
||||
bool lastDragging;
|
||||
|
||||
float cameraYaw;
|
||||
float CameraYaw { get { return cameraYaw; } }
|
||||
|
||||
float cameraPitch;
|
||||
float CameraPitch { get { return cameraPitch; } }
|
||||
|
||||
float cameraDistance;
|
||||
float CameraDistance { get { return cameraDistance; } }
|
||||
|
||||
public PlayerEntity() :
|
||||
base(Game1.currentInstance.models["dude"])
|
||||
{
|
||||
AnimationClip = Game1.currentInstance.modelExtras[Model].Clips[0];
|
||||
AnimationLooping = true;
|
||||
|
||||
cameraDistance = 200;
|
||||
}
|
||||
|
||||
public override void Update(GameTime gameTime, KeyboardState keyboardState, MouseState mouseState)
|
||||
{
|
||||
base.Update(gameTime, keyboardState, mouseState);
|
||||
|
||||
var shift = keyboardState.IsKeyDown(Keys.LeftShift);
|
||||
|
||||
if (keyboardState.IsKeyDown(Keys.W))
|
||||
Position += Vector3.Transform(new Vector3(0, 0, shift ? -3 :-1), Matrix.CreateRotationY(Rotation.X));
|
||||
|
||||
if (keyboardState.IsKeyDown(Keys.S))
|
||||
Position += Vector3.Transform(new Vector3(0, 0, shift ? 3 : 1), Matrix.CreateRotationY(Rotation.X));
|
||||
|
||||
if (keyboardState.IsKeyDown(Keys.A))
|
||||
Rotation.X += 0.05f;
|
||||
|
||||
if (keyboardState.IsKeyDown(Keys.D))
|
||||
Rotation.X -= 0.05f;
|
||||
|
||||
Rotation.X = MathHelper.WrapAngle(Rotation.X);
|
||||
|
||||
if (Game1.currentInstance.IsActive)
|
||||
{
|
||||
bool currentlyDragging = mouseState.LeftButton == ButtonState.Pressed;
|
||||
|
||||
if (currentlyDragging)
|
||||
{
|
||||
var centerX = Game1.currentInstance.graphicsDeviceManager.PreferredBackBufferWidth / 2;
|
||||
var centerY = Game1.currentInstance.graphicsDeviceManager.PreferredBackBufferHeight / 2;
|
||||
|
||||
if (lastDragging)
|
||||
{
|
||||
cameraYaw -= (mouseState.X - centerX) / 500.0f;
|
||||
cameraPitch -= (mouseState.Y - centerY) / 500.0f;
|
||||
|
||||
cameraYaw = MathHelper.WrapAngle(cameraYaw);
|
||||
cameraPitch = MathHelper.Clamp(cameraPitch, -MathHelper.PiOver2, MathHelper.PiOver2);
|
||||
}
|
||||
|
||||
Mouse.SetPosition(centerX, centerY);
|
||||
}
|
||||
|
||||
lastDragging = currentlyDragging;
|
||||
}
|
||||
|
||||
if (keyboardState.IsKeyDown(Keys.W) ||
|
||||
keyboardState.IsKeyDown(Keys.S) ||
|
||||
keyboardState.IsKeyDown(Keys.A) ||
|
||||
keyboardState.IsKeyDown(Keys.D))
|
||||
{
|
||||
AnimationPlaying = true;
|
||||
AnimationSpeed = keyboardState.IsKeyDown(Keys.S) ? (shift ? -3 : -1) : (shift ? 3 : 1);
|
||||
if (Game1.currentInstance.IsActive && mouseState.LeftButton == ButtonState.Released)
|
||||
{
|
||||
cameraYaw = MathHelper.SmoothStep(cameraYaw, new List<float>() { Rotation.X - MathHelper.TwoPi, Rotation.X, Rotation.X + MathHelper.TwoPi }.OrderBy(o => Math.Abs(o - cameraYaw)).First(), 0.1f);
|
||||
cameraPitch = MathHelper.SmoothStep(cameraPitch, Rotation.Y + (MathHelper.PiOver4 / 4), 0.1f);
|
||||
}
|
||||
|
||||
Game1.currentInstance.SendPacket(new Packet() {
|
||||
{ "type", "PLAYER" },
|
||||
{ "position", Position },
|
||||
{ "rotation", Rotation }
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimationPlaying = false;
|
||||
}
|
||||
|
||||
UpdateWorld();
|
||||
|
||||
var test = new Vector3(0, 50, 0);
|
||||
|
||||
var view = Matrix.CreateLookAt(test + Position + Vector3.Transform(new Vector3(0, cameraDistance, 0), Matrix.CreateRotationX(cameraPitch - MathHelper.PiOver2) * Matrix.CreateRotationY(cameraYaw - MathHelper.Pi)), test + Position, Vector3.Up);
|
||||
foreach (var model in Game1.currentInstance.models.Values)
|
||||
foreach (var mesh in model.Meshes)
|
||||
foreach (var effect in mesh.Effects)
|
||||
if (effect is IEffectMatrices)
|
||||
{
|
||||
var meffect = effect as IEffectMatrices;
|
||||
meffect.View = view;
|
||||
}
|
||||
Game1.currentInstance.terrain.View = view;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace FluckyGame.Client.Entities
|
||||
{
|
||||
public class TerrainEntity : Entity
|
||||
{
|
||||
VertexPositionColor[] vertices;
|
||||
short[] indices;
|
||||
BasicEffect effect;
|
||||
GraphicsDevice graphicsDevice;
|
||||
|
||||
public Matrix View { set { effect.View = value; } }
|
||||
|
||||
public TerrainEntity(int width, int height, GraphicsDevice graphicsDevice, Matrix projection) :
|
||||
base()
|
||||
{
|
||||
this.graphicsDevice = graphicsDevice;
|
||||
effect = new BasicEffect(this.graphicsDevice);
|
||||
effect.Projection = projection;
|
||||
effect.VertexColorEnabled = true;
|
||||
|
||||
vertices = new VertexPositionColor[width * height];
|
||||
indices = new short[(width - 1) * (height - 1) * 6];
|
||||
int currentIndex = 0;
|
||||
for (int x = 0; x < width; x++)
|
||||
for(int z = 0; z < height; z++)
|
||||
{
|
||||
vertices[x + z * width].Position = new Vector3(-8000 + (16000 / width * x), (float)Game1.random.NextDouble() * 50 - 50, -8000 + (16000 / height * z));
|
||||
vertices[x + z * width].Color = new Color(Game1.random.Next(0, 255), Game1.random.Next(0, 255), Game1.random.Next(0, 255));
|
||||
|
||||
if(x < width - 1 && z < height - 1)
|
||||
{
|
||||
short downLeft = (short)(x + z * width);
|
||||
short downRight = (short)((x + 1) + z * width);
|
||||
short upLeft = (short)(x + (z + 1) * width);
|
||||
short upRight = (short)((x + 1) + (z + 1) * width);
|
||||
|
||||
indices[currentIndex++] = downRight;
|
||||
indices[currentIndex++] = upLeft;
|
||||
indices[currentIndex++] = downLeft;
|
||||
indices[currentIndex++] = upRight;
|
||||
indices[currentIndex++] = upLeft;
|
||||
indices[currentIndex++] = downRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(GameTime gameTime)
|
||||
{
|
||||
base.Draw(gameTime);
|
||||
|
||||
effect.CurrentTechnique.Passes[0].Apply();
|
||||
graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, indices.Length / 3);
|
||||
}
|
||||
}
|
||||
}
|
132
src/FluckyGame.Client/FluckyGame.Client/FluckyGame.Client.csproj
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}</ProjectGuid>
|
||||
<ProjectTypeGuids>{6D335F3A-9D43-41b4-9D22-F6F17C4BE596};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FluckyGame.Client</RootNamespace>
|
||||
<AssemblyName>FluckyGame.Client</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
|
||||
<XnaPlatform>Windows</XnaPlatform>
|
||||
<XnaProfile>HiDef</XnaProfile>
|
||||
<XnaCrossPlatformGroupID>51098c2e-0727-4c82-8833-f5db8d6e4d2f</XnaCrossPlatformGroupID>
|
||||
<XnaOutputType>Game</XnaOutputType>
|
||||
<ApplicationIcon>Game.ico</ApplicationIcon>
|
||||
<Thumbnail>GameThumbnail.png</Thumbnail>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\x86\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;WINDOWS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<XnaCompressContent>false</XnaCompressContent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\x86\Release</OutputPath>
|
||||
<DefineConstants>TRACE;WINDOWS</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<XnaCompressContent>true</XnaCompressContent>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Graphics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="Microsoft.Xna.Framework.GamerServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Net" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Bone.cs" />
|
||||
<Compile Include="Entities\BouncingEntity.cs" />
|
||||
<Compile Include="Entities\Entity.cs" />
|
||||
<Compile Include="Entities\TerrainEntity.cs" />
|
||||
<Compile Include="Entities\ModelEntity.cs" />
|
||||
<Compile Include="Entities\PlayerEntity.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Game1.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Game.ico" />
|
||||
<Content Include="GameThumbnail.png">
|
||||
<XnaPlatformSpecific>true</XnaPlatformSpecific>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\FluckyGame.Library\FluckyGame.Library.csproj">
|
||||
<Project>{1cef270c-fce8-4bd1-920f-440d9cc8ed5b}</Project>
|
||||
<Name>FluckyGame.Library</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\FluckyGame.Client.Pipeline\FluckyGame.Client.Pipeline.Animation\FluckyGame.Client.Pipeline.Animation.csproj">
|
||||
<Project>{9975ed45-7a21-4f8a-9ec3-12f5845f681f}</Project>
|
||||
<Name>FluckyGame.Client.Pipeline.Animation</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\FluckyGame.ClientContent\FluckyGame.ClientContent.contentproj">
|
||||
<Name>FluckyGame.ClientContent</Name>
|
||||
<XnaReferenceType>Content</XnaReferenceType>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 und x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 4.5</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.targets" />
|
||||
<!--
|
||||
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
BIN
src/FluckyGame.Client/FluckyGame.Client/Game.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
362
src/FluckyGame.Client/FluckyGame.Client/Game1.cs
Normal file
@@ -0,0 +1,362 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using FluckyGame.Client.Entities;
|
||||
using FluckyGame.Client.Pipeline.Animation;
|
||||
using FluckyGame.Library;
|
||||
|
||||
namespace FluckyGame.Client
|
||||
{
|
||||
public class Game1 : Microsoft.Xna.Framework.Game
|
||||
{
|
||||
public static Game1 currentInstance;
|
||||
public static Random random;
|
||||
|
||||
SpriteBatch spriteBatch;
|
||||
SpriteFont spriteFont;
|
||||
|
||||
public GraphicsDeviceManager graphicsDeviceManager;
|
||||
|
||||
public Dictionary<string, Model> models;
|
||||
public Dictionary<Model, ModelExtra> modelExtras;
|
||||
public Dictionary<Model, List<Bone>> modelBones;
|
||||
|
||||
public List<Entity> entities;
|
||||
public Dictionary<string, ModelEntity> entitiesById;
|
||||
public PlayerEntity player;
|
||||
public TerrainEntity terrain;
|
||||
|
||||
bool[] last;
|
||||
bool wireframe;
|
||||
|
||||
public Thread networkingThread;
|
||||
public TcpClient tcpClient;
|
||||
public NetworkStream networkStream;
|
||||
private Queue<Packet> queue;
|
||||
private bool exiting;
|
||||
|
||||
static Game1()
|
||||
{
|
||||
random = new Random();
|
||||
}
|
||||
|
||||
public Game1(TcpClient tcpClient)
|
||||
{
|
||||
this.tcpClient = tcpClient;
|
||||
|
||||
currentInstance = this;
|
||||
|
||||
graphicsDeviceManager = new GraphicsDeviceManager(this)
|
||||
{
|
||||
PreferredBackBufferWidth = 1920 / 2,
|
||||
PreferredBackBufferHeight = 1080 / 2
|
||||
};
|
||||
Content.RootDirectory = "Content";
|
||||
|
||||
IsMouseVisible = true;
|
||||
|
||||
last = new bool[] { false, false, false, false, false, false, false, false, false, false };
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
spriteFont = Content.Load<SpriteFont>("SpriteFont");
|
||||
|
||||
models = new Dictionary<string, Model>();
|
||||
modelExtras = new Dictionary<Model, ModelExtra>();
|
||||
modelBones = new Dictionary<Model, List<Bone>>();
|
||||
|
||||
var projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 0.1f, 5000.0f);
|
||||
foreach (var modelName in new[] { "box", "cone", "cylinder", "dude", "figure", "monkey", "sphere", "torus", "Victoria-hat-dance", "Victoria-hat-tpose" })
|
||||
{
|
||||
var model = Content.Load<Model>(Path.Combine("Models", modelName));
|
||||
|
||||
foreach (var mesh in model.Meshes)
|
||||
{
|
||||
foreach (var effect in mesh.Effects)
|
||||
{
|
||||
if (effect is IEffectMatrices)
|
||||
(effect as IEffectMatrices).Projection = projection;
|
||||
|
||||
if (effect is IEffectLights)
|
||||
(effect as IEffectLights).EnableDefaultLighting();
|
||||
|
||||
if (effect is BasicEffect)
|
||||
(effect as BasicEffect).PreferPerPixelLighting = true;
|
||||
|
||||
if (effect is SkinnedEffect)
|
||||
(effect as SkinnedEffect).PreferPerPixelLighting = true;
|
||||
}
|
||||
}
|
||||
|
||||
models.Add(modelName, model);
|
||||
|
||||
var bones = new List<Bone>();
|
||||
foreach (ModelBone bone in model.Bones)
|
||||
bones.Add(new Bone(bone.Name, bone.Transform, bone.Parent != null ? bones[bone.Parent.Index] : null));
|
||||
modelBones.Add(model, bones);
|
||||
|
||||
if (model.Tag is ModelExtra)
|
||||
{
|
||||
var modelExtra = model.Tag as ModelExtra;
|
||||
modelExtras.Add(model, modelExtra);
|
||||
}
|
||||
}
|
||||
|
||||
var texture = Content.Load<Texture2D>(Path.Combine("Models", "figure_texture"));
|
||||
foreach (var mesh in models["figure"].Meshes)
|
||||
foreach (BasicEffect effect in mesh.Effects)
|
||||
{
|
||||
effect.Texture = texture;
|
||||
effect.TextureEnabled = true;
|
||||
}
|
||||
|
||||
entities = new List<Entity>()
|
||||
{
|
||||
(player = new PlayerEntity()),
|
||||
(terrain = new TerrainEntity(200, 200, GraphicsDevice, projection))
|
||||
};
|
||||
|
||||
entitiesById = new Dictionary<string, ModelEntity>();
|
||||
|
||||
queue = new Queue<Packet>();
|
||||
|
||||
networkStream = this.tcpClient.GetStream();
|
||||
|
||||
networkingThread = new Thread(ReceivePackets);
|
||||
networkingThread.IsBackground = true;
|
||||
networkingThread.Start();
|
||||
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
private void ReceivePackets()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var packet = Packet.Receive(networkStream);
|
||||
|
||||
lock (queue)
|
||||
queue.Enqueue(packet);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if (!exiting)
|
||||
{
|
||||
System.Windows.Forms.MessageBox.Show("Verbindungsfehler:\n\n" + ex.Message, "Verbindungsfehler!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
|
||||
Exit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SendPacket(Packet packet)
|
||||
{
|
||||
packet.Send(networkStream);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
lock(queue)
|
||||
{
|
||||
while(queue.Count > 0)
|
||||
{
|
||||
var packet = queue.Dequeue();
|
||||
|
||||
var type = (string)packet["type"];
|
||||
if (type == "NEW")
|
||||
{
|
||||
var model = (string)packet["model"];
|
||||
var position = (Vector3)packet["position"];
|
||||
var rotation = (Vector3)packet["rotation"];
|
||||
var scalation = (Vector3)packet["scalation"];
|
||||
var entity = new ModelEntity(
|
||||
models[model],
|
||||
position,
|
||||
rotation,
|
||||
scalation
|
||||
);
|
||||
entities.Add(entity);
|
||||
entitiesById.Add((string)packet["id"], entity);
|
||||
}
|
||||
else if(type == "REMOVE")
|
||||
{
|
||||
var id = (string)packet["id"];
|
||||
entities.Remove(entitiesById[id]);
|
||||
entitiesById.Remove(id);
|
||||
}
|
||||
else if (type == "UPDATE")
|
||||
{
|
||||
ModelEntity entity = entitiesById[(string)packet["id"]];
|
||||
if (packet.ContainsKey("position"))
|
||||
entity.Position = (Vector3)packet["position"];
|
||||
if (packet.ContainsKey("rotation"))
|
||||
entity.Rotation = (Vector3)packet["rotation"];
|
||||
if (packet.ContainsKey("scalation"))
|
||||
entity.Scalation = (Vector3)packet["scalation"];
|
||||
entity.UpdateWorld();
|
||||
}
|
||||
else
|
||||
throw new Exception("Unknown packet type!");
|
||||
}
|
||||
}
|
||||
|
||||
var kState = IsActive ? Keyboard.GetState() : new KeyboardState();
|
||||
var mState = IsActive ? Mouse.GetState() : new MouseState();
|
||||
|
||||
if (kState.IsKeyDown(Keys.Escape))
|
||||
{
|
||||
exiting = true;
|
||||
networkingThread.Abort();
|
||||
Exit();
|
||||
}
|
||||
|
||||
if (kState.IsKeyDown(Keys.D1) && !last[0])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "box" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(25) }
|
||||
});
|
||||
last[0] = kState.IsKeyDown(Keys.D1);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D2) && !last[1])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "cone" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(25) }
|
||||
});
|
||||
last[1] = kState.IsKeyDown(Keys.D2);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D3) && !last[2])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "cylinder" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(25) }
|
||||
});
|
||||
last[2] = kState.IsKeyDown(Keys.D3);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D4) && !last[3])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "dude" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(1) }
|
||||
});
|
||||
last[3] = kState.IsKeyDown(Keys.D4);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D5) && !last[4])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "monkey" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(25) }
|
||||
});
|
||||
last[4] = kState.IsKeyDown(Keys.D5);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D6) && !last[5])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "sphere" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(25) }
|
||||
});
|
||||
last[5] = kState.IsKeyDown(Keys.D6);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D7) && !last[6])
|
||||
SendPacket(new Packet() {
|
||||
{ "type", "ADD" },
|
||||
{ "model", "torus" },
|
||||
{ "position", player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)) + new Vector3(0, 25, 0) },
|
||||
{ "rotation", player.Rotation },
|
||||
{ "scalation", new Vector3(25) }
|
||||
});
|
||||
last[6] = kState.IsKeyDown(Keys.D7);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D8) && !last[7])
|
||||
entities.Add(new ModelEntity(models["Victoria-hat-tpose"], player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)), player.Rotation));
|
||||
last[7] = kState.IsKeyDown(Keys.D8);
|
||||
|
||||
if (kState.IsKeyDown(Keys.D9) && !last[8])
|
||||
{
|
||||
var entity = new ModelEntity(models["Victoria-hat-tpose"], player.Position + Vector3.Transform(new Vector3(0, 0, -100), Matrix.CreateRotationY(player.Rotation.X)), player.Rotation, new Vector3(0.4f));
|
||||
entity.AnimationClip = modelExtras[models["Victoria-hat-dance"]].Clips[0];
|
||||
entity.AnimationLooping = true;
|
||||
entity.AnimationPlaying = true;
|
||||
entities.Add(entity);
|
||||
}
|
||||
last[8] = kState.IsKeyDown(Keys.D9);
|
||||
|
||||
if (kState.IsKeyDown(Keys.R) && !last[9])
|
||||
wireframe = !wireframe;
|
||||
last[9] = kState.IsKeyDown(Keys.R);
|
||||
|
||||
foreach (var entity in entities)
|
||||
entity.Update(gameTime, kState, mState);
|
||||
|
||||
base.Update(gameTime);
|
||||
}
|
||||
|
||||
protected override void Draw(GameTime gameTime)
|
||||
{
|
||||
GraphicsDevice.Clear(Color.CornflowerBlue);
|
||||
|
||||
GraphicsDevice.BlendState = BlendState.Opaque;
|
||||
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
|
||||
|
||||
if(wireframe)
|
||||
{
|
||||
var rState = new RasterizerState();
|
||||
rState.FillMode = FillMode.WireFrame;
|
||||
GraphicsDevice.RasterizerState = rState;
|
||||
}
|
||||
|
||||
foreach (var entity in entities)
|
||||
entity.Draw(gameTime);
|
||||
|
||||
spriteBatch.Begin();
|
||||
|
||||
{
|
||||
var text = string.Format("{0} FPS", (int)(1000 / gameTime.ElapsedGameTime.TotalMilliseconds));
|
||||
spriteBatch.DrawString(spriteFont, text, new Vector2(graphicsDeviceManager.PreferredBackBufferWidth - spriteFont.MeasureString(text).X, 0), Color.White);
|
||||
}
|
||||
|
||||
spriteBatch.DrawString(spriteFont, string.Format("Player: Position: {0:F2}, {1:F2}, {2:F2} Rotation: {3:F2} {4:F2} {5:F2}", player.Position.X, player.Position.Y, player.Position.Z, player.Rotation.X, player.Rotation.Y, player.Rotation.Z), Vector2.Zero, Color.White);
|
||||
|
||||
spriteBatch.DrawString(spriteFont, "Press any key to spawn entity:", new Vector2(0, 40), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "1 - Box", new Vector2(0, 60), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "2 - Cone", new Vector2(0, 80), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "3 - Cylinder", new Vector2(0, 100), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "4 - Dude", new Vector2(0, 120), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "5 - Monkey", new Vector2(0, 140), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "6 - Sphere", new Vector2(0, 160), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "7 - Torus", new Vector2(0, 180), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "8 - Victoria (not synced)", new Vector2(0, 200), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, "9 - Victoria (dancing) (not synced)", new Vector2(0, 220), Color.White);
|
||||
spriteBatch.DrawString(spriteFont, string.Format("{0} entities", entities.Count), new Vector2(0, 260), Color.White);
|
||||
|
||||
spriteBatch.End();
|
||||
|
||||
base.Draw(gameTime);
|
||||
}
|
||||
}
|
||||
}
|
BIN
src/FluckyGame.Client/FluckyGame.Client/GameThumbnail.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
28
src/FluckyGame.Client/FluckyGame.Client/Program.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace FluckyGame.Client
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
TcpClient tcpClient;
|
||||
|
||||
try
|
||||
{
|
||||
tcpClient = new TcpClient("home.brunner.ninja", 8001);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Konnte keine Verbindung herstellen:\n\n" + ex.Message, "Konnte keine Verbindung herstellen!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
using (Game1 game = new Game1(tcpClient))
|
||||
game.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,34 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("FluckyGame.Client")]
|
||||
[assembly: AssemblyProduct("FluckyGame.Client")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type. Only Windows
|
||||
// assemblies support COM.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// On Windows, the following GUID is for the ID of the typelib if this
|
||||
// project is exposed to COM. On other platforms, it unique identifies the
|
||||
// title storage container when deploying this assembly to the device.
|
||||
[assembly: Guid("8cad4fa5-8d97-4c56-83af-8f305e78f60b")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{C47EAA2D-CEA4-47F0-A413-0DD04E8DEC23}</ProjectGuid>
|
||||
<ProjectTypeGuids>{96E2B04D-8817-42c6-938A-82C39BA4D311};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<XnaFrameworkVersion>v4.0</XnaFrameworkVersion>
|
||||
<OutputPath>bin\$(Platform)\$(Configuration)</OutputPath>
|
||||
<ContentRootDirectory>Content</ContentRootDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>FluckyGame.ClientContent</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.EffectImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.FBXImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.TextureImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.XImporter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.AudioImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
|
||||
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline.VideoImporters, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SpriteFont.spritefont">
|
||||
<Name>SpriteFont</Name>
|
||||
<Importer>FontDescriptionImporter</Importer>
|
||||
<Processor>FontDescriptionProcessor</Processor>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\box.fbx">
|
||||
<Name>box</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\cone.fbx">
|
||||
<Name>cone</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
<Compile Include="Models\cylinder.fbx">
|
||||
<Name>cylinder</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
<Compile Include="Models\monkey.fbx">
|
||||
<Name>monkey</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
<Compile Include="Models\sphere.fbx">
|
||||
<Name>sphere</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
<Compile Include="Models\torus.fbx">
|
||||
<Name>torus</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\Victoria-hat-tpose.FBX">
|
||||
<Name>Victoria-hat-tpose</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\Victoria-hat-dance.FBX">
|
||||
<Name>Victoria-hat-dance</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FluckyGame.Client.Pipeline\FluckyGame.Client.Pipeline.Animation\FluckyGame.Client.Pipeline.Animation.csproj">
|
||||
<Project>{9975ed45-7a21-4f8a-9ec3-12f5845f681f}</Project>
|
||||
<Name>FluckyGame.Client.Pipeline.Animation</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\dude.fbx">
|
||||
<Name>dude</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>AnimationProcessor</Processor>
|
||||
</Compile>
|
||||
<Compile Include="Models\figure.fbx">
|
||||
<Name>figure</Name>
|
||||
<Importer>FbxImporter</Importer>
|
||||
<Processor>ModelProcessor</Processor>
|
||||
</Compile>
|
||||
<None Include="Models\head.tga">
|
||||
<Name>head</Name>
|
||||
<Importer>TextureImporter</Importer>
|
||||
<Processor>TextureProcessor</Processor>
|
||||
</None>
|
||||
<None Include="Models\jacket.tga">
|
||||
<Name>jacket</Name>
|
||||
<Importer>TextureImporter</Importer>
|
||||
<Processor>TextureProcessor</Processor>
|
||||
</None>
|
||||
<None Include="Models\pants.tga">
|
||||
<Name>pants</Name>
|
||||
<Importer>TextureImporter</Importer>
|
||||
<Processor>TextureProcessor</Processor>
|
||||
</None>
|
||||
<None Include="Models\upBodyC.tga">
|
||||
<Name>upBodyC</Name>
|
||||
<Importer>TextureImporter</Importer>
|
||||
<Processor>TextureProcessor</Processor>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Models\figure_texture.png">
|
||||
<Name>figure_texture</Name>
|
||||
<Importer>TextureImporter</Importer>
|
||||
<Processor>TextureProcessor</Processor>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
After Width: | Height: | Size: 1.2 MiB |
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/box.fbx
Normal file
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/cone.fbx
Normal file
72565
src/FluckyGame.Client/FluckyGame.ClientContent/Models/dude.fbx
Normal file
7450
src/FluckyGame.Client/FluckyGame.ClientContent/Models/figure.fbx
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/head.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/jacket.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/monkey.fbx
Normal file
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/pants.tga
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/sphere.fbx
Normal file
BIN
src/FluckyGame.Client/FluckyGame.ClientContent/Models/torus.fbx
Normal file
After Width: | Height: | Size: 3.0 MiB |
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file contains an xml description of a font, and will be read by the XNA
|
||||
Framework Content Pipeline. Follow the comments to customize the appearance
|
||||
of the font in your game, and to change the characters which are available to draw
|
||||
with.
|
||||
-->
|
||||
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||
<Asset Type="Graphics:FontDescription">
|
||||
|
||||
<!--
|
||||
Modify this string to change the font that will be imported.
|
||||
-->
|
||||
<FontName>Segoe UI Mono</FontName>
|
||||
|
||||
<!--
|
||||
Size is a float value, measured in points. Modify this value to change
|
||||
the size of the font.
|
||||
-->
|
||||
<Size>14</Size>
|
||||
|
||||
<!--
|
||||
Spacing is a float value, measured in pixels. Modify this value to change
|
||||
the amount of spacing in between characters.
|
||||
-->
|
||||
<Spacing>0</Spacing>
|
||||
|
||||
<!--
|
||||
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||
will be used when placing characters.
|
||||
-->
|
||||
<UseKerning>true</UseKerning>
|
||||
|
||||
<!--
|
||||
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||
and "Bold, Italic", and are case sensitive.
|
||||
-->
|
||||
<Style>Regular</Style>
|
||||
|
||||
<!--
|
||||
If you uncomment this line, the default character will be substituted if you draw
|
||||
or measure text that contains characters which were not included in the font.
|
||||
-->
|
||||
<!-- <DefaultCharacter>*</DefaultCharacter> -->
|
||||
|
||||
<!--
|
||||
CharacterRegions control what letters are available in the font. Every
|
||||
character from Start to End will be built and made available for drawing. The
|
||||
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||
character set. The characters are ordered according to the Unicode standard.
|
||||
See the documentation for more information.
|
||||
-->
|
||||
<CharacterRegions>
|
||||
<CharacterRegion>
|
||||
<Start> </Start>
|
||||
<End>~</End>
|
||||
</CharacterRegion>
|
||||
</CharacterRegions>
|
||||
</Asset>
|
||||
</XnaContent>
|
55
src/FluckyGame.Library/FluckyGame.Library.csproj
Normal file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FluckyGame.Library</RootNamespace>
|
||||
<AssemblyName>FluckyGame.Library</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Packet.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
49
src/FluckyGame.Library/Packet.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace FluckyGame.Library
|
||||
{
|
||||
[Serializable]
|
||||
public class Packet : Dictionary<string, object>
|
||||
{
|
||||
private static readonly IFormatter formatter;
|
||||
|
||||
static Packet()
|
||||
{
|
||||
formatter = new BinaryFormatter();
|
||||
}
|
||||
|
||||
public Packet() : base() { }
|
||||
|
||||
public Packet(int capacity) : base(capacity) { }
|
||||
|
||||
public Packet(IEqualityComparer<string> comparer) : base(comparer) { }
|
||||
|
||||
public Packet(IDictionary<string, object> dictionary) : base(dictionary) { }
|
||||
|
||||
public Packet(int capacity, IEqualityComparer<string> comparer) : base(capacity, comparer) { }
|
||||
|
||||
public Packet(IDictionary<string, object> dictionary, IEqualityComparer<string> comparer) : base(dictionary, comparer) { }
|
||||
|
||||
public Packet(SerializationInfo info, StreamingContext context) : base(info, context) { }
|
||||
|
||||
public static Packet Receive(Stream stream)
|
||||
{
|
||||
var obj = formatter.Deserialize(stream);
|
||||
|
||||
var packet = obj as Packet;
|
||||
if (packet == null)
|
||||
throw new Exception("no packet received!");
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
public void Send(Stream stream)
|
||||
{
|
||||
formatter.Serialize(stream, this);
|
||||
}
|
||||
}
|
||||
}
|
36
src/FluckyGame.Library/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die einer Assembly zugeordnet sind.
|
||||
[assembly: AssemblyTitle("FluckyGame.Library")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FluckyGame.Library")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("1cef270c-fce8-4bd1-920f-440d9cc8ed5b")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
6
src/FluckyGame.Server/App.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
|
||||
</startup>
|
||||
</configuration>
|
40
src/FluckyGame.Server/BouncingEntity.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FluckyGame.Library;
|
||||
|
||||
namespace FluckyGame.Server
|
||||
{
|
||||
class BouncingEntity : Entity
|
||||
{
|
||||
private float ySpeed;
|
||||
|
||||
const float randomMin = 1;
|
||||
const float randomMax = 5;
|
||||
|
||||
public BouncingEntity(string id, string model, Vector3 position, Vector3 rotation, Vector3 scalation) :
|
||||
base(id, model, position, rotation, scalation)
|
||||
{
|
||||
ySpeed = ((float)Program.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (Position.Y > 0)
|
||||
ySpeed -= 0.1f;
|
||||
else
|
||||
ySpeed = ((float)Program.random.NextDouble() * (randomMax - randomMin)) + randomMin;
|
||||
|
||||
Position.Y += ySpeed;
|
||||
|
||||
lock (Program.clients)
|
||||
foreach (var client in Program.clients)
|
||||
client.SendPacket(new Packet() {
|
||||
{"type", "UPDATE" },
|
||||
{"id", Id },
|
||||
{"position", Position }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
148
src/FluckyGame.Server/Client.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Microsoft.Xna.Framework;
|
||||
using FluckyGame.Library;
|
||||
|
||||
namespace FluckyGame.Server
|
||||
{
|
||||
internal class Client
|
||||
{
|
||||
TcpClient tcpClient;
|
||||
NetworkStream networkStream;
|
||||
Thread thread;
|
||||
bool disconnecting;
|
||||
|
||||
Entity playerEntity;
|
||||
|
||||
public Client(TcpClient tcpClient)
|
||||
{
|
||||
Console.WriteLine("New connection from {0}", tcpClient.Client.RemoteEndPoint);
|
||||
this.tcpClient = tcpClient;
|
||||
this.networkStream = this.tcpClient.GetStream();
|
||||
|
||||
lock (Program.entities)
|
||||
{
|
||||
foreach (var entity in Program.entities)
|
||||
SendPacket(new Packet() {
|
||||
{"type", "NEW" },
|
||||
{"id", entity.Id },
|
||||
{"model", entity.Model },
|
||||
{"position", entity.Position },
|
||||
{"rotation", entity.Rotation },
|
||||
{"scalation", entity.Scalation }
|
||||
});
|
||||
|
||||
Program.entities.Add(playerEntity = new Entity(Guid.NewGuid().ToString(), "dude", Vector3.Zero, Vector3.Zero, new Vector3(1)));
|
||||
|
||||
lock (Program.clients)
|
||||
foreach (var client in Program.clients)
|
||||
if(client != this)
|
||||
client.SendPacket(new Packet() {
|
||||
{"type", "NEW" },
|
||||
{"id", playerEntity.Id },
|
||||
{"model", playerEntity.Model },
|
||||
{"position", playerEntity.Position },
|
||||
{"rotation", playerEntity.Rotation },
|
||||
{"scalation", playerEntity.Scalation }
|
||||
});
|
||||
}
|
||||
|
||||
thread = new Thread(ReceivePackets);
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
private void ReceivePackets()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var packet = Packet.Receive(networkStream);
|
||||
|
||||
var type = (string)packet["type"];
|
||||
|
||||
if (type == "ADD")
|
||||
{
|
||||
lock (Program.entities)
|
||||
{
|
||||
var entity = new Entity(
|
||||
Guid.NewGuid().ToString(),
|
||||
(string)packet["model"],
|
||||
(Vector3)packet["position"],
|
||||
(Vector3)packet["rotation"],
|
||||
(Vector3)packet["scalation"]
|
||||
);
|
||||
|
||||
Program.entities.Add(entity);
|
||||
|
||||
lock (Program.clients)
|
||||
foreach (var client in Program.clients)
|
||||
client.SendPacket(new Packet() {
|
||||
{"type", "NEW" },
|
||||
{"id", entity.Id },
|
||||
{"model", entity.Model },
|
||||
{"position", entity.Position },
|
||||
{"rotation", entity.Rotation },
|
||||
{"scalation", entity.Scalation }
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (type == "PLAYER")
|
||||
{
|
||||
playerEntity.Position = (Vector3)packet["position"];
|
||||
playerEntity.Rotation = (Vector3)packet["rotation"];
|
||||
|
||||
lock (Program.clients)
|
||||
foreach (var client in Program.clients)
|
||||
if(client != this)
|
||||
client.SendPacket(new Packet() {
|
||||
{"type", "UPDATE" },
|
||||
{"id", playerEntity.Id },
|
||||
{"position", playerEntity.Position },
|
||||
{"rotation", playerEntity.Rotation }
|
||||
});
|
||||
}
|
||||
else
|
||||
throw new Exception("Unknown packet type!");
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if(!disconnecting)
|
||||
Console.WriteLine(ex.Message);
|
||||
lock (Program.clients)
|
||||
Program.clients.Remove(this);
|
||||
lock (Program.entities)
|
||||
Program.entities.Remove(playerEntity);
|
||||
lock (Program.clients)
|
||||
foreach (var client in Program.clients)
|
||||
client.SendPacket(new Packet() {
|
||||
{ "type", "REMOVE" },
|
||||
{ "id", playerEntity.Id }
|
||||
});
|
||||
networkStream.Dispose();
|
||||
tcpClient.Dispose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void SendPacket(Packet packet)
|
||||
{
|
||||
if (disconnecting)
|
||||
return;
|
||||
try
|
||||
{
|
||||
//TODO: lock to avoid message mixing (one message sending while other)
|
||||
packet.Send(networkStream);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
disconnecting = true;
|
||||
thread.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
src/FluckyGame.Server/Entity.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FluckyGame.Server
|
||||
{
|
||||
class Entity
|
||||
{
|
||||
public string Id;
|
||||
public string Model;
|
||||
public Vector3 Position;
|
||||
public Vector3 Rotation;
|
||||
public Vector3 Scalation;
|
||||
|
||||
public Entity(string id, string model, Vector3 position, Vector3 rotation, Vector3 scalation)
|
||||
{
|
||||
Id = id;
|
||||
Model = model;
|
||||
Position = position;
|
||||
Rotation = rotation;
|
||||
Scalation = scalation;
|
||||
}
|
||||
|
||||
public virtual void Update() { }
|
||||
}
|
||||
}
|
71
src/FluckyGame.Server/FluckyGame.Server.csproj
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{85507C7D-93AB-4344-9290-4A79396C083E}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FluckyGame.Server</RootNamespace>
|
||||
<AssemblyName>FluckyGame.Server</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Xna.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553, processorArchitecture=x86" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BouncingEntity.cs" />
|
||||
<Compile Include="Client.cs" />
|
||||
<Compile Include="Entity.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FluckyGame.Library\FluckyGame.Library.csproj">
|
||||
<Project>{1cef270c-fce8-4bd1-920f-440d9cc8ed5b}</Project>
|
||||
<Name>FluckyGame.Library</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
89
src/FluckyGame.Server/Program.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace FluckyGame.Server
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
internal static List<Client> clients;
|
||||
|
||||
private static Thread acceptThread;
|
||||
|
||||
internal static Random random;
|
||||
internal static List<Entity> entities;
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Initializing FluckyGame Server 1.0...");
|
||||
|
||||
clients = new List<Client>();
|
||||
|
||||
acceptThread = new Thread(AcceptConnections);
|
||||
acceptThread.IsBackground = true;
|
||||
acceptThread.Start();
|
||||
|
||||
//Game Server Initialization
|
||||
random = new Random();
|
||||
entities = new List<Entity>();
|
||||
|
||||
const int testSize = 200;
|
||||
const int testStep = 50;
|
||||
for (var z = -testSize; z <= testSize; z += testStep)
|
||||
for (var x = -testSize; x <= testSize; x += testStep)
|
||||
{
|
||||
entities.Add(new BouncingEntity(
|
||||
Guid.NewGuid().ToString(),
|
||||
(new List<string>() { "box", "cone", "cylinder", "figure", "monkey", "sphere", "torus" }).OrderBy(o => random.Next()).First(),
|
||||
new Vector3(x, 50, z),
|
||||
Vector3.Zero,
|
||||
new Vector3(5)));
|
||||
}
|
||||
|
||||
const int minTime = 1000 / 60; //60 FPS
|
||||
|
||||
int count = 0;
|
||||
var dateTime = DateTime.Now;
|
||||
while (true)
|
||||
{
|
||||
var started = DateTime.Now;
|
||||
|
||||
var changedEntities = new List<Entity>();
|
||||
|
||||
lock (entities)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
entity.Update();
|
||||
}
|
||||
|
||||
count++;
|
||||
if((DateTime.Now - dateTime).TotalSeconds >= 1)
|
||||
{
|
||||
Console.WriteLine("{0} Updates per Second ({1} clients)", count, clients.Count);
|
||||
count = 0;
|
||||
dateTime = DateTime.Now;
|
||||
}
|
||||
|
||||
int elapsed = (int)(DateTime.Now - started).TotalMilliseconds;
|
||||
if (elapsed < minTime)
|
||||
Thread.Sleep(minTime - elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AcceptConnections()
|
||||
{
|
||||
var listener = new TcpListener(IPAddress.Any, 8001);
|
||||
listener.Start();
|
||||
while (true)
|
||||
{
|
||||
var client = new Client(listener.AcceptTcpClient());
|
||||
lock(clients)
|
||||
clients.Add(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
src/FluckyGame.Server/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die einer Assembly zugeordnet sind.
|
||||
[assembly: AssemblyTitle("FluckyGame.Server")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FluckyGame.Server")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("85507c7d-93ab-4344-9290-4a79396c083e")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
68
src/FluckyGame.sln
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluckyGame.Client", "FluckyGame.Client\FluckyGame.Client\FluckyGame.Client.csproj", "{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluckyGame.ClientContent", "FluckyGame.Client\FluckyGame.ClientContent\FluckyGame.ClientContent.contentproj", "{C47EAA2D-CEA4-47F0-A413-0DD04E8DEC23}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FluckyGame.Client.Pipeline", "FluckyGame.Client.Pipeline", "{84CFF729-9434-4313-80E9-38853290643D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluckyGame.Client.Pipeline.Animation", "FluckyGame.Client\FluckyGame.Client.Pipeline\FluckyGame.Client.Pipeline.Animation\FluckyGame.Client.Pipeline.Animation.csproj", "{9975ED45-7A21-4F8A-9EC3-12F5845F681F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluckyGame.Server", "FluckyGame.Server\FluckyGame.Server.csproj", "{85507C7D-93AB-4344-9290-4A79396C083E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluckyGame.Library", "FluckyGame.Library\FluckyGame.Library.csproj", "{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Debug|Any CPU.Build.0 = Debug|x86
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Debug|x86.Build.0 = Debug|x86
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Release|x86.ActiveCfg = Release|x86
|
||||
{8CAD4FA5-8D97-4C56-83AF-8F305E78F60B}.Release|x86.Build.0 = Release|x86
|
||||
{C47EAA2D-CEA4-47F0-A413-0DD04E8DEC23}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{C47EAA2D-CEA4-47F0-A413-0DD04E8DEC23}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C47EAA2D-CEA4-47F0-A413-0DD04E8DEC23}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{C47EAA2D-CEA4-47F0-A413-0DD04E8DEC23}.Release|x86.ActiveCfg = Release|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Debug|Any CPU.Build.0 = Debug|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Debug|x86.Build.0 = Debug|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Release|Any CPU.Build.0 = Release|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Release|x86.ActiveCfg = Release|x86
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F}.Release|x86.Build.0 = Release|x86
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{85507C7D-93AB-4344-9290-4A79396C083E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1CEF270C-FCE8-4BD1-920F-440D9CC8ED5B}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{9975ED45-7A21-4F8A-9EC3-12F5845F681F} = {84CFF729-9434-4313-80E9-38853290643D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|