refactored biome code. ui fixes

This commit is contained in:
j0sh.oleary11
2021-03-09 00:08:37 -08:00
parent 8e34ae1b68
commit 93094b1470
64 changed files with 1890 additions and 811 deletions

View File

@@ -151,6 +151,7 @@ local changeLogContentWindow = UIRect(script, {
BorderSize = 2,
BorderColor = Color(0.2, 0.2, 0.2),
BorderEnabled = true,
ClipsDescendants = true,
});
local updateLog = UIListContainer();
@@ -162,7 +163,7 @@ local changeLogTextEntries = require("assets.scripts.MenuScripts.ChangeLogGenera
for _, text in pairs(changeLogTextEntries) do
local displayedText = text;
local font = GraphicsEngine.Instance.Fonts.Arial10;
local font = GraphicsEngine.Instance.Fonts.Arial12;
local size = 18;
if (text:find(">>")) then
@@ -174,7 +175,7 @@ for _, text in pairs(changeLogTextEntries) do
size = 16;
displayedText = text:gsub(">", "");
elseif text:find("-") then
font = GraphicsEngine.Instance.Fonts.Arial10;
font = GraphicsEngine.Instance.Fonts.Arial12;
size = 12;
end

View File

@@ -103,6 +103,17 @@ for obj in list(worldListing:FindChildrenWithName("Entry")) do
TextYAlign = TextYAlignment.Center,
});
local subtext = Label(script, {
Name = "WorldData",
Parent = instance,
Size = UICoords(0, 0, 0.5, 1),
Position = UICoords(0,0, 0.5, 0),
Font = GraphicsEngine.Instance.Fonts.Arial14,
Text = obj.LastVersionPlayedOn,
TextColor = Color.White,
TextYAlign = TextYAlignment.Center,
});
instance.OnSelected:Bind(function()
selectedWorld = obj
end)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 281 B

View File

@@ -13,15 +13,17 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
<AssemblyName>CaveGame</AssemblyName>
<RootNamespace>CaveGame</RootNamespace>
<Version>2.1.0</Version>
<Version>2.3.0</Version>
<Company>Conarium Software</Company>
<Product>Computer Software</Product>
<Description>A game of mining, exploration, engineering, and explosive creativity!</Description>
<Copyright>Copyright Conarium Software 2019- 2020</Copyright>
<PackageLicenseExpression>Copyright Conarium Software 2019- 2020</PackageLicenseExpression>
<Copyright>Copyright Conarium Software 2019- 2021</Copyright>
<PackageLicenseExpression>Copyright Conarium Software 2019- 2021</PackageLicenseExpression>
<Authors>Joshua O'Leary, Tyler Stewart, Contributing Developers</Authors>
<PackageReleaseNotes>Testing version, not for release!</PackageReleaseNotes>
<StartupObject>Cave.Program</StartupObject>
<PackageProjectUrl>conarium.xyz</PackageProjectUrl>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<Optimize>false</Optimize>

View File

@@ -0,0 +1,9 @@
namespace CaveGame.Client
{
public class CaveGameArguments
{
public string AutoLoadWorld { get; set; } = "";
public string AutoConnectName { get; set; } = "";
public string AutoConnectAddress { get; set; } = "";
}
}

View File

@@ -16,13 +16,16 @@ using System.Threading.Tasks;
using CaveGame.Core.Game.Items;
using CaveGame.Core.Inventory;
using DataManagement;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Audio;
namespace CaveGame.Client
{
public class CaveGameGL : Microsoft.Xna.Framework.Game
{
// TODO: If running local server, shutdown server when player leaves the world
public GameSettings GameSettings { get; set; }
public GameSettings Settings { get; set; }
public IGameContext CurrentGameContext { get; set; }
private IGameContext PreviousGameContext { get; set; }
public GameClient GameClientContext { get; private set; }
@@ -37,8 +40,11 @@ namespace CaveGame.Client
public SteamManager SteamManager { get; private set; }
public static float ClickTimer { get; set; }
public void OnSetFPSLimit(int limit)
#region GameSettingMethods
// these functions don't actually toggle the associated flags
// they are just for applying changes to game state
// they should be triggered automatically by setting the flag in Game.Settings
public void SetFPSLimit(int limit)
{
if (limit == 0)
{
@@ -49,10 +55,8 @@ namespace CaveGame.Client
this.TargetElapsedTime = TimeSpan.FromSeconds(1d / (double)limit);
}
}
public void OnSetChatSize(GameChatSize size) { }
public void OnSetFullscreen(bool full)
public void SetChatSize(GameChatSize size) { }
public void SetFullscreen(bool full)
{
this.GraphicsDeviceManager.IsFullScreen = full;
@@ -68,6 +72,12 @@ namespace CaveGame.Client
}
GraphicsDeviceManager.ApplyChanges();
}
public void SetVSync(bool vsync)
{
this.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = vsync;
}
#endregion
// join local (singleplayer server
public void EnterLocalGame(WorldMetadata meta)
@@ -90,6 +100,7 @@ namespace CaveGame.Client
}
public void StartClient(string userName, string address)
{
GameClientContext?.Dispose();
@@ -100,16 +111,17 @@ namespace CaveGame.Client
CurrentGameContext = GameClientContext;
}
public CaveGameGL()
CaveGameArguments StartupArguments;
public CaveGameGL(CaveGameArguments arguments)
{
StartupArguments = arguments;
IsMouseVisible = true;
Content.RootDirectory = "Assets";
Window.AllowUserResizing = true;
Window.AllowAltF4 = true;
GameSettings = Configuration.Load<GameSettings>("settings.xml", true);
SteamManager = new SteamManager(this);
GraphicsDeviceManager = new GraphicsDeviceManager(this)
@@ -131,10 +143,18 @@ namespace CaveGame.Client
GraphicsEngine.LoadingDelay = 0.05f;
Splash.SplashTimer = 3f;
#endif
OnSetFPSLimit(GameSettings.FPSLimit);
// Initialize settings
Settings = Configuration.Load<GameSettings>("settings.xml", true);
Settings.game = this;
SetFPSLimit(Settings.FPSLimit);
SetFullscreen(Settings.Fullscreen);
SetChatSize(Settings.ChatSize);
SetVSync(Settings.VSync);
}
// Update graphics engine's known window size
void Window_ClientSizeChanged(object sender, EventArgs e) => GraphicsEngine.WindowSize = Window.ClientBounds.Size.ToVector2();
@@ -260,7 +280,7 @@ namespace CaveGame.Client
MenuContext.TimeoutMessage = timeout;
}
private void InitCommands()
private void InitCommands(CommandBar console)
{
// epic new .NET 5 feature
Command[] commands =
@@ -275,51 +295,81 @@ namespace CaveGame.Client
new ("gimme", "Gives you an item", new List<string>{"itemid", "amount"}, CmdRequestItemstack),
new ("crash", "Forces the game to implode", new List<string>{"fake_reason"}, CmdForceCrash),
};
commands.ForEach(c => Console.BindCommandInformation(c));
//commands.ForEach(Console.BindCommandInformation);
commands.ForEach(c => console.BindCommandInformation(c));
}
protected override void Initialize()
{
// setup window
Window.TextInput += TextInputManager.OnTextInput;
Window.ClientSizeChanged += new EventHandler<EventArgs>(Window_ClientSizeChanged);
OnSetFullscreen(GameSettings.Fullscreen);
SetFullscreen(Settings.Fullscreen);
// Create console
Console = new CommandBar(this);
InitCommands();
GameConsole.SetInstance(Console);
InitCommands(Console); // Inject commands
GameConsole.SetInstance(Console); // set Global console
Components.Add(Console);
// init steam
SteamManager.Initialize();
Components.Add(SteamManager);
base.Initialize();
}
protected override void LoadContent()
{
GameSounds.LoadAssets(Content);
// Load Sounds
// can be automated at a further point
AudioManager.RegisterSong("hey_bella", Content.Load<Song>("sound/mu/hey_bella"));
AudioManager.RegisterSong("mithril_ocean", Content.Load<Song>("sound/mu/mithril_ocean"));
AudioManager.RegisterSong("cliff", Content.Load<Song>("sound/mu/cliff"));
AudioManager.RegisterSong("big_brother", Content.Load<Song>("sound/mu/big_brother"));
AudioManager.RegisterEffect("click1", Content.Load<SoundEffect>("sound/click1"));
//AudioManager.RegisterEffect("ambient_lava", Content.Load<SoundEffect>("sound/ambient/lava"));
AudioManager.RegisterEffect("door", Content.Load<SoundEffect>("sound/door"));
GameSounds.LoadAssets(Content);
//MediaPlayer.Play(GameSounds.Mu_Hey_Bella);
AudioManager.PlaySong("hey_bella");
// Init content within graphics engine
GraphicsEngine.ContentManager = Content;
GraphicsEngine.GraphicsDevice = GraphicsDevice;
GraphicsEngine.GraphicsDeviceManager = GraphicsDeviceManager;
GraphicsEngine.Initialize();
GraphicsEngine.LoadAssets(GraphicsDevice);
GraphicsEngine.LoadAssets(GraphicsDevice); // begin texture loading routine
// game menu contexts
MenuContext = new MenuManager(this);
GameClientContext = new GameClient(this);
SettingsContext = new Settings(this);
// bind text input handler
Window.TextInput += SettingsContext.OnTextInput;
CurrentGameContext = MenuContext;
CurrentGameContext = MenuContext; // set me
// apply command line args
if (StartupArguments.AutoLoadWorld != "")
EnterLocalGame(new WorldMetadata {Name = StartupArguments.AutoLoadWorld, Seed = 420 });
if (StartupArguments.AutoConnectName != "")
StartClient(StartupArguments.AutoConnectName, StartupArguments.AutoConnectAddress);
}
// should this be here?
public void TakeScreenshot(string filename = "")
{
// doesn't work
bool wasEnabled = Console.Enabled;
Console.Enabled = false;
@@ -347,44 +397,52 @@ namespace CaveGame.Client
KeyboardState previousKB = Keyboard.GetState();
protected override void Update(GameTime gameTime)
{
// update graphics information
GraphicsEngine.WindowSize = Window.ClientBounds.Size.ToVector2();
GraphicsEngine.Update(gameTime);
GraphicsEngine.Update(gameTime); // graphics engine state
// if asset loading thread is not yet finished
if (!GraphicsEngine.ContentLoaded)
return;
return; // don't bother
if (Splash.SplashActive)
{
Splash.Update(gameTime);
//return;
}
// take screenshot
KeyboardState currentKB = Keyboard.GetState();
if (currentKB.IsKeyDown(Keys.F5) && !previousKB.IsKeyDown(Keys.F5)) {
if (currentKB.IsKeyDown(Keys.F5) && !previousKB.IsKeyDown(Keys.F5))
TakeScreenshot();
}
// gamestate management
// if context has changed, unload previous context
if (CurrentGameContext != PreviousGameContext && PreviousGameContext != null)
{
PreviousGameContext.Unload();
PreviousGameContext.Active = false;
}
// if current context is not loaded, initialize
if (CurrentGameContext.Active == false)
{
CurrentGameContext.Load();
CurrentGameContext.Active = true;
}
// update context
CurrentGameContext.Update(gameTime);
PreviousGameContext = CurrentGameContext;
ClickTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;
base.Update(gameTime);
}
// main debug screen?
// not game-dependent
private void DrawDebugOverlay()
{
GraphicsEngine.Begin();
@@ -395,7 +453,7 @@ namespace CaveGame.Client
protected override void OnExiting(object sender, EventArgs args)
{
GameSettings.Save();
Settings.Save();
GameClientContext.Disconnect();
SteamManager.Shutdown();
@@ -435,34 +493,48 @@ namespace CaveGame.Client
GFX.End();
}
private void DrawGameBackgroundGraphic(GraphicsEngine GFX)
{
// draw game BG at screen center
Vector2 center = GraphicsEngine.WindowSize / 2.0f;
Vector2 diff = (Mouse.GetState().Position.ToVector2() - center) / (center.Length() / 2.0f);
Vector2 origin = new Vector2(GraphicsEngine.BG.Width, GraphicsEngine.BG.Height) / 2.0f;
float horizscale = GraphicsEngine.WindowSize.X / (float)GraphicsEngine.BG.Width;
float vertscale = GraphicsEngine.WindowSize.Y / (float)GraphicsEngine.BG.Height;
float scale = Math.Max(horizscale, vertscale);
// TODO: Move this into menu context?
// reset graphics state
GraphicsEngine.Clear(Color.Black);
GraphicsEngine.Begin();
GraphicsEngine.Sprite(GraphicsEngine.BG, center - diff, null, Color.White, Rotation.Zero, origin, scale, SpriteEffects.None, 0);
GraphicsEngine.End();
}
protected override void Draw(GameTime gameTime)
{
// draw loading bar if still loading
if (!GraphicsEngine.ContentLoaded)
{
DrawLoadingBar(GraphicsEngine);
return;
}
// draw splash screen if active
if (Splash.SplashActive)
{
Splash.Draw(GraphicsEngine);
return;
}
GraphicsEngine.Clear(Color.Black);
GraphicsEngine.Begin();
Vector2 center = GraphicsEngine.WindowSize / 2.0f;
Vector2 origin = new Vector2(GraphicsEngine.BG.Width, GraphicsEngine.BG.Height) / 2.0f;
float horizscale = GraphicsEngine.WindowSize.X / (float)GraphicsEngine.BG.Width;
float vertscale = GraphicsEngine.WindowSize.Y / (float)GraphicsEngine.BG.Height;
float scale = Math.Max(horizscale, vertscale);
GraphicsEngine.Sprite(GraphicsEngine.BG, center, null, Color.White, Rotation.Zero, origin, scale, SpriteEffects.None, 0);
GraphicsEngine.End();
DrawGameBackgroundGraphic(GraphicsEngine);
// let current context draw
if (CurrentGameContext.Active == true)
CurrentGameContext.Draw(GraphicsEngine);
// debug screen
DrawDebugOverlay();
Console.Draw(GraphicsEngine);

View File

@@ -163,7 +163,7 @@
#begin Sound/ambient/lava.ogg
/importer:OggImporter
/processor:SongProcessor
/processor:SoundEffectProcessor
/processorParam:Quality=Best
/build:Sound/ambient/lava.ogg
@@ -173,6 +173,12 @@
/processorParam:Quality=Best
/build:Sound/click1.wav
#begin Sound/door.ogg
/importer:OggImporter
/processor:SoundEffectProcessor
/processorParam:Quality=Best
/build:Sound/door.ogg
#begin Sound/mu/big_brother.ogg
/importer:OggImporter
/processor:SongProcessor
@@ -197,3 +203,9 @@
/processorParam:Quality=Best
/build:Sound/mu/mithril_ocean.ogg
#begin Sound/wind_howl1.ogg
/importer:OggImporter
/processor:SoundEffectProcessor
/processorParam:Quality=Best
/build:Sound/wind_howl1.ogg

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -119,9 +119,9 @@ Window Dimensions: {Game.Window.ClientBounds.Width}x{Game.Window.ClientBounds.He
Window Dimensions: { Game.Window.ClientBounds.Width}x{ Game.Window.ClientBounds.Height}
Screen Dimensions: {Game.GraphicsDeviceManager.GraphicsDevice.Adapter.CurrentDisplayMode.Width}x{Game.GraphicsDeviceManager.GraphicsDevice.Adapter.CurrentDisplayMode.Height}<br/>
Fullscreen: {Game.GraphicsDeviceManager.IsFullScreen}<br/>
Settings.FPSLimit: {Game.GameSettings.FPSLimit}<br/>
Settings.CameraShake: {Game.GameSettings.CameraShake}<br/>
Settings.ParticlesEnabled: {Game.GameSettings.Particles}<br/>
Settings.FPSLimit: {Game.Settings.FPSLimit}<br/>
Settings.CameraShake: {Game.Settings.CameraShake}<br/>
Settings.ParticlesEnabled: {Game.Settings.Particles}<br/>
Game Context: {Game.CurrentGameContext}<br/>
<p></div>
</body>

View File

@@ -9,12 +9,32 @@ namespace Cave
{
[STAThread]
static void Main()
static void Main(string[] args)
{
Tile.AssertTileEnumeration();
using (var game = new CaveGameGL())
// parse command line arguments
CaveGameArguments arguments = new CaveGameArguments();
for (int x = 0; x < args.Length; x++)
{
#if !DEBUGBALLS
switch(args[x])
{
case "-world":
arguments.AutoLoadWorld = args[x + 1];
break;
case "-connect":
arguments.AutoConnectName = args[x + 1];
arguments.AutoConnectAddress = args[x + 2];
break;
default:
break;
}
}
Tile.AssertTileEnumeration();
using (var game = new CaveGameGL(arguments))
{
#if !DEBUG
try
{
@@ -31,7 +51,6 @@ namespace Cave
#else
game.Run();
game.Exit();
#endif
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

View File

@@ -34,6 +34,7 @@
<Compile Include="$(MSBuildThisFileDirectory)PauseMenu.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SavedWorldManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Splash.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StatusEffectDisplay.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UI\ContextButton.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UI\ScrollRect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UI\UINode.cs" />

View File

@@ -26,10 +26,6 @@ using System.Threading.Tasks;
namespace CaveGame.Client
{
using ArrowEntity = Core.Game.Entities.Arrow;
using BombEntity = Core.Game.Entities.Bomb;
using DynamiteEntity = Core.Game.Entities.Dynamite;
@@ -51,40 +47,54 @@ namespace CaveGame.Client
public class GameClient : IGameContext, IGameClient
{
public event ClientShutdown OnShutdown;
// should this be in gamesettings?
public int ChunkingRadius { get; set; }
public bool ShowChunkBoundaries { get; set; }
public static float CameraZoom = 2.0f;
// not sure why this is stored here.
public string NetworkUsername { get; private set; }
public string ConnectAddress { get; private set; }
public bool Active { get; set; }
public static float CameraZoom = 2.0f;
public bool ShowChunkBoundaries { get; set; }
public CaveGameGL Game { get; private set; }
// gameclient subsystems
public GameChat Chat { get; private set; }
public LocalWorld World { get; private set; }
public PlayerContainerFrontend Inventory { get; set; }
public Camera2D Camera { get; }
public Camera2D Camera { get; }
public StatusEffectDisplay StatusDisplay { get; private set; }
protected NetworkClient NetClient { get; set; }
Microsoft.Xna.Framework.Game IGameContext.Game => Game;
IClientWorld IGameClient.World => World;
//public Hotbar Hotbar { get; set; }
public int ChunkingRadius { get; set; }
// ?
int MyUserID { get; set; }
int MyPlayerID { get; set; }
int MyUserID;
int MyPlayerID;
public Game.Entities.LocalPlayer MyPlayer { get; private set; }
PauseMenu PauseMenu { get; set; }
protected List<RepeatingIntervalTask> ClientTasks { get; set; }
// Initialize events for networkmanager to listen for
// each event is bound to a PacketType ID
private Dictionary<PacketType, NetworkListener> NetworkEvents;
private void InitNetworkEvents() => NetworkEvents = new Dictionary<PacketType, NetworkListener>()
{
@@ -136,14 +146,17 @@ namespace CaveGame.Client
Camera = new Camera2D { Zoom = CameraZoom };
Chat = new GameChat(this);
PauseMenu = new PauseMenu(this);
StatusDisplay = new StatusEffectDisplay(this);
Inventory = new PlayerContainerFrontend();
// Game Event Scheduler
ClientTasks = new List<RepeatingIntervalTask>
{
new RepeatingIntervalTask(ReplicatePlayerState, 1 / 10.0f),
new RepeatingIntervalTask(ChunkUnloadingCheck, 1/2.0f),
new RepeatingIntervalTask(ChunkLoadingCheckUpdate, 1 / 2.0f),
};
ChunkingRadius = 1;
}
@@ -153,16 +166,9 @@ namespace CaveGame.Client
NetClient = new NetworkClient(login.ServerAddress);
}
protected struct FpsSample : GraphSample
{
public double Value { get; set; }
}
//protected GraphRenderer<FpsSample> FPSGraph { get; private set; }
//GraphRecorder<FpsSample> ImmediateData;
//GraphRecorder<FpsSample> AverageData;
private void Uncouple()
// Cleanup code after leaving any game server.
private void Logout()
{
PauseMenu.Open = false;
@@ -174,37 +180,42 @@ namespace CaveGame.Client
//Dispose();
}
// Fills the player's inventory with test items upon startup.
// This is testing data, and should be left out of the final game
// Called after creating a player.
// Should probably be done on the server...
private void FillInventory(Container container)
{
container.ForceSetSlot(0, 0, new ItemStack { Item = new RaycastTesterItem(), Quantity = 1 });
//Inventory.Container.ForceSetSlot(0, 0, new ItemStack {Item = new CopperPickaxe(), Quantity = 1 });
container.ForceSetSlot(0, 1, new ItemStack { Item = new IronPickaxe(), Quantity = 1 });
container.ForceSetSlot(0, 2, new ItemStack { Item = new LeadPickaxe(), Quantity = 1 });
container.ForceSetSlot(1, 0, new ItemStack { Item = new TileItem(new Core.Game.Tiles.OakPlank()), Quantity = 999 });
container.ForceSetSlot(1, 1, new ItemStack { Item = new GenericWallScraper(), Quantity = 1 });
container.ForceSetSlot(2, 0, new ItemStack { Item = new TileItem(new Core.Game.Tiles.StoneBrick()), Quantity = 999 });
container.ForceSetSlot(3, 0, new ItemStack { Item = new TileItem(new Core.Game.Tiles.ClayBrick()), Quantity = 999 });
container.ForceSetSlot(4, 0, new ItemStack { Item = new BombItem(), Quantity = 999 });
container.ForceSetSlot(5, 0, new ItemStack { Item = new TileItem(new RedTorch()), Quantity = 999 });
container.ForceSetSlot(6, 0, new ItemStack { Item = new TileItem(new GreenTorch()), Quantity = 999 });
container.ForceSetSlot(7, 0, new ItemStack { Item = new TileItem(new BlueTorch()), Quantity = 999 });
container.ForceSetSlot(8, 0, new ItemStack { Item = new TileItem(new Torch()), Quantity = 999 });
container.ForceSetSlot(9, 0, new ItemStack { Item = new TileItem(new Water()), Quantity = 999 });
container.ForceSetSlot(2, 1, new ItemStack { Item = new FurnaceItem(), Quantity = 999 });
container.ForceSetSlot(3, 1, new ItemStack { Item = new DoorItem(), Quantity = 999 });
container.ForceSetSlot(4, 1, new ItemStack { Item = new WorkbenchItem(), Quantity = 999 });
container.ForceSetSlot(5, 1, new ItemStack { Item = new WallItem(new Core.Game.Walls.StoneBrick()), Quantity = 999 });
container.ForceSetSlot(0, 3, ItemStack.Of<Nimdoc>(5));
container.ForceSetSlot(0, 1, ItemStack.Of<CopperPickaxe>());
container.ForceSetSlot(0, 1, ItemStack.Of<IronPickaxe>());
container.ForceSetSlot(0, 2, ItemStack.Of<LeadPickaxe>());
container.ForceSetSlot(1, 1, ItemStack.Of<GenericWallScraper>());
container.ForceSetSlot(0, 0, ItemStack.Of<BombItem>(999));
container.ForceSetSlot(1, 0, new ItemStack(TileItem.Of<Core.Game.Tiles.OakPlank>(), 999));
container.ForceSetSlot(2, 0, new ItemStack(TileItem.Of<Core.Game.Tiles.StoneBrick>(), 999));
container.ForceSetSlot(3, 0, new ItemStack(TileItem.Of<Core.Game.Tiles.ClayBrick>(), 999));
container.ForceSetSlot(4, 0, new ItemStack(TileItem.Of<GreenTorch>(), 999));
container.ForceSetSlot(5, 0, new ItemStack(TileItem.Of<RedTorch>(), 999));
container.ForceSetSlot(6, 0, new ItemStack(TileItem.Of<BlueTorch>(), 999));
container.ForceSetSlot(7, 0, new ItemStack(TileItem.Of<Lava>(), 999));
container.ForceSetSlot(8, 0, ItemStack.Of<FurnaceItem>(999));
container.ForceSetSlot(9, 0, ItemStack.Of<DoorItem>(999));
container.ForceSetSlot(1, 1, ItemStack.Of<WorkbenchItem>(999));
//container.ForceSetSlot(5, 1, new ItemStack { Item = new WallItem(new Core.Game.Walls.StoneBrick()), Quantity = 999 });
}
public void Disconnect()
{
Uncouple();
Logout();
Game.GoToMainMenu();
}
public void ForcedDisconnect(string kickReason)
{
Uncouple();
Logout();
Game.GoToTimeoutPage(kickReason);
}
@@ -576,8 +587,11 @@ namespace CaveGame.Client
}
#endregion
private void ReadIncomingPackets()
{
// read all queued packets
while (NetClient.HaveIncomingMessage())
{
NetworkMessage msg = NetClient.GetLatestMessage();
@@ -586,13 +600,15 @@ namespace CaveGame.Client
{
ServerKeepAlive = 0;
ev.Value.Invoke(msg);
}
}
}
}
float redrawTimer { get; set; }
// chunks are drawn to a back buffer, rather than redrawing the chunk each frame
// this causes quite a few issues.
private void RedrawChunkBuffers(GraphicsEngine GFX)
{
foreach (var chunkpair in World.Chunks)
@@ -603,20 +619,20 @@ namespace CaveGame.Client
}
}
private void EntityRendering(GraphicsEngine gfx)
private void DrawEntities(GraphicsEngine gfx)
{
foreach (Entity entity in World.Entities)
{
entity.Draw(gfx);
}
}
// draw foreground chunk buffers
// drawn after background
private void DrawChunkTileTextures(GraphicsEngine gfx)
{
foreach (var chunkpair in World.Chunks)
{
Chunk chunk = chunkpair.Value;
Vector2 pos = new Vector2(chunk.Coordinates.X * Globals.ChunkSize * Globals.TileSize, chunk.Coordinates.Y * Globals.ChunkSize * Globals.TileSize);
if (chunk.TileRenderBuffer != null)
@@ -624,6 +640,9 @@ namespace CaveGame.Client
}
}
// draw background chunk buffers
// drawn before entities & particles
private void DrawChunkWallTextures(GraphicsEngine gfx)
{
foreach (var chunkpair in World.Chunks)
@@ -636,6 +655,9 @@ namespace CaveGame.Client
gfx.Sprite(chunk.WallRenderBuffer, pos, Color.White);
}
}
// render a shitton of debug data
// todo: move to their own togglable datasets
private void DrawDebugInfo(GraphicsEngine gfx)
{
gfx.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp);
@@ -648,7 +670,6 @@ namespace CaveGame.Client
var tileCoords = mp;
mp *= 8;
var tileat = World.GetTile((int)tileCoords.X, (int)tileCoords.Y);
var wallat = World.GetWall((int)tileCoords.X, (int)tileCoords.Y);
@@ -658,8 +679,6 @@ namespace CaveGame.Client
debugStats.Add($"userid {MyUserID} netaddr {ConnectAddress}");
//debugStats.Add($"in {Math.Round(NetClient.BytesReceivedPerSecond / 1000.0f, 2)}kb/s || {Math.Round(NetClient.TotalBytesReceived / 1000.0f, 2)}kb total || {NetClient.PacketsReceived}ct");
//debugStats.Add($"out {Math.Round(NetClient.BytesSentPerSecond / 1000.0f, 2)}kb/s || {Math.Round(NetClient.TotalBytesSent / 1000.0f, 2)}kb total || {NetClient.PacketsSent}ct");
if (World!=null)
debugStats.Add($"entities {World.Entities.Count} furn {World.Furniture.Count}");
@@ -701,6 +720,8 @@ namespace CaveGame.Client
//gameClient.SendPacket(new RequestJoinPacket("jooj"));
}
// on connection failure
// show the "OOPS" screen
private void FailConnect(string reason)
{
Game.MenuContext.CurrentPage = Game.MenuContext.TimeoutPage;
@@ -717,13 +738,15 @@ namespace CaveGame.Client
{
// Just Pressed
if (mouse.LeftButton == ButtonState.Pressed && previous.LeftButton == ButtonState.Released)
{
Inventory.EquippedItem.Item.OnClientLMBDown(MyPlayer, this, Inventory.EquippedItem);
}
// being held
if (mouse.LeftButton == ButtonState.Pressed && previous.LeftButton == ButtonState.Pressed)
{
Inventory.EquippedItem.Item.OnClientLMBHeld(MyPlayer, this, Inventory.EquippedItem, gt);
}
// released
if (mouse.LeftButton == ButtonState.Released && previous.LeftButton == ButtonState.Pressed)
Inventory.EquippedItem.Item.OnClientLMBUp(MyPlayer, this, Inventory.EquippedItem);
}
// Object interaction
@@ -744,9 +767,11 @@ namespace CaveGame.Client
}
// send player direction and animation state to the server
// players are handled slightly differently in that animation state is controlled on the client, and replicated to the server
// sanity checking is in order
private void ReplicatePlayerState()
{
//Debug.WriteLine("Replicating");
if (MyPlayer != null)
{
NetClient?.SendPacket(new EntityPhysicsStatePacket(MyPlayer));
@@ -756,18 +781,17 @@ namespace CaveGame.Client
float scroll = 2;
// update game camera
private void UpdateCamera(GameTime gt)
{
MouseState mouse = Mouse.GetState();
// scroll
if (Keyboard.GetState().IsKeyDown(Keys.OemMinus))
{
scroll -= 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.OemPlus))
{
scroll += 0.01f;
}
//float ZoomFactor = ((mouse.ScrollWheelValue - IntitalScrollValue) * (Senitivity / 120)) + 2;
@@ -828,24 +852,11 @@ namespace CaveGame.Client
previousKB = currentKB;
}
public void Update(GameTime gt)
// hide keyboard events from the game engine while the
// chat or console are open.
private void UpdatePlayerIgnoresKeyboardInput()
{
//AverageData.Push(new FpsSample { Value = Game.FPSCounter.GetAverageFramerate()});
//ImmediateData.Push(new FpsSample { Value = Game.FPSCounter.GetExactFramerate() });
//NetClient.Update(gt);
redrawTimer += gt.GetDelta();
Profiler.StartRegion("Update");
ServerKeepAlive += gt.GetDelta();
UpdateInputs();
Camera.Update(gt);
ClientTasks.ForEach(ct => ct.Update(gt));
// check for player first
if (MyPlayer != null)
{
if (PauseMenu.Open == true || Chat.Open == true || Game.Console.Open == true)
@@ -853,28 +864,24 @@ namespace CaveGame.Client
else
MyPlayer.IgnoreInput = false;
}
}
Profiler.Start("UIUpdate");
public void Update(GameTime gt)
{
redrawTimer += gt.GetDelta();
ServerKeepAlive += gt.GetDelta();
UpdateInputs();
Camera.Update(gt);
ClientTasks.ForEach(ct => ct.Update(gt));
Inventory.Update(gt);
PauseMenu.Update(gt);
Chat.Update(gt);
Profiler.End();
//Profiler.Start("WorldUpdate");
World.Update(gt);
//Profiler.End();
Profiler.Start("Camera");
StatusDisplay.Update(gt);
HotbarUpdate(gt);
UpdateCamera(gt);
Profiler.End();
Profiler.Start("ReadPackets");
ReadIncomingPackets();
Profiler.End();
Profiler.EndRegion();
}
protected void DrawBackgroundLayer(GraphicsEngine GFX)
@@ -890,32 +897,20 @@ namespace CaveGame.Client
GFX.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, Camera.View);
if (PauseMenu.Open)
PauseMenu.DrawWaterPixelsFilter(GFX);
PauseMenu.DrawWaterPixelsFilter(GFX); // apply background blur
World.Sky.DrawBackground(GFX);
Profiler.Start("DrawChunkCanvases");
DrawChunkWallTextures(GFX);
World.Sky.DrawBackground(GFX); // 0: render sky/background
DrawChunkWallTextures(GFX); //
DrawChunkTileTextures(GFX);
Profiler.End();
Profiler.Start("DrawFurniture");
foreach (var furn in World.Furniture)
{
furn.Draw(GFX);
}
Profiler.End();
Profiler.Start("DrawEntities");
EntityRendering(GFX);
Profiler.End();
Profiler.Start("DrawParticles");
DrawEntities(GFX);
World.ParticleSystem.Draw(GFX);
Profiler.End();
if (!Inventory.EquippedItem.Equals(ItemStack.Empty))
{
Inventory.EquippedItem.Item?.OnClientDraw(GFX);
}
MouseState mouse = Mouse.GetState();
@@ -941,41 +936,31 @@ namespace CaveGame.Client
protected void DrawUILayer(GraphicsEngine GFX)
{
Profiler.Start("DrawUI");
GFX.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp);
Inventory.Draw(GFX);
StatusDisplay.Draw(GFX);
PauseMenu.Draw(GFX);
GFX.End();
Chat.Draw(GFX);
Profiler.End();
Profiler.Start("DrawDebug");
DrawDebugInfo(GFX);
Profiler.End();
}
public void Draw(GraphicsEngine GFX)
{
Profiler.StartRegion("Draw");
if (redrawTimer > (1.0f / 8.0f))
{
redrawTimer = 0;
Profiler.Start("DrawChunkBuffers");
RedrawChunkBuffers(GFX);
//Profiler.Track("DrawChunkBuffers", ()=>RedrawChunkBuffers(GFX));
Profiler.End("DrawChunkBuffers");
}
DrawBackgroundLayer(GFX);
DrawGameLayer(GFX);
DrawUILayer(GFX);
Profiler.EndRegion("Draw");
GFX.Begin(SpriteSortMode.Immediate);
Profiler.Draw(GFX);
// FPSGraph.Draw(GFX);
//FPSGraph.DrawLineGraph(GFX, ImmediateData);
// FPSGraph.DrawLineGraph(GFX, AverageData);

View File

@@ -50,22 +50,14 @@ namespace CaveGame.Client
}
}
// Old name for game settings, backward compatibility
[XmlRoot("XGameSettings")]
public class GameSettings : Configuration
{
public static SliderIndex<int>[] VolumeSliderOptions = SliderIndex<int>.GetIntArray(0, 100);
public static SliderIndex<int>[] FramerateCapSliderOptions =
{
new SliderIndex<int>("Unlimited", 0),
new SliderIndex<int>("240", 240),
new SliderIndex<int>("144", 144),
new SliderIndex<int>("120", 120),
new SliderIndex<int>("90", 90),
new SliderIndex<int>("60", 60),
new SliderIndex<int>("30", 30),
};
public static SliderIndex<int>[] VolumeSliderOptions = SliderIndex<int>.GetIntArray(0, 101);
public static SliderIndex<GameChatSize>[] ChatSizeSliderOptions =
{
@@ -78,12 +70,86 @@ namespace CaveGame.Client
public GameSettings()
{
CurrentSettings = this;
}
[XmlIgnore]
public CaveGameGL game;
[XmlIgnore]
private bool _fullscreen;
private bool _particles;
private bool _vsync;
private int _fpslimit;
private int _masterVolume;
private int _musicVolume;
private int _sfxVolume;
public bool Fullscreen {
get => _fullscreen;
set {
_fullscreen = value;
game?.SetFullscreen(value);
}
}
public bool Particles {
get => _particles;
set {
_particles = value;
}
}
public bool VSync
{
get => _vsync;
set
{
_vsync = value;
game?.SetVSync(value);
}
}
public int FPSLimit {
get => _fpslimit;
set {
_fpslimit = value;
game?.SetFPSLimit(value);
}
}
public int MasterVolume {
get => _masterVolume;
set {
_masterVolume = value;
AudioManager.MasterVolume = value / 100.0f;
}
}
public int MusicVolume { get => _musicVolume;
set
{
_musicVolume = value;
AudioManager.MusicVolume = value / 100.0f;
}
}
public int SFXVolume
{
get => _sfxVolume;
set
{
_sfxVolume = value;
}
}
public bool Fullscreen { get; set; }
public bool Particles { get; set; }
public int FPSLimit { get; set; }
public int FPSLimitIndex { get; set; }
public Keys MoveLeftKey { get; set; }
public Keys MoveRightKey { get; set; }
public Keys MoveDownKey { get; set; }
@@ -91,17 +157,11 @@ namespace CaveGame.Client
public Keys JumpKey { get; set; }
public GameChatSize ChatSize { get; set; }
public string TexturePackName { get; set; }
public int MasterVolume { get; set; }
public int MusicVolume { get; set; }
public int SFXVolume { get; set; }
public int MenuVolume { get; set; }
public bool CameraShake { get; set; }
public override void FillDefaults()
{
FPSLimit = 120;
FPSLimitIndex = 3;
FPSLimit = 60;
Fullscreen = false;
MoveDownKey = Keys.S;
MoveUpKey = Keys.W;
@@ -109,6 +169,10 @@ namespace CaveGame.Client
MoveLeftKey = Keys.A;
MoveRightKey = Keys.D;
ChatSize = GameChatSize.Normal;
MasterVolume = 100;
MusicVolume = 50;
SFXVolume = 75;
}
}

View File

@@ -58,7 +58,7 @@ namespace CaveGame.Client.Menu
{
Pages = new Dictionary<string, UIRoot>();
Game = _game;
rastering = new RasterizerState() { ScissorTestEnable = true };
rastering = new RasterizerState() { ScissorTestEnable = false };
}
public void Draw(GraphicsEngine GFX)

View File

@@ -83,26 +83,33 @@ namespace CaveGame.Client.Menu
TextYAlign = TextYAlignment.Center,
};
UIRect optionList = new UIRect
// Left-Side options
var LeftList = new UIRect
{
Parent = SettingsUI,
Size = new UICoords(0, 0, 0.6f, 0.7f),
Position = new UICoords(0, 0, 0.5f, 0.5f),
AnchorPoint = new Vector2(0.5f, 0.5f),
Size = new UICoords(0, 0, 0.3f, 0.8f),
Position = new UICoords(0, 0, 0.6f, 0.2f),
AnchorPoint = new Vector2(0f, 0f),
BGColor = Color.Transparent,
};
var LeftContainer = new UIListContainer{Padding = 2, Parent = LeftList};
UIListContainer container = new UIListContainer
Label graphicsLbl = new Label
{
Padding = 2,
Parent = optionList,
TextColor = Color.White,
Parent = LeftContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial16,
Text = "GRAPHICS",
TextXAlign = TextXAlignment.Center,
};
TextButton fullscreenBtn = new TextButton
{
Parent = container,
Parent = LeftContainer,
TextColor = Color.White,
Text = "Fullscreen: "+ReadableBoolean(GameSettings.CurrentSettings.Fullscreen),
Text = "Fullscreen: " + ReadableBoolean(Game.Settings.Fullscreen),
Font = GFX.Fonts.Arial14,
Size = new UICoords(0, 25, 1, 0),
TextXAlign = TextXAlignment.Center,
@@ -112,19 +119,17 @@ namespace CaveGame.Client.Menu
};
void updateFullscreenBnt(TextButton b, MouseState m)
{
GameSettings.CurrentSettings.Fullscreen = !GameSettings.CurrentSettings.Fullscreen;
fullscreenBtn.Text = "Fullscreen: " + ReadableBoolean(GameSettings.CurrentSettings.Fullscreen);
GameSettings.CurrentSettings.Save();
Game.OnSetFullscreen(GameSettings.CurrentSettings.Fullscreen);
Game.Settings.Fullscreen = !Game.Settings.Fullscreen;
fullscreenBtn.Text = "Fullscreen: " + ReadableBoolean(Game.Settings.Fullscreen);
}
fullscreenBtn.OnLeftClick += updateFullscreenBnt;
// Particles toggle
TextButton particlesBtn = new TextButton
{
Parent = container,
Parent = LeftContainer,
TextColor = Color.White,
Text = "Particles: " + ReadableBoolean(GameSettings.CurrentSettings.Particles),
Text = "Particles: " + ReadableBoolean(Game.Settings.Particles),
Font = GFX.Fonts.Arial14,
Size = new UICoords(0, 25, 1, 0),
TextXAlign = TextXAlignment.Center,
@@ -134,56 +139,70 @@ namespace CaveGame.Client.Menu
};
void updateParticles(TextButton b, MouseState m)
{
particlesBtn.Text = "Particles: " + ReadableBoolean(GameSettings.CurrentSettings.Particles);
GameSettings.CurrentSettings.Particles = !GameSettings.CurrentSettings.Particles;
GameSettings.CurrentSettings.Save();
Game.Settings.Particles = !Game.Settings.Particles;
particlesBtn.Text = "Particles: " + ReadableBoolean(Game.Settings.Particles);
}
particlesBtn.OnLeftClick += updateParticles;
// Framerate Cap
Label fpsCapText = new Label
{
TextColor = Color.White,
Parent = container,
Parent = LeftContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial14,
Text = "Framerate Cap: " + GameSettings.CurrentSettings.FPSLimit,
Text = "FPS Cap: " + Game.Settings.FPSLimit,
};
Slider<SliderIndex<int>> fpsCapSlider = new UI.Slider<SliderIndex<int>>
NumericSlider fpsCapSlider = new NumericSlider
{
DataSet = GameSettings.FramerateCapSliderOptions,
Parent = container,
Minimum = 30, Maximum = 241, Interval = 30,
Parent = LeftContainer,
Size = new UICoords(0, 25, 0.5f, 0),
AnchorPoint = new Vector2(0.0f, 0.0f),
UnselectedBGColor = new Color(0.6f, 0.6f, 0.6f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Scrubber = new Scrubber { Width=20},
Scrubber = new Scrubber { Width = 20 },
BGColor = new Color(0.25f, 0.25f, 0.25f),
};
void onFpsCapSliderChanged(Slider<SliderIndex<int>> sl, SliderIndex<int> val, int index)
void onFpsCapSliderChanged(NumericSlider slider, float value)
{
GameSettings.CurrentSettings.FPSLimitIndex = index;
GameSettings.CurrentSettings.FPSLimit = val.Value;
fpsCapText.Text = "FPS Cap:" + val.Display;
Game.OnSetFPSLimit(val.Value);
GameSounds.MenuBlip?.Play(0.8f, 1, 0.0f);
fpsCapText.Text = "FPS Cap:" + (int)value;
Game.Settings.FPSLimit = (int)value;
}
fpsCapSlider.OnValueChanged += onFpsCapSliderChanged;
//fpsCapSlider.SetIndex(GameSettings.CurrentSettings.FPSLimitIndex);
// Right-Side options
UIRect RightList = new UIRect
{
Parent = SettingsUI,
Size = new UICoords(0, 0, 0.3f, 0.8f),
Position = new UICoords(0, 0, 0.1f, 0.2f),
AnchorPoint = new Vector2(0f, 0f),
BGColor = Color.Transparent,
};
UIListContainer RightContainer = new UIListContainer
{
Padding = 2,
Parent = RightList,
};
// chat size slider
Label chatSizeText = new Label
{
TextColor = Color.White,
Parent = container,
Parent = LeftContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial14,
Text = "Chat Size: " + GameSettings.ChatSizeSliderOptions[(int)GameSettings.CurrentSettings.ChatSize].Display,
Text = "Chat Size: " + Game.Settings.ChatSize,
};
Slider<SliderIndex<GameChatSize>> chatSizeSlider = new UI.Slider<SliderIndex<GameChatSize>>
{
DataSet = GameSettings.ChatSizeSliderOptions,
Parent = container,
Parent = LeftContainer,
Size = new UICoords(0, 25, 0.5f, 0),
AnchorPoint = new Vector2(0.0f, 0.0f),
UnselectedBGColor = new Color(0.6f, 0.6f, 0.6f),
@@ -193,13 +212,120 @@ namespace CaveGame.Client.Menu
};
void onChatSliderChanged(Slider<SliderIndex<GameChatSize>> sl, SliderIndex<GameChatSize> val, int index)
{
GameSettings.CurrentSettings.ChatSize = val.Value;
Game.Settings.ChatSize = val.Value;
chatSizeText.Text = "Chat Size:" + val.Display;
Game.OnSetChatSize(val.Value);
GameSounds.MenuBlip?.Play(0.8f, 1, 0.0f);
}
chatSizeSlider.OnValueChanged += onChatSliderChanged;
//chatSizeSlider.SetIndex((int)GameSettings.CurrentSettings.ChatSize);
Label soundLbl = new Label
{
TextColor = Color.White,
Parent = RightContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial16,
Text = "SOUND",
TextXAlign = TextXAlignment.Center,
};
Label masterVolumeLabel = new Label
{
TextColor = Color.White,
Parent = RightContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial14,
Text = "Master Volume: " + GameSettings.CurrentSettings.MasterVolume + "%",
};
Slider<SliderIndex<int>> masterVolumeSlider = new UI.Slider<SliderIndex<int>>
{
DataSet = GameSettings.VolumeSliderOptions,
Parent = RightContainer,
Size = new UICoords(0, 20, 1f, 0),
AnchorPoint = new Vector2(0.0f, 0.0f),
UnselectedBGColor = new Color(0.6f, 0.6f, 0.6f),
SelectedBGColor = new Color(0.0f, 0.0f, 0.0f),
Scrubber = new Scrubber { Width = 20 },
BGColor = new Color(0.25f, 0.25f, 0.25f),
};
void onMasterVolumeSliderChanged(Slider<SliderIndex<int>> sl, SliderIndex<int> val, int index)
{
GameSettings.CurrentSettings.MasterVolume = val.Value;
masterVolumeLabel.Text = "Master Volume: " + val.Display + "%";
GameSounds.MenuBlip?.Play(val.Value/100.0f, 1, 0.0f);
}
masterVolumeSlider.OnValueChanged += onMasterVolumeSliderChanged;
Label musicVolumeLabel = new Label
{
TextColor = Color.White,
Parent = RightContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial14,
Text = "Music Volume: " + GameSettings.ChatSizeSliderOptions[(int)GameSettings.CurrentSettings.ChatSize].Display,
};
Slider<SliderIndex<int>> musicVolumeSlider = new UI.Slider<SliderIndex<int>>
{
DataSet = GameSettings.VolumeSliderOptions,
Parent = RightContainer,
Size = new UICoords(0, 25, 1f, 0),
AnchorPoint = new Vector2(0.0f, 0.0f),
UnselectedBGColor = new Color(0.6f, 0.6f, 0.6f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Scrubber = new Scrubber { Width = 20 },
BGColor = new Color(0.25f, 0.25f, 0.25f),
};
void onMusicVolumeSliderChanged(Slider<SliderIndex<int>> sl, SliderIndex<int> val, int index)
{
GameSettings.CurrentSettings.MusicVolume = val.Value;
musicVolumeLabel.Text = "Music Volume: " + val.Display + "%";
Game.Settings.MusicVolume = val.Value;
GameSounds.MenuBlip?.Play(val.Value / 100.0f, 1, 0.0f);
}
musicVolumeSlider.OnValueChanged += onMusicVolumeSliderChanged;
Label sfxVolumeLabel = new Label
{
TextColor = Color.White,
Parent = RightContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial14,
Text = GetSFXLabelText(GameSettings.CurrentSettings.SFXVolume),
};
NumericSlider sfxVolumeSlider = new NumericSlider
{
Maximum = 100, Minimum = 0, Interval = 1,
Parent = RightContainer,
Size = new UICoords(0, 25, 1f, 0),
AnchorPoint = new Vector2(0.0f, 0.0f),
UnselectedBGColor = new Color(0.6f, 0.6f, 0.6f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Scrubber = new Scrubber { Width = 20 },
BGColor = new Color(0.25f, 0.25f, 0.25f),
};
string GetSFXLabelText(float value) => "SFX Volume: " + Math.Floor(value) + "%";
void OnSFXVolumeSliderChanged(NumericSlider slider, float value)
{
GameSettings.CurrentSettings.SFXVolume = (int)value;
AudioManager.EffectVolume = value / 100.0f;
sfxVolumeLabel.Text = GetSFXLabelText(GameSettings.CurrentSettings.SFXVolume);
}
sfxVolumeSlider.OnValueChanged += OnSFXVolumeSliderChanged;
Label controlLbl = new Label
{
TextColor = Color.White,
Parent = RightContainer,
Size = new UICoords(0, 25, 1, 0),
Font = GFX.Fonts.Arial16,
Text = "CONTROLS",
TextXAlign = TextXAlignment.Center,
};
void bindButtonClick(TextButton b, MouseState m)
{
@@ -224,7 +350,7 @@ namespace CaveGame.Client.Menu
TextYAlign = TextYAlignment.Center,
UnselectedBGColor = new Color(0.2f, 0.2f, 0.2f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Parent = container,
Parent = RightContainer,
};
jumpKeybindButton.OnLeftClick += bindButtonClick;
jumpKeybindButton.OnRebind += jumpRebind;
@@ -246,7 +372,7 @@ namespace CaveGame.Client.Menu
TextYAlign = TextYAlignment.Center,
UnselectedBGColor = new Color(0.2f, 0.2f, 0.2f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Parent = container,
Parent = RightContainer,
};
upKeybindButton.OnLeftClick += bindButtonClick;
upKeybindButton.OnRebind += upRebind;
@@ -263,7 +389,7 @@ namespace CaveGame.Client.Menu
TextYAlign = TextYAlignment.Center,
UnselectedBGColor = new Color(0.2f, 0.2f, 0.2f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Parent = container,
Parent = RightContainer,
};
void downRebind(Keys key)
{
@@ -284,7 +410,7 @@ namespace CaveGame.Client.Menu
TextYAlign = TextYAlignment.Center,
UnselectedBGColor = new Color(0.2f, 0.2f, 0.2f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Parent = container,
Parent = RightContainer,
};
void leftRebind(Keys key)
{
@@ -304,7 +430,7 @@ namespace CaveGame.Client.Menu
TextYAlign = TextYAlignment.Center,
UnselectedBGColor = new Color(0.2f, 0.2f, 0.2f),
SelectedBGColor = new Color(0.1f, 0.1f, 0.1f),
Parent = container,
Parent = RightContainer,
};
void rightRebind(Keys key)
{

View File

@@ -13,10 +13,9 @@ namespace CaveGame.Client
public bool SplashActive => (SplashTimer > 0);
public float SplashTimer { get; set; }
public Splash()
{
SplashTimer = 5;
SplashTimer = 7;
}
public void Update(GameTime gt)
@@ -24,26 +23,22 @@ namespace CaveGame.Client
SplashTimer -= gt.GetDelta();
}
public void Draw(GraphicsEngine GraphicsEngine)
{
GraphicsEngine.Clear(Color.Black);
//GraphicsEngine.Begin();
var splash = GraphicsEngine.Textures["csoft_wp2.png"];
GraphicsEngine.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp);
Vector2 center = new Vector2(GraphicsEngine.WindowSize.X / 2.0f, GraphicsEngine.WindowSize.Y / 2.0f);
Vector2 origin = new Vector2(GraphicsEngine.EyeOfHorus.Width / 2.0f, GraphicsEngine.EyeOfHorus.Height / 2.0f);
float scale = 8;
Vector2 origin = new Vector2(splash.Width / 2.0f, splash.Height / 2.0f);
var scale = center/origin;
Vector2 bounds = GraphicsEngine.Fonts.Arial30.MeasureString("CONARIUM SOFTWARE");
GraphicsEngine.Sprite(GraphicsEngine.EyeOfHorus, center - new Vector2(0, (float)Math.Sin(SplashTimer * 2) * 10), null, Color.White, Rotation.Zero, origin, scale, SpriteEffects.None, 0);
Color drawColor = Color.White;
GraphicsEngine.Sprite(splash, center, null, drawColor, Rotation.Zero, origin, scale, SpriteEffects.None, 0);
GraphicsEngine.Text(
font: GraphicsEngine.Fonts.Arial30,
text: "CONARIUM SOFTWARE",
position: center + new Vector2(0, 100), Color.White, TextXAlignment.Center, TextYAlignment.Center);
GraphicsEngine.End();
}
}

View File

@@ -0,0 +1,43 @@
using CaveGame.Core;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Client
{
public class StatusEffectDisplay
{
GameClient Client { get; set; }
public StatusEffectDisplay(GameClient client)
{
Client = client;
}
public void Update(GameTime gt)
{
var player = Client.MyPlayer;
if (player == null)
return;
}
public void Draw(GraphicsEngine GFX)
{
var player = Client.MyPlayer;
if (player == null)
return;
int idx = 0;
foreach(var effect in player.ActiveEffects)
{
var TopRight = new Vector2(GFX.WindowSize.X-100, idx*20);
GFX.Rect(Color.Gray, TopRight, new Vector2(90, 20));
GFX.Text(effect.EffectName+": "+effect.Duration, TopRight);
idx++;
}
}
}
}

View File

@@ -51,6 +51,11 @@ namespace CaveGame.Client.UI
this.InitFromLuaPropertyTable(state, table);
}
public delegate void SliderChangedEV(NumericSlider slider, float index);
public event SliderChangedEV OnValueChanged;
public float Minimum { get; set; }
public float Maximum { get; set; }
public float Interval { get; set; }
@@ -115,6 +120,7 @@ namespace CaveGame.Client.UI
float percentage = offset / SliderTotalWidth;
var translated = Math.Clamp(Maths.NearestMultiple(percentage * range, Interval), 0, range);
Value = translated + Minimum;
OnValueChanged?.Invoke(this, Value);
}
prevMouse = mouse;

View File

@@ -17,10 +17,8 @@ using Microsoft.Xna.Framework.Input;
namespace CaveGame.Client.UI
{
public static class TypeCastingHax
{
{
public static void InitFromLuaPropertyTable(this object thing, Lua environment, LuaTable table)
{
foreach (KeyValuePair<object, object> kvp in environment.GetTableDict(table))

View File

@@ -23,8 +23,6 @@ namespace CaveGame.Client
}
}
public static Color[] SkyColors =
{
new Color(0, 2, 6), new Color(5, 5, 30), //0 or 24
@@ -47,11 +45,15 @@ namespace CaveGame.Client
}
private void DrawSkyColorGradient(GraphicsEngine GFX)
{
if (World.Client.Camera.Position.Y > 600)
{
GFX.Rect(Color.Black, Vector2.Zero, World.Client.Camera.WindowSize);
return;
}
for (int y = 0; y < 10; y++)
{
int hourTime = (int)Math.Floor(((World.TimeOfDay + 1) % 24) / 2);
@@ -72,14 +74,20 @@ namespace CaveGame.Client
}
}
Random rng = new Random();
float rotation = 0;
private void DrawBackgroundParallax(GraphicsEngine GFX)
{
if (World.Client.Camera.Position.Y > 600)
{
return;
}
Vector2 lill = Rotation.FromDeg(World.TimeOfDay * 360.0f).ToUnitVector() * 0.1f;
float starfieldPar = 0.85f;
float scale = 1.5f;
float scale = 0.25f;
float textureWidth = GFX.Starfield.Width * scale;
float textureHeight = GFX.Starfield.Height * scale;
@@ -89,16 +97,16 @@ namespace CaveGame.Client
(float)pos.Y / textureHeight
) * starfieldPar;
var textureCenter = new Vector2(GFX.Starfield.Width / 2.0f, GFX.Starfield.Height / 2.0f);
for (int tx = -2; tx < 2; tx++)
for (int tx = -3; tx < 3; tx++)
{
for (int ty = -2; ty < 2; ty++)
for (int ty = -3; ty < 3; ty++)
{
float xPos = tx + gridPos.X;
float yPos = ty + gridPos.Y;
GFX.Sprite(GFX.Starfield, new Vector2(xPos * textureWidth, yPos * textureHeight), null, Color.White, Rotation.Zero, Vector2.Zero, scale, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 0);
GFX.Sprite(GFX.Starfield, new Vector2(xPos * textureWidth, yPos * textureHeight)+lill, null, Color.White, Rotation.FromDeg((tx+ty).Mod(4)*90), textureCenter, scale, Microsoft.Xna.Framework.Graphics.SpriteEffects.None, 0);
}
}

43
Core/AudioManager.cs Normal file
View File

@@ -0,0 +1,43 @@
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core
{
public class AudioManager
{
public static Dictionary<string, Song> Songs = new Dictionary<string, Song>();
public static Dictionary<string, SoundEffect> Effects = new Dictionary<string, SoundEffect>();
public static void RegisterEffect(string effectname, SoundEffect effect)
{
Effects.Add(effectname, effect);
}
public static void RegisterSong(string songname, Song song)
{
Songs.Add(songname, song);
}
public static void PlaySong(string songname)
{
MediaPlayer.Volume = (MasterVolume * MusicVolume);
MediaPlayer.Play(Songs[songname]);
}
public static void PlayEffect(string effectname, float volume = 1, float pitch = 1, float pan = 0)
{
var effect = Effects[effectname].CreateInstance();
effect.Volume = (MasterVolume*EffectVolume*volume);
effect.Pitch = pitch;
effect.Pan = pan;
effect.Play();
}
public static float MasterVolume { get; set; } = 1;
public static float MusicVolume { get; set; } = 0.1f;
public static float EffectVolume { get; set; } = 1;
}
}

View File

@@ -10,11 +10,20 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)AssetManagement\AssetLoader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)AudioManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Enums\DamageType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Enums\Direction.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Enums\GameSteamAchievement.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Enums\TextAlignment.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Biomes\Badlands.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Biomes\Biome.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Biomes\Desert.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Biomes\Forest.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Biomes\Mountain.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Biomes\Plains.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Camera.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Entities\Zombie.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Game\Items\Nimdoc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interfaces\ICaveGameImplementation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interfaces\IDamageSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interfaces\IEntityManager.cs" />
@@ -100,7 +109,6 @@
<MonoGameContentReference Include="$(MSBuildThisFileDirectory)Content\Content.mgcb" />
</ItemGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)Game\Items\" />
<Folder Include="$(MSBuildThisFileDirectory)DataTypes\" />
<Folder Include="$(MSBuildThisFileDirectory)Game\Structures\" />
<Folder Include="$(MSBuildThisFileDirectory)Logging\" />

View File

@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Biomes
{
public class Badlands : Biome
{
public Badlands(Generator g) : base(g) { }
public override float GetHeight(int x)
{
float baseline = Simplex.Noise(x / 80f) * 8;
float raised = (float)(Octave4.Noise2D(x / 6.0f, (-x * 0.03f)) + 0.5f);
if (raised > 0.4)
raised = (raised * 4) + 5;
return 40+baseline + raised;
}
public override void StructurePass(IGameWorld world, int x, int y)
{
}
public override void SurfacePass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + Generator.GetBiomeSurface(worldX) - Generator.GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 3)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Sandstone());
}
else if (depth <= 6)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Clay());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 9)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Sandstone());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 12)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Clay());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 15)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Sandstone());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 18)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Clay());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 30;
if (noise + depth > 30.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
else
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
}
}
}
}

