Created
April 3, 2022 06:41
-
-
Save jmcd/6e664910b260430961dc80e8bd9e2511 to your computer and use it in GitHub Desktop.
Bouncing balls in MonoGame
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace MonoGameCross_PlatformDesktopApplication1 | |
{ | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Input; | |
public static class Program | |
{ | |
[STAThread] | |
private static void Main() | |
{ | |
using var game = new Game1(); | |
game.Run(); | |
} | |
} | |
internal class Ball | |
{ | |
public Vector2 Position = Vector2.Zero; | |
public Texture2D? Texture; | |
public Vector2 Velocity = Vector2.Zero; | |
public void Reposition(float elapsedTotalSeconds) | |
{ | |
Position.X += Velocity.X * elapsedTotalSeconds; | |
Position.Y += Velocity.Y * elapsedTotalSeconds; | |
} | |
public void BounceInside(Rectangle bounds) | |
{ | |
if (Texture is null) { return; } | |
float o; | |
if (Position.X < 0 && Velocity.X < 0) | |
{ | |
Position.X *= -1; | |
Velocity.X *= -1; | |
} | |
else if ((o = Position.X - (bounds.Width - Texture.Width)) > 0 && Velocity.X > 0) | |
{ | |
Position.X -= o; | |
Velocity.X *= -1; | |
} | |
if (Position.Y < 0 && Velocity.Y < 0) | |
{ | |
Position.Y *= -1; | |
Velocity.Y *= -1; | |
} | |
else if ((o = Position.Y - (bounds.Height - Texture.Width)) > 0 && Velocity.Y > 0) | |
{ | |
Position.Y -= o; | |
Velocity.Y *= -1; | |
} | |
} | |
} | |
public class Game1 : Game | |
{ | |
private GraphicsDeviceManager _graphics; | |
private SpriteBatch? _spriteBatch; | |
private ICollection<Ball>? balls; | |
public Game1() | |
{ | |
_graphics = new(this); | |
Content.RootDirectory = "Content"; | |
IsMouseVisible = true; | |
} | |
protected override void Initialize() | |
{ | |
// TODO: Add your initialization logic here | |
base.Initialize(); | |
} | |
protected override void LoadContent() | |
{ | |
_spriteBatch = new(GraphicsDevice); | |
var random = Random.Shared; | |
// TODO: use this.Content to load your game content here | |
//var ballTexture = Content.Load<Texture2D>("ball"); | |
var ballList = new List<Ball>(); | |
for (var i = 0; i < 30; i++) | |
{ | |
var texture = TextureFactory.CreateCircle(GraphicsDevice, random.Next(10, 40), random.Next(Colors.Values)); | |
ballList.Add(new() | |
{ | |
Texture = texture, | |
Velocity = new(random.Next(800), random.Next(800)), | |
Position = new(random.Next(GraphicsDevice.Viewport.Width - texture.Width), random.Next(GraphicsDevice.Viewport.Height - texture.Height)), | |
}); | |
} | |
balls = ballList; | |
} | |
protected override void Update(GameTime gameTime) | |
{ | |
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) | |
{ | |
Exit(); | |
} | |
// TODO: Add your update logic here | |
if (balls is not null) | |
{ | |
foreach (var ball in balls) | |
{ | |
ball.Reposition((float)gameTime.ElapsedGameTime.TotalSeconds); | |
ball.BounceInside(_graphics.GraphicsDevice.Viewport.Bounds); | |
} | |
} | |
base.Update(gameTime); | |
} | |
protected override void Draw(GameTime gameTime) | |
{ | |
GraphicsDevice.Clear(Color.CornflowerBlue); | |
// TODO: Add your drawing code here | |
if (_spriteBatch is not null) | |
{ | |
_spriteBatch.Begin(); | |
if (balls is not null) | |
{ | |
foreach (var ball in balls) | |
{ | |
_spriteBatch.Draw(ball.Texture, ball.Position, Color.White); | |
} | |
} | |
_spriteBatch.End(); | |
} | |
base.Draw(gameTime); | |
} | |
} | |
public static class TextureFactory | |
{ | |
public static Texture2D CreateCircle(GraphicsDevice graphicsDevice, int radius, Color color) | |
{ | |
var diameter = radius * 2; | |
var texture = new Texture2D(graphicsDevice, diameter, diameter); | |
texture.SetData(CreateCircleData(radius, color)); | |
return texture; | |
} | |
private static Color[] CreateCircleData(int radius, Color color) | |
{ | |
var diameter = radius * 2; | |
var radiusSquared = radius * radius; | |
var colorData = new Color[diameter * diameter]; | |
for (var x = 0; x < diameter; x++) | |
{ | |
for (var y = 0; y < diameter; y++) | |
{ | |
var index = x * diameter + y; | |
var pos = new Vector2(x - radius, y - radius); | |
colorData[index] = pos.LengthSquared() <= radiusSquared ? color : Color.Transparent; | |
} | |
} | |
return colorData; | |
} | |
} | |
public static class RandomExn | |
{ | |
public static T Next<T>(this Random random, IList<T> values) => values[random.Next(values.Count)]; | |
} | |
public static class Colors | |
{ | |
public static readonly Color[] Values = | |
{ | |
Color.Transparent, | |
Color.AliceBlue, | |
Color.AntiqueWhite, | |
Color.Aqua, | |
Color.Aquamarine, | |
Color.Azure, | |
Color.Beige, | |
Color.Bisque, | |
Color.Black, | |
Color.BlanchedAlmond, | |
Color.Blue, | |
Color.BlueViolet, | |
Color.Brown, | |
Color.BurlyWood, | |
Color.CadetBlue, | |
Color.Chartreuse, | |
Color.Chocolate, | |
Color.Coral, | |
Color.CornflowerBlue, | |
Color.Cornsilk, | |
Color.Crimson, | |
Color.Cyan, | |
Color.DarkBlue, | |
Color.DarkCyan, | |
Color.DarkGoldenrod, | |
Color.DarkGray, | |
Color.DarkGreen, | |
Color.DarkKhaki, | |
Color.DarkMagenta, | |
Color.DarkOliveGreen, | |
Color.DarkOrange, | |
Color.DarkOrchid, | |
Color.DarkRed, | |
Color.DarkSalmon, | |
Color.DarkSeaGreen, | |
Color.DarkSlateBlue, | |
Color.DarkSlateGray, | |
Color.DarkTurquoise, | |
Color.DarkViolet, | |
Color.DeepPink, | |
Color.DeepSkyBlue, | |
Color.DimGray, | |
Color.DodgerBlue, | |
Color.Firebrick, | |
Color.FloralWhite, | |
Color.ForestGreen, | |
Color.Fuchsia, | |
Color.Gainsboro, | |
Color.GhostWhite, | |
Color.Gold, | |
Color.Goldenrod, | |
Color.Gray, | |
Color.Green, | |
Color.GreenYellow, | |
Color.Honeydew, | |
Color.HotPink, | |
Color.IndianRed, | |
Color.Indigo, | |
Color.Ivory, | |
Color.Khaki, | |
Color.Lavender, | |
Color.LavenderBlush, | |
Color.LawnGreen, | |
Color.LemonChiffon, | |
Color.LightBlue, | |
Color.LightCoral, | |
Color.LightCyan, | |
Color.LightGoldenrodYellow, | |
Color.LightGray, | |
Color.LightGreen, | |
Color.LightPink, | |
Color.LightSalmon, | |
Color.LightSeaGreen, | |
Color.LightSkyBlue, | |
Color.LightSlateGray, | |
Color.LightSteelBlue, | |
Color.LightYellow, | |
Color.Lime, | |
Color.LimeGreen, | |
Color.Linen, | |
Color.Magenta, | |
Color.Maroon, | |
Color.MediumAquamarine, | |
Color.MediumBlue, | |
Color.MediumOrchid, | |
Color.MediumPurple, | |
Color.MediumSeaGreen, | |
Color.MediumSlateBlue, | |
Color.MediumSpringGreen, | |
Color.MediumTurquoise, | |
Color.MediumVioletRed, | |
Color.MidnightBlue, | |
Color.MintCream, | |
Color.MistyRose, | |
Color.Moccasin, | |
Color.MonoGameOrange, | |
Color.NavajoWhite, | |
Color.Navy, | |
Color.OldLace, | |
Color.Olive, | |
Color.OliveDrab, | |
Color.Orange, | |
Color.OrangeRed, | |
Color.Orchid, | |
Color.PaleGoldenrod, | |
Color.PaleGreen, | |
Color.PaleTurquoise, | |
Color.PaleVioletRed, | |
Color.PapayaWhip, | |
Color.PeachPuff, | |
Color.Peru, | |
Color.Pink, | |
Color.Plum, | |
Color.PowderBlue, | |
Color.Purple, | |
Color.Red, | |
Color.RosyBrown, | |
Color.RoyalBlue, | |
Color.SaddleBrown, | |
Color.Salmon, | |
Color.SandyBrown, | |
Color.SeaGreen, | |
Color.SeaShell, | |
Color.Sienna, | |
Color.Silver, | |
Color.SkyBlue, | |
Color.SlateBlue, | |
Color.SlateGray, | |
Color.Snow, | |
Color.SpringGreen, | |
Color.SteelBlue, | |
Color.Tan, | |
Color.Teal, | |
Color.Thistle, | |
Color.Tomato, | |
Color.Turquoise, | |
Color.Violet, | |
Color.Wheat, | |
Color.White, | |
Color.WhiteSmoke, | |
Color.Yellow, | |
Color.YellowGreen, | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment