There actually isn't a lot of state information in many pinball games, including this one. All state is explained here.
Each player has a score, a simple number.
Each player has a count of total balls for the game -- increases if they achieve an extra ball.
The number of balls, from total, that player has used. When used reaches total, no additional balls will be given, game over for player when balls drain.
List of player initials currently playing - can't change during game. Just used for achievement tracking.
Simple list of mode names completed by each player for current game.
The current mode being played, a simple string equal to the name of the mode. Might change to an ID based system when adding achievement tracking, so that achievements persist if names are changed.
Tasks completed for the current mode - mode name, step name, and switch number.
TBD - some info to support combo shot tracking (if it cannot be tracked based on light/switch status), and also a UI component that shows points earned and special bonus points like "+10,000 Combo Shot Bonus". Maybe the UI shows points flying by as you get them, like the numbers when you shoot an enemy in Apex Legends.
When certain things happen like a goal being completed, or a combo shot hit, a video will play. Like most things in React, this is done with a state update.
The current player, a 0 based index, a simple number.
As switches are activated (hit/pressed), game logic is applied to toggle a hit/lit state.
Number of credits available (not spent).
Number of balls moving on playfield, just a count.
Switch id for each kicker that contains a ball.
An error, if unable to connect to FAST controller.
The first time we connect to a new serial port from a new browser/device, we need to get permission. This is done with a one-time setup process. It needs to be redone if certain data is cleared/reset, but it should never expire if changes to the host computer are not done. Hopefully in the future browsers will have a feature flag to disable this security.
At startup we need to connect to FAST controller before certain modes can start.
For some switches we don't just track hits, we want to know the current state. This state is just an array of booleans, one for each switch, indexed by switch number, true = open.
Basic NextJS bootstrap, with very few changes. You don't need to spend much time in here - see NextJS docs if you do.
All React components go here. They are all client components (not server), since we don't care about SSR, SSG or SEO.
Component for blinking (flashing) text. Used for selecting number of players and initials before game starts.
Entry point. Provides contexts and renders StartController.
Controls a game. Renders only while a game is running. Decides which mode is active. Renders game status and slides.
Renders game status during game. Player scores, ball count, shot information, and tells players whos turn it is.
All slides go here. Slides are UI views.
The slide displayed during attract mode. Attracts players -- makes them want to play the game.
The slide displayed during game play. For now we only have one game slide. In the future we may add more.
Base slide component rendered by all slides. Handles common styles and transitions used by all slides.
Holds logic for starting and ending games. Decides if we are in attract mode or game mode.
Holds all of the constants - things that do not change, unless a developer changes them.
Information about audio files.
List of coils in your game.
Limits we set to avoid the game being overly complex.
Information about flippers.
Keyboard mappings for testing with virtual hardware.
LED/Lights/Bulbs/GI -- all goes here.
Information about game modes.
Show me the money!
The node boards in our system. Also known as I/O boards.
Without rules, we have chaos.
Mostly options to toggle while doing development and testing on virtual hardware.
Information about switches goes here.
Context - data, state and functions shared by multiple components.
Exposes methods to support audio.
Only available while a game is active. Do not use in non-game components, like attract mode or start controller. Has features for general game play.
Communicates with FAST hardware, or optional virtual hardware for testing while away from your real machine.
Provides machine information, like number of credits (coins inserted), state of coin door, tilt, and logged in users (future feature).
Contains all of the first class citizens (aka things or nouns) that exist in our code.
Also known as a driver, but in our game driver is a person, so call these coils. Common pinball hardware -- electromagnet.
Flip out!
The one and only game object - get from GameContext while a game is active.
Holds information about hardware, mostly from the FAST controller. Get from HardwareContext.
I've heard them called a few names, including "Saucer Hole Kicker". In our game they are homes/garages/safe-houses. They hold the ball for a period of time, then kick it out. VPX calls them kickers, which is easy to spell and say, so I will too.
A light, in the form of LED, GI, or anything else.
Holds information available about the machine state, available from MachineContext, such as the number of credits. If it isn't hardware related, and persists across multiple games, it probably goes here.
A game mode. More like a mission, with tasks you need to complete.
One step in a mode. Modes require multiple steps to complete.
You, and your friends.
A special shot that is good enough to have a name. Shown on the display when achieved.
A thing that can be opened or closed, 0/1, true/false, happy/sad.
A specific switch type that is a goal for a mode step. Includes an image and videos to display.
A place for boring code that you are proud off, but nobody cares about, get over it.
Some functions that are helpful, but native arrays do not have yet.
Stuff that Math might have eventually.
Do stuff with objects, easier.
String functions.
You didn't see me.
NextJS concept - put font, video, image and audio files here.
I'm stupid, you probably are too, so keep it simple stupid.
If you don't need it now, you aren't going to need it, just delete it or don't build it in the first place.
This is custom code made for a single game, not a general purpose library to build lots of games. That said, you could use this as a bootstrap and delete everything you do not need (most important), and add only things you do need for another game. I know, NextJS is bloat, but I didn't feel like doing all the boilerplate work to start from scratch, so we have a platform that mostly should stay out of our way.
I'm not the guy that maintains open source projects in my free time -- please don't ask me to add features to this, it is my game, copy it and make it your own, and maintain it yourself. That said, I'm usually happy to answer questions and help, just don't ask me to write the code or tell you exactly how to write the code. Do most of the work yourself, or use one of the amazing open source projects available like MPF, where many people will help you and maybe even add entire features just for you.
This is a Next.js project bootstrapped with create-next-app
.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
Open http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx
. The page auto-updates as you edit the file.
API routes can be accessed on http://localhost:3000/api/hello. This endpoint can be edited in pages/api/hello.ts
.
The pages/api
directory is mapped to /api/*
. Files in this directory are treated as API routes instead of React pages.
This project uses next/font
to automatically optimize and load Inter, a custom Google Font.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.