32
Core/Game/Biomes/Biome.cs Normal file
View File

@@ -0,0 +1,32 @@
using CaveGame.Core.Noise;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Biomes
{
public abstract class Biome
{
public int Seed => Generator.Seed;
public OctaveNoise Octave4 => Generator.Octave4;
public OctaveNoise Octave2 => Generator.Octave2;
public OctaveNoise Octave3 => Generator.Octave3;
public OctaveNoise Octave8 => Generator.Octave8;
public SimplexNoise Simplex => Generator.Simplex;
protected Generator Generator;
public Biome(Generator generator)
{
Generator = generator;
}
public abstract float GetHeight(int x);
public abstract void SurfacePass(ref Chunk chunk, int chunkX, int chunkY);
public abstract void StructurePass(IGameWorld world, int x, int y);
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Biomes
{
public class Desert : Biome
{
public Desert(Generator gen) : base(gen) { }
public override float GetHeight(int x)
{
float n = (float)Simplex.Noise(x / 100.420f) * 10 + (float)Octave4.Noise2D(x / 100.0f, (-x * 0.10f) + (x / 20.0f)) * 20;
return n;
}
public override void StructurePass(IGameWorld world, int x, int y)
{
}
public override void SurfacePass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + Generator.GetBiomeSurface(worldX) - Generator.GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Tiles.Sand());
}
else if (depth <= 5)
{
chunk.SetTile(chunkX, chunkY, new Tiles.Sand());
chunk.SetWall(chunkX, chunkY, new Walls.Sandstone());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
var noise = Simplex.Noise(chunkX / 4.0f, chunkY / 4.0f) * 30;
if (noise + depth > 30.5)
chunk.SetTile(chunkX, chunkY, new Tiles.Sandstone());
else
chunk.SetTile(chunkX, chunkY, new Tiles.Sand());
}
}
}
}

