using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using TibzGame.Core.Inputs; using TibzGame.Core.ScreenManager; using Johnmagotchi.GameContent.Objects; using System.Text.Json; using Johnmagotchi.GameContent.Objects.UI; using Johnmagotchi.Core.tools; namespace Johnmagotchi.Screen.BattleMapScreens { public abstract class BaseMapScreen : GameScreen { SpriteBatch SpriteBatch; protected BattleMap CurrentMap; public MapCursor MapCursor; public UnitDisplay UnitDisplay; protected int cursorIndexX; protected int cursorIndexY; protected int scrollOffsetX; protected int scrollOffsetY; public int CursorQuadrant; private readonly ulong CURSOR_HOLD_FRAMES = 25; private readonly int SCROLL_BOOST_TIME_FRAMES = 60; private readonly int CURSOR_SCROLL_NEXT_INC_FRAMES= 5; private readonly int SCROLL_TILES_FROM_EDGE_X = 3; private readonly int SCROLL_TILES_FROM_EDGE_Y = 2; private int scrollTimer ; // frames until click to next private int scrollTotalDuration; protected string tempSave; public bool ScreenScrollLock = false; private bool IsNewMap = true; public abstract void ChildInit(); public abstract void ChildUpdate(); public abstract void ChildDraw(); public BaseMapScreen(){ this.CurrentMap = new BattleMap(24,20); this.MapCursor = new MapCursor(); this.UnitDisplay = new UnitDisplay(); this.isDrawPriority = true; this.isUpdatePriority = true; saveCurrentMap(); } public BaseMapScreen(BattleMap existingMap){ this.CurrentMap = existingMap.GetClone(); this.MapCursor = new MapCursor(); this.UnitDisplay = new UnitDisplay(); this.isDrawPriority = true; this.isUpdatePriority = true; this.IsNewMap = false; } public override void Init() { scrollTimer =0; scrollTotalDuration =0; cursorIndexX = 2; cursorIndexY = 2; scrollOffsetX=0; scrollOffsetY=0; SpriteBatch = new SpriteBatch(screenManager.GraphicsDevice); this.MapCursor.Init(screenManager); this.UnitDisplay.Init(screenManager); if (this.IsNewMap) { this.CurrentMap.Init(screenManager); } else { this.CurrentMap.InitFromReload(ScreenManager); } ChildInit(); } public override void Destroy() { throw new NotImplementedException(); } public override void Draw() { // bool stopXScroll = false; //bool stopYScroll = false; if ((this.CurrentMap.width * MapTile.TILE_WIDTH_PX) < this.ScreenManager.GetScaledPixelScreenWidth()) { // center width scrollOffsetX = (this.ScreenManager.GetScaledPixelScreenWidth() - (this.CurrentMap.width * MapTile.TILE_WIDTH_PX))/2; // stopXScroll = true; } if ((this.CurrentMap.height * MapTile.TILE_HEIGHT_PX) < this.ScreenManager.GetScaledPixelScreenHeight()){ // center height scrollOffsetY = (this.ScreenManager.GetScaledPixelScreenHeight() - (this.CurrentMap.height * MapTile.TILE_HEIGHT_PX))/2; // stopYScroll = true; } this.CurrentMap.DrawMap(scrollOffsetX, scrollOffsetY);// should draw background //draw on top of background : //cursor this.MapCursor.Draw( (MapTile.TILE_WIDTH_PX *cursorIndexX) + scrollOffsetX , (MapTile.TILE_HEIGHT_PX * cursorIndexY) + scrollOffsetY); // units this.CurrentMap.DrawUnits(scrollOffsetX, scrollOffsetY);// should draw background // Call child draw classes ChildDraw(); // anthing that has priorty top layer should go here // ui overlay UnitDisplay.Draw(CursorQuadrant); } public override void Update() { // Updates UpdateCursorQuadrant(); // This doesnt need to be called every frame, but its easy. so. /// Keyboard / Controller controls if (! screenManager.inputs.isMouseMode) { if (screenManager.inputs.mouseInput.leftClick.isJustReleased) { TibzLog.Debug(" Changed To Mouse Controls"); screenManager.inputs.isMouseMode = true; } //Check Button Presses if (screenManager.inputs.editorInputs.navLeft.isJustPressed) { TickCursorLeft(); } if (screenManager.inputs.editorInputs.navRight.isJustPressed) { TickCursorRight(); } if (screenManager.inputs.editorInputs.navUp.isJustPressed) { TickCursorUp(); } if (screenManager.inputs.editorInputs.navDown.isJustPressed) { TickCursorDown(); } if (screenManager.inputs.editorInputs.saveButton.isJustPressed) { saveCurrentMap(); } if (screenManager.inputs.editorInputs.loadButton.isJustPressed) { loadCurrentMap(); } //Button Holds if (screenManager.inputs.editorInputs.navLeft.heldTime > CURSOR_HOLD_FRAMES) { IncrementScrollTimers(); if (scrollTimer > CURSOR_SCROLL_NEXT_INC_FRAMES) { scrollTimer = 0; TickCursorLeft(); } } if (screenManager.inputs.editorInputs.navRight.heldTime > CURSOR_HOLD_FRAMES) { IncrementScrollTimers(); if (scrollTimer > CURSOR_SCROLL_NEXT_INC_FRAMES) { scrollTimer = 0; TickCursorRight(); } } if (screenManager.inputs.editorInputs.navUp.heldTime > CURSOR_HOLD_FRAMES) { IncrementScrollTimers(); if (scrollTimer > CURSOR_SCROLL_NEXT_INC_FRAMES) { scrollTimer = 0; TickCursorUp(); } } if (screenManager.inputs.editorInputs.navDown.heldTime > CURSOR_HOLD_FRAMES) { IncrementScrollTimers(); if (scrollTimer > CURSOR_SCROLL_NEXT_INC_FRAMES) { scrollTimer = 0; TickCursorDown(); } } if (ScreenManager.inputs.editorInputs.navLeft.isJustReleased || // reset scroll timers on release ScreenManager.inputs.editorInputs.navRight.isJustReleased || ScreenManager.inputs.editorInputs.navUp.isJustReleased || ScreenManager.inputs.editorInputs.navDown.isJustReleased) { scrollTimer = 0; scrollTotalDuration = 0; } } else { if (screenManager.inputs.editorInputs.confirm.isJustPressed) { TibzLog.Debug(" Reverted to keyboard controls"); screenManager.inputs.isMouseMode = false; } UpdateCursorMouse(); if (screenManager.inputs.mouseInput.leftClick.isJustPressed) { screenManager.inputs.editorInputs.confirm.isJustPressed = true; } if (screenManager.inputs.mouseInput.rightClick.isJustPressed) { screenManager.inputs.editorInputs.cancel.isJustPressed = true; } } // update battle map CurrentMap.Update(); // update unit display UnitDisplay.Update( CurrentMap.getUnitAtLocation(cursorIndexX, cursorIndexY)); // End Update, call child ChildUpdate(); } protected virtual void TickCursorLeft() { if (cursorIndexX > 0) cursorIndexX --; else cursorIndexX = 0; // adjust screen after mouse movement tickLeftScroll(); } protected virtual void TickCursorRight() { if (cursorIndexX < CurrentMap.width -1) cursorIndexX ++; // zero indexed so -1 else cursorIndexX = CurrentMap.width -1; // adjust screen after mouse movement tickRightScroll(); } protected virtual void TickCursorUp() { if (cursorIndexY > 0) cursorIndexY --; else cursorIndexY = 0; // adjust screen after mouse movement tickUpScroll(); } protected virtual void TickCursorDown() { if (cursorIndexY < CurrentMap.height -1) cursorIndexY ++; // zero indexed so -1 else cursorIndexY = CurrentMap.height -1; // adjust screen after mouse movement tickDownScroll(); } private void IncrementScrollTimers() { scrollTimer++; scrollTotalDuration++; if (scrollTotalDuration > SCROLL_BOOST_TIME_FRAMES){ scrollTimer ++; // double the speed of scroll if held for over 70 frames } } protected void tickLeftScroll(){ if (ScreenScrollLock){ return; } int currentOffsetTilesX = - scrollOffsetX / MapTile.TILE_WIDTH_PX; // since the offset scrolling left is negative we need to invert this sign int currentOffsetTilesY = scrollOffsetY / MapTile.TILE_HEIGHT_PX; int totalWidthTiles = this.screenManager.GetScaledPixelScreenWidth() / MapTile.TILE_WIDTH_PX; int TilesFromLeftEdge = cursorIndexX - currentOffsetTilesX; System.Console.WriteLine("Scroll offset px: {0}", scrollOffsetX); if ( TilesFromLeftEdge < SCROLL_TILES_FROM_EDGE_X) { scrollOffsetX += MapTile.TILE_WIDTH_PX; // scroll left } if (scrollOffsetX >= 0 ) // scroll limit { scrollOffsetX = 0; } } protected void tickRightScroll(){ if (ScreenScrollLock){ return; } int currentOffsetTilesX = - scrollOffsetX / MapTile.TILE_WIDTH_PX; // invert sign here int currentOffsetTilesY = scrollOffsetY / MapTile.TILE_HEIGHT_PX; int totalWidthTiles = this.screenManager.GetScaledPixelScreenWidth() / MapTile.TILE_WIDTH_PX; int TilesFromLeftEdge = cursorIndexX - currentOffsetTilesX; System.Console.WriteLine("Scroll offset px: {0}", scrollOffsetX); System.Console.WriteLine("Scroll offset limit: {0}", -1* (CurrentMap.width * MapTile.TILE_WIDTH_PX - this.screenManager.GetScaledPixelScreenWidth())); if ( TilesFromLeftEdge >= totalWidthTiles - SCROLL_TILES_FROM_EDGE_X) { scrollOffsetX -= MapTile.TILE_WIDTH_PX; // scroll right } if (scrollOffsetX <= -1* (CurrentMap.width * MapTile.TILE_WIDTH_PX - this.screenManager.GetScaledPixelScreenWidth())) { scrollOffsetX = -1* (CurrentMap.width * MapTile.TILE_WIDTH_PX - this.screenManager.GetScaledPixelScreenWidth()); } } protected void tickUpScroll(){ if (ScreenScrollLock){ return; } int currentOffsetTilesY = - scrollOffsetY / MapTile.TILE_HEIGHT_PX; int totalHeightTiles = this.screenManager.GetScaledPixelScreenHeight() / MapTile.TILE_HEIGHT_PX; int tilesFromTop = cursorIndexY - currentOffsetTilesY; //System.Console.WriteLine("Scroll offset px: {0}", scrollOffsetY); if ( tilesFromTop < SCROLL_TILES_FROM_EDGE_Y){ scrollOffsetY += MapTile.TILE_HEIGHT_PX; // scroll up } if (scrollOffsetY >= 0 ) { scrollOffsetY = 0; } } protected void tickDownScroll(){ if (ScreenScrollLock){ return; } int currentOffsetTilesY = - scrollOffsetY / MapTile.TILE_HEIGHT_PX; int totalHeightTiles = this.screenManager.GetScaledPixelScreenHeight() / MapTile.TILE_HEIGHT_PX; int tilesFromTop = cursorIndexY - currentOffsetTilesY; // System.Console.WriteLine("Scroll offset px: {0}", scrollOffsetY); if ( tilesFromTop > totalHeightTiles - SCROLL_TILES_FROM_EDGE_Y){ scrollOffsetY -= MapTile.TILE_HEIGHT_PX; // scroll up } if (scrollOffsetY <= -1* (CurrentMap.height * MapTile.TILE_HEIGHT_PX - this.screenManager.GetScaledPixelScreenHeight())) { scrollOffsetY = -1* (CurrentMap.height * MapTile.TILE_HEIGHT_PX - this.screenManager.GetScaledPixelScreenHeight()); } } public string saveCurrentMap(){ System.Console.WriteLine("Saving...."); CurrentMap.SerializeAll(); tempSave = JsonSerializer.Serialize(CurrentMap); // System.Console.WriteLine("save json: {0}", tempSave); return tempSave; } public void loadCurrentMap(){ if (tempSave.Length > 10){ System.Console.WriteLine("Loading...."); this.CurrentMap = JsonSerializer.Deserialize(tempSave); this.CurrentMap.InitFromReload(screenManager); this.CurrentMap.deserializeMapTiles(); this.CurrentMap.DeserializeUnitData(); } else{ System.Console.WriteLine("valid save state not found"); } } private void UpdateCursorQuadrant() { if ((MapTile.TILE_HEIGHT_PX * cursorIndexY) + scrollOffsetY < ScreenManager.GetScaledPixelScreenHeight() / 2) // top { if ((MapTile.TILE_WIDTH_PX * cursorIndexX) + scrollOffsetX > ScreenManager.GetScaledPixelScreenWidth() / 2) // right { CursorQuadrant = 1; } else // left { CursorQuadrant = 2; } } else //bottom { if ((MapTile.TILE_WIDTH_PX * cursorIndexX) + scrollOffsetX < ScreenManager.GetScaledPixelScreenWidth() / 2) // left { CursorQuadrant = 3; } else // right { CursorQuadrant = 4; } } } private void UpdateCursorMouse() { int x = screenManager.inputs.mouseInput.x; int y = screenManager.inputs.mouseInput.y; //TibzLog.Debug("Mouse Pos: x - "+ x + " , y - " + y ); int xSelectedTileIndex = x * ScreenManager.BASE_ZOOM_LEVEL / ( MapTile.TILE_WIDTH_PX * 2 ); int ySelectedTileIndex = y * ScreenManager.BASE_ZOOM_LEVEL / (MapTile.TILE_HEIGHT_PX * 2 ); cursorIndexX = xSelectedTileIndex; cursorIndexY = ySelectedTileIndex; } } }