Open In App

Create a Spin the Bottle game using React-Native

Last Updated : 27 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

React-Native is an open-source framework used to develop cross-platform applications i.e., you can write code in React-Native and publish it as an Android or IOS app. In this article, we will build a basic Spin the Bottle game in React-Native. This is a multi-player game. Usually, people sit in a round with a bottle at the center. When the bottle stops spinning, the turn goes to the person at whom the bottle's tip stops.

Playground

Note: This Section is to interact with the app which you are going to build.

Prerequisites

Step-by-Step Implementation

Step 1: Create a React Native Project

Now, create a project with the following command.

npx create-expo-app app-name --template

Note: Replace the app-name with your app name for example : react-native-demo-app

Next, you might be asked to choose a template. Select one based on your preference as shown in the image below. I am selecting the blank template because it will generate a minimal app that is as clean as an empty canvas in JavaScript.

It completes the project creation and displays a message: "Your Project is ready!" as shown in the image below.

Now go into your project folder, i.e., react-native-demo

cd app-name

Project Structure:

Step 2: Run  Application

Start the server by using the following command.

npx expo start

Then, the application will display a QR code.

  • For the Android users,
    • For the Android Emulator, press " a" as mentioned in the image below.
    • For the Physical Device, download the " Expo Go " app from the Play Store. Open the app, and you will see a button labeled " Scan QR Code. " Click that button and scan the QR code; it will automatically build the Android app on your device.
  • For iOS users, simply scan the QR code using the Camera app .
  • If you're using a web browser, it will provide a local host link that you can use as mentioned in the image below.

Step 3: Start Coding

- Approach to create Spin the Bottle Game:

The game screen will display a bottle and a SPIN button. The bottle will start spinning when the SPIN button is clicked. The bottle will stop at a random position to indicate the turn of a person. The random position can be set using the Math.random() function. The spinning animation can be set using the Animated module of React-Native. The Spin the Bottle game can be used to play the famous games like Truth or Dare, Pictionary, Two Truths and a Lie etc.

Let's dive into the code in detail.

Import libraries:

Import required libraries at the top of the file.

JavaScript
// Import required hooks and components from React and React Native
import { useRef } from 'react';
import {
  View,
  Pressable,
  Text,
  Animated,
  Easing,
  StyleSheet,
} from 'react-native';


StyleSheet:

Create a StyleSheet to style components like container, geekText, bottle, etc.

JavaScript
// Styles for the components
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  geekText: {
    marginBottom: '10%',
    fontSize: 25,
    color: '#228B22',
    fontWeight: 'bold',
  },
  bottle: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  rectangle3: {
    width: 30,
    height: 14,
    backgroundColor: '#43E71A', // Top part of the bottle
  },
  rectangle2: {
    width: 100,
    height: 106,
    backgroundColor: '#B4F6A3', // Neck of the bottle
    borderTopLeftRadius: 40,
    borderTopRightRadius: 40,
    overflow: 'hidden',
  },
  rectangle1: {
    width: 100,
    height: 157,
    backgroundColor: '#A2F74D', // Body of the bottle
  },
  spinButton: {
    alignItems: 'center',
    marginTop: '20%',
    borderRadius: 5,
    paddingTop: 6,
    paddingBottom: 6,
    paddingLeft: 15,
    paddingRight: 15,
  },
  spinButtonText: {
    fontSize: 18,
    color: 'white',
    userSelect: 'none', // Prevents accidental text selection on desktop
  },
});


Title Text:

This title explains what the app does. We use the text "Spin the bottle" to show that the app is to play the Spin the bottle Game.

JavaScript
{/* Title Text */}
<Text style={styles.geekText}>Spin the bottle</Text>


- Spin Button:

This button is used to call startSpinAnimation and the function contains the game logic to spin the bottle.

JavaScript
// Animated value that controls the rotation
const spinValue = useRef(new Animated.Value(0)).current;
// Ref to prevent multiple spins at the same time
const isSpinning = useRef(false);

// Function to start the spin animation
const startSpinAnimation = () => {
 if (!isSpinning.current) {
  isSpinning.current = true;
  spinValue.setValue(0); // Reset the spin value before starting

  Animated.timing(spinValue, {
    // Randomize spin by adding a decimal to 10 full rotations
    toValue: 10 + generateRandomDecimal(),
    duration: 2000, // Duration of animation in milliseconds
    easing: Easing.bezier(0.16, 1, 0.3, 1), // Smooth acceleration/deceleration
    useNativeDriver: false, // Not using native driver as rotation is in degrees
  }).start(() => {
    isSpinning.current = false; // Mark as not spinning when animation completes
    // Optional: Add logic here after spinning ends
  });
 }
};

{/* Spin Button */}
<Pressable
    style={({ pressed }) => [
      styles.spinButton,
      {
        backgroundColor: pressed ? '#0F9D58' : '#14EF37', // Button press feedback
      },
    ]}
    onPress={startSpinAnimation}>
    <Text style={styles.spinButtonText}>SPIN</Text>
</Pressable>


- Display Bottle:

Below code is used to display the bottle which is spinning.

JavaScript
// Interpolating the animated value to degrees for rotation
const spin = spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg'], // One full rotation
});

{/* Animated bottle built using nested Views */}
<Animated.View style={[styles.bottle, { transform: [{ rotate: spin }] }]}>
    <View style={styles.rectangle3}></View>
    <View style={styles.rectangle2}></View>
    <View style={styles.rectangle1}></View>
</Animated.View>

Now, wrap all design code with a View component, return it from the App component, and place all methods and useStates within the App component. Ensure to export the App.

Complete Source Code

App.js:

App.js
// Import required hooks and components from React and React Native
import { useRef } from 'react';
import {
  View,
  Pressable,
  Text,
  Animated,
  Easing,
  StyleSheet,
} from 'react-native';

// Function to generate a random decimal between 0.00 and 1.00
const generateRandomDecimal = () => {
  const randomNumber = Math.random();
  return parseFloat(randomNumber.toFixed(2));
};

// Main component that implements the spinning bottle animation
const SpinBottle = () => {
  // Animated value that controls the rotation
  const spinValue = useRef(new Animated.Value(0)).current;

  // Ref to prevent multiple spins at the same time
  const isSpinning = useRef(false);

  // Function to start the spin animation
  const startSpinAnimation = () => {
    if (!isSpinning.current) {
      isSpinning.current = true;
      spinValue.setValue(0); // Reset the spin value before starting

      Animated.timing(spinValue, {
        // Randomize spin by adding a decimal to 10 full rotations
        toValue: 10 + generateRandomDecimal(),
        duration: 2000, // Duration of animation in milliseconds
        easing: Easing.bezier(0.16, 1, 0.3, 1), // Smooth acceleration/deceleration
        useNativeDriver: false, // Not using native driver as rotation is in degrees
      }).start(() => {
        isSpinning.current = false; // Mark as not spinning when animation completes
        // Optional: Add logic here after spinning ends
      });
    }
  };

  // Interpolating the animated value to degrees for rotation
  const spin = spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg'], // One full rotation
  });

  return (
    <View style={styles.container}>
      {/* Title Text */}
      <Text style={styles.geekText}>Spin the bottle</Text>

      {/* Animated bottle built using nested Views */}
      <Animated.View style={[styles.bottle, { transform: [{ rotate: spin }] }]}>
        <View style={styles.rectangle3}></View>
        <View style={styles.rectangle2}></View>
        <View style={styles.rectangle1}></View>
      </Animated.View>

      {/* Spin Button */}
      <Pressable
        style={({ pressed }) => [
          styles.spinButton,
          {
            backgroundColor: pressed ? '#0F9D58' : '#14EF37', // Button press feedback
          },
        ]}
        onPress={startSpinAnimation}>
        <Text style={styles.spinButtonText}>SPIN</Text>
      </Pressable>
    </View>
  );
};

// App root component rendering the SpinBottle
export default function App() {
  return <SpinBottle />;
}

// Styles for the components
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
  },
  geekText: {
    marginBottom: '10%',
    fontSize: 25,
    color: '#228B22',
    fontWeight: 'bold',
  },
  bottle: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  rectangle3: {
    width: 30,
    height: 14,
    backgroundColor: '#43E71A', // Top part of the bottle
  },
  rectangle2: {
    width: 100,
    height: 106,
    backgroundColor: '#B4F6A3', // Neck of the bottle
    borderTopLeftRadius: 40,
    borderTopRightRadius: 40,
    overflow: 'hidden',
  },
  rectangle1: {
    width: 100,
    height: 157,
    backgroundColor: '#A2F74D', // Body of the bottle
  },
  spinButton: {
    alignItems: 'center',
    marginTop: '20%',
    borderRadius: 5,
    paddingTop: 6,
    paddingBottom: 6,
    paddingLeft: 15,
    paddingRight: 15,
  },
  spinButtonText: {
    fontSize: 18,
    color: 'white',
    userSelect: 'none', // Prevents accidental text selection on desktop
  },
});

Output:



Next Article

Similar Reads