View File

@@ -0,0 +1,61 @@
using CaveGame.Core.WorldGeneration;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Biomes
{
public class Forest : Biome
{
public Forest(Generator g) : base(g) { }
public override float GetHeight(int x)
{
float n = (float)Simplex.Noise(x / 100.420f) * 10 + (float)Octave4.Noise2D(x / 60.0f, (-x * 0.10f) + (x / 20.0f)) * 30;
return 20 + n;
}
public override void StructurePass(IGameWorld world, int x, int y)
{
float depth = y + Generator.GetBiomeSurface(x) - Generator.GetBaseSurface(x, y);
if (depth < 3)
{
if (Generator.RNG.Next(7) == 2 && world.GetTile(x, y) is Game.Tiles.Grass && world.GetTile(x, y - 1) is Game.Tiles.Air)
{
TreeGenerator.GenerateTree(world, Generator.RNG, x, y - 1);
}
}
}
public override void SurfacePass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + Generator.GetBiomeSurface(worldX) - Generator.GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Grass());
}
else if (depth <= 30)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Dirt());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 40;
if (noise + depth > 40.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
else
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
}
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Biomes
{
public class Mountain : Biome
{
public Mountain(Generator g) : base(g) { }
public override float GetHeight(int x)
{
float simplex = (float)Simplex.Noise(x / 50.420f);
float octave = (float)Octave8.Noise2D(x / 120.0f, (-x * 0.05f) + (x / 40.0f));
float n = (simplex * 15) * (octave * 15);
float a = Simplex.Noise(x / 10.0f) * 2;
float b = Simplex.Noise(x / 5.0f) * 2;
return (a + b + 100) + n;
}
public override void StructurePass(IGameWorld world, int x, int y)
{
}
public override void SurfacePass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + Generator.GetBiomeSurface(worldX) - Generator.GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
}
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Grass());
}
else if (depth <= 3)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Dirt());
}
else
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
}
if (depth > 0)
{
///
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 10;
if (worldY - noise + depth > 10.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
}
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Biomes
{
public class Plains : Biome
{
public Plains(Generator gen) : base(gen) { }
public override float GetHeight(int x)
{
return Simplex.Noise(x / 100.420f) * 4;
}
public override void StructurePass(IGameWorld world, int x, int y)
{
}
public override void SurfacePass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + Generator.GetBiomeSurface(worldX) - Generator.GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Grass());
}
else if (depth <= 30)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Dirt());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 30;
if (noise + depth > 30.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
else
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
}
}
}
}

View File

@@ -3,6 +3,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CaveGame.Core.Game.Entities
@@ -22,6 +23,10 @@ namespace CaveGame.Core.Game.Entities
}
public interface IEntity : IDamageSource
{
List<StatusEffect> ActiveEffects { get; }
bool AffectedBy<T>() where T : StatusEffect;
Rectangle GetCollisionRect();
Vector2 Position { get; set; }
Vector2 BoundingBox { get; }
@@ -29,7 +34,7 @@ namespace CaveGame.Core.Game.Entities
float DurationAlive { get; set; }
bool Dead { get; set; }
int Health { get; set; }
int Defense { get; set; }
int Defense { get; }
int MaxHealth { get; }
//void Update(IGameWorld world, GameTime gt);
void ClientUpdate(IGameClient client, GameTime gt);
@@ -50,10 +55,7 @@ namespace CaveGame.Core.Game.Entities
}
public interface IThinker
{
float Anger { get; }
float Fear { get; }
float ResponseTime { get; } // time between Think() ticks
int IQ { get; } // affects properties within Think() such as accuracy of pathfinding
float ReactionTime { get; } // time between Think() ticks
void Think(IGameServer server, GameTime gt);
}
@@ -66,7 +68,7 @@ namespace CaveGame.Core.Game.Entities
public virtual Vector2 BoundingBox { get; }
public virtual int Health { get; set; }
public virtual int Defense { get; set; }
public virtual int Defense { get; }
public virtual int MaxHealth { get; }
public virtual Vector2 Position { get; set; }
#endregion
@@ -76,17 +78,14 @@ namespace CaveGame.Core.Game.Entities
public bool RemoteControlled { get; set; }
public int EntityNetworkID { get; set; }
public List<StatusEffect> ActiveEffects { get; private set; }
public Light3 Illumination { get; set; }
public Rectangle GetCollisionRect() => new Rectangle(TopLeft.ToPoint(), (BoundingBox*2).ToPoint());
public void ClearActiveEffects() => ActiveEffects.Clear();
public void AddEffect(StatusEffect effect)
{
}
public Entity() {
ActiveEffects = new List<StatusEffect>();
@@ -113,10 +112,18 @@ namespace CaveGame.Core.Game.Entities
}
public virtual void ClientUpdate(IGameClient client, GameTime gt) {
DurationAlive += gt.GetDelta();
Illumination = client.World.Lighting.GetLight(Position.ToTileCoords());
foreach (StatusEffect effect in ActiveEffects.ToArray())
{
effect.Duration -= gt.GetDelta();
effect.Tick(client.World, gt);
}
ActiveEffects.RemoveAll(e => e.Duration < 0);
}
public virtual void ServerUpdate(IGameServer server, GameTime gt) {
@@ -126,15 +133,29 @@ namespace CaveGame.Core.Game.Entities
foreach (StatusEffect effect in ActiveEffects.ToArray())
{
effect.Duration -= gt.GetDelta();
effect.Tick(gt);
effect.Tick(server.World, gt);
}
ActiveEffects.RemoveAll(e => e.Duration < 0);
}
public virtual void Draw(GraphicsEngine gfx) { }
}
// Status Effect stuff
public List<StatusEffect> ActiveEffects { get; private set; }
public void ClearActiveEffects() => ActiveEffects.Clear();
public void AddEffect(StatusEffect effect)
{
effect.TargetEntity = this;
ActiveEffects.Add(effect);
}
// Check if entity has status effect type
public bool AffectedBy<T>() where T: StatusEffect => ActiveEffects.OfType<T>().Any();
}
}

View File

@@ -2,8 +2,7 @@
using CaveGame.Core.Game.Tiles;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
namespace CaveGame.Core.Game.Entities
{
@@ -117,7 +116,14 @@ namespace CaveGame.Core.Game.Entities
{
if (t is Lava _)
{
Damage(DamageType.Lava, null, 1);
// Add burning effect
if (!AffectedBy<StatusEffects.Burning>())
AddEffect(new StatusEffects.Burning(5));
// continually reset burning duration to 5 while touching lava
ActiveEffects.Find(e => e is StatusEffects.Burning).Duration = 5;
return true;
}
return false;

View File

@@ -18,7 +18,71 @@ using CaveGame.Core.Game.Items;
namespace CaveGame.Core.Game.Entities
{
public class Player : PhysicsEntity, ICanBleed, IServerPhysicsObserver, IClientPhysicsObserver
public class Humanoid : PhysicsEntity
{
public virtual int BaseDefense { get; }
public virtual int DefenseModifier { get; set; }
public virtual int ArmorDefense
{
get
{
int sum = 0;
if (ArmorSlots[0, 0].Item is IArmorItem defensive1)
sum += defensive1.Defense;
if (ArmorSlots[0, 1].Item is IArmorItem defensive2)
sum += defensive2.Defense;
if (ArmorSlots[0, 2].Item is IArmorItem defensive3)
sum += defensive3.Defense;
return sum;
}
}
public override int Defense => BaseDefense + DefenseModifier + ArmorDefense;
public Humanoid() : base()
{
ArmorSlots = new Container(1, 3);
ArmorSlots.ItemWhitelistEnabled = true;
ArmorSlots.ItemTagWhitelist = new List<ItemTag> { ItemTag.Armor };
}
public Direction Facing { get; set; }
public bool Walking { get; set; }
public override float Mass { get; }
public Color Color { get; set; }
public Container ArmorSlots { get; set; }
const float walk_anim_time = 1.25f;
const float push_anim_time = 1.0f;
protected virtual Texture2D Sprite { get; }
public virtual Rectangle GetAnimationFrame() { throw new NotImplementedException(); }
public override void Draw(GraphicsEngine gfx)
{
int flipSprite = 0;
if (Facing == Direction.Left)
flipSprite = 0;
if (Facing == Direction.Right)
flipSprite = 1;
DrawHealth(gfx);
//DrawName(gfx);
gfx.Sprite(Sprite, Position, GetAnimationFrame(), Illumination.MultiplyAgainst(Color), Rotation.Zero, new Vector2(8, 12), 1, (SpriteEffects)flipSprite, 0);
}
}
public class Player : Humanoid, ICanBleed, IServerPhysicsObserver, IClientPhysicsObserver
{
public static Rectangle SP_IDLE = new Rectangle(0, 0, 16, 24);
public static Rectangle SP_WALK0 = new Rectangle(16, 0, 16, 24);
@@ -54,18 +118,13 @@ namespace CaveGame.Core.Game.Entities
public bool OnRope { get; set; }
public User User { get; set; }
public string DisplayName { get; set; }
public Direction Facing { get; set; }
public Color Color { get; set; }
public bool Walking { get; set; }
public bool Pushing { get; set; }
public Container Inventory { get; set; }
public Container ArmorSlots { get; set; }
protected float animationTimer;
protected float landingImpactAnim;
public Player()
{
@@ -84,20 +143,13 @@ namespace CaveGame.Core.Game.Entities
}
public override void ClientUpdate(IGameClient client, GameTime gt)
{
animationTimer += (float)gt.ElapsedGameTime.TotalSeconds * 5;
base.ClientUpdate(client, gt);
}
public void ServerPhysicsStep(IServerWorld world, float step)=> PhysicsStep(world, step);
public void ServerPhysicsTick(IServerWorld world, float step) => ServerPhysicsStep(world, step);
public void DrawName(GraphicsEngine GFX)
@@ -125,7 +177,7 @@ namespace CaveGame.Core.Game.Entities
{
spriteFrame = WALK_CYCLE.GetSpriteFrame(animationTimer * walk_anim_time);
if (Pushing)
spriteFrame = SP_PUSH0; //PUSH_CYCLE.GetSpriteFrame(animationTimer * push_anim_time);
spriteFrame = SP_PUSH0;
}
if (!OnGround)
{
@@ -135,8 +187,6 @@ namespace CaveGame.Core.Game.Entities
spriteFrame = SP_FALL;
}
DrawHealth(gfx);
DrawName(gfx);
@@ -152,8 +202,6 @@ namespace CaveGame.Core.Game.Entities
}
// public override Vector2 TopLeft => GetTopLeft();
const float threshold = 0.1f;
protected override void SolidCollisionReaction(IGameWorld world, Tile t, Vector2 separation, Vector2 normal, Point tilePos)

View File

@@ -78,8 +78,9 @@ namespace CaveGame.Core.Game.Entities
public float Fear { get; }
public float ResponseTime { get; }
public int IQ { get; }
public float ReactionTime { get; }
float animationTimer;
float animationTimer;
float triggeredAnimationTimer;
float autonomousMovement;

View File

@@ -0,0 +1,149 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace CaveGame.Core.Game.Entities
{
public enum ThinkerState
{
IDLE,
SEARCHING,
ATTACKWINDUP,
ATTACK,
ATTACKTRANSITION,
STUN,
DEAD,
}
public class Zombie : PhysicsEntity, IServerPhysicsObserver, ICanBleed, IThinker
{
public static Random RNG = new Random();
public override Vector2 BoundingBox => new Vector2(8, 12);
public override float Mass => 1.4f;
public override Vector2 Friction => new Vector2(5.0f, 1f);
public override int MaxHealth => 20;
public float ReactionTime => 0.2f;
public ThinkerState StateOfMind { get; set; }
public float ThinkingTimer { get; set; }
public static Rectangle[] ANIMATIONS =
{
};
public Entity Target { get; set; }
public float TargetTime { get; set; }
public Zombie()
{
}
public override void Damage(DamageType type, IDamageSource source, int amount)
{
if (source is Entity assaulter)
{
Target = assaulter;
TargetTime = 10;
}
base.Damage(type, source, amount);
}
public override void ServerUpdate(IGameServer server, GameTime gt)
{
TargetTime -= gt.GetDelta();
ThinkingTimer += gt.GetDelta();
if (ThinkingTimer > ReactionTime)
{
ThinkingTimer = 0;
Think(server, gt);
}
base.ServerUpdate(server, gt);
}
public void Think(IGameServer server, GameTime gt)
{
// stop paying attention to dead entities
if (Target == null || Target.Dead == true)
TargetTime = 0;
// look for new target
if (TargetTime <= 0)
{
// pick nearest player
Player closest = null;
foreach (var ent in server.World.Entities)
{
if (!(ent is Player plr))
continue;
if (closest == null)
{
closest = plr;
continue;
}
if (closest.Position.Distance(Position) > plr.Position.Distance(Position))
closest = plr;
}
}
}
public override void ClientUpdate(IGameClient client, GameTime gt)
{
base.ClientUpdate(client, gt);
}
/*public override void Draw(GraphicsEngine GFX)
{
Rectangle spriteFrame = SP_IDLE;
int flipSprite = 0;
if (Facing == Direction.Left)
flipSprite = 0;
if (Facing == Direction.Right)
flipSprite = 1;
if (Walking)
{
spriteFrame = WALK_CYCLE.GetSpriteFrame(animationTimer * walk_anim_time);
if (Pushing)
spriteFrame = SP_PUSH0; //PUSH_CYCLE.GetSpriteFrame(animationTimer * push_anim_time);
}
if (!OnGround)
{
if (Velocity.Y > 0)
spriteFrame = SP_JUMP;
else
spriteFrame = SP_FALL;
}
DrawHealth(gfx);
DrawName(gfx);
GFX.Sprite(GFX.Zombie, Position, spriteFrame, Illumination.MultiplyAgainst(Color), Rotation.Zero, new Vector2(8, 12), 1, (SpriteEffects)flipSprite, 0);
base.Draw(GFX);
}*/
public void ServerPhysicsTick(IServerWorld world, float step)
{
throw new NotImplementedException();
}
}
}

View File

@@ -338,6 +338,7 @@ namespace CaveGame.Core.Furniture
return;
State = DoorState.OpenLeft;
AudioManager.PlayEffect("door", 1, 1, -0.7f);
client.Send(new Network.OpenDoorPacket(FurnitureNetworkID, player.Facing));
} else
{
@@ -349,6 +350,7 @@ namespace CaveGame.Core.Furniture
return;
State = DoorState.OpenRight;
AudioManager.PlayEffect("door", 1, 1, 0.7f);
client.Send(new Network.OpenDoorPacket(FurnitureNetworkID, player.Facing));
}
}
@@ -356,6 +358,7 @@ namespace CaveGame.Core.Furniture
{
client.Send(new Network.CloseDoorPacket(FurnitureNetworkID));
State = DoorState.Closed;
AudioManager.PlayEffect("door", 1, 0.8f, 0f);
}
}
}

View File

@@ -18,6 +18,22 @@ namespace CaveGame.Core.Inventory
public class ItemStack: IEquatable<ItemStack>
{
public ItemStack()
{
}
public ItemStack(Item item, int quantity = 1)
{
this.Item = item;
this.quantity = quantity;
}
public static ItemStack Of<T>(int quantity = 1) where T: Item, new()
{
ItemStack stack = new ItemStack { Quantity = quantity, Item = new T() };
return stack;
}
public static ItemStack Empty = new ItemStack { Quantity = 0 };
public Item Item;

View File

@@ -19,6 +19,7 @@ using CaveGame.Core.Inventory;
namespace CaveGame.Core.Game.Items
{
using JsonString = String;
public enum ItemID : short
{
CopperIngot, LeadIngot, TinIngot, ChromiumIngot, AluminiumIngot,
@@ -28,9 +29,13 @@ namespace CaveGame.Core.Game.Items
public enum ItemTag
{
Armor, Potion
}
public interface IArmorItem
{
int Defense { get; }
}
public interface IItem
{
short ID { get; }
@@ -54,7 +59,7 @@ namespace CaveGame.Core.Game.Items
}
public virtual string Namespace => "cavegame";
public virtual string[] Tooltip { get; }
public virtual int MaxStack => 99;
public virtual string Name => this.GetType().Name;
public virtual string DisplayName => Name;
@@ -62,7 +67,6 @@ namespace CaveGame.Core.Game.Items
public virtual Texture2D Texture { get; }
public bool MouseDown { get; set; }
public void Draw(GraphicsEngine GFX, Texture2D texture, Vector2 position, float scale)
{
GFX.Sprite(texture, position, null, Color.Gray, Rotation.Zero, Vector2.Zero, scale, SpriteEffects.None, 0);
@@ -72,7 +76,7 @@ namespace CaveGame.Core.Game.Items
{
MouseDown = true;
}
public virtual void OnClientLMBUp(Player player, IGameClient client)
public virtual void OnClientLMBUp(Player player, IGameClient client, ItemStack stack)
{
MouseDown = false;
}
@@ -168,6 +172,36 @@ namespace CaveGame.Core.Game.Items
}
public class Potion : Item
{
public override string[] Tooltip => new string[]{
""
};
public override string DisplayName => base.DisplayName;
public override Texture2D Texture => GraphicsEngine.Instance.Potion;
public virtual void OnDrink(Player player)=> player.AddEffect(new StatusEffects.Burning(10));
public override void OnClientLMBDown(Player player, IGameClient client, ItemStack stack)
{
base.OnClientLMBDown(player, client, stack);
stack.Quantity--;
OnDrink(player);
}
}
public class Speed : Potion
{
public override string DisplayName => "Speed Potion";
public override void OnDrink(Player player) => player.AddEffect(new StatusEffects.AmphetamineRush(10));
}
public class GlowPotion : Potion
{
}
public class GenericPickaxe : Item
{
public virtual float SwingTime => 0.15f;
@@ -336,6 +370,15 @@ namespace CaveGame.Core.Game.Items
{
Tile = tile;
}
public static TileItem Of<T>() where T: Tile, new()
{
return new TileItem { Tile = new T() };
}
public static TileItem Of<T>(T Tobj) where T : Tile, new()
{
return new TileItem { Tile = Tobj };
}
public override void OnClientLMBHeld(Player player, IGameClient client, ItemStack stack, GameTime gt)
{
MouseState mouse = Mouse.GetState();
@@ -419,53 +462,7 @@ namespace CaveGame.Core.Game.Items
public override void Draw(GraphicsEngine GFX, Vector2 position, float scale) => Draw(GFX, GFX.BombSprite, position, scale);
}
public class RaycastTesterItem : Item
{
public override int MaxStack => 1;
public override void Draw(GraphicsEngine GFX, Vector2 position, float scale) => Draw(GFX, GFX.Bong, position, scale);
public Vector2 RaySurfaceNormal { get; set; }
public Vector2 RayEndpoint { get; set; }
public Vector2 RayStartpoint { get; set; }
public override void OnClientLMBHeld(Player player, IGameClient client, ItemStack stack, GameTime gt)
{
RayStartpoint = player.Position;
MouseState mouse = Mouse.GetState();
var mp = client.Camera.ScreenToWorldCoordinates(mouse.Position.ToVector2());
var unitVec = (mp - player.Position);
unitVec.Normalize();
var result = client.World.TileRaycast(player.Position, Rotation.FromUnitVector(unitVec));
if (result.Hit)
{
RayEndpoint = result.Intersection;
RaySurfaceNormal = result.SurfaceNormal;
}
base.OnClientLMBHeld(player, client, stack, gt);
}
public override void OnClientDraw(GraphicsEngine GFX)
{
if (MouseDown)
{
GFX.Line(Color.Green, RayStartpoint, RayEndpoint, 1.0f);
GFX.Line(Color.Yellow, RayEndpoint, RayEndpoint + (RaySurfaceNormal * 10), 1.0f);
}
base.OnClientDraw(GFX);
}
}
public class SplatterItem : Item
{

94
Core/Game/Items/Nimdoc.cs Normal file
View File

@@ -0,0 +1,94 @@
using CaveGame.Core.Game.Entities;
using CaveGame.Core.Inventory;
using CaveGame.Core.Network;
using DataManagement;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Items
{
public class Nimdoc : Item
{
public override int MaxStack => 1;
public override void Draw(GraphicsEngine GFX, Vector2 position, float scale)
{
int frame = ((int)(GFX.GlobalAnimationTimer * 8.0f)).Mod(10);
var quad = new Rectangle(0, frame * 16, 16, 16);
GFX.Sprite(GFX.Nimdoc, position, quad, Color.White, Rotation.Zero, Vector2.Zero, scale, SpriteEffects.None, 0);
}
public Vector2 RaySurfaceNormal { get; set; }
public Vector2 RayEndpoint { get; set; }
public Vector2 RayStartpoint { get; set; }
public override void OnClientLMBHeld(Player player, IGameClient client, ItemStack stack, GameTime gt)
{
RayStartpoint = player.Position;
MouseState mouse = Mouse.GetState();
var mp = client.Camera.ScreenToWorldCoordinates(mouse.Position.ToVector2());
var unitVec = (mp - player.Position);
unitVec.Normalize();
var result = client.World.TileRaycast(player.Position, Rotation.FromUnitVector(unitVec), player.Position.Distance(mp)+1);
if (result.Hit)
{
// set goalpoints for electric arc to align to
RayEndpoint = result.Intersection;
RaySurfaceNormal = result.SurfaceNormal;
// damage tile
// NOTE: this sends a shit ton of packets?, find a way to condense
client.Send(new DamageTilePacket(result.TileCoordinates, 1));
}
base.OnClientLMBHeld(player, client, stack, gt);
}
public static Random RNG = new Random();
public override void OnClientDraw(GraphicsEngine GFX)
{
if (MouseDown)
{
// debug lines
GFX.Line(Color.Green, RayStartpoint, RayEndpoint, 1.0f);
GFX.Line(Color.Yellow, RayEndpoint, RayEndpoint + (RaySurfaceNormal * 10), 1.0f);
// holy fuck
Vector2 prev = RayStartpoint;
int distanceSlices = (int)RayStartpoint.Distance(RayEndpoint)/4;
for (int i = 0; i < distanceSlices; i++)
{
float dist = (i / (float)distanceSlices);
float range = Math.Clamp(dist*2, 0, 1);
if (dist > 0.5f)
range = 1 - (Math.Clamp(dist, 0, 1));
var stepPoint = RayStartpoint.Lerp(RayEndpoint, i / (float)distanceSlices);
var wave = Rotation.FromUnitVector((RayStartpoint - RayEndpoint).Unit()).RotateDeg(70 + (RNG.NextFloat()*20));
float leanTo = (float) Math.Floor(Math.Sin(GFX.GlobalAnimationTimer*2) * 10)/3.0f;
float waveForm = (float)Math.Sin(i + Math.Round(GFX.GlobalAnimationTimer * 6, 1) * 10);
var final = stepPoint + (wave.ToUnitVector() * (leanTo + waveForm+ RNG.NextFloat()) * (range*20));
GFX.Line(Color.Cyan, prev, final, 1.2f);
prev = final;
}
}
base.OnClientDraw(GFX);
}
}
}

View File

@@ -2,46 +2,93 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace CaveGame.Core.Game.StatusEffects
{
// POTION SELLER? https://www.youtube.com/watch?v=R_FQU4KzN7A
public abstract class StatusEffect
{
public float Duration { get; set; }
public abstract string EffectName { get; }
public abstract string EffectDescription { get; }
public Entity TargetEntity { get; set; }
public StatusEffect(float duration)
{
Duration = duration;
}
public virtual void Tick(GameTime gt)
{
}
public virtual void Tick(IGameWorld world, GameTime gt) { }
public virtual void OnAdded(Entity victim) { }
public virtual void OnRemoved(Entity victim) { }
}
public class AmphetamineRush : StatusEffect
{
public override string EffectName => "Amped";
public override string EffectDescription { get; }
public AmphetamineRush(float duration) : base(duration)
{
}
}
public class Burning : StatusEffect
{
public override string EffectName => "Burning";
public override string EffectDescription => "";
protected float fireDamageTimer { get; set; }
float particleTimer;
public Burning(float duration) : base(duration)
{
fireDamageTimer = 0;
}
Random rand = new Random();
public override void Tick(IGameWorld world, GameTime gt)
{
particleTimer += gt.GetDelta();
if (particleTimer > (0.01f))
{
if (world is IClientWorld localWorld)
{
for (int i = 0; i < 2; i++)
{
// calculate random position along the bottom face of the entity
Vector2 RandomX = new Vector2(rand.Next(0, (int)TargetEntity.BoundingBox.X * 2) - (TargetEntity.BoundingBox.X), TargetEntity.BoundingBox.Y);
Vector2 spawnCoords = TargetEntity.Position + RandomX;
localWorld.ParticleSystem.Add(new FireParticle { Position = TargetEntity.Position + RandomX });
}
}
particleTimer = 0;
}
fireDamageTimer += gt.GetDelta();
// damage target
if (fireDamageTimer > (0.1f))
{
TargetEntity.Damage(DamageType.Fire, null, 1);
fireDamageTimer = 0;
}
base.Tick(world, gt);
}
}
//TODO:
// Regenerate Status Effect
// Speed Status Effect
//
public class Poisoned : StatusEffect
{
public override string EffectName => "Poisoned";
@@ -49,8 +96,20 @@ namespace CaveGame.Core.Game.StatusEffects
public Poisoned(float duration) : base(duration)
{
tickTimer = 0;
}
float tickTimer;
public override void Tick(IGameWorld world, GameTime gt)
{
if (tickTimer > (0.1f))
{
TargetEntity.Damage(DamageType.Poison, null, 1);
tickTimer = 0;
}
base.Tick(world, gt);
}
}
}

View File

@@ -8,6 +8,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace CaveGame.Core.Game.Tiles
@@ -27,10 +28,6 @@ namespace CaveGame.Core.Game.Tiles
public override void Draw(GraphicsEngine GFX, int x, int y, Light3 color)
{
#if EDITOR
GFX.Sprite(GFX.TileSheet, new Vector2(x * Globals.TileSize, y * Globals.TileSize), Quad, Color);
return;
#endif
GFX.Sprite(GFX.TileSheet, new Vector2(x * Globals.TileSize, y * Globals.TileSize), TileMap.Soil, color.MultiplyAgainst(Color.SaddleBrown));
var corner = new Rectangle(9 * Globals.TileSize, 6 * Globals.TileSize, Globals.TileSize, Globals.TileSize);
@@ -80,6 +77,7 @@ namespace CaveGame.Core.Game.Tiles
public void LocalTileUpdate<T>(IGameWorld world, int x, int y)
{
bool planetop = IsEmpty(world, x, y - 1);
bool planebottom = IsEmpty(world, x, y + 1);
bool planeleft = IsEmpty(world, x - 1, y);
@@ -96,7 +94,7 @@ namespace CaveGame.Core.Game.Tiles
bool cornerb = (gright && gabove && air_tr);
bool cornerc = (gright && gbelow && air_br);
bool cornerd = (gleft && gbelow && air_bl);
byte newNumber = TileState;
byte newNumber = 0;
newNumber.Set(7, planetop);
newNumber.Set(6, planeleft);
newNumber.Set(5, planebottom);
@@ -111,6 +109,7 @@ namespace CaveGame.Core.Game.Tiles
{
TileState = newNumber;
world.DoUpdatePropogation(x, y);
//world.SetTileUpdated(x, y);
}
}
}

View File

@@ -7,8 +7,6 @@ using System.Text;
namespace CaveGame.Core.Game.Tiles
{
public abstract class Liquid : Tile, ILiquid, INonSolid, INonMinable
{
@@ -180,6 +178,8 @@ namespace CaveGame.Core.Game.Tiles
public void LocalTileUpdate(IGameWorld world, int x, int y)
{
var below = world.GetTile(x, y + 1);
if (below is Water _)

View File

@@ -1,17 +1,167 @@
using Microsoft.Xna.Framework;
using CaveGame.Core.Game.Entities;
using DataManagement;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Tiles
{
public class TNT : Tile, ITileUpdate
public interface IPowerSource { }
public interface IConductive {
bool Powered { get; set; }
void Power(IConductive source);
}
public interface IPartiallyConductive
{
void IsFaceConductive(Face face);
}
public class Wire : Tile, ITileUpdate, IWaterBreakable, INonSolid, IConductive
{
public void Power(IPowerSource source) { }
public IConductive PowerSource { get; set; }
public bool Powered
{
get => TileState.Get(0);
set => TileState.SetF(0, value);
}
public bool StateChanged
{
get => TileState.Get(1);
set => TileState.SetF(1, value);
}
public void Propagate(IGameWorld world, int x, int y)
{
if (world.GetTile(x, y-1) is IConductive wireAbove && !wireAbove.Powered)
{
wireAbove.Power(this);
}
if (world.GetTile(x, y + 1) is IConductive wireBelow && !wireBelow.Powered)
{
wireBelow.Power(this);
}
if (world.GetTile(x-1, y) is IConductive wireLeft && !wireLeft.Powered)
{
wireLeft.Power(this);
}
if (world.GetTile(x + 1, y) is IConductive wireRight && !wireRight.Powered)
{
wireRight.Power(this);
}
}
public void TileUpdate(IGameWorld world, int x, int y)
{
if (PowerSource != null && PowerSource.Powered == false)
{
Powered = false;
world.SetTileUpdated(x, y);
}
}
public void Power(IConductive source)
{
Powered = true;
PowerSource = source;
}
}
public class TNT : Tile, ITileUpdate, IConductive
{
public override Rectangle Quad => TileMap.TNT;
public override byte Hardness => 1;
public void TileUpdate(IGameWorld world, int x, int y) { }
public bool Powered { get; set; }
public void TileUpdate(IGameWorld world, int x, int y) {
if (Powered)
{
world.SetTile(x, y, new Air());
world.Explosion(new Explosion {
BlastPressure = 1,
BlastRadius = 1,
Position = new Vector2(x+0.5f, y+0.5f)*8,
}, true, true);
}
}
public void Power(IConductive source)
{
Powered = true;
}
}
public class Switch : Tile, ITileUpdate, IClickableTile, IPowerSource
{
public static Rectangle FlickedOff = new Rectangle(12*8, 0, 8, 8);
public static Rectangle FlickedOn = new Rectangle(12*8, 1*8, 8, 8);
public override void Draw(GraphicsEngine GFX, int x, int y, Light3 color)
{
Rectangle sprite = FlickedOff;
if (On)
sprite = FlickedOn;
GFX.Sprite(
texture: GFX.TileSheet,
position: new Vector2(x * Globals.TileSize, y * Globals.TileSize),
quad: sprite, color.MultiplyAgainst(Color),
rotation: Rotation.Zero,
origin: Vector2.Zero,
scale: 1,
efx: SpriteEffects.None,
layer: 0
);
}
public bool On
{
get => TileState.Get(0);
set => TileState.SetF(0, value);
}
public override Rectangle Quad => TileMap.SwitchOff;
public void PowerAdjacent(IGameWorld world, int x, int y)
{
if (world.GetTile(x, y-1) is IConductive ductAbove && !ductAbove.Powered)
{
}
}
public void OnClick(IGameWorld world, Player clicker)
{
On = !On;
}
public void TileUpdate(IGameWorld world, int x, int y)
{
if (On)
PowerAdjacent(world, x, y);
if (!On)
{
}
}
}
public class Switch { }
public class ANDGate { }
public class ORGate { }
public class XORGate { }

View File

@@ -1,9 +1,17 @@
using System;
using CaveGame.Core.Game.Entities;
using System;
using System.Collections.Generic;
using System.Text;
namespace CaveGame.Core.Game.Tiles
{
public interface IClickableTile
{
void OnClick(IGameWorld world, Player clicker);
}
public interface IWaterBreakable { }
public interface INonMinable { }
public interface INonSolid { }

View File

@@ -121,5 +121,8 @@ namespace CaveGame.Core.Game.Tiles
public static Dictionary<string, Rectangle> Atlas = new Dictionary<string, Rectangle> {
};
public static Rectangle SwitchOff = Quad(0, 11);
public static Rectangle SwitchOn = Quad(1, 11);
}
}

View File

@@ -24,12 +24,26 @@ namespace CaveGame.Core
public const int TileSize = 8;
public const int ChunkSize = 32;
public const string CurrentVersionString = "2.3.0";
public const string CurrentVersionFullString = "2.3.0 Beta";
public const string CurrentVersionString = "2.3.1";
public const string CurrentVersionFullString = "2.3.1 Beta";
public static UpdateDescription[] UpdateLog =
{
new UpdateDescription
{
VersionString = "2.4",
Date = "2021 Feb 31",
UpdateName = "Patch 1",
ChangeLog = new string[]
{
"+ Cleaned up look and feel of menus.",
},
Notes = new string[]
{
}
},
new UpdateDescription
{
VersionString = "2.3.0",

View File

@@ -138,6 +138,8 @@ namespace CaveGame.Core
public bool LoadFonts { get; set; }
public float GlobalAnimationTimer { get; private set; }
public static GraphicsEngine Instance { get; private set; }
@@ -154,6 +156,8 @@ namespace CaveGame.Core
public Texture2D CloudBackground => Textures["clouds.png"];
public Texture2D Starfield => Textures["stars.png"];
public Texture2D Nimdoc => Textures["items:nimdoc_anim.png"];
public Texture2D Explosion => Textures["michaelbay.png"];
public Texture2D BowSprite => Textures["items:bow.png"];
public Texture2D BombSprite => Textures["items:bomb.png"];
@@ -179,7 +183,8 @@ namespace CaveGame.Core
public Texture2D Campfire => Textures["items:campfire.png"];
public Texture2D Player => Textures["entities:player.png"];
public Texture2D ArrowEntity => Textures["entities:arrow.png"];
public Texture2D Zombie => Textures["entities:zombie.png"];
public Texture2D ArrowEntity => Textures["entities:arrow.png"];
public Texture2D VoidMonster => Textures["entities:wurmhole.png"];
public Texture2D Bee => Textures["entities:bee.png"];
public Texture2D Goldfish => Textures["entities:gregothy.png"];
@@ -307,12 +312,19 @@ namespace CaveGame.Core
public void Update(GameTime gt)
{
// move asset loading to it's own class?
if (LoadingQueue.Count > 0)
LoadNextAsset(GraphicsDevice);
if (LoadingQueue.Count == 0)
ContentLoaded = true;
// increase global anim time.
// used by items, entities, and tiles when an internal state is otherwise not ideal.
GlobalAnimationTimer += gt.GetDelta();
}
public void Clear(Color color) => GraphicsDevice.Clear(color);

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Collections.Concurrent;
using CaveGame.Core.Game.Entities;
namespace CaveGame.Core
{
@@ -271,9 +272,81 @@ namespace CaveGame.Core
}
public class FireParticle
public class FireParticle : Particle
{
public static Vector2 Origin => new Vector2(16, 16);
public override float MaxParticleAge => 0.3f;
public Vector2 Position { get; set; }
public Vector2 Scale { get; set; }
public Color Color { get; set; }
Rotation Rotation { get; set; }
Random RNG = new Random();
public static Color[] ColorGradient =
{
new Color(1, 1, 0), // fire starts yellow
new Color(1, 0, 0), // turns red
};
public Color GetColor()
{
int alpha = (int)((this.ParticleAge * 2.0f) % 2);
return Color.Lerp(Color.Yellow, Color.Red, this.ParticleAge * 3.0f);
}
public static float[] SizeGradient = { 2.0f, 3.5f, 1.0f };
public Vector2 GetSizeV2()
{
int alpha = (int)(this.ParticleAge * 2) % 2;
return new Vector2(2, 2);//Vector2(SizeGradient[alpha], SizeGradient[alpha]);
}
float rngRise;
public FireParticle()
{
Dead = false;
ParticleAge = 0;
Rotation = Rotation.FromDeg(RNG.Next(0, 360));
rngRise = (float)RNG.NextDouble()+1.0f;
}
public override void Update(GameTime gt)
{
ParticleAge += (float)gt.ElapsedGameTime.TotalSeconds;
count += gt.GetDelta();
Position -= new Vector2(0, gt.GetDelta() * ((rngRise+1f)*24f));
}
float count = 0;
public override void PhysicsStep(IGameWorld world, float step)
{
}
public override void Draw(GraphicsEngine gfx)
{
gfx.Rect(GetColor(), Position, new Vector2(2, 2));
}
public void Initialize(Vector2 _position, Color _color, Rotation _rotation, Vector2 _scale)
{
ParticleAge = 0;
Position = _position;
Color = _color;
Scale = _scale;
Dead = false;
}
}
public class DustParticle
{
@@ -293,10 +366,6 @@ namespace CaveGame.Core
const int MAX_PARTICLES = 4096;
ObjectPool<SmokeParticle> SmokeParticlePool = new ObjectPool<SmokeParticle>(() => new SmokeParticle());
//ObjectPool<SmokeParticle> SmokeParticlePool = new ObjectPool<SmokeParticle>(() => new SmokeParticle());
ObjectPool<ExplosionParticle> ExplosionParticlePool = new ObjectPool<ExplosionParticle>(() => new ExplosionParticle());
private List<Particle> Particles;
public IGameWorld World { get; set; }
@@ -312,14 +381,14 @@ namespace CaveGame.Core
public void EmitSmokeParticle(Vector2 position, Color color, Rotation rotation, Vector2 scale, Vector2 accel)
{
var myParticle = SmokeParticlePool.Get();
var myParticle = new SmokeParticle();
myParticle.Initialize(position, color, rotation, scale, accel);
Add(myParticle);
}
public void EmitExplosionParticle(Vector2 position)
{
var myParticle = ExplosionParticlePool.Get();
var myParticle = new ExplosionParticle();
myParticle.Initialize(position, Color.White, Rotation.Zero, new Vector2(2.0f));
Add(myParticle);
}
@@ -336,18 +405,6 @@ namespace CaveGame.Core
if (particle.Dead)
{
if (particle is SmokeParticle smokey)
SmokeParticlePool.Return(smokey);
Particles.Remove(particle);
continue;
}
if (particle.Dead)
{
if (particle is ExplosionParticle bomb)
ExplosionParticlePool.Return(bomb);
Particles.Remove(particle);
continue;

View File

@@ -151,7 +151,7 @@ namespace CaveGame.Core
GFX.GraphicsDevice.SetRenderTarget(TileRenderBuffer);
GFX.Clear(Color.Black * 0f);
GFX.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
GFX.Begin(SpriteSortMode.Immediate);
Tile tile;
for (int x = 0; x < ChunkSize; x++)

View File

@@ -503,7 +503,7 @@ namespace CaveGame.Core
Vector2 normal = face.ToSurfaceNormal();
return new TileRaycastResult { Hit = true, Intersection = intersection, SurfaceNormal = normal, TileCoordinates = tile_coords, Face = face };
return new TileRaycastResult { Hit = true, Intersection = intersection, SurfaceNormal = normal, TileCoordinates = tile_coords, Face = face, Target = tileAt };
}
return new TileRaycastResult { Hit = false };

View File

@@ -5,6 +5,12 @@ using DataManagement;
using CaveGame.Core.WorldGeneration;
using CaveGame.Core.Game.Tiles;
using System.Numerics;
using System.Collections.Generic;
using CaveGame.Core.Game.Biomes;
// Copyright 2020 Conarium Software
// author: joshms
namespace CaveGame.Core
{
@@ -18,73 +24,12 @@ namespace CaveGame.Core
}
public interface IBiomeImplementation
{
}
public abstract class Biome
{
public virtual SurfaceBiome BiomeID => SurfaceBiome.Forest;
public int Seed => Generator.Seed;
public OctaveNoise Octave4 => Generator.Octave4;
public OctaveNoise Octave2 => Generator.Octave2;
public OctaveNoise Octave3 => Generator.Octave3;
public OctaveNoise Octave8 => Generator.Octave8;
public SimplexNoise Simplex => Generator.Simplex;
private Generator Generator;
public Biome(Generator generator)
{
Generator = generator;
}
public abstract float GetHeight(int x);
public abstract void SurfacePass(Chunk chunk, int x, int y);
public abstract void StructurePass(IGameWorld world, int x, int y);
}
/* public class MountainsBiome : Biome
{
public override float GetHeight(int x)
{
}
public override void SurfacePass(Chunk chunk, int x, int y)
{
}
}
public class ForestBiome : Biome
{
}
public class PlainsBiome : Biome
{
}
public class DesertBiome : Biome
{
}*/
public class Generator
{
public const float BIOME_SIZE = 10000.5f;
public const float BIOME_TRANSITION = 0.2f;
public Dictionary<SurfaceBiome, Biome> Biomes { get; private set; }
public int Seed { get; set; }
@@ -95,12 +40,15 @@ namespace CaveGame.Core
public SimplexNoise Simplex;
public Random RNG;
private SurfaceBiome[] biomemap;
// Generates the biome map.
private void GenerateBiomeNoiseMap()
{
int sampleCounts = 100;
float biomeRepeatChance = 0.35f;
int sampleCounts = 100;
float biomeRepeatChance = 0.35f; // Skew biome probability towards repeating.
int biomeCount = 5;
biomemap = new SurfaceBiome[sampleCounts];
@@ -117,6 +65,14 @@ namespace CaveGame.Core
}
}
public SurfaceBiome GetDominantSurfaceBiome(int x)
{
float alpha = (Simplex.Noise(x / BIOME_SIZE) + 1) / 2.0f; // transform from [-1, 1] to [0, 1]
int biome = (int)Math.Floor(alpha * 100.0f);
return biomemap[biome];
}
public Generator(int WorldSeed)
{
Seed = WorldSeed;
@@ -126,82 +82,27 @@ namespace CaveGame.Core
Octave2 = new OctaveNoise(seed: Seed, octaves: 2);
Simplex = new SimplexNoise();
RNG = new Random(Seed: WorldSeed);
Biomes = new Dictionary<SurfaceBiome, Biome>
{
[SurfaceBiome.Plains] = new Plains(this),
[SurfaceBiome.Badlands] = new Badlands(this),
[SurfaceBiome.Desert] = new Desert(this),
[SurfaceBiome.Forest] = new Forest(this),
[SurfaceBiome.Mountains] = new Mountain(this),
};
GenerateBiomeNoiseMap();
}
private SurfaceBiome GetDominantSurfaceBiome(int x)
{
float alpha = (Simplex.Noise(x/BIOME_SIZE)+1)/2.0f; // transform from [-1, 1] to [0, 1]
int biome = (int)Math.Floor(alpha * 100.0f);
return biomemap[biome];
}
private float GetDesertHeight(int x)
{
float n = (float)Simplex.Noise(x / 100.420f) * 10 + (float)Octave4.Noise2D(x / 100.0f, (-x * 0.10f) + (x / 20.0f)) * 20;
return n;
}
private float GetForestHeight(int x)
{
public float GetHeightmap(int x, SurfaceBiome biome) => Biomes[biome].GetHeight(x);
float n = (float)Simplex.Noise(x/100.420f)*10 + (float)Octave4.Noise2D(x/60.0f, (-x*0.10f)+(x/20.0f))*30;
return 20 + n;
}
private float GetMountainHeight(int x)
{
float simplex = (float)Simplex.Noise(x / 50.420f);
float octave = (float)Octave8.Noise2D(x / 120.0f, (-x * 0.05f) + (x / 40.0f));
float n = (simplex * 15) * (octave * 15);
float a = Simplex.Noise(x / 10.0f) * 2;
float b = Simplex.Noise(x / 5.0f) * 2;
return (a+b + 100) + n;
}
private float GetPlainsHeight(int x)
public float GetBiomeSurface(int x)
{
return Simplex.Noise(x / 100.420f)*4;
}
private float GetBandlandsHeight(int x)
{
float baseline = Simplex.Noise(x / 80f) * 8;
float raised = (float)(Octave4.Noise2D(x / 6.0f, (-x * 0.03f))+0.5f);
if (raised > 0.8)
raised = (raised*5) + 25;
else if (raised > 0.4)
raised = (raised*10) + 15;
return baseline + raised;
}
private float GetHeightmap(int x, SurfaceBiome biome)
{
if (biome == SurfaceBiome.Desert)
return GetDesertHeight(x);
if (biome == SurfaceBiome.Forest)
return GetForestHeight(x);
if (biome == SurfaceBiome.Mountains)
return GetMountainHeight(x);
if (biome == SurfaceBiome.Plains)
return GetPlainsHeight(x);
if (biome == SurfaceBiome.Badlands)
return GetBandlandsHeight(x);
return 0;
}
private float GetBiomeSurface(int x)
{
SurfaceBiome primaryBiome = GetDominantSurfaceBiome(x);
SurfaceBiome secondaryBiome = GetSecondarySurfaceBiome(x);
@@ -215,7 +116,7 @@ namespace CaveGame.Core
public const float SURFACE_BASE_HEIGHT = -40;
private float GetBaseSurface(int x, int y)
public float GetBaseSurface(int x, int y)
{
float surfacePass1 = Octave4.Noise2D(x: x, y: y, xScale: 10.0, yScale: 10.0, xOffset: -2405, yOffset: 222);
float surfacePass2 = Octave4.Noise2D(x: x, y: y, xScale: 325.0, yScale: 299.0, xOffset: 2, yOffset: -9924);
@@ -225,7 +126,8 @@ namespace CaveGame.Core
private SurfaceBiome GetSecondarySurfaceBiome(int x)
// what the fuck?
public SurfaceBiome GetSecondarySurfaceBiome(int x)
{
float alpha = (Simplex.Noise(x / BIOME_SIZE) + 1) / 2.0f; // transform from [-1, 1] to [0, 1]
int biome = (int)Math.Floor(alpha * 100.0f);
@@ -238,7 +140,7 @@ namespace CaveGame.Core
}
private float GetPrimarySurfaceBiomeScale(int x)
public float GetPrimarySurfaceBiomeScale(int x)
{
float biomedelta = GetPrimarySurfaceBiomeStrength(x);
if (biomedelta > (1 - BIOME_TRANSITION)) // begin blending with biome on the right side
@@ -256,7 +158,7 @@ namespace CaveGame.Core
return 1;
}
private float GetSecondarySurfaceBiomeScale(int x)
public float GetSecondarySurfaceBiomeScale(int x)
{
float biomedelta = GetPrimarySurfaceBiomeStrength(x);
if (biomedelta > (1- BIOME_TRANSITION)) // begin blending with biome on the right side
@@ -273,7 +175,7 @@ namespace CaveGame.Core
return 0;
}
private float GetPrimarySurfaceBiomeStrength(int x)
public float GetPrimarySurfaceBiomeStrength(int x)
{
float alpha = (Simplex.Noise(x / BIOME_SIZE) + 1) / 2.0f; // transform from [-1, 1] to [0, 1]
int biome = (int)Math.Floor(alpha * 100.0f);
@@ -281,186 +183,6 @@ namespace CaveGame.Core
return biomedelta;
}
private void MountainsPass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + GetBiomeSurface(worldX) - GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
}
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Grass());
}
else if (depth <= 3)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Dirt());
}
else
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
}
if (depth > 0)
{
///
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 10;
if (worldY - noise + depth > 10.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
}
}
private void ForestPass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + GetBiomeSurface(worldX) - GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Grass());
}
else if (depth <= 30)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Dirt());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 40;
if (noise + depth > 40.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
else
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
}
}
private void DesertPass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + GetBiomeSurface(worldX) - GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Sand());
}
else if (depth <= 5)
{
chunk.SetTile(chunkX, chunkY, new Sand());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
var noise = Simplex.Noise(chunkX / 4.0f, chunkY / 4.0f) * 30;
if (noise + depth > 30.5)
chunk.SetTile(chunkX, chunkY, new Sandstone());
else
chunk.SetTile(chunkX, chunkY, new Sand());
}
}
private void PlainsPass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + GetBiomeSurface(worldX) - GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 1.5f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Grass());
}
else if (depth <= 30)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Dirt());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 30;
if (noise + depth > 30.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
else
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
}
}
private void BadlandsPass(ref Chunk chunk, int chunkX, int chunkY)
{
int worldX = ((chunk.Coordinates.X * Globals.ChunkSize) + chunkX);
int worldY = ((chunk.Coordinates.Y * Globals.ChunkSize) + chunkY);
float depth = worldY + GetBiomeSurface(worldX) - GetBaseSurface(worldX, worldY);
if (depth < 0)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
else if (depth <= 3)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Sandstone());
}
else if (depth <= 6)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Clay());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 9)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Sandstone());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 12)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Clay());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 15)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Sandstone());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else if (depth <= 18)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Clay());
chunk.SetWall(chunkX, chunkY, new Game.Walls.Sandstone());
}
else
{
chunk.SetWall(chunkX, chunkY, new Game.Walls.Stone());
var noise = Simplex.Noise(worldX / 4.0f, worldY / 4.0f) * 30;
if (noise + depth > 30.5)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Stone());
else
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Dirt());
}
}
//public float Get
public void HeightPass(ref Chunk chunk)
{
@@ -475,24 +197,9 @@ namespace CaveGame.Core
float depth = worldY + GetBiomeSurface(worldX) - GetBaseSurface(worldX, worldY);
SurfaceBiome biome = GetDominantSurfaceBiome(worldX);
// Surface Biome Generation
if (biome == SurfaceBiome.Mountains)
MountainsPass(ref chunk, chunkX, chunkY);
if (biome == SurfaceBiome.Forest)
ForestPass(ref chunk, chunkX, chunkY);
if (biome == SurfaceBiome.Desert)
DesertPass(ref chunk, chunkX, chunkY);
if (biome == SurfaceBiome.Plains)
PlainsPass(ref chunk, chunkX, chunkY);
if (biome == SurfaceBiome.Badlands)
BadlandsPass(ref chunk, chunkX, chunkY);
Biomes[biome].SurfacePass(ref chunk, chunkX, chunkY);
// Cave and other structures
@@ -553,42 +260,9 @@ namespace CaveGame.Core
} else
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
}
}
/*if (cavetiny > 0.45f)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
if (cave2 > -0.1f && cave2 < 0.1f)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
if (depth > 5)
{
if (cave1 * cavetiny > 0.5f)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
if (cave1 > 0.8f)
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
}
if (depth > 500)
{
if (cave1 > 0.75f)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Air());
// bruh caves
if (cave1 < 0.15f && cave2 < 0.15)
{
chunk.SetTile(chunkX, chunkY, new Game.Tiles.Mud());
}
}
}*/
if (depth > 50 && chunk.GetTile(chunkX, chunkY) is Game.Tiles.Air && Simplex.Noise(worldX / 5.0f, worldY / 8.0f) > 0.98f)
{
@@ -627,15 +301,8 @@ namespace CaveGame.Core
}
public void StructurePass(IGameWorld world, int x, int y)
{
float depth = y + GetBiomeSurface(x) - GetBaseSurface(x, y);
if (GetDominantSurfaceBiome(x) == SurfaceBiome.Forest && depth < 3)
{
if (RNG.Next(7) == 2 && world.GetTile(x, y) is Game.Tiles.Grass && world.GetTile(x, y - 1) is Game.Tiles.Air)
{
TreeGenerator.GenerateTree(world, RNG, x, y - 1);
}
}
SurfaceBiome biome = GetDominantSurfaceBiome(x);
Biomes[biome].StructurePass(world, x, y);
}
}
}

