Added 3D Variant, still nedds improvment

This commit is contained in:
Jan Grießhaber
2024-10-24 16:16:43 +02:00
parent 73c8cbca39
commit 1bb56adceb
14 changed files with 577 additions and 33 deletions

View File

@@ -0,0 +1,36 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-mgcb": {
"version": "3.8.1.303",
"commands": [
"mgcb"
]
},
"dotnet-mgcb-editor": {
"version": "3.8.1.303",
"commands": [
"mgcb-editor"
]
},
"dotnet-mgcb-editor-linux": {
"version": "3.8.1.303",
"commands": [
"mgcb-editor-linux"
]
},
"dotnet-mgcb-editor-windows": {
"version": "3.8.1.303",
"commands": [
"mgcb-editor-windows"
]
},
"dotnet-mgcb-editor-mac": {
"version": "3.8.1.303",
"commands": [
"mgcb-editor-mac"
]
}
}
}

View File

@@ -0,0 +1,53 @@
#----------------------------- Global Properties ----------------------------#
/outputDir:bin/$(Platform)
/intermediateDir:obj/$(Platform)
/platform:Windows
/config:
/profile:Reach
/compress:False
#-------------------------------- References --------------------------------#
#---------------------------------- Content ---------------------------------#
#begin Models/Cube.fbx
/importer:FbxImporter
/processor:ModelProcessor
/processorParam:ColorKeyColor=0,0,0,0
/processorParam:ColorKeyEnabled=True
/processorParam:DefaultEffect=BasicEffect
/processorParam:GenerateMipmaps=True
/processorParam:GenerateTangentFrames=False
/processorParam:PremultiplyTextureAlpha=True
/processorParam:PremultiplyVertexColors=True
/processorParam:ResizeTexturesToPowerOfTwo=False
/processorParam:RotationX=0
/processorParam:RotationY=0
/processorParam:RotationZ=0
/processorParam:Scale=1
/processorParam:SwapWindingOrder=False
/processorParam:TextureFormat=Compressed
/build:Models/Cube.fbx
#begin Models/Cube.fbx
/importer:FbxImporter
/processor:ModelProcessor
/processorParam:ColorKeyColor=0,0,0,0
/processorParam:ColorKeyEnabled=True
/processorParam:DefaultEffect=BasicEffect
/processorParam:GenerateMipmaps=True
/processorParam:GenerateTangentFrames=False
/processorParam:PremultiplyTextureAlpha=True
/processorParam:PremultiplyVertexColors=True
/processorParam:ResizeTexturesToPowerOfTwo=False
/processorParam:RotationX=0
/processorParam:RotationY=0
/processorParam:RotationZ=0
/processorParam:Scale=1
/processorParam:SwapWindingOrder=False
/processorParam:TextureFormat=Compressed
/build:Models/Cube.fbx

