using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Media; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace LunaLightXMG { public class LunaLightGame : Game { // Class Objects private Player player; private PlayerInput playerInput; private List enemies; private int numOfEnemies; private GraphicsDeviceManager graphics; private Camera2D camera2D; private SpriteBatch spriteBatch; // Native retro scale private int retroWidth = 320; private int retroHeight = 180; // Test Render Target Handler private RenderHandler renderHandler; bool resizing; // Test sprites - eventually handle in a sprite manager? private Texture2D platformTexture; private Texture2D sinkArea; // Test platforms private Platform[] platforms; private int numOfPlatforms; // Music private SoundEffect sinkBeats; private SoundEffectInstance backgroundMusicInstance; // Debugging private SpriteFont debugFont; private Texture2D debugGrid; // Utility private static Random random; public LunaLightGame() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; IsMouseVisible = true; Window.ClientSizeChanged += OnClientSizeChanged; Window.AllowUserResizing = true; IsMouseVisible = true; // Test player input and movement with abstracted player class Vector2 initPlayerPosition = new Vector2(163, 0); player = new Player(initPlayerPosition); playerInput = new PlayerInput(); enemies = new List(); random = new Random(42); // Init number of platforms / enemies numOfPlatforms = 4; numOfEnemies = 10; } protected override void Initialize() { // Set initial window size graphics.PreferredBackBufferWidth = 1920; graphics.PreferredBackBufferHeight = 1080; graphics.ApplyChanges(); playerInput.HasControl = true; // May need to find a new home for this base.Initialize(); // Initialize camera camera2D = new Camera2D(retroWidth, retroHeight); // camera test - set level bounds camera2D.SetLevelBounds(new Rectangle(0,0,480,270)); // Testing - default 320x180 renderHandler.CalculateRenderDestination(); // Play music // PlayBackgroundMusic(sinkBeats); // Generate random platforms - test this idea out... platforms = PlatformGenerator.CreatePlatforms(numOfPlatforms); } // Testing camera and render target handler ------------------------ private void TestCameraWhilePlaying() { KeyboardState keyboardState = Keyboard.GetState(); var KeyK = keyboardState.IsKeyDown(Keys.K); var KeyL = keyboardState.IsKeyDown(Keys.L); var KeyB = keyboardState.IsKeyDown(Keys.B); var KeyN = keyboardState.IsKeyDown(Keys.N); var KeyM = keyboardState.IsKeyDown(Keys.M); if (KeyK) { camera2D.Rotation -= 0.01f; } if (KeyL) { camera2D.Rotation += 0.01f; } if (KeyB) { renderHandler.ZoomIn(); } if (KeyN) { renderHandler.ZoomNormalize(); } if (KeyM) { renderHandler.ZoomOut(); } } // --------------------------------------- protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); // Test platform platformTexture = Content.Load("platform"); sinkArea = Content.Load("Sink area"); // Music sinkBeats = Content.Load("music/sinkBeats"); // load player sprite player.LoadContent(Content); // player sprite is now handled in player.cs // Spawn 10 enemies at the start of the level enemies = SpawnEnemies(numOfEnemies); // Test Render Target Handler renderHandler = new RenderHandler(GraphicsDevice, spriteBatch, retroWidth, retroHeight); // Debugging debugFont = Content.Load("fonts/debugFont"); debugGrid = Content.Load("debugGrid"); } protected override void Update(GameTime gameTime) { // Temporary quit game - eventually handle in a pause menu class if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); // Check for game reset if (Keyboard.GetState().IsKeyDown(Keys.R)) ResetGame(); // Test player input and movement with abstracted player class playerInput.Update(); player.Update(gameTime, playerInput, platforms); foreach (var enemy in enemies) { enemy.Update(gameTime, player, platforms); } // test render handler zoom renderHandler.UpdateZoom(); // Update camera position camera2D.Follow(player.position); // camera testing TestCameraWhilePlaying(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); // // Test Render Target Handler - Draw sprites to the render (target renderHandler.BeginRenderTarget(camera2D.GetViewMatrix()); // Test draw tiles foreach (var platform in platforms) { platform.Draw(spriteBatch, platformTexture); // Assuming all tiles use the same texture for now } // Test player input and movement with abstracted player class player.Draw(spriteBatch); foreach (var enemy in enemies) { enemy.Draw(spriteBatch); } renderHandler.EndRenderTarget(); renderHandler.DrawRenderTarget(); // Debugging DrawDebugInfo(); base.Draw(gameTime); } #region Methods private List SpawnEnemies(int numberOfEnemies) { List enemies = new List(); for (int i = 0; i < numberOfEnemies; i++) { Vector2 spawnPosition = new Vector2(16 + i * 3, -16); Enemy enemy = new Enemy(spawnPosition, GetRandomValueBetween1And3()); enemy.LoadContent(Content); enemies.Add(enemy); } return enemies; } private void PlayBackgroundMusic(SoundEffect backgroundMusic) { if (backgroundMusicInstance == null || backgroundMusicInstance.State != SoundState.Playing) { if (backgroundMusicInstance != null) { backgroundMusicInstance.Dispose(); } backgroundMusicInstance = backgroundMusic.CreateInstance(); backgroundMusicInstance.IsLooped = true; backgroundMusicInstance.Play(); } } private void OnClientSizeChanged(object sender, EventArgs eventArgs) { if (!resizing && Window.ClientBounds.Width > 0 && Window.ClientBounds.Height > 0) { resizing = true; renderHandler.CalculateRenderDestination(); resizing = false; } } private void DrawDebugInfo() { spriteBatch.Begin(); // Draw debug messages spriteBatch.DrawString(debugFont, $"VSP: {player.vsp}", new Vector2(10, 10), Color.White); spriteBatch.DrawString(debugFont, $"Grounded: {player.grounded}", new Vector2(10, 30), Color.White); spriteBatch.DrawString(debugFont, $"Walled: {player.walled}", new Vector2(10, 50), Color.White); spriteBatch.DrawString(debugFont, $"Position: {player.position}", new Vector2(10, 70), Color.White); spriteBatch.DrawString(debugFont, $"Camera Position: {camera2D.Position}", new Vector2(10, 90), Color.White); spriteBatch.DrawString(debugFont, $"Camera Rotation: {camera2D.Rotation}", new Vector2(10, 110), Color.White); spriteBatch.DrawString(debugFont, $"Render Target Zoom: {renderHandler.ZoomLevel}", new Vector2(10, 130), Color.White); spriteBatch.DrawString(debugFont, $"Camera Rotation Control - Rotate left: K, Rotate right: L", new Vector2(10, 190), Color.White); spriteBatch.DrawString(debugFont, $"Render Target Zoom Control - Zoom in: B, Zoom normal: N, Zoom out: M", new Vector2(10, 210), Color.White); spriteBatch.End(); } public static float GetRandomValueBetween1And3() { return (float)(1 + 2 * random.NextDouble()); } private void ResetGame() { // reset cam camera2D.Rotation = 0; camera2D.Zoom = 1f; // reset render target zoom renderHandler.ZoomNormalize(); // Reset player position player.Reset(new Vector2(163, 0)); // Clear and respawn enemies enemies.Clear(); enemies = SpawnEnemies(numOfEnemies); // Regenerate platforms platforms = PlatformGenerator.CreatePlatforms(numOfPlatforms); } #endregion } }