Skip to main content
3D Pinball for Windows - Space Cadet is the classic pinball game embedded through an iframe from 98.js.org.

Features

  • Full Pinball Gameplay: Authentic Space Cadet pinball
  • Keyboard Controls: Flipper controls and ball launch
  • Score Tracking: Points and high scores
  • Missions: Complete missions for bonus points
  • Sound Effects: Original pinball sounds
  • Device Detection: Blocks on mobile and small screens

Component Structure

Location: src/WinXP/apps/Pinball/index.jsx
function PinBall({ isFocus }) {
  const gameUrl = 'https://98.js.org/programs/pinball/space-cadet.html';
  
  return (
    <AppContainer>
      <StyledIframe
        src={gameUrl}
        frameBorder="0"
        title="3D Pinball for Windows - Space Cadet"
      />
      {!isFocus && <Overlay />}
    </AppContainer>
  );
}

Configuration

From apps/index.jsx:
Pinball: {
  name: 'Pinball',
  header: {
    icon: pinballIcon16,
    title: '3D Pinball for Windows - Space Cadet',
  },
  component: WrappedPinball,
  defaultSize: checkPinballBlock()
    ? { width: 380, height: 0 }
    : { width: 600, height: 470 },
  defaultOffset: checkPinballBlock()
    ? getCenter(380, 200)
    : getCenter(600, 470),
  resizable: false,
  minimized: false,
  maximized: checkPinballBlock() ? false : shouldMaximize(600, 470, false),
  multiInstance: false,
}

Device Detection

Pinball blocks on mobile devices and screens smaller than 600x470:
const checkPinballBlock = () => isMobileUA() || isScreenTooSmall(600, 470);

const WrappedPinball = props => {
  if (checkPinballBlock()) {
    return (
      <ErrorBox
        {...props}
        message="Incompatible Device / Screen: 3D Pinball requires a desktop environment and a screen size of at least 600x470px."
        title="Compatibility Warning"
      />
    );
  }
  return <PinballComponent {...props} />;
};

Detection Functions

const isMobileUA = () => {
  if (typeof window === 'undefined') return false;
  const userAgent = navigator.userAgent || navigator.vendor || window.opera;
  return (
    /android/i.test(userAgent) ||
    (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream)
  );
};

const isScreenTooSmall = (minW, minH) => {
  if (typeof window === 'undefined') return false;
  return window.innerWidth < minW || window.innerHeight < minH;
};

Keyboard Controls

  • Z: Left flipper
  • /: Right flipper
  • Space: Launch ball
  • X: Nudge left
  • Period (.): Nudge right
  • Up Arrow: Nudge up
  • F2: New game
  • F3: Pause
  • F4: Options
  • F8: Demo mode

Focus Overlay

To prevent the iframe from capturing all input when the window is not focused:
const Overlay = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  background-color: transparent;
`;

{!isFocus && <Overlay />}
This allows:
  • Clicking on the window to focus it
  • Dragging the window when not focused
  • Resizing (though pinball is not resizable)

Styling

const AppContainer = styled.div`
  width: 100%;
  height: 100%;
  position: relative;
  background-color: #309f6a; // Classic pinball green felt
  overflow: hidden;
`;

const StyledIframe = styled.iframe`
  display: block;
  width: 100%;
  height: 100%;
  border: none;
`;

Game Features

Missions

Space Cadet includes various missions:
  • Science Missions: Complete scientific objectives
  • Cadet Missions: Training exercises
  • Training Missions: Basic skill challenges
  • Special Missions: Bonus missions for high scores

Scoring Elements

  • Bumpers: 500-1000 points
  • Launch Ramp: Variable points based on speed
  • Target Lanes: 1000-5000 points
  • Spinners: 100 points per spin
  • Bonus Multipliers: 2x, 3x, 5x, 10x
  • Extra Balls: Awarded for high scores

Special Features

  • Hyperspace: Teleport ball to different location
  • Multiball: Multiple balls in play
  • Jackpot: High-value targets
  • Fuel Lights: Complete to activate features
  • Mission Targets: Hit specific targets for missions

98.js.org Integration

The game is hosted on 98.js.org, which provides:
  • WebAssembly-compiled pinball engine
  • Accurate physics simulation
  • Original graphics and sounds
  • Saved high scores (in browser storage)

Limitations

  • Internet Required: Loads from external URL
  • No Customization: Cannot modify game settings from Web XP
  • Single Instance: Only one pinball game at a time
  • Not Resizable: Fixed window size for optimal gameplay
  • Desktop Only: Requires keyboard controls

Error Handling

If the game fails to load:
// The iframe will show a browser error page
// or the 98.js.org error message
Consider adding error detection:
const [loadError, setLoadError] = useState(false);

<StyledIframe
  src={gameUrl}
  onError={() => setLoadError(true)}
  title="3D Pinball for Windows - Space Cadet"
/>

{loadError && (
  <ErrorMessage>
    Failed to load pinball. Please check your internet connection.
  </ErrorMessage>
)}

Usage Example

import { Pinball } from 'src/WinXP/apps';

function Desktop() {
  const [focusedWindow, setFocusedWindow] = useState(null);
  
  return (
    <Window 
      title="3D Pinball for Windows - Space Cadet"
      onFocus={() => setFocusedWindow('pinball')}
    >
      <Pinball isFocus={focusedWindow === 'pinball'} />
    </Window>
  );
}

Performance

  • Game runs in separate iframe context
  • WebAssembly provides near-native performance
  • No impact on main Web XP thread
  • Memory managed by browser iframe isolation

Accessibility

  • Keyboard-only controls (no mouse required)
  • High contrast ball and table elements
  • Audio cues for game events
  • Clear visual feedback for hits and targets

Alternative Hosting

To host the game locally:
  1. Download the pinball files from 98.js.org
  2. Host them on your server
  3. Update the iframe source:
const gameUrl = '/local-pinball/space-cadet.html';
This provides:
  • Offline gameplay
  • Faster loading
  • No external dependencies
  • Full control over game files

Build docs developers (and LLMs) love