Binary file not shown.

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameOfLife3D.GameModel
{
//Max Val is 27
internal static class Balancing
{
public static readonly int MIN_ALIVE = 6;
public static readonly int MAX_ALIVE = 11;
public static readonly int CREATE_MIN = 8;
public static readonly int CREATE_MAX = 9;
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameOfLife3D.GameModel
{
internal struct Cell
{
public bool isAlive;
public int X, Y, Z;
public override string ToString()
{
return $"{X}:{Y}:{Z}::{isAlive}";
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GameOfLife3D.GameModel
{
internal class GameOfLifeModel
{
private int X_DIM,Y_DIM,Z_DIM;
public GameOfLifeModel(int SizeX,int SizeY,int SizeZ) {
Map = new(SizeX,SizeY,SizeZ);
X_DIM = SizeX;
Y_DIM = SizeY;
Z_DIM = SizeZ;
}
public GameOfLifeModel(int Size)
{
Map = new(Size);
X_DIM = Size;
Y_DIM = Size;
Z_DIM = Size;
}
private GameOfLifeModel() { }
public Map Map { get; init; }
public void Update()
{
Map.Update();
}
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace GameOfLife3D.GameModel
{
internal class Map
{
private Cell[,,] _Cells;
private int _SizeX, _SizeY, _SizeZ;
public Cell[,,] Cells => _Cells;
public int AliveCell => GetAliveCells();
public Map SwapMap;
public Map(int XSize, int YSize, int ZSize)
{
_Cells = new Cell[XSize, YSize, ZSize];
StoreDimensions(XSize, YSize, ZSize);
InitializeCells();
}
private void StoreDimensions(int xSize, int ySize, int zSize)
{
_SizeX = xSize;
_SizeY = ySize;
_SizeZ = zSize;
}
public Map(int Size)
{
_Cells = new Cell[Size, Size, Size];
StoreDimensions(Size, Size, Size);
InitializeCells();
}
public void Update()
{
if (SwapMap == null)
{
SwapMap = new(_SizeX, _SizeY, _SizeZ);
}
foreach (var cell in _Cells)
{
SwapMap.GetCell(cell.X, cell.Y, cell.Z).isAlive = GetNewState(GetAliveCount(cell), cell.isAlive);
}
this.CloneFrom(SwapMap);
}
private static bool GetNewState(int value, bool CurrentCellState)
{
if (value < Balancing.MIN_ALIVE)
return false;
if (value >= Balancing.MIN_ALIVE && value < Balancing.CREATE_MIN)
return CurrentCellState;
if (value >= Balancing.CREATE_MIN && value < Balancing.CREATE_MAX)
return true;
if (value > Balancing.CREATE_MAX && value < Balancing.MAX_ALIVE)
return CurrentCellState;
return false;
}
private int GetAliveCount(Cell cell)
{
int AliveCount = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
for (int k = -1; k <= 1; k++)
{
AliveCount += GetCell(cell.X + i, cell.Y + j, cell.Z + k).isAlive ? 1 : 0;
if (AliveCount > Balancing.MAX_ALIVE)
{ return AliveCount; }
}
}
}
return AliveCount;
}
private void CloneFrom(Map source)
{
this._Cells = source.Cells;
}
private void InitializeCells()
{
for (int i = 0; i < _Cells.GetLength(0); i++)
{
for (int j = 0; j < _Cells.GetLength(1); j++)
{
for (int k = 0; k < _Cells.GetLength(2); k++)
{
_Cells[i, j, k].X = i;
_Cells[i, j, k].Y = j;
_Cells[i, j, k].Z = k;
}
}
}
}
public ref Cell GetCell(int x, int y, int z)
{
//Clamp Values to Bound
x = Math.Clamp(x, 0, _SizeX-1);
y = Math.Clamp(y, 0, _SizeY-1);
z = Math.Clamp(z, 0, _SizeZ-1);
return ref _Cells[x, y, z];
}
private int GetAliveCells()
{
int aliveCount = 0;
foreach (Cell cell in _Cells)
{
aliveCount += cell.isAlive ? 1 : 0;
}
return aliveCount;
}
public void SetRandom(int mod = 2)
{
for (int i = 0; i < _Cells.GetLength(0); i++)
{
for (int j = 0; j < _Cells.GetLength(1); j++)
{
for (int k = 0; k < _Cells.GetLength(2); k++)
{
_Cells[i, j, k].isAlive = Random.Shared.Next() % mod == 0;
//_Cells[i, j, k].isAlive = true;
}
}
}
}
}
}

178
GameOfLife3D/GameOfLife.cs Normal file
View File

@@ -0,0 +1,178 @@
using GameOfLife3D.GameModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
namespace GameOfLife3D
{
public class GameOfLife : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private GameOfLifeModel _gameOfLife;
private bool paused= false;
private Model model;
Vector3 CameraTarget, CameraPosition;
Matrix ProjectionMatrix, ViewMatrix, WorldMatrix;
private bool orbit = false;
Matrix TranslationMatrix;
int tickcount = 0;
public GameOfLife()
{
_graphics = new GraphicsDeviceManager(this);
_graphics.PreferredBackBufferWidth = 1920;
_graphics.PreferredBackBufferHeight = 1080;
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
_gameOfLife = new(16);
_gameOfLife.Map.SetRandom(2);
model = Content.Load<Model>("Models/Cube");
CameraTarget = new(0f,0f,0f);
CameraPosition = new(0f, 0f, -30f);
ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(60f), _graphics.GraphicsDevice.Viewport.AspectRatio, 1f, 1000f);
ViewMatrix = Matrix.CreateLookAt(CameraPosition, CameraTarget,new Vector3(0f,1f,0f));
WorldMatrix = Matrix.CreateWorld(CameraTarget, Vector3.Forward, Vector3.Up);
TranslationMatrix = Matrix.CreateTranslation(new Vector3(0f, 0f, 0f));
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if(Keyboard.GetState().IsKeyDown(Keys.P))
{
paused = !paused;
}
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
CameraPosition.X -= 0.1f;
CameraTarget.X -= 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
CameraPosition.X += 0.1f;
CameraTarget.X += 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
CameraPosition.Y -= 0.1f;
CameraTarget.Y -= 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
CameraPosition.Y += 0.1f;
CameraTarget.Y += 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.OemPlus))
{
CameraPosition.Z += 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.OemMinus))
{
CameraPosition.Z -= 0.1f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Space))
{
orbit = !orbit;
}
if (orbit)
{
Matrix rotationMatrix = Matrix.CreateRotationY(
MathHelper.ToRadians(1f));
CameraPosition = Vector3.Transform(CameraPosition,
rotationMatrix);
}
ViewMatrix = Matrix.CreateLookAt(CameraPosition, CameraTarget,
Vector3.Up);
TranslationMatrix = Matrix.CreateTranslation(
new Vector3(
0f,
0f,
(float)Math.Sin(gameTime.ElapsedGameTime.TotalMilliseconds)*10f));
//WorldMatrix.Translation = TranslationMatrix.Translation;
tickcount++;
if (!paused)
{
if (tickcount % 20 == 0)
{
_gameOfLife.Update();
}
}
// TODO: Add your update logic here
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
foreach (var cell in _gameOfLife.Map.Cells)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.AmbientLightColor = cell.isAlive ? Color.AliceBlue.ToVector3() : Color.Green.ToVector3();
effect.View = ViewMatrix;
effect.World = Matrix.CreateTranslation(cell.X*2.1f, cell.Y*2.1f, cell.Z * 2.1f);
effect.Projection = ProjectionMatrix;
}
if (cell.isAlive)
{
mesh.Draw();
}
}
//model.Draw(WorldMatrix * Matrix.CreateTranslation(new Vector3(cell.X, cell.Y, cell.Z)), ViewMatrix, ProjectionMatrix);
}
// TODO: Add your drawing code here
base.Draw(gameTime);
}
protected void GeneratorCubeModel()
{
}
}
}

View File

@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<RollForward>Major</RollForward>
<PublishReadyToRun>false</PublishReadyToRun>
<TieredCompilation>false</TieredCompilation>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>Icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MonoGame.Framework.WindowsDX" Version="3.8.1.303" />
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
</ItemGroup>
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
<Message Text="Restoring dotnet tools" Importance="High" />
<Exec Command="dotnet tool restore" />
</Target>
</Project>

BIN
GameOfLife3D/Icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

3
GameOfLife3D/Program.cs Normal file
View File

@@ -0,0 +1,3 @@

using var game = new GameOfLife3D.GameOfLife();
game.Run();

43
GameOfLife3D/app.manifest Normal file
View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="GameOfLife3D"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>