react-native-games
Version:
Free games for your react native projects.
409 lines (325 loc) ⢠17.2 kB
Markdown
# š® react-native-games
**react-native-games** is a collection of high-performance games for your React Native projects. Built with modern React Native technologies including Skia, Reanimated, Gesture Handler and TypeScript for smooth 60fps gameplay across iOS, Android, and Web platforms.
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 20px 0;">
<div>
<strong>š High Performance</strong><br/>
⢠60fps gameplay with React Native Skia<br/>
⢠Optimized animations using Reanimated 3<br/>
⢠Delta time physics loops<br/>
⢠React.memo optimizations<br/>
⢠Minimal re-renders with direct store subscriptions
</div>
<div>
<strong>š± Cross-Platform</strong><br/>
⢠iOS, Android, and Web support<br/>
⢠Consistent performance across platforms<br/>
⢠Responsive design for all screen sizes<br/>
⢠Dynamic offset handling for notches<br/>
⢠Adaptive UI components
</div>
<div>
<strong>šµ Rich Audio & Haptics</strong><br/>
⢠Sound effects and speech synthesis<br/>
⢠Haptic feedback for immersive experience<br/>
⢠Configurable audio settings<br/>
⢠Per-game sound customization
</div>
<div>
<strong>šÆ Customizable</strong><br/>
⢠Multiple difficulty levels<br/>
⢠Adjustable game parameters<br/>
⢠Persistent settings storage<br/>
⢠Unified settings interface
</div>
<div>
<strong>š® Game Features</strong><br/>
⢠Physics simulation and collisions<br/>
⢠Particle systems and visual effects<br/>
⢠Procedural generation (mazes, obstacles)<br/>
⢠Score systems and achievements<br/>
⢠Progressive difficulty scaling
</div>
<div>
<strong>š ļø Developer Friendly</strong><br/>
⢠TypeScript support throughout<br/>
⢠Shared components (GameControlButton, ScoreBoard)<br/>
⢠Consistent API across all games<br/>
⢠Easy integration and customization<br/>
⢠Comprehensive documentation
</div>
</div>
## šÆ Available Games
| Screenshot | Game Details |
|------------|--------------|
| <img src="https://cdn.worklage.com/playtura/screenshots/fruit-ninja.png" alt="Fruit Ninja" width="120"/> | **š Fruit Ninja**<br/>Slice flying fruits with finger swipes - avoid the bombs!<br/><br/>⢠Fixed 60-second gameplay sessions<br/>⢠Physics-based slicing with particle effects and combo system<br/>⢠Difficulty affects fruit spawn rate and bomb frequency |
| <img src="https://cdn.worklage.com/playtura/screenshots/candy-crush.png" alt="Candy Crush" width="120"/> | **š¬ Candy Crush**<br/>Match colorful candies in this puzzle game<br/><br/>⢠Match-3 puzzle with colorful candies<br/>⢠Create special candies with 4+ matches<br/>⢠Cascading combos and satisfying animations<br/>⢠Difficulty affects level objectives and move limits |
| <img src="https://cdn.worklage.com/playtura/screenshots/flappy-bird.png" alt="Flappy Bird" width="120"/> | **š¦ Flappy Bird**<br/>Navigate bird through pipes with precise timing<br/><br/>⢠Classic tap-to-flap mechanics with gravity physics<br/>⢠Navigate through pipes with pixel-perfect collision<br/>⢠Progressive difficulty with increasing pipe speed<br/>⢠Difficulty affects pipe gap size and spawn frequency |
| <img src="https://cdn.worklage.com/playtura/screenshots/colors-sort.png" alt="Colors Sort" width="120"/> | **šØ Colors Sort**<br/>Sort colored liquids into matching tubes<br/><br/>⢠Sort colored liquids into matching tubes<br/>⢠Logic puzzle with increasing complexity<br/>⢠Satisfying pour animations and sound effects<br/>⢠Difficulty affects number of tubes and colors |
| <img src="https://cdn.worklage.com/playtura/screenshots/dino-jump.png" alt="Dino Jump" width="120"/> | **š¦ Dino Jump**<br/>Chrome offline dino game - jump to avoid obstacles!<br/><br/>⢠Endless runner with tap-to-jump mechanics<br/>⢠Collect stars for extra lives (max 3 lives)<br/>⢠Game durations: easy 2 mins, medium 3 mins, hard 5 mins<br/>⢠Dynamic ground height based on device offset (150px or 250px)<br/>⢠Difficulty affects obstacle spawn rate and game speed |
| <img src="https://cdn.worklage.com/playtura/screenshots/popit-fidget.png" alt="Popit Fidget" width="120"/> | **𫧠Popit Fidget**<br/>Pop satisfying bubbles in this relaxing fidget toy game<br/><br/>⢠Relaxing bubble popping with satisfying sound effects<br/>⢠Different bubble shapes and colors for variety<br/>⢠Difficulty affects bubble responsiveness and patterns |
| <img src="https://cdn.worklage.com/playtura/screenshots/whack-a-mole.png" alt="Whack A Mole" width="120"/> | **š± Whack A Mole**<br/>Whack cute cats popping from holes - fast reflexes needed!<br/><br/>⢠Cat spawn intervals: easy 2000ms, medium 1500ms, hard 1000ms<br/>⢠Cat visible duration: easy 2500ms, medium 2000ms, hard 1500ms<br/>⢠Grid sizes: easy/medium 3x3, hard 4x4 |
| <img src="https://cdn.worklage.com/playtura/screenshots/balloon-blaster.png" alt="Balloon Blaster" width="120"/> | **š Balloon Blaster**<br/>Pop rising balloons before they escape - quick taps win!<br/><br/>⢠Fixed 60-second gameplay sessions<br/>⢠Balloon spawn interval: 1200ms, rise speed: 0.08<br/>⢠Physics-based balloon movement with particle effects |
| <img src="https://cdn.worklage.com/playtura/screenshots/space-fighter.png" alt="Space Fighter" width="120"/> | **š Space Fighter**<br/>Pilot spaceship through asteroid fields in endless space<br/><br/>⢠Horizontal drag controls with smooth spacecraft movement<br/>⢠Dynamic spacecraft positioning based on device offset<br/>⢠Progressive difficulty with asteroid spawn intervals<br/>⢠1-second collision immunity after each hit<br/>⢠Difficulty affects asteroid speed and spawn frequency |
| <img src="https://cdn.worklage.com/playtura/screenshots/maze-runner.png" alt="Maze Runner" width="120"/> | **𧩠Maze Runner**<br/>Navigate ball through mazes using tilt and physics controls<br/><br/>⢠Grid sizes: easy 8x8, medium 10x10, hard 12x12<br/>⢠Procedurally generated mazes with intelligent pathfinding<br/>⢠Game over modal only appears on maze completion (not on stop)<br/>⢠White time display for better visibility<br/>⢠Difficulty affects maze complexity and time limits |
| <img src="https://cdn.worklage.com/playtura/screenshots/sliding-numbers.png" alt="Sliding Numbers" width="120"/> | **š¢ Sliding Numbers**<br/>Solve the classic 15-puzzle with numbers<br/><br/>⢠Classic 15-puzzle with numbered tiles<br/>⢠Grid sizes: easy 3x3, medium 4x4, hard 5x5<br/>⢠Timer challenge to solve as fast as possible<br/>⢠Smooth tile sliding animations |
| <img src="https://cdn.worklage.com/playtura/screenshots/game-2048.png" alt="2048 Game" width="120"/> | **š® 2048 Game**<br/>Merge tiles to reach 2048 and beyond<br/><br/>⢠Swipe to merge tiles with same numbers<br/>⢠Reach 2048 tile to win, continue for higher scores<br/>⢠Undo moves feature for strategic gameplay<br/>⢠Difficulty affects starting tile values and spawn rate |
| <img src="https://cdn.worklage.com/playtura/screenshots/fruit-merger.png" alt="Fruit Merger" width="120"/> | **š Fruit Merger**<br/>Merge fruits to create bigger ones<br/><br/>⢠Merge fruits to create bigger ones (watermelon evolution)<br/>⢠Physics-based dropping and merging mechanics<br/>⢠Combo system for multiple merges<br/>⢠Difficulty affects merge requirements and spawn rate |
| <img src="https://cdn.worklage.com/playtura/screenshots/snake.png" alt="Snake & Eggs" width="120"/> | **š Snake & Eggs**<br/>Classic snake game with modern touch controls<br/><br/>⢠Classic snake gameplay with modern touch controls<br/>⢠Swipe or tap to change direction<br/>⢠Grow by eating food, avoid walls and yourself<br/>⢠Difficulty affects snake speed and grid size |
## š¦ Installation
```sh
npm install react-native-games
# or
yarn add react-native-games
```
## š§ Peer Dependencies
This library requires the following peer dependencies to be installed in your project:
```sh
npm install @shopify/react-native-skia react-native-reanimated react-native-gesture-handler react-native-worklets expo-speech expo-haptics
```
### Platform Setup
Follow the installation guides for each peer dependency:
- **[@shopify/react-native-skia](https://shopify.github.io/react-native-skia/docs/getting-started/installation)** - Graphics
- **[react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started)** - Animations
- **[react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation)** - Gestures
- **[expo-speech](https://docs.expo.dev/versions/latest/sdk/speech/)** - Sounds
- **[expo-haptics](https://docs.expo.dev/versions/latest/sdk/haptics/)** - Haptics
## š Usage
### Simple Implementation
For basic usage without settings persistence:
```tsx
import React, { useState } from 'react';
import { View } from 'react-native';
import { DEFAULT_GAME_SETTINGS, FruitNinja } from 'react-native-games';
export default function GameScreen() {
const [settings, setSettings] = useState(DEFAULT_GAME_SETTINGS);
return (
<View style={{ flex: 1 }}>
<FruitNinja settings={settings} onSettingsChange={setSettings} />
</View>
);
}
```
### Advanced Implementation Example
All games use the same props pattern for consistency. Here's a complete example with settings persistence and navigation integration:
```tsx
import { View, TouchableOpacity } from 'react-native';
import { useState, useLayoutEffect } from 'react';
import { useNavigation, useTheme } from '@react-navigation/native';
import { Ionicons } from '@expo/vector-icons';
import { DEFAULT_GAME_SETTINGS, GAME_IDS, type GameSettings, FruitNinja } from 'react-native-games';
import { StorageService } from '../services/StorageService';
export default function FruitNinjaScreen() {
const { colors } = useTheme();
const storedSettings = StorageService.get(GAME_IDS.FRUIT_NINJA);
const [settings, setSettings] = useState(storedSettings || DEFAULT_GAME_SETTINGS);
const navigation = useNavigation();
const handleSettingsChange = (newSettings: GameSettings) => {
setSettings(newSettings);
StorageService.set(GAME_IDS.FRUIT_NINJA, newSettings);
};
const handleToggleSettingsModal = () => {
setSettings({...settings, isVisible: !settings.isVisible});
};
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity className="p-2" onPress={handleToggleSettingsModal}>
<Ionicons name="settings-outline" size={24} color={colors.text} />
</TouchableOpacity>
),
});
}, [navigation, handleToggleSettingsModal]);
return (
<View className="flex-1 bg-background">
<FruitNinja settings={settings} onSettingsChange={handleSettingsChange} />
</View>
);
}
```
### Available Games
All games use the same props interface:
```tsx
// Import any game you want
import {
FruitNinja,
CandyCrush,
FlappyBird,
ColorsSort,
DinoJump,
PopitFidget,
WhackAMole,
BalloonBlaster,
SpaceFighter,
MazeRunner,
SlidingNumbers,
Game2048,
FruitMerger,
Snake
} from 'react-native-games';
// All games accept the same props:
<GameComponent
settings={settings}
onSettingsChange={handleSettingsChange}
/>
```
### Game Settings & Configuration
All games use the unified `GameSettings` interface:
```tsx
interface GameSettings {
isVisible: boolean; // Settings modal visibility
difficulty: 'easy' | 'medium' | 'hard';
enableSounds: boolean; // Audio feedback
enableHaptics: boolean; // Haptic feedback
}
// Default settings for all games
const DEFAULT_GAME_SETTINGS = {
isVisible: false,
difficulty: 'medium',
enableSounds: true,
enableHaptics: true,
offset: 0,
};
```
### Game Settings
Each game includes built-in settings screens with a unified, simplified interface:
- **Difficulty Levels**: Easy, Medium, Hard - each game has custom difficulty descriptions and behaviors
- **Sound Effects**: Toggle audio feedback on/off
- **Haptic Feedback**: Toggle vibration feedback on/off
All games use a centralized settings system for consistency and ease of maintenance. Game durations and difficulty behaviors are customized per game for optimal gameplay experience.
## š API Reference
### Exported Constants & Types
```tsx
import {
// Game IDs Enum
GAME_IDS,
// Default Settings
DEFAULT_GAME_SETTINGS,
// Games List & Mapping
GAMES_LIST,
GAMES_MAPPING,
// TypeScript Types
type GameSettings,
type GameProps,
type GameDefinition,
type GameComponent,
// All Game Components
FruitNinja,
CandyCrush,
FlappyBird,
ColorsSort,
DinoJump,
PopitFidget,
WhackAMole,
BalloonBlaster,
SpaceFighter,
MazeRunner,
SlidingNumbers,
Game2048,
FruitMerger,
Snake
} from 'react-native-games';
```
### GAME_IDS Enum
All available game identifiers:
```tsx
GAME_IDS.FRUIT_NINJA // 'fruit-ninja'
GAME_IDS.CANDY_CRUSH // 'candy-crush'
GAME_IDS.FLAPPY_BIRD // 'flappy-bird'
GAME_IDS.COLORS_SORT // 'colors-sort'
GAME_IDS.DINO_JUMP // 'dino-jump'
GAME_IDS.POPIT_FIDGET // 'popit-fidget'
GAME_IDS.WHACK_A_MOLE // 'whack-a-mole'
GAME_IDS.BALLOON_BLASTER // 'balloon-blaster'
GAME_IDS.SPACE_FIGHTER // 'space-fighter'
GAME_IDS.MAZE_RUNNER // 'maze-runner'
GAME_IDS.SLIDING_NUMBERS // 'sliding-numbers'
GAME_IDS.GAME_2048 // 'game-2048'
GAME_IDS.FRUIT_MERGER // 'fruit-merger'
GAME_IDS.SNAKE // 'snake'
```
### DEFAULT_GAME_SETTINGS
Default configuration for all games:
```tsx
const DEFAULT_GAME_SETTINGS = {
isVisible: false, // Settings modal visibility
difficulty: 'medium', // Game difficulty level
enableSounds: true, // Audio feedback enabled
enableHaptics: true, // Haptic feedback enabled
offset: 0, // Top offset for notch/status bar
};
// Example: Custom settings with offset
const customSettings = {
...DEFAULT_GAME_SETTINGS,
offset: 50, // Moves game elements 50px down from top
};
```
### GAMES_LIST
Array of all game definitions with metadata:
```tsx
// GAMES_LIST is an array of GameDefinition objects
GAMES_LIST.forEach(game => {
console.log(game.id); // GAME_IDS enum value
console.log(game.title); // Display title
console.log(game.description); // Game description
console.log(game.component); // React component
});
// Example: Find a specific game
const fruitNinja = GAMES_LIST.find(g => g.id === GAME_IDS.FRUIT_NINJA);
```
### GAMES_MAPPING
Object mapping game IDs to their components:
```tsx
// Access game component by ID
const GameComponent = GAMES_MAPPING[GAME_IDS.FRUIT_NINJA];
// Render dynamically
<GameComponent settings={settings} onSettingsChange={handleChange} />
```
### TypeScript Types
```tsx
// Game settings interface
interface GameSettings {
isVisible: boolean; // Settings modal visibility
difficulty: 'easy' | 'medium' | 'hard';
enableSounds: boolean; // Audio feedback
enableHaptics: boolean; // Haptic feedback
offset?: number; // Optional padding from top (default: 0)
}
// Game component props
interface GameProps {
settings?: GameSettings;
onSettingsChange?: (settings: GameSettings) => void;
}
```
## š License
This library is available under a **dual licensing model**:
### š **Non-Commercial License (Free)**
- ā
**Personal projects** and learning
- ā
**Educational use** and research
- ā
**Open source projects** (non-commercial)
- ā
**Portfolio** and demonstration apps
### š¼ **Commercial License (Paid)**
Required for commercial use including:
- š¢ **Commercial applications** and products
- š° **Revenue-generating** projects
- šŖ **App Store** or **Play Store** apps with monetization
- š **Enterprise** and business applications
**Commercial licensing includes:**
- Full commercial usage rights
- Priority support and maintenance
- Custom feature development consideration
- Optional attribution removal
**Get Commercial License:**
š§ Email: [niranjan.devasani@gmail.com](mailto:niranjan.devasani@gmail.com?subject=React%20Native%20Games%20-%20Commercial%20License%20Request)
See the complete [LICENSE](LICENSE) file for detailed terms and definitions.
## š Acknowledgments
- Built with [React Native Skia](https://shopify.github.io/react-native-skia/) for high-performance graphics
- Powered by [React Native Reanimated](https://docs.swmansion.com/react-native-reanimated/) for smooth animations
- Enhanced with [React Native Worklets](https://github.com/margelo/react-native-worklets) for high-performance JavaScript
- State management with [Zustand](https://github.com/pmndrs/zustand) and [Immer](https://github.com/immerjs/immer)
- Created with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
## š Support
- š§ **Email**: niranjan.devasani@gmail.com
- š **Issues**: [GitHub Issues](https://github.com/ursnj/nayan-ui/issues)
- š **Website**: [https://www.nayanui.com/games](https://www.nayanui.com/games)
---
**Made with ā¤ļø by [Niranjan Devasani](https://github.com/ursnj)**