-
Notifications
You must be signed in to change notification settings - Fork 0
/
App.js
138 lines (116 loc) · 3.5 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { StatusBar } from 'expo-status-bar'
import React, { useState, useEffect } from 'react'
import { StyleSheet, View, Vibration, Text } from 'react-native'
import { Accelerometer } from 'expo-sensors'
import Ball from './components/Ball'
import { SCREEN_HEIGHT, SCREEN_WIDTH, BALL_SIZE, BALL_RAYON, NUMBER_OF_BALLS, GRAVITY } from './helpers/utils'
const App = () => {
// Variable du timer
const [timer, setTimer] = useState(0)
// Position de la balle
const [ballTop, setBallTop] = useState(SCREEN_HEIGHT / 2 - BALL_RAYON)
const [ballLeft, setBallLeft] = useState(SCREEN_WIDTH / 2 - BALL_RAYON)
// Les fonctions de l'accéléromètre
Accelerometer.setUpdateInterval(15)
// Les data du capteur
const [data, setData] = useState({
x: 0,
y: 0,
z: 0,
})
const [subscription, setSubscription] = useState(null)
// Voir la documentation de expo
const _subscribe = () => {
setSubscription(
Accelerometer.addListener(accelerometerData => {
setData(accelerometerData)
})
)
}
// Voir la documentation de expo
const _unsubscribe = () => {
subscription && subscription.remove()
setSubscription(null)
}
useEffect(() => {
_subscribe()
return () => _unsubscribe()
}, [])
const { x, y, z } = data
// Tableau avec toutes les balles
let balls = []
// Création de chaque balle en fonction du nombre de balle
for (let i = 0; i < NUMBER_OF_BALLS; i++) {
const ball = <Ball
key={i}
size={BALL_SIZE}
left={ballLeft}
top={ballTop}
borderRadius={BALL_RAYON}
/>
// Ajout des balles au tableau
balls.push(ball)
}
// Animation des balles avec les conditions de l'écran et des collisions
useEffect(() => {
// On bouge la ball uniquement si elle est dans l'écran
if(ballTop < SCREEN_HEIGHT - BALL_SIZE && ballTop > 0 && ballLeft < SCREEN_WIDTH - BALL_SIZE && ballLeft > 0) {
const interval = setInterval(() => {
setBallTop(ballTop => ballTop - round(y) * GRAVITY)
setBallLeft(ballLeft => ballLeft + round(x) * GRAVITY)
}, 3)
// On clear l'interval pour ne pas surcharger la batterie du téléphone
return () => clearInterval(interval)
}
// Si la ball touche le haut de l'écran
if(ballTop <= 0) {
setBallTop(1)
Vibration.vibrate()
}
// Si la ball touche le bas de l'écran
if(ballTop >= SCREEN_HEIGHT - BALL_SIZE) {
setBallTop(SCREEN_HEIGHT - BALL_SIZE - 1)
Vibration.vibrate()
}
// Si la ball touche la gauche de l'écran
if(ballLeft <= 0) {
setBallLeft(1)
Vibration.vibrate()
}
// Si la ball touche la droite de l'écran
if(ballLeft >= SCREEN_WIDTH - BALL_SIZE) {
setBallLeft(SCREEN_WIDTH - BALL_SIZE - 1)
Vibration.vibrate()
}
}, [ballTop, ballLeft])
// On ajoute 1 au timer toutes les secondes car 1000ms = 1s
useEffect(() => {
setInterval(() => {
setTimer(timer => timer + 1)
}, 1000)
}, [])
// On affiche la view
return (
<View style={styles.container}>
<StatusBar style="auto" />
<Text>Temps écoulé : {timer}s</Text>
{balls}
</View>
)
}
// Fonction pour arrondir les données de l'accéléromètre qui sont avec trop de décimal par défaut
const round = (n) => {
if (!n) {
return 0
}
return Math.floor(n * 100) / 100
}
// Stylesheet
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
justifyContent: 'center',
alignItems: 'center'
},
})
export default App