Created
May 4, 2021 20:17
-
-
Save Genbox/9737d1155efcdd00c9858cf7a492323e to your computer and use it in GitHub Desktop.
Detect ground with type check
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
using Genbox.VelcroPhysics.Collision.ContactSystem; | |
using Genbox.VelcroPhysics.Dynamics; | |
using Genbox.VelcroPhysics.Factories; | |
using Genbox.VelcroPhysics.Utilities; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Input; | |
namespace Genbox.VelcroPhysics.MonoGame.Samples.HelloWorld | |
{ | |
public sealed class Game1 : Game | |
{ | |
private readonly GraphicsDeviceManager _graphics; | |
private SpriteBatch _batch; | |
private KeyboardState _oldKeyState; | |
private GamePadState _oldPadState; | |
private SpriteFont _font; | |
private readonly World _world; | |
private Body _circleBody; | |
private Body _groundBody; | |
private Texture2D _circleSprite; | |
private Texture2D _groundSprite; | |
// Simple camera controls | |
private Matrix _view; | |
private Vector2 _cameraPosition; | |
private Vector2 _screenCenter; | |
private Vector2 _groundOrigin; | |
private Vector2 _circleOrigin; | |
#if !XBOX | |
private const string Text = "Press A or D to rotate the ball\n" + | |
"Press Space to jump\n" + | |
"Use arrow keys to move the camera"; | |
#else | |
const string Text = "Use left stick to move\n" + | |
"Use right stick to move camera\n" + | |
"Press A to jump\n"; | |
#endif | |
public Game1() | |
{ | |
_graphics = new GraphicsDeviceManager(this); | |
_graphics.PreferredBackBufferWidth = 800; | |
_graphics.PreferredBackBufferHeight = 480; | |
Content.RootDirectory = "Content"; | |
//Create a world with gravity. | |
_world = new World(new Vector2(0, 9.82f)); | |
} | |
protected override void LoadContent() | |
{ | |
// Initialize camera controls | |
_view = Matrix.Identity; | |
_cameraPosition = Vector2.Zero; | |
_screenCenter = new Vector2(_graphics.GraphicsDevice.Viewport.Width / 2f, _graphics.GraphicsDevice.Viewport.Height / 2f); | |
_batch = new SpriteBatch(_graphics.GraphicsDevice); | |
_font = Content.Load<SpriteFont>("font"); | |
// Load sprites | |
_circleSprite = Content.Load<Texture2D>("CircleSprite"); // 96px x 96px => 1.5m x 1.5m | |
_groundSprite = Content.Load<Texture2D>("GroundSprite"); // 512px x 64px => 8m x 1m | |
/* We need XNA to draw the ground and circle at the center of the shapes */ | |
_groundOrigin = new Vector2(_groundSprite.Width / 2f, _groundSprite.Height / 2f); | |
_circleOrigin = new Vector2(_circleSprite.Width / 2f, _circleSprite.Height / 2f); | |
// Velcro Physics expects objects to be scaled to MKS (meters, kilos, seconds) | |
// 1 meters equals 64 pixels here | |
ConvertUnits.SetDisplayUnitToSimUnitRatio(64f); | |
/* Circle */ | |
// Convert screen center from pixels to meters | |
Vector2 circlePosition = ConvertUnits.ToSimUnits(_screenCenter) + new Vector2(0, -1.5f); | |
// Create the circle fixture | |
_circleBody = BodyFactory.CreateCircle(_world, ConvertUnits.ToSimUnits(96 / 2f), 1f, circlePosition, BodyType.Dynamic); | |
// Give it some bounce and friction | |
_circleBody.Restitution = 0.3f; | |
_circleBody.Friction = 0.5f; | |
_circleBody.OnCollision += OnCollision; | |
_circleBody.SleepingAllowed = false; | |
/* Ground */ | |
Vector2 groundPosition = ConvertUnits.ToSimUnits(_screenCenter) + new Vector2(0, 1.25f); | |
// Create the ground fixture | |
_groundBody = BodyFactory.CreateRectangle(_world, ConvertUnits.ToSimUnits(512f), ConvertUnits.ToSimUnits(64f), 1f, groundPosition); | |
_groundBody.BodyType = BodyType.Static; | |
_groundBody.Restitution = 0.3f; | |
_groundBody.Friction = 0.5f; | |
} | |
private bool _collisionWithGround; | |
private void OnCollision(Fixture fixtureA, Fixture fixtureB, Contact contact) | |
{ | |
_collisionWithGround = fixtureB.Body == _groundBody; | |
} | |
/// <summary> | |
/// Allows the game to run logic such as updating the world, | |
/// checking for collisions, gathering input, and playing audio. | |
/// </summary> | |
/// <param name="gameTime">Provides a snapshot of timing values.</param> | |
protected override void Update(GameTime gameTime) | |
{ | |
_collisionWithGround = false; | |
HandleGamePad(); | |
HandleKeyboard(); | |
//We update the world | |
_world.Step((float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.001f); | |
base.Update(gameTime); | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
if (disposing) | |
{ | |
_graphics.Dispose(); | |
_batch.Dispose(); | |
_circleSprite.Dispose(); | |
_groundSprite.Dispose(); | |
} | |
base.Dispose(disposing); | |
} | |
private void HandleGamePad() | |
{ | |
GamePadState padState = GamePad.GetState(0); | |
if (padState.IsConnected) | |
{ | |
if (padState.Buttons.Back == ButtonState.Pressed) | |
Exit(); | |
if (padState.Buttons.A == ButtonState.Pressed && _oldPadState.Buttons.A == ButtonState.Released) | |
_circleBody.ApplyLinearImpulse(new Vector2(0, -10)); | |
_circleBody.ApplyForce(padState.ThumbSticks.Left); | |
_cameraPosition.X -= padState.ThumbSticks.Right.X; | |
_cameraPosition.Y += padState.ThumbSticks.Right.Y; | |
_view = Matrix.CreateTranslation(new Vector3(_cameraPosition - _screenCenter, 0f)) * Matrix.CreateTranslation(new Vector3(_screenCenter, 0f)); | |
_oldPadState = padState; | |
} | |
} | |
private void HandleKeyboard() | |
{ | |
KeyboardState state = Keyboard.GetState(); | |
// Move camera | |
if (state.IsKeyDown(Keys.Left)) | |
_cameraPosition.X += 1.5f; | |
if (state.IsKeyDown(Keys.Right)) | |
_cameraPosition.X -= 1.5f; | |
if (state.IsKeyDown(Keys.Up)) | |
_cameraPosition.Y += 1.5f; | |
if (state.IsKeyDown(Keys.Down)) | |
_cameraPosition.Y -= 1.5f; | |
_view = Matrix.CreateTranslation(new Vector3(_cameraPosition - _screenCenter, 0f)) * Matrix.CreateTranslation(new Vector3(_screenCenter, 0f)); | |
// We make it possible to rotate the circle body | |
if (state.IsKeyDown(Keys.A)) | |
_circleBody.ApplyTorque(-10); | |
if (state.IsKeyDown(Keys.D)) | |
_circleBody.ApplyTorque(10); | |
if (state.IsKeyDown(Keys.Space) && _oldKeyState.IsKeyUp(Keys.Space)) | |
_circleBody.ApplyLinearImpulse(new Vector2(0, -10)); | |
if (state.IsKeyDown(Keys.Escape)) | |
Exit(); | |
_oldKeyState = state; | |
} | |
/// <summary> | |
/// This is called when the game should draw itself. | |
/// </summary> | |
/// <param name="gameTime">Provides a snapshot of timing values.</param> | |
protected override void Draw(GameTime gameTime) | |
{ | |
GraphicsDevice.Clear(Color.CornflowerBlue); | |
//Draw circle and ground | |
_batch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, _view); | |
_batch.Draw(_circleSprite, ConvertUnits.ToDisplayUnits(_circleBody.Position), null, Color.White, _circleBody.Rotation, _circleOrigin, 1f, SpriteEffects.None, 0f); | |
_batch.Draw(_groundSprite, ConvertUnits.ToDisplayUnits(_groundBody.Position), null, Color.White, 0f, _groundOrigin, 1f, SpriteEffects.None, 0f); | |
_batch.End(); | |
// Display instructions | |
_batch.Begin(); | |
_batch.DrawString(_font, _collisionWithGround ? "On ground" : "Not on ground", new Vector2(12f, 12f), Color.Black); | |
_batch.End(); | |
base.Draw(gameTime); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment