import React , { useCallback , useImperativeHandle , useMemo } from 'react' ; import { ArcadeCollider , ArcadeImageProps , GameObject , useGameLoop , useScene , ArcadeImage , } from 'react-phaser-fiber' ; export interface BallProps extends Omit < ArcadeImageProps , 'ref' | 'texture' | 'x' | 'y' > { paddleRef : React . RefObject < Phaser . Physics . Arcade . Image > ; snapToPaddle : boolean ; onReset : ( ) => void ; } function Ball ( { paddleRef , snapToPaddle , onReset , ... props } , ref ) { const scene = useScene ( ) ; const ball = useMemo ( ( ) => new Phaser . Physics . Arcade . Image ( scene , 0 , 0 , 'assets' , 'ball1' ) , [ scene ] ) ; useImperativeHandle ( ref , ( ) => ball ) ; useGameLoop ( useCallback ( ( ) => { if ( paddleRef . current && snapToPaddle ) { ball . setPosition ( paddleRef . current . x , paddleRef . current . y - 48 ) ; } if ( ball . y > 800 ) { ball . setVelocity ( 0 ) ; onReset ( ) ; } } , [ ball , snapToPaddle , onReset , paddleRef ] ) ) ; return ( < ArcadeImage instance = { ball } name = "ball" bounce = { 1 } collideWorldBounds { ... props } > < ArcadeCollider with = "paddle" onCollide = { ( self , paddle ) => { if ( ball . x < paddle . x ) { const diff = paddle . x - ball . x ; ball . setVelocityX ( - 10 * diff ) ; } else if ( ball . x > paddle . x ) { const diff = ball . x - paddle . x ; ball . setVelocityX ( 10 * diff ) ; } else { ball . setVelocityX ( 2 + Math . random ( ) * 8 ) ; } } } /> < /ArcadeImage>); } export default React . forwardRef ( Ball ) ;