I have built something similar to the popular game Flappy Bird - an object falls, and the user clicks a button causing that object to jump with the aim of making sure it doesn't hit the bottom of the screen.
I originally built this through many updates to state, ie the falling object and 'jump' effect was achieved by moving the position of the object a few pixels and re-rendering. Like this for example:
//falling effect
gameTimerId = setInterval(()=>{
setObjectHeight(objectHeight => objectHeight - 5)
}, 30)
return ()=>{
clearInterval(gameTimerId)
}
//jump effect (struggling to replicate this below)
const jump = () => {
if(!isGameOver && (objectHeight < screenHeight)){
setObjectHeight(objectHeight => objectHeight 50)
console.log("jumped!")
}
}
This is obviously a very inefficient way of doing things, so I have been trying to rework this using the react Animated API, which would animate using the UI thread.
I can achieve the falling effect, but am struggling to make the object jump while the falling effect is active. When the user clicks 'jump' the object should begin falling again but from a height slightly above where it currently is. I have read the docs and tried numerous options, none of which seem to work. Here is what I have so far:
export default App = () => {
// animated value for height of square on screen
const squareHeight = useRef(new Animated.Value(Dimensions.get('screen').height / 2)).current;
//gravity animation
const gravity = Animated.timing(squareHeight, {
toValue: 0,
duration: 2000,
useNativeDriver: true,
})
//start falling effect on component loading
useEffect(() => {
gravity.start()
}, []);
//PROBLEM - this should restart falling effect from square's current location 10px
const jump = () => {
//squareHeight.setValue(squareHeight 10)
gravity.start()
}
return (
<>
<Animated.View
style={[
{
position: 'absolute',
backgroundColor: 'blue',
width: 50,
height: 60,
bottom: squareHeight,
},
]}/>
<Button title="Jump!" onPress={jump}> </Button>
</>
);
};
I'm new to react native animated so grateful for help as to how to achieve this! Thanks.
CodePudding user response:
Change your jump function to this:
const jump = () => {
//squareHeight.setValue(squareHeight 10)
squareHeight._startingValue = squareHeight._value 10; // new starting value
gravity.reset();
gravity.start();
}
Explanation:
- First change your starting value of animation.
- Then reset the animation so it can be started again.
- Then start the animation.