Commit 6eefc77c authored by Lelkada L L P S M's avatar Lelkada L L P S M

flip cards game

parent 90633411
......@@ -9,6 +9,7 @@ import SpeechTherapyScreen from './screens/SpeechTherapyScreen';
import ProgressMapScreen from './screens/ProgressMapScreen';
import WordGameScreen from './screens/WordGameScreen';
import PhoneticWordScreen from './screens/PhoneticWordsScreen';
import FlipCardGameScreen from './screens/FlipCardGameScreen';
const MainStack = createStackNavigator(
{
......@@ -36,6 +37,9 @@ const MainStack = createStackNavigator(
PhoneticWord: {
screen: PhoneticWordScreen,
},
FlipCardGame: {
screen: FlipCardGameScreen,
},
},
{
initialRouteName: 'Login',
......
......@@ -5,6 +5,7 @@ npm install react-navigation
npm install @expo/vector-icons
expo install react-native-gesture-handler react-native-reanimated
expo install expo-screen-orientation
expo install react-native-svg
......
This diff is collapsed.
......@@ -18,11 +18,14 @@
"expo-status-bar": "~1.4.4",
"react": "18.2.0",
"react-native": "^0.71.4",
"react-native-draggable": "^3.3.0",
"react-native-draggable-flatlist": "^4.0.1",
"react-native-gesture-handler": "~2.9.0",
"react-native-orientation-locker": "^1.5.0",
"react-native-reanimated": "~2.14.4",
"react-native-safe-area-context": "4.5.0",
"react-native-screens": "~3.20.0",
"react-native-svg": "13.4.0",
"react-native-swiper": "^1.6.0",
"react-navigation": "^4.4.4",
"react-navigation-stack": "^2.10.4"
......
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, TouchableOpacity, Image, Text, Modal, Button } from 'react-native';
import { Audio } from 'expo-av';
const Card = ({ image, audio, onFlip, gameOver, correct }) => {
const [isFlipped, setIsFlipped] = useState(false);
useEffect(() => {
if (gameOver) {
setIsFlipped(true);
}
}, [gameOver]);
const handleFlip = async () => {
if (!isFlipped && !gameOver) {
setIsFlipped(true);
await Audio.Sound.createAsync(audio, { shouldPlay: true });
onFlip(image);
setTimeout(() => {
setIsFlipped(true);
}, 800);
}
};
return (
<TouchableOpacity
style={[styles.card, correct && gameOver ? styles.correctCard : null]}
onPress={handleFlip}
>
<Image source={isFlipped ? image : require('./assets/ST/owl.png')} style={styles.cardImage} />
</TouchableOpacity>
);
};
const MessageBox = ({ visible, onClose }) => {
return (
<Modal animationType="slide" transparent={true} visible={visible}>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
<Text style={styles.modalText}>Game Over</Text>
<Button title="Close" onPress={onClose} />
</View>
</View>
</Modal>
);
};
export default function FlipCardGame() {
const [gameOver, setGameOver] = useState(false);
const images = [
{ image: require('./assets/CG/content/vegetable.png'), audio: require('./assets/CG/content/vegetable.m4a') },
{ image: require('./assets/CG/content/kitchen.png'), audio: require('./assets/CG/content/kitchen.m4a') },
{ image: require('./assets/CG/content/pot.png'), audio: require('./assets/CG/content/pot.m4a') },
];
const mainImage = require('./assets/CG/content/kitchen.png');
const handleCardFlip = (image) => {
if (image === mainImage) {
setGameOver(true);
}
};
return (
<View style={styles.container}>
<Image source={mainImage} style={styles.mainImage} />
<View style={styles.cardsContainer}>
{images.map((img, index) => (
<Card
key={index}
image={img.image}
audio={img.audio}
onFlip={handleCardFlip}
gameOver={gameOver}
correct={img.image === mainImage}
/>
))}
</View>
<MessageBox visible={gameOver} onClose={() => setGameOver(false)} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
mainImage: {
width: '100%',
height: '40%',
resizeMode: 'contain',
},
cardsContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
width: '100%',
paddingTop: 20,
},
card: {
width: '30%',
aspectRatio: 1,
backgroundColor: '#ccc',
justifyContent: 'center',
alignItems: 'center',
},
cardImage: {
width: '100%',
height: '100%',
resizeMode: 'contain',
},
correctCard: {
borderColor: 'green',
borderWidth: 5,
},
});
This diff is collapsed.
import React, { useState, useEffect,useRef } from 'react';
import { StyleSheet, View, Image } from 'react-native';
import Animated, { useSharedValue, useAnimatedGestureHandler, useAnimatedStyle, withSpring , runOnJS} from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';
import { useWindowDimensions } from 'react-native';
const images = [
{
id: 1,
src: require('./assets/CG/content/kitchen.png'),
bwSrc: require('./assets/CG/content/kitchen.png'),
},
{
id: 2,
src: require('./assets/CG/content/pot.png'),
bwSrc: require('./assets/CG/content/pot.png'),
},
{
id: 3,
src: require('./assets/CG/content/vegetable.png'),
bwSrc: require('./assets/CG/content/vegetable.png'),
},
];
// ... images array ...
export default function App() {
const windowDimensions = useWindowDimensions();
const halfWidth = windowDimensions.width / 2;
const [correctCount, setCorrectCount] = useState(0);
const popAnim = useRef(new Animated.Value(0)).current;
const popInterpolation = popAnim.interpolate({
inputRange: [0, 1],
outputRange: [1, 1.2], // Scale from 1 to 1.2
});
const startPopAnimation = () => {
Animated.sequence([
Animated.timing(popAnim, {
toValue: 1,
duration: 100,
useNativeDriver: true,
}),
Animated.timing(popAnim, {
toValue: 0,
duration: 100,
useNativeDriver: true,
}),
]).start();
};
const onDrop = (id, event) => {
const correctImage = images.find((img) => img.id === id);
correctImage.correctPosition = {
x: event.absoluteX - 100,
y: event.absoluteY - 100,
};
setCorrectCount((prev) => prev + 1);
if (correctCount + 1 === images.length) {
startPopAnimation();
}
};
const shuffledImages = [...images].sort(() => Math.random() - 0.5);
return (
<View style={styles.container}>
<View style={styles.leftSide}>
{images.map((image) => (
<DraggableImage key={image.id} image={image} onDrop={onDrop} />
))}
</View>
<View style={styles.rightSide}>
{shuffledImages.map((image, index) => (
<View key={image.id} style={styles.targetContainer}>
<Image style={styles.targetImage} source={image.bwSrc} />
<View
style={styles.dropZone}
onLayout={(event) => {
const layout = event.nativeEvent.layout;
images.find((img) => img.id === image.id).correctPosition = {
x: layout.x,
y: layout.y,
};
}}
/>
</View>
))}
</View>
</View>
);
}
const DraggableImage = ({ image, onDrop }) => {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const setCorrectPosition = (id, position) => {
images.find((img) => img.id === id).correctPosition = position;
};
const gestureHandler = useAnimatedGestureHandler({
onStart: (_, ctx) => {
ctx.startX = translateX.value;
ctx.startY = translateY.value;
},
onActive: (event, ctx) => {
translateX.value = ctx.startX + event.translationX;
translateY.value = ctx.startY + event.translationY;
},
onEnd: (event) => {
if (!image.correctPosition) return;
const correctPosition = image.correctPosition;
const isCorrectPosition =
Math.abs(translateX.value - correctPosition.x) < 50 &&
Math.abs(translateY.value - correctPosition.y) < 50;
if (isCorrectPosition) {
runOnJS(onDrop)(image.id, event);
translateX.value = withSpring(correctPosition.x);
translateY.value = withSpring(correctPosition.y);
} else {
translateX.value = withSpring(0);
translateY.value = withSpring(0);
}
},
});
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: translateX.value,
},
{
translateY: translateY.value,
},
],
};
});
return (
<PanGestureHandler onGestureEvent={gestureHandler}>
<Animated.View style={[styles.draggableImage, animatedStyle]}>
<Image style={styles.image} source={image.src} />
</Animated.View>
</PanGestureHandler>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
},
leftSide: {
flex: 1,
justifyContent: 'space-around',
alignItems: 'center',
},
rightSide: {
flex: 1,
justifyContent: 'space-around',
alignItems: 'center',
},
draggableImage: {
width: 100,
height: 100,
},
targetImage: {
width: 100,
height: 100,
},
image: {
width: '100%',
height: '100%',
},
animatedElement: {
width: 100,
height: 100,
backgroundColor: 'blue',
},
dropZone: {
width: 100,
height: 100,
backgroundColor: 'gray',
marginBottom: 10,
},
});
\ No newline at end of file
......@@ -107,7 +107,7 @@ export default function ContentGenerationScreen({ navigation }) {
{index === cards.length - 1 && (
<TouchableOpacity
onPress={() => navigation.navigate('WordGame')}
onPress={() => navigation.navigate('FlipCardGame')}
style={styles.nextButton}
>
<MaterialIcons name="keyboard-arrow-right" size={65} color="#FFCE6D" />
......
......@@ -1074,7 +1074,7 @@
"@babel/types" "^7.4.4"
"esutils" "^2.0.2"
"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7":
"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7", "@babel/preset-typescript@^7.17.12":
"integrity" "sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg=="
"resolved" "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.0.tgz"
"version" "7.21.0"
......@@ -2606,6 +2606,11 @@
"type-is" "~1.6.18"
"unpipe" "1.0.0"
"boolbase@^1.0.0":
"integrity" "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
"resolved" "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz"
"version" "1.0.0"
"bplist-creator@0.1.0":
"integrity" "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg=="
"resolved" "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz"
......@@ -3176,6 +3181,30 @@
"resolved" "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz"
"version" "2.0.0"
"css-select@^5.1.0":
"integrity" "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg=="
"resolved" "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz"
"version" "5.1.0"
dependencies:
"boolbase" "^1.0.0"
"css-what" "^6.1.0"
"domhandler" "^5.0.2"
"domutils" "^3.0.1"
"nth-check" "^2.0.1"
"css-tree@^1.1.3":
"integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="
"resolved" "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz"
"version" "1.1.3"
dependencies:
"mdn-data" "2.0.14"
"source-map" "^0.6.1"
"css-what@^6.1.0":
"integrity" "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
"resolved" "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz"
"version" "6.1.0"
"dag-map@~1.0.0":
"integrity" "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw=="
"resolved" "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz"
......@@ -3352,6 +3381,36 @@
dependencies:
"path-type" "^4.0.0"
"dom-serializer@^2.0.0":
"integrity" "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="
"resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz"
"version" "2.0.0"
dependencies:
"domelementtype" "^2.3.0"
"domhandler" "^5.0.2"
"entities" "^4.2.0"
"domelementtype@^2.3.0":
"integrity" "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
"resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz"
"version" "2.3.0"
"domhandler@^5.0.1", "domhandler@^5.0.2":
"integrity" "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="
"resolved" "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz"
"version" "5.0.3"
dependencies:
"domelementtype" "^2.3.0"
"domutils@^3.0.1":
"integrity" "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q=="
"resolved" "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz"
"version" "3.0.1"
dependencies:
"dom-serializer" "^2.0.0"
"domelementtype" "^2.3.0"
"domhandler" "^5.0.1"
"ee-first@1.1.1":
"integrity" "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
"resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz"
......@@ -3386,6 +3445,11 @@
dependencies:
"once" "^1.4.0"
"entities@^4.2.0":
"integrity" "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
"resolved" "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz"
"version" "4.5.0"
"env-editor@^0.4.1":
"integrity" "sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA=="
"resolved" "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz"
......@@ -4949,6 +5013,11 @@
"resolved" "https://registry.npmjs.org/md5hex/-/md5hex-1.0.0.tgz"
"version" "1.0.0"
"mdn-data@2.0.14":
"integrity" "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="
"resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz"
"version" "2.0.14"
"media-typer@0.3.0":
"integrity" "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
"resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
......@@ -5677,6 +5746,13 @@
dependencies:
"path-key" "^3.0.0"
"nth-check@^2.0.1":
"integrity" "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="
"resolved" "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz"
"version" "2.1.1"
dependencies:
"boolbase" "^1.0.0"
"nullthrows@^1.1.1":
"integrity" "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="
"resolved" "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz"
......@@ -6231,7 +6307,21 @@
"jscodeshift" "^0.13.1"
"nullthrows" "^1.1.1"
"react-native-gesture-handler@>= 1.0.0", "react-native-gesture-handler@>= 1.5.0", "react-native-gesture-handler@~2.9.0":
"react-native-draggable-flatlist@^4.0.1":
"integrity" "sha512-ZO1QUTNx64KZfXGXeXcBfql67l38X7kBcJ3rxUVZzPHt5r035GnGzIC0F8rqSXp6zgnwgUYMfB6zQc5PKmPL9Q=="
"resolved" "https://registry.npmjs.org/react-native-draggable-flatlist/-/react-native-draggable-flatlist-4.0.1.tgz"
"version" "4.0.1"
dependencies:
"@babel/preset-typescript" "^7.17.12"
"react-native-draggable@^3.3.0":
"integrity" "sha512-aU20CaKBmzXrwE9eTJZ+GDOr52mXLchg5Vydbx5rz8nYXlN+ppHIoTPgyXduyWNwpZ/DR6tyFtMwdgUHpuN6oA=="
"resolved" "https://registry.npmjs.org/react-native-draggable/-/react-native-draggable-3.3.0.tgz"
"version" "3.3.0"
dependencies:
"prop-types" "^15.7.2"
"react-native-gesture-handler@>= 1.0.0", "react-native-gesture-handler@>= 1.5.0", "react-native-gesture-handler@>=2.0.0", "react-native-gesture-handler@~2.9.0":
"integrity" "sha512-a0BcH3Qb1tgVqUutc6d3VuWQkI1AM3+fJx8dkxzZs9t06qA27QgURYFoklpabuWpsUTzuKRpxleykp25E8m7tg=="
"resolved" "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.9.0.tgz"
"version" "2.9.0"
......@@ -6257,7 +6347,7 @@
"resolved" "https://registry.npmjs.org/react-native-orientation-locker/-/react-native-orientation-locker-1.5.0.tgz"
"version" "1.5.0"
"react-native-reanimated@~2.14.4":
"react-native-reanimated@>=2.8.0", "react-native-reanimated@~2.14.4":
"integrity" "sha512-DquSbl7P8j4SAmc+kRdd75Ianm8G+IYQ9T4AQ6lrpLVeDkhZmjWI0wkutKWnp6L7c5XNVUrFDUf69dwETLCItQ=="
"resolved" "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.14.4.tgz"
"version" "2.14.4"
......@@ -6290,6 +6380,14 @@
"react-freeze" "^1.0.0"
"warn-once" "^0.1.0"
"react-native-svg@13.4.0":
"integrity" "sha512-B3TwK+H0+JuRhYPzF21AgqMt4fjhCwDZ9QUtwNstT5XcslJBXC0FoTkdZo8IEb1Sv4suSqhZwlAY6lwOv3tHag=="
"resolved" "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.4.0.tgz"
"version" "13.4.0"
dependencies:
"css-select" "^5.1.0"
"css-tree" "^1.1.3"
"react-native-swiper@^1.6.0":
"integrity" "sha512-OnkTTZi+9uZUgy0uz1I9oYDhCU3z36lZn+LFsk9FXPRelxb/KeABzvPs3r3SrHWy1aA67KGtSFj0xNK2QD0NJQ=="
"resolved" "https://registry.npmjs.org/react-native-swiper/-/react-native-swiper-1.6.0.tgz"
......@@ -6338,7 +6436,7 @@
"whatwg-fetch" "^3.0.0"
"ws" "^6.2.2"
"react-native@*", "react-native@^0.71.0", "react-native@^0.71.4", "react-native@>=0.42.0", "react-native@>=0.57", "react-native@>=0.63.2":
"react-native@*", "react-native@^0.71.0", "react-native@^0.71.4", "react-native@>=0.42.0", "react-native@>=0.57", "react-native@>=0.63.2", "react-native@>=0.64.0":
"integrity" "sha512-3hSYqvWrOdKhpV3HpEKp1/CkWx8Sr/N/miCrmUIAsVTSJUR7JW0VvIsrV9urDhUj/s6v2WF4n7qIEEJsmTCrPw=="
"resolved" "https://registry.npmjs.org/react-native/-/react-native-0.71.4.tgz"
"version" "0.71.4"
......@@ -6981,6 +7079,11 @@
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
"version" "0.6.1"
"source-map@^0.6.1":
"integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz"
"version" "0.6.1"
"source-map@^0.7.3":
"integrity" "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="
"resolved" "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment