refactored biome code. ui fixes
@@ -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
|
||||
|
||||
|
@@ -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)
|
||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 281 B |
@@ -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>
|
||||
|
9
CaveGL/CaveGameArguments.cs
Normal 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; } = "";
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
||||
|
BIN
CaveGL/Content/Sound/door.ogg
Normal file
BIN
CaveGL/Content/Sound/door.wav
Normal file
BIN
CaveGL/Content/Sound/drip.ogg
Normal file
BIN
CaveGL/Content/Sound/wind_howl1.ogg
Normal 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>
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
|
BIN
CaveGL/assets/sound/door.xnb
Normal file
BIN
CaveGL/assets/sound/wind_howl1.xnb
Normal file
BIN
CaveGL/assets/textures/csoft3.png
Normal file
After Width: | Height: | Size: 318 KiB |
BIN
CaveGL/assets/textures/csoft_wp2.png
Normal file
After Width: | Height: | Size: 395 KiB |
BIN
CaveGL/assets/textures/items/nimdoc_anim.png
Normal file
After Width: | Height: | Size: 470 B |
BIN
CaveGL/assets/textures/items/nimdoc_mki.png
Normal file
After Width: | Height: | Size: 293 B |
BIN
CaveGL/assets/textures/items/purplestaff_anim.png
Normal file
After Width: | Height: | Size: 342 B |
@@ -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" />
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
43
Client/StatusEffectDisplay.cs
Normal 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
@@ -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))
|
||||
|
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
@@ -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\" />
|
||||
|
78
Core/Game/Biomes/Badlands.cs
Normal 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
@@ -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);
|
||||
}
|
||||
}
|
52
Core/Game/Biomes/Desert.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
61
Core/Game/Biomes/Forest.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
70
Core/Game/Biomes/Mountain.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
Core/Game/Biomes/Plains.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
149
Core/Game/Entities/Zombie.cs
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 _)
|
||||
|
@@ -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 { }
|
||||
|
@@ -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 { }
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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",
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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++)
|
||||
|
@@ -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 };
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -17,7 +17,10 @@ namespace StandaloneServer
|
||||
public string Text;
|
||||
public ConsoleColor Color;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
public static class Program
|
||||
{
|
||||
private delegate bool ConsoleCtrlHandlerDelegate(int sig);
|
||||
|