View File

@@ -51,8 +51,7 @@ namespace CaveGame.Core
return new Color(
(col.R / 255.0f) * (Red / 127.0f),
(col.G / 255.0f) * (Green / 127.0f),
(col.B / 255.0f) * (Blue / 127.0f),
col.A
(col.B / 255.0f) * (Blue / 127.0f)
);
}

View File

@@ -11,6 +11,7 @@ namespace CaveGame.Core
public int Seed { get; set; }
public string Name { get; set; }
public string LastPlayTime { get; set; }
public string LastVersionPlayedOn { get; set; }
public static WorldMetadata LoadWorldData(string directory)
@@ -21,8 +22,11 @@ namespace CaveGame.Core
WorldMetadata Metadata = new WorldMetadata
{
Name = worldmetaXML["Metadata"]["Name"]?.InnerText,
LastPlayTime = worldmetaXML["Metadata"]["Timestamp"]?.InnerText,
LastPlayTime = worldmetaXML["Metadata"]["LastPlayed"]?.InnerText,
Seed = Int32.Parse(worldmetaXML["Metadata"]["Seed"]?.InnerText),
LastVersionPlayedOn = worldmetaXML["Metadata"]["LastVersion"]?.InnerText,
};

View File

@@ -15,8 +15,17 @@ namespace DataManagement
else
a = (byte)(a & ~(1 << pos));
}
public static byte SetF(this byte a, int pos, bool value)
{
if (value)
a = (byte)(a | (1 << pos));
else
a = (byte)(a & ~(1 << pos));
public static bool Get(this byte a, int pos)
return a;
}
public static bool Get(this byte a, int pos)
{
return ((a & (1 << pos)) != 0);
}

View File

@@ -47,6 +47,26 @@ namespace CaveGame.Server
public WorldMetadata Metadata { get; private set; }
protected void WriteWorldDataToMetadata()
{
// Serialize world info into file.
XmlWriter worldXml = XmlWriter.Create(Path.Combine("Worlds", WorldName, "WorldMetadata.xml"));
worldXml.WriteStartDocument();
worldXml.WriteStartElement("Metadata");
worldXml.WriteElementString("Name", WorldName);
worldXml.WriteElementString("Seed", WorldSeed.ToString());
worldXml.WriteElementString("TimeOfDay", TimeOfDay.ToString());
worldXml.WriteElementString("LastPlayed", DateTime.Now.ToString());
worldXml.WriteElementString("LastVersion", Globals.CurrentVersionFullString);
worldXml.WriteEndDocument();
worldXml.Close();
}
public ServerWorld(WorldMetadata metadata) : base()
{
TileNetworkUpdateQueue = new Queue<Point>();
@@ -61,19 +81,8 @@ namespace CaveGame.Server
CreateDirectoryIfNull(Path.Combine("Worlds", WorldName));
CreateDirectoryIfNull(Path.Combine("Worlds", WorldName, "Chunks"));
// Serialize world info into file.
XmlWriter worldXml = XmlWriter.Create(Path.Combine("Worlds", WorldName, "WorldMetadata.xml"));
worldXml.WriteStartDocument();
worldXml.WriteStartElement("Metadata");
worldXml.WriteElementString("Name", WorldName);
worldXml.WriteElementString("Seed", WorldSeed.ToString());
worldXml.WriteElementString("TimeOfDay", TimeOfDay.ToString());
worldXml.WriteEndDocument();
worldXml.Close();
WriteWorldDataToMetadata();
WorldTimedTasks.Add(new(ProcessTileUpdateRequests, 1 / 10.0f));
WorldTimedTasks.Add(new(DoRandomTileTicks, 1 / 5.0f));
WorldTimedTasks.Add(new(SendTileNetworkUpdates, 1 / 5.0f));
@@ -131,7 +140,12 @@ namespace CaveGame.Server
public void SaveData()
{
CreateDirectoryIfNull(Path.Combine("Worlds", WorldName));
WriteWorldDataToMetadata();
foreach (var kvp in Chunks)
{
Chunk chunk = kvp.Value;

View File

@@ -17,7 +17,10 @@ namespace StandaloneServer
public string Text;
public ConsoleColor Color;
}
//
//
//
//
public static class Program
{
private delegate bool ConsoleCtrlHandlerDelegate(int sig);