Random musings on programming, mostly.
React
Last blog post I discussed some of the strategies and techniques I used for building a board game using React. I talked mostly about reducers and redux-saga. That post can be read here.
Just to recap quickly though, I discussed how I came to design my reducers, briefly how reducers handle actions, and that reducers have to be pure, that is, they do not mutate the state. If you are still struggling with how to write pure functions I suggest taking a look at this. Finally we discussed sagas and how I used those to model much of my game logic. Sagas allow us to listen for actions that are dispatched to the redux store and then issue actions in response. This comes in very handy when, for example, a user is done moving her pawn. Our saga listens for that action, then inspects the user’s hand to determine if any cards need to be discarded or played, it then dispatches an action to reflect that.
Now that we are back up to speed, I’ve decided to shift gears and talk about a few of the UI elements I used. In particular Modals and Alerts. These are the icing on the cake, that sweet sugary goodness that makes the game look good when playing.
Modals are windows that essentially force themselves to the front. In my use case these come in handy when a user logins, so he or she can choose to start a new game or load a game. I also used a modal to signify the end of the game, this way the modal pops up indicating the game is over and allows the user to start a new game if they so choose. There are several Modal Component libraries out there, and even React-Bootstrap has them if you are so inclined. I didn’t want the entire React-Bootstrap library though so I chose to use React-Modal. The developers of React-Modal didn’t a brilliant job of creating components that are both easy to use and easy to customize. Usage is well layed out in the docs, but let’s take a look anyway. The following is the basic component I designed for my end game modal.
import React, { Component } from 'react' import Modal from 'react-modal' import { connect } from 'react-redux' import { closeEndGameModal, newGame } from '../actions/ActionCreators' const customStyles = { content : { top : '50%', left : '50%', right : 'auto', bottom : 'auto', marginRight : '-50%', transform : 'translate(-50%, -50%)', zIndex : 1, backgroundColor : 'black', textAlign : 'center', } }; class EndGameModal extends Component { afterOpenModal() { // references are now sync'd and can be accessed. } closeModal() { this.props.dispatch(newGame()) this.props.dispatch(closeEndGameModal()) } render() { return ( <div> <Modal isOpen={this.props.modalIsOpen} onAfterOpen={() => this.afterOpenModal()} onRequestClose={(e) => e.preventDefault()} style={customStyles} contentLabel="End Game Modal" > <h2>Game Over!</h2> <button onClick={() => this.closeModal()}>Play Again!</button> </Modal> </div> ); } } export default connect()(EndGameModal)
Most notably the component requires two props, isOpen and contentLabel. Content label, is simply a label for the component, it can be displayed on the modal but doesn’t have to be. isOpen is a boolean that tells the modal whether it is open or not. In most cases you could have left the state in the modal itself. I chose to put it in the redux store just like the rest of the state though, this allows our sagas to check the status of the modal and send actions in response. You can render these anywhere you like, I chose to render it on my Board component.
Alerts, in this case, are those spiffy little windows that pop up in the lower left corner when a city is infected. Again there are many different alerts available online if you don’t want to create your own. I chose React-Alert. This is another top notch component that is both easy to use and easy to customize to your liking. In fact these are so easy to use, a quick glance at the docs should get you up and running with no trouble, but let’s take a look anyway.
import Alert from 'react-s-alert' import 'react-s-alert/dist/s-alert-css-effects/jelly.css'; import './Alerts.css' ... <Alert stack= effect={'jelly'} timeout={5000} />
That’s pretty much it. Some custom css, a jelly effect that the developer of React-Alert provides for you if you like and the component itself. You should render these in the component that you want the alert to display in. In this case I chose App. This ensures the Alerts display in the bottom left corner of the entire window. So how do we trigger an alert? That is also about as simple as can be.
Alert.info(`Infection Phase: Placing ${color} cube in ${name}`,{ position: 'bottom-left' })
This is found in the infect saga. The program infects cities after the player is done moving and discarding and then displays an alert in the bottom-left of the screen saying which city and the color of the disease. Awesome!
I hope any of you who took the time to read this learned something or at least got some ideas for future projects. It has truly been a blast building this, although the work is not done by any means. Feel free to checkout the project on the links at the top of the page. I’d love to get some feedback, there is still much work to do and much refactoring, but the product to date has turned out much better than I had ever envisioned.