Skip to content

Commit

Permalink
Adds keyboard input and controls are persisted to the computer (#6)
Browse files Browse the repository at this point in the history
* Adds snake language around the keyboard

* adds persistence and system for persisting controls

* Adds controls to the main menu that can then be saved and loaded as needed

* Adds gamescores object

* Adds controls for snakeboost

* Issue is with the clients

* Adds items

* Adds connection logic to the gameplayview

* Adds setup method

* Adds keyboard input that works between client and server

* Centers the square

* Adds comments

* Adds logic

* Removes TODOs
  • Loading branch information
MaxEdwards20 authored Mar 27, 2024
1 parent 5a547b0 commit 8d549e9
Show file tree
Hide file tree
Showing 31 changed files with 665 additions and 554 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,21 @@ A game of Snake built using C# in the MonoGame framework, themed around everyone

<!-- TODO -->
<!-- Screenshots: -->

## Notes

- For tomorrow: Solve the keyboard input problem with the entities and components. I am thinking I will keep the MenuKeyboardInput and add the controls directly to the system keyboard input.

For office hours:

- How would you suggest we save the user controls? I am trying to think of this in an entity component system way. I am thinking of having a component that holds the controls and then a system that reads the controls and updates the entity. I am not sure if this is the best way to do it.
- We already have the keyboard input system. Would that be the best place to put the controls? How do give the gameplay access to the controls component?


## Debugging

### Connection Refused
- Try switching ports. A few options are 4000, 4010, 3000, 3010
- Use netcat on Mac or Linux to see whether the server is available.
`nc -vz 192.168.4.20 3000`
- Turn off your firewall. On macOS that is found in System Preferences > Security & Privacy > Firewall
33 changes: 22 additions & 11 deletions src/Client/ClientMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using System.Collections.Generic;
using Shared.Components;
using Shared.Systems;

namespace Client
{
Expand All @@ -18,17 +20,24 @@ public class ClientMain : Game
private SpriteBatch m_spriteBatch;
private IGameState m_currentState;
private Dictionary<MenuStateEnum, IGameState> m_states;
private KeyboardInput m_keyboardInput;
private bool newState = false;
private MenuKeyboardInput m_menuKeyboardInput;
private bool newState;
private SoundEffect selectSound;
private Texture2D m_background;
private GameModel m_gameModel;
private Controls m_controls;
private SettingsPersistence m_settingsPersistence;

public ClientMain()
{
m_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
m_keyboardInput = new KeyboardInput();
m_menuKeyboardInput = new MenuKeyboardInput();
IsMouseVisible = true;
m_gameModel = new GameModel();
m_controls = new Controls();
m_settingsPersistence = new SettingsPersistence();

}

protected override void Initialize()
Expand All @@ -37,22 +46,26 @@ protected override void Initialize()
m_graphics.PreferredBackBufferWidth = 1920;
m_graphics.PreferredBackBufferHeight = 1080;
m_graphics.ApplyChanges();

// Load the controls
// We pass in our own controls so we always have them as a default if they were not saved
m_settingsPersistence.LoadControls(m_controls);

// Create all the game states here
m_states = new Dictionary<MenuStateEnum, IGameState>
{
{ MenuStateEnum.MainMenu, new MainMenuView() },
{ MenuStateEnum.GamePlay, new GamePlayView() },
{ MenuStateEnum.GamePlay, new GamePlayView(m_controls) },
{ MenuStateEnum.HighScores, new HighScoresView() },
{ MenuStateEnum.Controls, new ControlSettingsView() },
{ MenuStateEnum.Controls, new ControlSettingsView(m_controls) },
{ MenuStateEnum.Help, new HelpView() },
{ MenuStateEnum.Credits, new AboutView() }
};

// Give all game states a chance to initialize, other than constructor
foreach (var item in m_states)
{
item.Value.initialize(this.GraphicsDevice, m_graphics, m_keyboardInput);
item.Value.initialize(this.GraphicsDevice, m_graphics, m_menuKeyboardInput);
}

// We are starting with the main menu
Expand All @@ -64,8 +77,8 @@ protected override void Initialize()
protected override void LoadContent()
{
m_spriteBatch = new SpriteBatch(GraphicsDevice);

// Load background music TODO: Pick a background song
// Load background music
var backgroundMusic = Content.Load<Song>("Audio/backgroundMusic");
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
Expand All @@ -81,7 +94,6 @@ protected override void LoadContent()
item.Value.loadContent(this.Content);
}

MessageQueueClient.instance.initialize("localhost", 3000);
}

protected override void Update(GameTime gameTime)
Expand All @@ -101,10 +113,9 @@ protected override void Update(GameTime gameTime)
if (cState != m_currentState)
{
newState = true;
m_currentState.initializeSession();
m_currentState.initialize();
}
}

base.Update(gameTime);
}

Expand Down
File renamed without changes
32 changes: 13 additions & 19 deletions src/Client/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using Shared.Entities;
using System;
using System.Collections.Generic;
using Client.Menu;
using Shared.Components;

namespace Client
{
Expand All @@ -15,6 +17,7 @@ public class GameModel
private Systems.KeyboardInput m_systemKeyboardInput;
private Systems.Interpolation m_systemInterpolation = new Systems.Interpolation();
private Systems.Renderer m_systemRenderer = new Systems.Renderer();
private Controls m_controls;

/// <summary>
/// This is where everything performs its update.
Expand All @@ -25,55 +28,47 @@ public void update(TimeSpan elapsedTime)
m_systemKeyboardInput.update(elapsedTime);
m_systemInterpolation.update(elapsedTime);
}

/// <summary>
/// Where we render everything
/// </summary>

public void render(TimeSpan elapsedTime, SpriteBatch spriteBatch)
{
m_systemRenderer.update(elapsedTime, spriteBatch);
m_systemRenderer.render(elapsedTime, spriteBatch);
}

/// <summary>
/// This is where all game model initialization occurs. In the case
/// of this "game', start by initializing the systems and then
/// loading the art assets.
/// </summary>
public bool initialize(ContentManager contentManager)
public bool initialize(ContentManager contentManager, Controls controls)
{
m_contentManager = contentManager;

m_systemNetwork.registerNewEntityHandler(handleNewEntity);
m_systemNetwork.registerRemoveEntityHandler(handleRemoveEntity);
m_controls = controls;

m_systemKeyboardInput = new Systems.KeyboardInput(new List<Tuple<Shared.Components.Input.Type, Keys>>
{
Tuple.Create(Shared.Components.Input.Type.Thrust, Keys.W),
Tuple.Create(Shared.Components.Input.Type.RotateLeft, Keys.A),
Tuple.Create(Shared.Components.Input.Type.RotateRight, Keys.D)
});
{ }, m_controls);

return true;
}

public void shutdown()
{

}

public void signalKeyPressed(Keys key)
{
m_systemKeyboardInput.keyPressed(key);
}

public void signalKeyReleased(Keys key)
{
m_systemKeyboardInput.keyReleased(key);
}

/// <summary>
/// Based upon an Entity received from the server, create the
/// entity at the client.
/// </summary>
private Entity createEntity(Shared.Messages.NewEntity message)
{
Entity entity = new Entity(message.id);


if (message.hasAppearance)
{
Expand Down Expand Up @@ -151,6 +146,5 @@ private void handleRemoveEntity(Shared.Messages.RemoveEntity message)
{
removeEntity(message.id);
}

}
}
32 changes: 0 additions & 32 deletions src/Client/IO/Control.cs

This file was deleted.

Loading

0 comments on commit 8d549e9

Please sign in to comment.