/// <summary> /// This method is used by MonoGame Android to adjust the game's drawn to area to fill /// as much of the screen as possible whilst retaining the aspect ratio inferred from /// aspectRatio = (PreferredBackBufferWidth / PreferredBackBufferHeight) /// /// NOTE: this is a hack that should be removed if proper back buffer to screen scaling /// is implemented. To disable it's effect, in the game's constructor use: /// /// graphics.IsFullScreen = true; /// graphics.PreferredBackBufferHeight = Window.ClientBounds.Height; /// graphics.PreferredBackBufferWidth = Window.ClientBounds.Width; /// /// </summary> internal void ResetClientBounds() { #if ANDROID float preferredAspectRatio = (float)PreferredBackBufferWidth / (float)PreferredBackBufferHeight; float displayAspectRatio = (float)GraphicsDevice.DisplayMode.Width / (float)GraphicsDevice.DisplayMode.Height; float adjustedAspectRatio = preferredAspectRatio; if ((preferredAspectRatio > 1.0f && displayAspectRatio < 1.0f) || (preferredAspectRatio < 1.0f && displayAspectRatio > 1.0f)) { // Invert preferred aspect ratio if it's orientation differs from the display mode orientation. // This occurs when user sets preferredBackBufferWidth/Height and also allows multiple supported orientations adjustedAspectRatio = 1.0f / preferredAspectRatio; } const float EPSILON = 0.00001f; var newClientBounds = new Rectangle(); if (displayAspectRatio > (adjustedAspectRatio + EPSILON)) { // Fill the entire height and reduce the width to keep aspect ratio newClientBounds.Height = _graphicsDevice.DisplayMode.Height; newClientBounds.Width = (int)(newClientBounds.Height * adjustedAspectRatio); newClientBounds.X = (_graphicsDevice.DisplayMode.Width - newClientBounds.Width) / 2; } else if (displayAspectRatio < (adjustedAspectRatio - EPSILON)) { // Fill the entire width and reduce the height to keep aspect ratio newClientBounds.Width = _graphicsDevice.DisplayMode.Width; newClientBounds.Height = (int)(newClientBounds.Width / adjustedAspectRatio); newClientBounds.Y = (_graphicsDevice.DisplayMode.Height - newClientBounds.Height) / 2; } else { // Set the ClientBounds to match the DisplayMode newClientBounds.Width = GraphicsDevice.DisplayMode.Width; newClientBounds.Height = GraphicsDevice.DisplayMode.Height; } // Ensure buffer size is reported correctly _graphicsDevice.PresentationParameters.BackBufferWidth = newClientBounds.Width; _graphicsDevice.PresentationParameters.BackBufferHeight = newClientBounds.Height; // Set the veiwport so the (potentially) resized client bounds are drawn in the middle of the screen _graphicsDevice.Viewport = new Viewport(newClientBounds.X, -newClientBounds.Y, newClientBounds.Width, newClientBounds.Height); ((AndroidGameWindow)_game.Window).ChangeClientBounds(newClientBounds); // Touch panel needs latest buffer size for scaling TouchPanel.DisplayWidth = newClientBounds.Width; TouchPanel.DisplayHeight = newClientBounds.Height; Android.Util.Log.Debug("MonoGame", "GraphicsDeviceManager.ResetClientBounds: newClientBounds=" + newClientBounds.ToString()); #endif }
/// <summary> /// Makes a game window of a specified size. /// </summary> /// <param name="g"></param> /// <param name="r"></param> public static void MakeWindow(GraphicsDeviceManager g, Rectangle r) { if ((r.Width > GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width) || (r.Height > GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height)) return; g.PreferredBackBufferWidth = r.Width; g.PreferredBackBufferHeight = r.Height; g.IsFullScreen = false; g.ApplyChanges(); Log.Write("Created window with params " + r.ToString(), Alert.Info); }
public void ReplaceRenderStates(SpriteSortMode sortMode, BlendState blendState, SamplerState samplerState, DepthStencilState depthStencilState, RasterizerState rasterizerState, Effect effect, Matrix transformMatrix, Rectangle scissorRectangle) { bool isNewRender = currentParameters.HasValue == false; var newParameters = new BeginParameters(); newParameters.ChangeRecord = new List<StateChangeInfo>(); newParameters.SortMode = sortMode; newParameters.BlendState = blendState; newParameters.SamplerState = samplerState; newParameters.DepthStencilState = depthStencilState; newParameters.RasterizerState = rasterizerState; newParameters.Effect = effect; newParameters.TransformMatrix = transformMatrix; try { newParameters.ScissorRectangle = scissorRectangle; } catch(Exception e) { throw new Exception("Could not set scissor rectangle to:" + scissorRectangle.ToString(), e); } if (currentParameters != null) { beginParametersUsedThisFrame.Add(currentParameters.Value); } currentParameters = newParameters; if (beginEndState == SpriteBatchBeginEndState.Began) { SpriteBatch.End(); } try { SpriteBatch.GraphicsDevice.ScissorRectangle = scissorRectangle; } catch(Exception e) { throw new Exception("Error trying to set scissor rectangle:" + scissorRectangle.ToString()); } beginEndState = SpriteBatchBeginEndState.Began; SpriteBatch.Begin(sortMode, blendState, samplerState, depthStencilState, rasterizerState, effect, transformMatrix); }
private void SetRectangleInfo(Microsoft.Xna.Framework.Rectangle r) { textBox4.Text = r.Location.ToString(); textBox5.Text = r.ToString(); }
private static bool pixelPerfect(Texture2D t1, Rectangle r1, Texture2D t2, Rectangle r2) { //Found here: http://gamedev.stackexchange.com/questions/15191/is-there-a-good-way-to-get-pixel-perfect-collision-detection-in-xna Color[] bits1 = new Color[t1.Width * t1.Height]; Color[] bits2 = new Color[t2.Width * t2.Height]; t1.GetData(bits1); t2.GetData(bits2); //Intersection Bounds int x1 = Math.Max(r1.X, r2.X); int x2 = Math.Min(r1.Right, r2.Right); int y1 = Math.Max(r1.Y, r2.Y); int y2 = Math.Min(r1.Bottom, r2.Bottom); for (int y = y1; y < y2; y++) { for (int x = x1; x < x2; x++) { Color colorA = bits1[x - r1.X + (y - r1.Y) * t1.Width]; Color colorB = bits2[x - r2.X + (y - r2.Y) * t2.Width]; if (colorA.A == 255 && colorB.A == 255) { Debug.WriteLine("Collision Detected."); Debug.WriteLine("Texture 1 Information:"); Debug.WriteLine("Bounds: " + t1.Bounds.ToString()); Debug.WriteLine("Rect: " + r1.ToString()); Debug.WriteLine("Texture 2 Information:"); Debug.WriteLine("Bounds: " + t2.Bounds.ToString()); Debug.WriteLine("Rect: " + r2.ToString()); Debug.WriteLine(colorA.ToString() + " " + colorB.ToString()); return true; } } } return false; }
// Draw one of the squares at a grid coordinate. void DrawQuarterCircle(ISpriteBatch spriteBatch, TextureContent content, Rectangle rect, Vector2 gridOrigin, int beat, Color color, float filledness, int depth) { // we prefer beats to start at upper left, but left to this logic, they start at lower left // position of this measure Vector2 position = gridOrigin + new Vector2(((beat / 4) % 4) * rect.Width, (beat / 16) * rect.Height); Vector2 offset; switch (beat % 4) { case 0: offset = new Vector2(1, 1); break; case 1: offset = new Vector2(0, 1); break; case 2: offset = new Vector2(0, 0); break; case 3: offset = new Vector2(1, 0); break; default: offset = Vector2.Zero; break; // NOTREACHED } position += offset * new Vector2(rect.Width, rect.Height); Rectangle destRect = new Rectangle( rect.Left + (int)position.X, rect.Top + (int)position.Y, rect.Width, rect.Height); Spam.Graphics.WriteLine(new string(' ', depth * 4 + 4) + Label + ": beat " + beat + ", filledness " + filledness + ", destRect " + destRect.ToString()); // Use NonPremultiplied, as our sprite textures are not premultiplied spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied); Vector2 origin = new Vector2(0); // always draw a hollow quarter circle spriteBatch.Draw( content.QuarterHollowCircle, destRect, null, color, (float)((beat % 4 + 2) * Math.PI / 2), origin, SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically, 0); // now maybe draw a filled circle Vector4 v = color.ToVector4(); v *= filledness; color = new Color(v); spriteBatch.Draw( content.QuarterFilledCircle, destRect, null, color, (float)((beat % 4 + 2) * Math.PI / 2), origin, SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically, 0); spriteBatch.End(); }