├── .gitignore ├── .gitattributes ├── fna_starterkit ├── FNA.dll ├── SDL2.dll ├── FAudio.dll ├── FNA3D.dll ├── base │ ├── fonts │ │ ├── ntr.xnb │ │ └── ntr.spritefont │ ├── sound │ │ ├── click.wav │ │ └── rollover.wav │ ├── textures │ │ ├── white.png │ │ ├── white.xnb │ │ ├── orange.png │ │ └── orange.xnb │ ├── bloom │ │ ├── BloomCombine.xnb │ │ ├── BloomExtract.xnb │ │ └── GaussianBlur.xnb │ └── models │ │ └── chair │ │ ├── chair.fbx │ │ ├── chair.xnb │ │ ├── skin.png │ │ ├── skin.xnb │ │ ├── skin_0.xnb │ │ └── chair.blend ├── libtheorafile.dll ├── Newtonsoft.Json.dll ├── app.config ├── system │ ├── camera3d.cs │ ├── globals.cs │ ├── program.cs │ ├── bloom │ │ ├── bloomsettings.cs │ │ └── bloomcomponent.cs │ ├── screen.cs │ ├── settingsmanager.cs │ ├── soundmanager.cs │ ├── screenmanager.cs │ ├── helpers.cs │ └── inputmanager.cs ├── game │ ├── loadscreen.cs │ ├── pausemenu.cs │ ├── button.cs │ ├── worldscreen.cs │ ├── entity.cs │ └── optionspage.cs ├── Properties │ └── AssemblyInfo.cs └── fna_starterkit.csproj ├── LICENSE.md ├── fna_starterkit.sln └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.user 2 | *.suo 3 | [Bb]in/ 4 | [Oo]bj/ 5 | .vs/ -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /fna_starterkit/FNA.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/FNA.dll -------------------------------------------------------------------------------- /fna_starterkit/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/SDL2.dll -------------------------------------------------------------------------------- /fna_starterkit/FAudio.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/FAudio.dll -------------------------------------------------------------------------------- /fna_starterkit/FNA3D.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/FNA3D.dll -------------------------------------------------------------------------------- /fna_starterkit/base/fonts/ntr.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/fonts/ntr.xnb -------------------------------------------------------------------------------- /fna_starterkit/libtheorafile.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/libtheorafile.dll -------------------------------------------------------------------------------- /fna_starterkit/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /fna_starterkit/base/sound/click.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/sound/click.wav -------------------------------------------------------------------------------- /fna_starterkit/base/sound/rollover.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/sound/rollover.wav -------------------------------------------------------------------------------- /fna_starterkit/base/textures/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/textures/white.png -------------------------------------------------------------------------------- /fna_starterkit/base/textures/white.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/textures/white.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/textures/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/textures/orange.png -------------------------------------------------------------------------------- /fna_starterkit/base/textures/orange.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/textures/orange.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/bloom/BloomCombine.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/bloom/BloomCombine.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/bloom/BloomExtract.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/bloom/BloomExtract.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/bloom/GaussianBlur.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/bloom/GaussianBlur.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/models/chair/chair.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/models/chair/chair.fbx -------------------------------------------------------------------------------- /fna_starterkit/base/models/chair/chair.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/models/chair/chair.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/models/chair/skin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/models/chair/skin.png -------------------------------------------------------------------------------- /fna_starterkit/base/models/chair/skin.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/models/chair/skin.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/models/chair/skin_0.xnb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/models/chair/skin_0.xnb -------------------------------------------------------------------------------- /fna_starterkit/base/models/chair/chair.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blendogames/fna_starterkit/HEAD/fna_starterkit/base/models/chair/chair.blend -------------------------------------------------------------------------------- /fna_starterkit/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /fna_starterkit/base/fonts/ntr.spritefont: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | NTR 7 | 20 8 | 1 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ~ 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Blendo Games 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /fna_starterkit.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fna_starterkit", "fna_starterkit\fna_starterkit.csproj", "{B501204A-60C2-444C-AB9C-87B1374EE9FE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B501204A-60C2-444C-AB9C-87B1374EE9FE}.Debug|x86.ActiveCfg = Debug|x86 15 | {B501204A-60C2-444C-AB9C-87B1374EE9FE}.Debug|x86.Build.0 = Debug|x86 16 | {B501204A-60C2-444C-AB9C-87B1374EE9FE}.Release|x86.ActiveCfg = Release|x86 17 | {B501204A-60C2-444C-AB9C-87B1374EE9FE}.Release|x86.Build.0 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /fna_starterkit/system/camera3d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Xna.Framework; 4 | 5 | namespace fna_starterkit 6 | { 7 | //Very basic 3D camera. 8 | public class Camera3D 9 | { 10 | const float NEAR_PLANE = 1; 11 | const float FAR_PLANE = 500; 12 | 13 | public Matrix ViewMatrix { get; private set; } 14 | public Matrix ProjectionMatrix { get; private set; } 15 | private float AspectRatio { get; set; } //Update this in case we resize window. 16 | private float FieldOfView { get; set; } 17 | public Vector3 cameraPosition; 18 | 19 | public Camera3D() 20 | { 21 | AspectRatio = Globals.screenManager.GraphicsDevice.Viewport.AspectRatio; 22 | FieldOfView = MathHelper.ToRadians(90); //fov 23 | } 24 | 25 | public void Update(GameTime gameTime) 26 | { 27 | ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(FieldOfView, AspectRatio, NEAR_PLANE, FAR_PLANE); 28 | ViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraPosition + new Vector3(0, 0, -100), Vector3.Up); 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /fna_starterkit/game/loadscreen.cs: -------------------------------------------------------------------------------- 1 | #define SKIPMAINMENU 2 | 3 | using System; 4 | 5 | using Microsoft.Xna.Framework; 6 | 7 | 8 | 9 | namespace fna_starterkit 10 | { 11 | //This is the first screen the player sees. It is basically here just so the player has something to look at while the game loads. 12 | public class LoadScreen : Screen 13 | { 14 | bool loadDone; 15 | int loadTimer; //Let it sit for a short time so the game has time to draw something on the screen. 16 | 17 | public LoadScreen() 18 | { 19 | this.transitionOffTime = 0; 20 | this.transitionOnTime = 0; 21 | } 22 | 23 | public override void Update(GameTime gameTime) 24 | { 25 | loadTimer += gameTime.ElapsedGameTime.Milliseconds; 26 | 27 | if (!loadDone && loadTimer >= 100) 28 | { 29 | loadDone = true; 30 | 31 | //load the content data. 32 | Globals.Initialize(getContentManager); 33 | 34 | ExitScreen(); 35 | 36 | //Load game world. 37 | Worldscreen worldscreen = new Worldscreen(); 38 | Globals.screenManager.AddScreen(worldscreen); 39 | } 40 | 41 | base.Update(gameTime); 42 | } 43 | 44 | public override void Draw2D(GameTime gameTime) 45 | { 46 | base.Draw2D(gameTime); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /fna_starterkit/system/globals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using Microsoft.Xna.Framework.Content; 6 | using Microsoft.Xna.Framework.Audio; 7 | 8 | namespace fna_starterkit 9 | { 10 | public static class Globals 11 | { 12 | public static string WINDOWNAME = "FNA Starter Kit"; //Title that appears in window. 13 | public static string SETTINGSFOLDERNAME = "fna_starterkit"; //Folder that settings are saved in. 14 | 15 | public static Color COLOR_BACKGROUND = new Color(100, 149, 237); 16 | public static Vector3 CAMERAPOS = new Vector3(0, 0, 200); 17 | 18 | public static ScreenManager screenManager; 19 | 20 | public static string baseFolder; //Tells FNA ContentManager what folder to load content from. Defaults to "base". Use this to load player-made mods. 21 | 22 | 23 | public static Texture2D white; 24 | public static Texture2D orange; 25 | 26 | 27 | public static SpriteFont fontNTR; 28 | 29 | public static Random random; 30 | 31 | public static Vector3 backgroundcolor; 32 | 33 | public static void Initialize(ContentManager Content) 34 | { 35 | random = new Random(); 36 | 37 | fontNTR = Content.Load("fonts\\ntr"); 38 | fontNTR.LineSpacing = 28; 39 | 40 | orange = Content.Load("textures\\orange"); 41 | } 42 | } 43 | 44 | 45 | } -------------------------------------------------------------------------------- /fna_starterkit/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("blendo_fnakit")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("blendo_fnakit")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9e7bf64c-a265-4c71-9e7b-c80a427b3740")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FNA Starter Kit 2 | 3 | ## About FNA 4 | [FNA](https://github.com/FNA-XNA/FNA) is a game framework made by [Ethan Lee](https://flibitijibibo.com). To read more about FNA, [click here.](https://fna-xna.github.io) 5 | 6 | # About this starter kit 7 | I made this starter kit for folks to use as basic scaffolding for their own FNA projects. I like FNA a lot -- it's cleanly-written, thoughtfully-designed, flexible -- and I hope this starter kit helps give you a foothold in using it. 8 | 9 | Previous iterations of this code was used in parts of [Flotilla](https://blendogames.com/flotilla), [Atom Zombie Smasher](https://blendogames.com/atomzombiesmasher), [Air Forte](https://blendogames.com/airforte), [Planetfriend](https://lauramichet.itch.io/planetfriend), [Acre 6](https://blendogames.itch.io/acre6), [Tall Bagel](https://lauramichet.itch.io/tallbagel), and [Tall Bagel 2](https://lauramichet.itch.io/tallbagel2). 10 | 11 | ## What does it do? 12 | This kit has simple implementations of: 13 | - input management (keyboard/mouse/gamepad). 14 | - rendering a 3D model. 15 | - rendering a 2D sprite. 16 | - rendering 2D text. 17 | - playing sound effects. 18 | - a manager for the stack of screens. 19 | - game options (screen resolution, sound volume, etc). 20 | - saving/loading a settings file. 21 | 22 | ## Usage 23 | This kit is intended as a **starting point**, some very simple scaffolding to get you up and running quickly. Note that for your own projects, you'll definitely want to expand and modify this starter kit. 24 | 25 | - This is written in C# and a .sln solution for Visual Studio 2015 is provided. 26 | - For the content pipeline, I wrote a tool that may be helpful: [XNB Watcher](https://blendogames.itch.io/blendo-xnb-watcher). 27 | - You may need to install the XNA Redistributable. For modern machines, you may need to use this install process: https://flatredball.com/visual-studio-2017-xna-setup 28 | 29 | ## License 30 | This source code is licensed under the zlib license. Read the license details here: [LICENSE.md](https://github.com/blendogames/fna_starterkit/blob/master/LICENSE.md) 31 | 32 | ## Credits 33 | - by [Brendon Chung](http://blendogames.com) 34 | - FNA by [Ethan Lee](https://flibitijibibo.com) 35 | - Json.NET by [Newtonsoft](https://www.newtonsoft.com/json) 36 | -------------------------------------------------------------------------------- /fna_starterkit/system/program.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.IO; 8 | 9 | namespace fna_starterkit 10 | { 11 | //This is the entry point when the game is run. 12 | class Program 13 | { 14 | #if WINDOWS 15 | [System.Runtime.InteropServices.DllImport("user32.dll")] //Adjust for Windows desktop scaling 16 | static extern bool SetProcessDPIAware(); 17 | #endif 18 | 19 | static void Main(string[] args) 20 | { 21 | 22 | #if WINDOWS 23 | try 24 | { 25 | SetProcessDPIAware(); //Adjust for Windows scale 26 | } 27 | catch 28 | { 29 | } 30 | #endif 31 | 32 | const string BASEFOLDERNAME = "base"; 33 | 34 | string baseFolder = BASEFOLDERNAME; 35 | 36 | foreach (string arg in args) 37 | { 38 | if (arg.Equals("--attempt-highdpi")) 39 | { 40 | Environment.SetEnvironmentVariable("FNA_GRAPHICS_ENABLE_HIGHDPI", "1"); 41 | } 42 | 43 | if (arg.Equals("-mod") && args.Length > 1) 44 | { 45 | baseFolder = args[1]; 46 | } 47 | } 48 | 49 | Globals.baseFolder = baseFolder; 50 | 51 | if (string.Compare(baseFolder, BASEFOLDERNAME, StringComparison.InvariantCultureIgnoreCase) != 0) 52 | { 53 | string directoryCheck = Path.Combine(Environment.CurrentDirectory, baseFolder); 54 | if (!Directory.Exists(directoryCheck)) 55 | { 56 | Helpers.FatalPopup("Failed to find mod folder:\n'{0}'\n\nPlease make sure this folder exists.", directoryCheck); 57 | } 58 | } 59 | 60 | using (Globals.screenManager = new ScreenManager()) 61 | { 62 | #if DEBUG 63 | Globals.screenManager.Run(); //If debug build, then don't wrap it up in a try/catch block. 64 | #else 65 | try 66 | { 67 | Globals.screenManager.Run(); 68 | } 69 | catch (Exception e) 70 | { 71 | Helpers.ErrorPopup(e.ToString()); //If any crash happens, display it to the player. 72 | } 73 | #endif 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /fna_starterkit/game/pausemenu.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Input; 5 | 6 | namespace fna_starterkit 7 | { 8 | 9 | public class PauseMenu : Screen 10 | { 11 | const int MARGIN_LEFT = 50; 12 | 13 | Button[] buttons; 14 | 15 | public PauseMenu() 16 | { 17 | this.transitionOffTime = 200; 18 | this.transitionOnTime = 200; 19 | 20 | Reinitialize(); //Set up all the buttons. 21 | } 22 | 23 | public override void Reinitialize() 24 | { 25 | buttons = new Button[] 26 | { 27 | new Button("Resume", HitButton_Resume), 28 | new Button("Options", HitButton_Settings), 29 | new Button("Exit to desktop", HitButton_Quit) 30 | }; 31 | 32 | 33 | for (int i = 0; i < buttons.Length; i++) 34 | { 35 | buttons[i].SetPosition(new Vector2(100, 200 + i * 90)); 36 | } 37 | } 38 | 39 | 40 | public override void Update(GameTime gameTime) 41 | { 42 | base.Update(gameTime); 43 | } 44 | 45 | public override void UpdateInput(GameTime gameTime) 46 | { 47 | if (!Globals.screenManager.IsActive) 48 | return; 49 | 50 | if (InputManager.GetKeyboardClick(Keys.Escape)) 51 | { 52 | HitButton_Resume(null, null); 53 | } 54 | 55 | for (int i = 0; i < buttons.Length; i++) 56 | { 57 | buttons[i].Update(gameTime); 58 | } 59 | 60 | base.UpdateInput(gameTime); 61 | } 62 | 63 | private void HitButton_Resume(object sender, ButtonArgs data) 64 | { 65 | ExitScreen(); 66 | } 67 | 68 | private void HitButton_Settings(object sender, ButtonArgs data) 69 | { 70 | Globals.screenManager.AddScreen(new OptionsPage()); 71 | } 72 | 73 | private void HitButton_Quit(object sender, ButtonArgs data) 74 | { 75 | Globals.screenManager.Exit(); 76 | } 77 | 78 | public override void Draw2D(GameTime gameTime) 79 | { 80 | //Dark BG. 81 | Globals.screenManager.getSpriteBatch.Draw(Globals.white, new Rectangle(0, 0, Globals.screenManager.Window.ClientBounds.Width, Globals.screenManager.Window.ClientBounds.Height), (Color.PaleVioletRed * .8f) * this.getTransition); 82 | 83 | //header title. 84 | Globals.screenManager.getSpriteBatch.DrawString(Globals.fontNTR, "FNA Starter Kit", new Vector2(100,100), Color.White * this.getTransition); 85 | 86 | //Buttons. 87 | for (int i = 0; i < buttons.Length; i++) 88 | { 89 | buttons[i].Draw2D(gameTime); 90 | } 91 | 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /fna_starterkit/game/button.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Xna.Framework; 4 | 5 | namespace fna_starterkit 6 | { 7 | public class Button 8 | { 9 | const int BUTTON_BUFFERMARGIN = 20; 10 | 11 | protected string displayText; 12 | protected event EventHandler leftclickEvent; 13 | 14 | protected Vector2 position; 15 | public Vector2 GetPosition { get { return position; } } 16 | 17 | protected Rectangle backRect; 18 | public Rectangle GetRect { get { return backRect; } } 19 | 20 | protected bool hover; 21 | public bool GetHover { get { return hover; } } 22 | 23 | bool lastHover; 24 | 25 | protected ButtonArgs buttonArgs; 26 | public ButtonArgs GetButtonArgs { get { return buttonArgs; } } 27 | 28 | public Button(string _displayText, EventHandler _leftclickEvent, ButtonArgs _arg = null) 29 | { 30 | displayText = _displayText; 31 | leftclickEvent = _leftclickEvent; 32 | 33 | Vector2 textBox = Globals.fontNTR.MeasureString(displayText); 34 | backRect = new Rectangle((int)position.X, (int)position.Y, (int)textBox.X + BUTTON_BUFFERMARGIN * 2, (int)textBox.Y); 35 | 36 | if (_arg != null) 37 | { 38 | buttonArgs = _arg; 39 | } 40 | else 41 | { 42 | buttonArgs = new ButtonArgs(); 43 | } 44 | } 45 | 46 | public void SetDisplayText(string value) 47 | { 48 | this.displayText = value; 49 | } 50 | 51 | public virtual void SetPosition(Vector2 _position) 52 | { 53 | position = _position; 54 | backRect.X = (int)_position.X; 55 | backRect.Y = (int)_position.Y; 56 | } 57 | 58 | public virtual void Update(GameTime gameTime) 59 | { 60 | hover = backRect.Contains((int)InputManager.getMousePosition.X, (int)InputManager.getMousePosition.Y); 61 | 62 | //ignore if mouse cursor is outside window. 63 | Point pos = new Point((int)InputManager.getMousePosition.X, (int)InputManager.getMousePosition.Y); 64 | if (!Globals.screenManager.GraphicsDevice.Viewport.Bounds.Contains(pos)) 65 | hover = false; 66 | 67 | 68 | if (hover && InputManager.GetMouseClick(0) && leftclickEvent != null) 69 | { 70 | leftclickEvent(this, buttonArgs); 71 | Globals.screenManager.GetSoundManager.Play("click"); 72 | } 73 | 74 | if (lastHover != hover) 75 | { 76 | lastHover = hover; 77 | 78 | if (hover) 79 | { 80 | Globals.screenManager.GetSoundManager.Play("rollover"); 81 | } 82 | } 83 | } 84 | 85 | public virtual void Draw2D(GameTime gameTime) 86 | { 87 | Globals.screenManager.getSpriteBatch.Draw(Globals.white, backRect, hover ? Color.Goldenrod : Color.Chocolate); 88 | Globals.screenManager.getSpriteBatch.DrawString(Globals.fontNTR, displayText, position + new Vector2(BUTTON_BUFFERMARGIN,0), Color.Black); 89 | } 90 | } 91 | 92 | public class ButtonArgs : EventArgs 93 | { 94 | public int var00, var01; 95 | } 96 | } -------------------------------------------------------------------------------- /fna_starterkit/game/worldscreen.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | using Microsoft.Xna.Framework; 6 | using Microsoft.Xna.Framework.Graphics; 7 | using Microsoft.Xna.Framework.Input; 8 | 9 | 10 | namespace fna_starterkit 11 | { 12 | public class Worldscreen : Screen 13 | { 14 | Camera3D camera; 15 | public Camera3D GetCamera { get { return camera; } } 16 | 17 | Entity chair; 18 | 19 | public Worldscreen() 20 | { 21 | camera = new Camera3D(); 22 | camera.cameraPosition = Globals.CAMERAPOS; 23 | 24 | chair = new Entity("models/chair/chair.xnb"); 25 | chair.SetPosition(new Vector3(0, 0, 50)); 26 | } 27 | 28 | public override void Update(GameTime gameTime) 29 | { 30 | base.Update(gameTime); 31 | } 32 | 33 | public override void UpdateInput(GameTime gameTime) 34 | { 35 | if (!Globals.screenManager.IsActive) 36 | return; //If game window is not focused, then exit here. 37 | 38 | camera.Update(gameTime); //Update the camera. 39 | 40 | 41 | if (InputManager.GetKeyboardHeld(Keys.W) || InputManager.GetKeyboardHeld(Keys.Up)) 42 | { 43 | chair.SetPosition(new Vector3(chair.GetPosition.X, chair.GetPosition.Y + (gameTime.ElapsedGameTime.Milliseconds * .1f), chair.GetPosition.Z)); 44 | } 45 | else if (InputManager.GetKeyboardHeld(Keys.S) || InputManager.GetKeyboardHeld(Keys.Down)) 46 | { 47 | chair.SetPosition(new Vector3(chair.GetPosition.X, chair.GetPosition.Y + (gameTime.ElapsedGameTime.Milliseconds * -.1f), chair.GetPosition.Z)); 48 | } 49 | 50 | if (InputManager.GetKeyboardHeld(Keys.A) || InputManager.GetKeyboardHeld(Keys.Left)) 51 | { 52 | chair.SetPosition(new Vector3(chair.GetPosition.X + (gameTime.ElapsedGameTime.Milliseconds * -.1f), chair.GetPosition.Y, chair.GetPosition.Z)); 53 | } 54 | else if (InputManager.GetKeyboardHeld(Keys.D) || InputManager.GetKeyboardHeld(Keys.Right)) 55 | { 56 | chair.SetPosition(new Vector3(chair.GetPosition.X + (gameTime.ElapsedGameTime.Milliseconds * .1f), chair.GetPosition.Y, chair.GetPosition.Z)); 57 | } 58 | 59 | 60 | if (InputManager.GetKeyboardClick(Keys.Escape)) //Handle key input. 61 | { 62 | Globals.screenManager.AddScreen(new PauseMenu()); 63 | } 64 | } 65 | 66 | 67 | public override void Draw2D(GameTime gameTime) 68 | { 69 | //Draw a message in center of screen. 70 | string message = "FNA Starter Kit\n\nWASD = move chair\nESC = menu"; 71 | Vector2 messageSize = Globals.fontNTR.MeasureString(message); 72 | Globals.screenManager.getSpriteBatch.DrawString(Globals.fontNTR, message, new Vector2(Globals.screenManager.Window.ClientBounds.Width / 2 - messageSize.X / 2, 20 ), Color.White); 73 | 74 | //Draw image of an orange. 75 | Globals.screenManager.getSpriteBatch.Draw(Globals.orange, new Rectangle(20, 20, 200, 200), Color.White); 76 | } 77 | 78 | public override void Draw3D(GameTime gameTime) 79 | { 80 | //Render the chair model. 81 | chair.Draw3D(gameTime, this.camera); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /fna_starterkit/system/bloom/bloomsettings.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // BloomSettings.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | namespace fna_starterkit 11 | { 12 | /// 13 | /// Class holds all the settings used to tweak the bloom effect. 14 | /// 15 | public class BloomSettings 16 | { 17 | #region Fields 18 | 19 | 20 | // Name of a preset bloom setting, for display to the user. 21 | public readonly string Name; 22 | 23 | 24 | // Controls how bright a pixel needs to be before it will bloom. 25 | // Zero makes everything bloom equally, while higher values select 26 | // only brighter colors. Somewhere between 0.25 and 0.5 is good. 27 | public readonly float BloomThreshold; 28 | 29 | 30 | // Controls how much blurring is applied to the bloom image. 31 | // The typical range is from 1 up to 10 or so. 32 | public readonly float BlurAmount; 33 | 34 | 35 | // Controls the amount of the bloom and base images that 36 | // will be mixed into the final scene. Range 0 to 1. 37 | public readonly float BloomIntensity; 38 | public readonly float BaseIntensity; 39 | 40 | 41 | // Independently control the color saturation of the bloom and 42 | // base images. Zero is totally desaturated, 1.0 leaves saturation 43 | // unchanged, while higher values increase the saturation level. 44 | public readonly float BloomSaturation; 45 | public readonly float BaseSaturation; 46 | 47 | 48 | #endregion 49 | 50 | 51 | /// 52 | /// Constructs a new bloom settings descriptor. 53 | /// 54 | public BloomSettings(string name, float bloomThreshold, float blurAmount, 55 | float bloomIntensity, float baseIntensity, 56 | float bloomSaturation, float baseSaturation) 57 | { 58 | Name = name; 59 | BloomThreshold = bloomThreshold; 60 | BlurAmount = blurAmount; 61 | BloomIntensity = bloomIntensity; 62 | BaseIntensity = baseIntensity; 63 | BloomSaturation = bloomSaturation; 64 | BaseSaturation = baseSaturation; 65 | } 66 | 67 | 68 | /// 69 | /// Table of preset bloom settings, used by the sample program. 70 | /// 71 | public static BloomSettings[] PresetSettings = 72 | { 73 | // Name Thresh Blur Bloom Base BloomSat BaseSat 74 | new BloomSettings("Default", 0.25f, 4, 1.25f, 1, 1, 1), 75 | new BloomSettings("Soft", 0, 3, 1, 1, 1, 1), 76 | new BloomSettings("Desaturated", 0.5f, 8, 2, 1, 0, 1), 77 | new BloomSettings("Saturated", 0.25f, 4, 2, 1, 2, 0), 78 | new BloomSettings("Blurry", 0, 2, 1, 0.1f, 1, 1), 79 | new BloomSettings("Subtle", 0.5f, 2, 1, 1, 1, 1), 80 | new BloomSettings("Blendo", 0.3f, 6, 1, 1, 1, 1), //BC this is the one we use. 81 | new BloomSettings("off", 0.6f, 2, 0.4f, 1, 1, 1), 82 | }; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /fna_starterkit/system/screen.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | using Microsoft.Xna.Framework.Content; 6 | 7 | namespace fna_starterkit 8 | { 9 | public enum ScreenState 10 | { 11 | Active, 12 | Deactivated, 13 | TransitionOn, 14 | TransitionOff 15 | } 16 | 17 | //A screen. i.e. options menu, title screen, game screen, etc. All of the screens are handled through ScreenManager. 18 | public abstract class Screen 19 | { 20 | public SpriteBatch getSpriteBatch { get { return Globals.screenManager.getSpriteBatch; } } 21 | public ContentManager getContentManager { get { return Globals.screenManager.Content; } } 22 | public GraphicsDeviceManager getGraphicsDevice { get { return Globals.screenManager.getGraphicsDevice; } } 23 | 24 | ScreenState state = ScreenState.Active; 25 | public ScreenState getState { get { return state; } } 26 | 27 | protected int transitionOnTime; 28 | protected int transitionOffTime; 29 | int transitionTimer; 30 | float transition; 31 | public float getTransition { get { return transition; } } 32 | 33 | public Screen() 34 | { 35 | transitionOnTime = 300; 36 | transitionOffTime = 100; 37 | state = ScreenState.TransitionOn; 38 | } 39 | 40 | //This gets called when resolution is changed. Use this function to recalculate & re-arrange UI elements for new screen resolution, etc. 41 | public virtual void Reinitialize() 42 | { 43 | } 44 | 45 | //Immediately remove this screen from the stack, no transition. 46 | public virtual void KillScreen() 47 | { 48 | state = ScreenState.Deactivated; 49 | } 50 | 51 | //Remove this screen from the stack with a nice transition. 52 | public virtual void ExitScreen() 53 | { 54 | transitionTimer = transitionOffTime; 55 | state = ScreenState.TransitionOff; 56 | } 57 | 58 | /// 59 | /// Gets called every frame. 60 | /// 61 | public virtual void Update(GameTime gameTime) 62 | { 63 | //update the transition states. 64 | if (state == ScreenState.TransitionOn) 65 | { 66 | transitionTimer = (int)MathHelper.Min(transitionTimer + gameTime.ElapsedGameTime.Milliseconds, transitionOnTime); 67 | transition = (float)transitionTimer / transitionOnTime; 68 | 69 | if (transitionTimer >= transitionOnTime) 70 | { 71 | state = ScreenState.Active; 72 | } 73 | } 74 | else if (state == ScreenState.TransitionOff) 75 | { 76 | transitionTimer = (int)MathHelper.Max(transitionTimer - gameTime.ElapsedGameTime.Milliseconds, 0); 77 | transition = (float)transitionTimer / transitionOffTime; 78 | 79 | if (transitionTimer <= 0) 80 | { 81 | state = ScreenState.Deactivated; 82 | } 83 | } 84 | } 85 | 86 | //Gets called every frame, but only if this screen is on top of the stack. 87 | public virtual void UpdateInput(GameTime gameTime) 88 | { 89 | } 90 | 91 | //Draw 3D things. 92 | public virtual void Draw3D(GameTime gameTime) 93 | { 94 | } 95 | 96 | //Draw 2D things. 97 | public virtual void Draw2D(GameTime gameTime) 98 | { 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /fna_starterkit/game/entity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | 6 | namespace fna_starterkit 7 | { 8 | //Basic game object. Renders a 3D model. 9 | public class Entity 10 | { 11 | protected Model myModel; 12 | protected Matrix[] transforms; 13 | 14 | protected Vector3 modelPosition; 15 | public Vector3 GetPosition { get { return modelPosition; } } 16 | 17 | protected Matrix modelRotation; 18 | public Matrix GetRotation { get { return modelRotation; } } 19 | 20 | protected Vector3 color; 21 | public Vector3 GetColor { get { return color; } } 22 | 23 | protected bool shaded; 24 | 25 | protected float scale; 26 | 27 | public Entity(string modelPath) 28 | { 29 | modelPosition = Vector3.Zero; 30 | 31 | try 32 | { 33 | //Attempt to load model. 34 | myModel = Globals.screenManager.Content.Load(modelPath.Substring(0, modelPath.LastIndexOf(".xnb"))); 35 | } 36 | catch (Exception e) 37 | { 38 | Helpers.FatalPopup("Failed to load model:\n'{0}'\n\nError: {1}", modelPath, e.Message); 39 | } 40 | 41 | transforms = new Matrix[myModel.Bones.Count]; 42 | modelRotation = Matrix.Identity; 43 | 44 | color = new Vector3(.64f, .64f, .64f); 45 | shaded = true; 46 | scale = 1.0f; 47 | } 48 | 49 | public virtual void SetScale(float value) 50 | { 51 | scale = value; 52 | } 53 | 54 | public virtual void SetShaded(bool value) 55 | { 56 | shaded = value; 57 | } 58 | 59 | public virtual void SetRotation(Matrix _matrix) 60 | { 61 | modelRotation = _matrix; 62 | } 63 | 64 | public virtual void SetPosition(Vector3 _position) 65 | { 66 | modelPosition = _position; 67 | } 68 | 69 | public virtual void SetColor(Vector3 _color) 70 | { 71 | color = _color; 72 | } 73 | 74 | public void SetModel(string path) 75 | { 76 | try 77 | { 78 | myModel = Globals.screenManager.Content.Load(path.Substring(0, path.LastIndexOf(".xnb"))); 79 | } 80 | catch (Exception e) 81 | { 82 | Helpers.ErrorPopup(string.Format("Failed to load model:\n{0}\n\n{1}", path, e.Message)); 83 | } 84 | 85 | transforms = new Matrix[myModel.Bones.Count]; 86 | } 87 | 88 | public virtual void Draw3D(GameTime gameTime, Camera3D camera) 89 | { 90 | myModel.CopyAbsoluteBoneTransformsTo(transforms); 91 | 92 | foreach (ModelMesh mesh in myModel.Meshes) 93 | { 94 | foreach (BasicEffect effect in mesh.Effects) 95 | { 96 | effect.LightingEnabled = shaded; 97 | 98 | if (shaded) 99 | { 100 | effect.DiffuseColor = color; 101 | effect.DirectionalLight0.DiffuseColor = new Vector3(.7f, .7f, .7f); 102 | Vector3 lightAngle = new Vector3(20,-60, -60); 103 | lightAngle.Normalize(); 104 | effect.DirectionalLight0.Direction = lightAngle; 105 | effect.AmbientLightColor = new Vector3(.3f, .3f, .3f); 106 | } 107 | else 108 | { 109 | effect.DiffuseColor = color; 110 | effect.AmbientLightColor = new Vector3(1,1,1); 111 | } 112 | 113 | 114 | effect.View = camera.ViewMatrix; 115 | effect.Projection = camera.ProjectionMatrix; 116 | effect.World = transforms[mesh.ParentBone.Index] * modelRotation * Matrix.CreateScale(scale) * Matrix.CreateTranslation(modelPosition) ; 117 | } 118 | 119 | mesh.Draw(); 120 | } 121 | 122 | 123 | 124 | 125 | } 126 | 127 | // --- end of file 128 | } 129 | } -------------------------------------------------------------------------------- /fna_starterkit/system/settingsmanager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | using Microsoft.Xna.Framework.Audio; 7 | 8 | using Newtonsoft.Json; 9 | 10 | namespace fna_starterkit 11 | { 12 | //Add or remove new settings here. They'll be added to the json settings file. 13 | public class SettingsProfile 14 | { 15 | [JsonProperty("screenwidth")] 16 | public int screenwidth { get; set; } 17 | 18 | [JsonProperty("screenheight")] 19 | public int screenheight { get; set; } 20 | 21 | [JsonProperty("fullscreen")] 22 | public bool fullscreen { get; set; } 23 | 24 | [JsonProperty("soundvolume")] 25 | public float soundvolume { get; set; } 26 | 27 | [JsonProperty("invertmouse")] 28 | public bool invertmouse { get; set; } 29 | } 30 | 31 | public class SettingsManager 32 | { 33 | static readonly string SETTINGS_FILEPATH = GetSettingsPath(); 34 | 35 | SettingsProfile settings; 36 | public SettingsProfile GetSettings { get { return settings; } } 37 | 38 | static string GetSettingsPath() //Get the settings file, dependent on the platform. 39 | { 40 | string os = SDL2.SDL.SDL_GetPlatform(); 41 | string osDir = string.Empty; 42 | if (os.Equals("Linux")) 43 | { 44 | osDir = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); 45 | if (string.IsNullOrEmpty(osDir)) 46 | { 47 | osDir = Environment.GetEnvironmentVariable("HOME"); 48 | if (string.IsNullOrEmpty(osDir)) 49 | { 50 | return "base/settings.json"; // Oh well. 51 | } 52 | osDir = Path.Combine(osDir, ".local/share"); 53 | } 54 | osDir = Path.Combine(osDir, Globals.SETTINGSFOLDERNAME); 55 | } 56 | else if (os.Equals("Mac OS X")) 57 | { 58 | osDir = Environment.GetEnvironmentVariable("HOME"); 59 | if (string.IsNullOrEmpty(osDir)) 60 | { 61 | return "base/settings.json"; // Oh well. 62 | } 63 | osDir = Path.Combine(osDir, "Library/Application Support", Globals.SETTINGSFOLDERNAME); 64 | } 65 | else if (os.Equals("Windows")) 66 | { 67 | return Path.Combine(Globals.baseFolder, "settings.json"); 68 | } 69 | else 70 | { 71 | throw new NotSupportedException("Unhandled SDL2 platform!"); 72 | } 73 | if (!Directory.Exists(osDir)) 74 | { 75 | Directory.CreateDirectory(osDir); 76 | } 77 | return Path.Combine(osDir, "settings.json"); 78 | } 79 | 80 | public SettingsManager() 81 | { 82 | settings = new SettingsProfile(); //Empty settings. 83 | } 84 | 85 | public static void OpenConfigFile() 86 | { 87 | string os = SDL2.SDL.SDL_GetPlatform(); 88 | if (os.Equals("Windows") || os.Equals("Mac OS X")) 89 | { 90 | System.Diagnostics.Process.Start(SETTINGS_FILEPATH); 91 | } 92 | else 93 | { 94 | System.Diagnostics.Process.Start( 95 | "xdg-open", 96 | SETTINGS_FILEPATH 97 | ); 98 | } 99 | } 100 | 101 | //Load settings from settings file. 102 | public bool ReadSettingsFromFile() 103 | { 104 | if (!File.Exists(SETTINGS_FILEPATH)) //Ensure settings file exists. 105 | return false; 106 | 107 | string rawStrings = Helpers.GetFileContents(SETTINGS_FILEPATH); 108 | 109 | if (string.IsNullOrEmpty(rawStrings)) //Ensure settings file has stuff in it. 110 | return false; 111 | 112 | //Attempt to load the settings json file. 113 | try 114 | { 115 | SettingsProfile profile = JsonConvert.DeserializeObject(rawStrings); 116 | settings = profile; //Load it into the current settings. 117 | } 118 | catch 119 | { 120 | return false; 121 | } 122 | 123 | //yay everything worked. 124 | return true; 125 | } 126 | 127 | //Commit settings to the settings file. 128 | public bool WriteSettingsToFile() 129 | { 130 | try 131 | { 132 | using (StreamWriter file = File.CreateText(SETTINGS_FILEPATH)) 133 | { 134 | string output = JsonConvert.SerializeObject(settings, Formatting.Indented); 135 | file.Write(output); 136 | } 137 | } 138 | catch (Exception err) 139 | { 140 | Helpers.ErrorPopup("Failed to write settings file:\n{0}\n\n{1}", SETTINGS_FILEPATH, err.Message); 141 | return false; 142 | } 143 | 144 | return true; 145 | } 146 | 147 | 148 | //Directly opens the json config file in the player's text editor. 149 | public static void OpenSettingsInEditor() 150 | { 151 | string os = SDL2.SDL.SDL_GetPlatform(); 152 | if (os.Equals("Windows") || os.Equals("Mac OS X")) 153 | { 154 | System.Diagnostics.Process.Start(SETTINGS_FILEPATH); 155 | } 156 | else 157 | { 158 | System.Diagnostics.Process.Start( 159 | "xdg-open", 160 | SETTINGS_FILEPATH 161 | ); 162 | } 163 | } 164 | } 165 | } -------------------------------------------------------------------------------- /fna_starterkit/system/soundmanager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | 5 | using Microsoft.Xna.Framework; 6 | using Microsoft.Xna.Framework.Graphics; 7 | using Microsoft.Xna.Framework.Audio; 8 | 9 | namespace fna_starterkit 10 | { 11 | public class SoundManager 12 | { 13 | Dictionary soundDictionary; 14 | 15 | public SoundManager() 16 | { 17 | string dirPath = Path.Combine(Globals.baseFolder, "sound"); 18 | 19 | if (!Directory.Exists(dirPath)) 20 | { 21 | Helpers.ErrorPopup("SoundManager failed to find directory:\n{0}", Path.Combine(Environment.CurrentDirectory, dirPath)); 22 | return; 23 | } 24 | 25 | //Get all the .wav files in the sounds folder. 26 | DirectoryInfo dirInfo = new DirectoryInfo(dirPath); 27 | FileInfo[] fileArray = dirInfo.GetFiles("*.wav"); 28 | 29 | //Generate a dictionary of all .wav sound files. This creates a library of sounds for the game. We bypass the XNB content pipeline, and just load .wav files directly. 30 | soundDictionary = new Dictionary(); 31 | 32 | 33 | for (int i = 0; i < fileArray.Length; i++) 34 | { 35 | if (!File.Exists(fileArray[i].FullName)) 36 | { 37 | Helpers.ErrorPopup(string.Format("SoundManager can't find file:\n{0}", fileArray[i].FullName)); 38 | continue; 39 | } 40 | 41 | SoundEntry newEntry = new SoundEntry(); 42 | if (!newEntry.Initialize(fileArray[i].FullName)) 43 | continue; 44 | 45 | string cueName = Path.GetFileNameWithoutExtension(fileArray[i].FullName); 46 | soundDictionary.Add(cueName, newEntry); //Add the entry to the sound library. 47 | } 48 | } 49 | 50 | 51 | 52 | public void Play(string cuename) 53 | { 54 | SoundEntry entry; 55 | if (soundDictionary.TryGetValue(cuename, out entry)) 56 | { 57 | entry.Play(); 58 | } 59 | else 60 | { 61 | Helpers.FatalPopup("Failed to find sound: {0}", cuename); 62 | } 63 | } 64 | 65 | public void SetLoop(string cuename, bool value) 66 | { 67 | SoundEntry entry; 68 | if (soundDictionary.TryGetValue(cuename, out entry)) 69 | { 70 | entry.SetLoop(value); 71 | } 72 | } 73 | 74 | public void SetPitch(string cuename, float value) 75 | { 76 | SoundEntry entry; 77 | if (soundDictionary.TryGetValue(cuename, out entry)) 78 | { 79 | entry.SetPitch(value); 80 | } 81 | } 82 | 83 | public void SetVolume(string cuename, float value) 84 | { 85 | SoundEntry entry; 86 | if (soundDictionary.TryGetValue(cuename, out entry)) 87 | { 88 | entry.SetVolume(value); 89 | } 90 | } 91 | 92 | public void StopAllSound() 93 | { 94 | foreach (KeyValuePair entry in soundDictionary) 95 | { 96 | entry.Value.Stop(); 97 | } 98 | } 99 | 100 | public void StopSound(string cuename) 101 | { 102 | SoundEntry entry; 103 | if (soundDictionary.TryGetValue(cuename, out entry)) 104 | { 105 | entry.Stop(); 106 | } 107 | } 108 | 109 | 110 | public void Update(GameTime gameTime) 111 | { 112 | } 113 | } 114 | 115 | public class SoundEntry 116 | { 117 | SoundEffect effect; 118 | SoundEffectInstance instance; 119 | 120 | public SoundEntry() 121 | { 122 | } 123 | 124 | public bool Initialize(string filepath) 125 | { 126 | try 127 | { 128 | //Load .wav files directly. Bypass the content pipeline. 129 | System.IO.FileStream fs = new System.IO.FileStream(filepath, System.IO.FileMode.Open, FileAccess.Read); 130 | effect = SoundEffect.FromStream(fs); 131 | fs.Dispose(); 132 | 133 | instance = effect.CreateInstance(); 134 | } 135 | catch (Exception e) 136 | { 137 | Helpers.ErrorPopup(string.Format("Failed to load sound:\n{0}\n\n{1}", filepath, e.Message)); 138 | return false; 139 | } 140 | 141 | return true; 142 | } 143 | 144 | public void Stop() 145 | { 146 | if (instance.State == SoundState.Stopped || instance.State == SoundState.Paused) 147 | return; 148 | 149 | instance.Stop(); 150 | } 151 | 152 | public void Pause() 153 | { 154 | if (instance.State == SoundState.Paused || instance.State == SoundState.Stopped) 155 | return; 156 | 157 | instance.Pause(); 158 | } 159 | 160 | public void SetVolume(float value) 161 | { 162 | instance.Volume = value; 163 | } 164 | 165 | public void SetPitch(float value) 166 | { 167 | instance.Pitch = value; 168 | } 169 | 170 | public void SetLoop(bool value) 171 | { 172 | if (instance.IsLooped == value) 173 | { 174 | return; 175 | } 176 | 177 | if (instance.State != SoundState.Stopped) 178 | { 179 | Console.WriteLine("SPEC VIOLATION, TELL FLIBITIJIBIBO:\n\n" + Environment.StackTrace); 180 | return; 181 | } 182 | 183 | instance.IsLooped = value; 184 | } 185 | 186 | public void Play() 187 | { 188 | if (instance.State == SoundState.Stopped) 189 | { 190 | instance.Play(); 191 | } 192 | else if (instance.State == SoundState.Paused) 193 | { 194 | instance.Resume(); 195 | } 196 | else 197 | { 198 | instance.Stop(); 199 | instance.Play(); 200 | } 201 | } 202 | } 203 | } -------------------------------------------------------------------------------- /fna_starterkit/system/screenmanager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | using Microsoft.Xna.Framework.Content; 7 | using Microsoft.Xna.Framework.Audio; 8 | using Microsoft.Xna.Framework.Input; 9 | 10 | 11 | 12 | namespace fna_starterkit 13 | { 14 | //ScreenManager is the backbone of the game. It handles the stack of all the different screens. 15 | //Screens can be added and removed from the stack. The top screen in the stack is the one the player interacts with. 16 | //We also handle the game initialization here. 17 | public class ScreenManager : Game 18 | { 19 | List screens = new List(); 20 | 21 | GraphicsDeviceManager graphics; 22 | public GraphicsDeviceManager getGraphicsDevice { get { return graphics; } } 23 | 24 | SpriteBatch spriteBatch; 25 | public SpriteBatch getSpriteBatch { get { return spriteBatch; } } 26 | 27 | BloomComponent bloom; 28 | public BloomComponent getBloom { get { return bloom; } } 29 | 30 | SoundManager soundManager; 31 | public SoundManager GetSoundManager { get { return soundManager; } } 32 | 33 | SettingsManager settingsManager; 34 | public SettingsManager GetSettingsManager { get { return settingsManager; } } 35 | 36 | public ScreenManager() 37 | { 38 | //Initialize the game. 39 | graphics = new GraphicsDeviceManager(this); 40 | 41 | settingsManager = new SettingsManager(); 42 | bool foundSettings = settingsManager.ReadSettingsFromFile(); 43 | 44 | //If there are no settings found 45 | if (!foundSettings) 46 | { 47 | //No settings found. Use default settings. 48 | DisplayMode defaultMode = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode; 49 | settingsManager.GetSettings.screenwidth = defaultMode.Width; 50 | settingsManager.GetSettings.screenheight = defaultMode.Height; 51 | settingsManager.GetSettings.fullscreen = true; 52 | settingsManager.GetSettings.soundvolume = 1.0f; 53 | 54 | //Write the settings file. 55 | settingsManager.WriteSettingsToFile(); 56 | } 57 | 58 | 59 | //Settings are now loaded. Hook them into all the game systems. 60 | if (Environment.OSVersion.Platform == PlatformID.Win32NT) 61 | { 62 | this.Window.IsBorderlessEXT = settingsManager.GetSettings.fullscreen; 63 | } 64 | else 65 | { 66 | graphics.IsFullScreen = settingsManager.GetSettings.fullscreen; 67 | } 68 | 69 | graphics.PreferredBackBufferWidth = settingsManager.GetSettings.screenwidth; 70 | graphics.PreferredBackBufferHeight = settingsManager.GetSettings.screenheight; 71 | SoundEffect.MasterVolume = settingsManager.GetSettings.soundvolume; 72 | 73 | graphics.SynchronizeWithVerticalRetrace = true; //vsync 74 | graphics.PreferMultiSampling = true; 75 | this.IsFixedTimeStep = false; 76 | this.Window.Title = Globals.WINDOWNAME; 77 | this.Window.AllowUserResizing = false; 78 | this.IsMouseVisible = true; 79 | 80 | soundManager = new SoundManager(); 81 | 82 | Content.RootDirectory = Globals.baseFolder; 83 | TargetElapsedTime = TimeSpan.FromSeconds(1 / 60.0f); 84 | } 85 | 86 | //Call this when player changes their screen resolution while in-game. 87 | public void InitializeAllScreens() 88 | { 89 | for (int i = screens.Count - 1; i >= 0; i--) 90 | { 91 | if (screens[i] == null) 92 | continue; 93 | 94 | screens[i].Reinitialize(); 95 | } 96 | } 97 | 98 | //Add a new screen to the stack. 99 | public void AddScreen(Screen screen) 100 | { 101 | screens.Add(screen); 102 | } 103 | 104 | //Check whether the screen is at the top of the stack. 105 | public bool GetIsTopScreen(Screen screen) 106 | { 107 | return (screens[screens.Count - 1] == screen); 108 | } 109 | 110 | 111 | protected override void Initialize() 112 | { 113 | bloom = new BloomComponent(this); 114 | bloom.Settings = BloomSettings.PresetSettings[6]; 115 | Components.Add(bloom); //Add bloom. 116 | base.Initialize(); 117 | } 118 | 119 | protected override void LoadContent() 120 | { 121 | spriteBatch = new SpriteBatch(GraphicsDevice); 122 | Globals.white = Content.Load("textures\\white"); 123 | 124 | AddScreen(new LoadScreen()); //Go to the loading screen. 125 | } 126 | 127 | protected override void UnloadContent() 128 | { 129 | } 130 | 131 | //This gets called every frame. This is the main update loop. 132 | protected override void Update(GameTime gameTime) 133 | { 134 | InputManager.Update(gameTime); 135 | 136 | for (int i = screens.Count - 1; i >= 0; i--) 137 | { 138 | if (screens[i] == null) //Just in case.... 139 | continue; 140 | 141 | //remove any screens waiting to be removed. 142 | if (screens[i].getState == ScreenState.Deactivated) 143 | { 144 | screens.RemoveAt(i); 145 | continue; 146 | } 147 | 148 | //update screen. 149 | screens[i].Update(gameTime); 150 | } 151 | 152 | //update input only on screen on top of the stack. 153 | if (screens.Count > 0) 154 | { 155 | screens[screens.Count - 1].UpdateInput(gameTime); 156 | } 157 | 158 | soundManager.Update(gameTime); 159 | 160 | base.Update(gameTime); 161 | } 162 | 163 | //Draw 2D and 3D stuff. 164 | protected override void Draw(GameTime gameTime) 165 | { 166 | bloom.BeginDraw(); 167 | GraphicsDevice.Clear(Globals.COLOR_BACKGROUND); 168 | 169 | for (int i = 0; i < screens.Count; i++) 170 | { 171 | if (screens[i] == null) 172 | continue; 173 | 174 | //Draw 3D things. 175 | screens[i].Draw3D(gameTime); 176 | 177 | //Draw 2D things. 178 | spriteBatch.Begin(); 179 | screens[i].Draw2D(gameTime); 180 | spriteBatch.End(); 181 | graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default; 182 | } 183 | 184 | graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default; 185 | 186 | base.Draw(gameTime); 187 | } 188 | 189 | public void ResetBloom() 190 | { 191 | Components.Remove(bloom); 192 | bloom.Dispose(); 193 | bloom = new BloomComponent(this); 194 | bloom.Settings = BloomSettings.PresetSettings[6]; 195 | Components.Add(bloom); 196 | } 197 | 198 | //Delete all screens from the stack. 199 | public void ExitAllScreens() 200 | { 201 | screens.Clear(); 202 | } 203 | 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /fna_starterkit/fna_starterkit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {B501204A-60C2-444C-AB9C-87B1374EE9FE} 9 | WinExe 10 | Properties 11 | frogtalk 12 | tallbagel2 13 | v4.5 14 | 15 | 16 | 512 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | false 30 | false 31 | true 32 | 33 | 34 | x86 35 | true 36 | full 37 | false 38 | bin\Debug\ 39 | TRACE;DEBUG 40 | prompt 41 | 4 42 | false 43 | true 44 | 45 | 46 | x86 47 | pdbonly 48 | true 49 | bin\Release\ 50 | TRACE 51 | prompt 52 | 4 53 | false 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | bin\x86\Release OSX Linux\ 64 | TRACE 65 | true 66 | pdbonly 67 | x86 68 | prompt 69 | MinimumRecommendedRules.ruleset 70 | 71 | 72 | bin\x86\Release Windows\ 73 | TRACE;WINDOWS 74 | true 75 | pdbonly 76 | x86 77 | prompt 78 | MinimumRecommendedRules.ruleset 79 | 80 | 81 | 82 | .\FNA.dll 83 | 84 | 85 | .\Newtonsoft.Json.dll 86 | 87 | 88 | True 89 | 90 | 91 | True 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | PreserveNewest 117 | 118 | 119 | PreserveNewest 120 | 121 | 122 | PreserveNewest 123 | 124 | 125 | PreserveNewest 126 | 127 | 128 | PreserveNewest 129 | 130 | 131 | PreserveNewest 132 | 133 | 134 | 135 | 136 | 137 | PreserveNewest 138 | 139 | 140 | PreserveNewest 141 | 142 | 143 | PreserveNewest 144 | 145 | 146 | PreserveNewest 147 | 148 | 149 | PreserveNewest 150 | 151 | 152 | PreserveNewest 153 | 154 | 155 | PreserveNewest 156 | 157 | 158 | PreserveNewest 159 | 160 | 161 | 162 | 163 | False 164 | Microsoft .NET Framework 4.5 %28x86 and x64%29 165 | true 166 | 167 | 168 | False 169 | .NET Framework 3.5 SP1 170 | false 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 186 | -------------------------------------------------------------------------------- /fna_starterkit/system/helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | 7 | namespace fna_starterkit 8 | { 9 | //A grab bag of helper functions. 10 | public static class Helpers 11 | { 12 | public static readonly float PI2 = (float)Math.PI * 2; 13 | 14 | public static float CubicEaseIn(float lerpValue) 15 | { 16 | return lerpValue * lerpValue * lerpValue; 17 | } 18 | 19 | public static float CubicEaseOut(float lerpValue) 20 | { 21 | float f = (lerpValue - 1); 22 | return f * f * f + 1; 23 | } 24 | 25 | public static float CubicSmoothStep(float lerpValue) 26 | { 27 | if (lerpValue < .5f) 28 | { 29 | return 4 * lerpValue * lerpValue * lerpValue; 30 | } 31 | else 32 | { 33 | float f = ((2 * lerpValue) - 2); 34 | return .5f * f * f * f + 1; 35 | } 36 | } 37 | 38 | public static void FatalPopup(string bodyText, params string[] args) 39 | { 40 | ErrorPopup(bodyText + "\n\nEXITING NOW.", args); 41 | Environment.Exit(0); 42 | } 43 | 44 | public static void ErrorPopup(string bodyText, params string[] args) 45 | { 46 | SDL2.SDL.SDL_ShowSimpleMessageBox( 47 | SDL2.SDL.SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR, 48 | "ERROR!", 49 | string.Format(bodyText, args), 50 | IntPtr.Zero 51 | ); 52 | } 53 | 54 | public static float PopLerp(float minSize, float maxSize, float normalSize, float transition) 55 | { 56 | if (transition >= 1) 57 | return normalSize; 58 | 59 | if (transition <= 0) 60 | return minSize; 61 | 62 | float popPoint = 0.6f; 63 | float popRemnant = 0.4f; 64 | 65 | if (transition < popPoint) 66 | { 67 | transition /= popPoint; 68 | return MathHelper.Lerp(minSize, maxSize, transition); 69 | } 70 | 71 | transition -= popPoint; 72 | transition /= popRemnant; 73 | 74 | return MathHelper.Lerp(maxSize, normalSize, transition); 75 | } 76 | 77 | 78 | public static float Pulse(GameTime gameTime, float amount, float pulseSpeed) 79 | { 80 | return (float)(amount * Math.Sin(gameTime.TotalGameTime.TotalSeconds * pulseSpeed)); 81 | } 82 | 83 | public static string WordWrap(string text, float maxLineWidth, SpriteFont textFont) 84 | { 85 | string[] words = text.Split(' '); 86 | string workString = string.Empty; 87 | float currentLineWidth = 0; 88 | float spaceWidth = textFont.MeasureString(" ").X; 89 | 90 | foreach (string word in words) 91 | { 92 | Vector2 size = textFont.MeasureString(word); 93 | 94 | if (word.Contains("\n")) 95 | { 96 | workString += (word + " "); 97 | currentLineWidth = size.X + spaceWidth; 98 | } 99 | else if (currentLineWidth + size.X < maxLineWidth) 100 | { 101 | workString += (word + " "); 102 | currentLineWidth += size.X + spaceWidth; 103 | } 104 | else 105 | { 106 | //do a line break. start a new line. 107 | workString += "\n" + word + " "; 108 | currentLineWidth = size.X + spaceWidth; 109 | } 110 | } 111 | 112 | return workString; 113 | } 114 | 115 | public static Vector2 GetAngledVector(float distance, float angle) 116 | { 117 | Vector2 basePos = new Vector2(0, 0); 118 | basePos.Y += (float)Math.Sin(angle) * distance; 119 | basePos.X += (float)Math.Cos(angle) * distance; 120 | 121 | return basePos; 122 | } 123 | 124 | public static float GetVectorAngle(Vector2 position, Vector2 targetPosition) 125 | { 126 | Vector2 direction = targetPosition - position; 127 | 128 | float adjacent = direction.X; 129 | float opposite = direction.Y; 130 | return (float)System.Math.Atan2(opposite, adjacent); 131 | } 132 | 133 | public static float GetAngleBetweenTwoV3(Vector3 v1, Vector3 v2) 134 | { 135 | v1.Normalize(); 136 | v2.Normalize(); 137 | double Angle = (float)Math.Acos(Vector3.Dot(v1, v2)); 138 | return (float)Angle; 139 | } 140 | 141 | public static float GetPitchBetweenTwoV3(Vector3 v1, Vector3 v2) 142 | { 143 | Vector3 dir = v2 - v1; 144 | 145 | float adjusted = (float)Math.Sqrt(Math.Pow(dir.X, 2) + Math.Pow(dir.Z, 2)); 146 | return (float)Math.Atan2(adjusted, dir.Y); 147 | 148 | } 149 | 150 | public static float GetDot(Vector3 origin, Vector3 target, Vector3 originFacing) 151 | { 152 | Vector3 dir = Vector3.Normalize(target - origin); 153 | float frontDot = Vector3.Dot(originFacing, dir); 154 | 155 | return frontDot; 156 | } 157 | 158 | public static float RadiansDistance(float a0, float a1) 159 | { 160 | float max = (float)Math.PI * 2f; 161 | float da = (a1 - a0) % max; 162 | return 2f * (da % max) - da; 163 | } 164 | 165 | public static float LerpRadians(float a0, float a1, float alpha) 166 | { 167 | var distance = RadiansDistance(a0, a1); 168 | return a0 + distance * alpha; 169 | } 170 | 171 | public static float RadiansBetween(float x1, float y1, float x2, float y2, bool wrap) 172 | { 173 | float deltaY = y2 - y1; 174 | float deltaX = x2 - x1; 175 | var ret = (float)Math.Atan2(deltaY, deltaX); 176 | if (wrap) { while (ret < 0) ret += PI2; } 177 | return ret; 178 | } 179 | 180 | //Find where a ray intersects with a flat plane. 181 | public static Vector3? GetRayPlaneIntersectionPoint(Ray ray, Plane plane) 182 | { 183 | float? distance = ray.Intersects(plane); 184 | 185 | if (distance.HasValue) 186 | { 187 | return ray.Position + ray.Direction * distance.Value; 188 | } 189 | 190 | return null; 191 | } 192 | 193 | public static bool WriteTextFile(string stringArray, string fullPath) 194 | { 195 | try 196 | { 197 | using (StreamWriter writer = new StreamWriter(fullPath)) 198 | { 199 | writer.Write(stringArray); 200 | } 201 | 202 | return true; 203 | } 204 | catch (Exception e) 205 | { 206 | Helpers.ErrorPopup("Error writing text file. ({0})", e.Message); 207 | } 208 | 209 | return false; 210 | } 211 | 212 | public static string GetFileContents(string filepath) 213 | { 214 | string output = string.Empty; 215 | 216 | try 217 | { 218 | using (FileStream stream = File.Open(filepath, FileMode.Open, FileAccess.Read)) 219 | { 220 | using (StreamReader reader = new StreamReader(stream)) 221 | { 222 | output = reader.ReadToEnd(); //dump file contents into a string. 223 | } 224 | } 225 | } 226 | catch (Exception e) 227 | { 228 | Helpers.ErrorPopup("Error reading text file. ({0})", e.Message); 229 | return string.Empty; 230 | } 231 | 232 | return output; 233 | } 234 | 235 | public static Vector3 GetForwardVector(Quaternion quaternion) 236 | { 237 | Quaternion temporaryQuaternion = quaternion; 238 | temporaryQuaternion.Conjugate(); 239 | return Vector3.Transform(Vector3.Forward, temporaryQuaternion); 240 | } 241 | 242 | public static Matrix CreateLookMatrix(Vector3 startPoint, Vector3 targetPoint) 243 | { 244 | Matrix matrix = Matrix.CreateLookAt(startPoint, targetPoint, Vector3.Up); 245 | float yaw = (float)Math.Atan2(matrix.M13, matrix.M33); 246 | float pitch = (float)Math.Asin(-matrix.M23); 247 | float roll = (float)Math.Atan2(matrix.M21, matrix.M22); 248 | 249 | return Matrix.CreateFromYawPitchRoll(yaw, pitch, roll); 250 | } 251 | 252 | 253 | 254 | // --- end of file --- 255 | } 256 | } -------------------------------------------------------------------------------- /fna_starterkit/game/optionspage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Microsoft.Xna.Framework; 5 | using Microsoft.Xna.Framework.Graphics; 6 | using Microsoft.Xna.Framework.Input; 7 | using Microsoft.Xna.Framework.Audio; 8 | 9 | namespace fna_starterkit 10 | { 11 | public class OptionsPage : Screen 12 | { 13 | const int MARGIN_TOP = 100; 14 | const int MARGIN_LEFT = 50; 15 | 16 | const int RESOLUTION_COOLDOWNTIME = 300; 17 | 18 | Button[] buttons; 19 | Button[] resolutionButtons; 20 | 21 | Point desktopResolution; 22 | 23 | int resolutionCooldown; 24 | 25 | Button volumeButton; 26 | 27 | public OptionsPage() 28 | { 29 | this.transitionOffTime = 100; 30 | this.transitionOnTime = 300; 31 | Globals.screenManager.IsMouseVisible = true; 32 | 33 | volumeButton = new Button("Sound volume: ????", HitButton_Volume); 34 | 35 | buttons = new Button[] 36 | { 37 | new Button("Fullscreen toggle", HitButton_Fullscreen), 38 | volumeButton, 39 | new Button("Done", HitButton_Resume) 40 | }; 41 | 42 | int buttonStartY = MARGIN_TOP; 43 | for (int i = 0; i < buttons.Length; i++) 44 | { 45 | buttons[i].SetPosition(new Vector2(MARGIN_LEFT, buttonStartY)); 46 | buttonStartY += 70; 47 | } 48 | 49 | UpdateVolumeButtonText(); 50 | 51 | //Create resolution buttons. 52 | resolutionCooldown = RESOLUTION_COOLDOWNTIME; 53 | Reinitialize(); 54 | } 55 | 56 | public override void Reinitialize() 57 | { 58 | if (resolutionCooldown < RESOLUTION_COOLDOWNTIME) //Add a cooldown to resolution changes, to prevent misclicks or doubleclicks from causing multiple resolution changes. 59 | return; 60 | 61 | resolutionCooldown = 0; 62 | 63 | //Create all the resolution buttons. 64 | List