9.2 Make the collision sound more realistic

In the previous section (9.1) we completed the class that MusicNote plays audio. The following is the code for the collision sound effect playback. It can be seen from the above that we calculate the resultant force of the ball in motion according to the data of the gravity sensor, thereby determining the volume of the collision sound effect, and also determining the length of time when the collision sound fades out. So we can simulate the sound effect of the collision in a relatively simple way. When the speed of the ball is relatively large, the sound of the collision is large and the time of fading is long. When the ball collides slightly, the sound of the collision is small and it quickly fades out.

if collideXY in [1,2,4,8]:
    if (lastCollideXY != collideXY) and (abs(vX) > 0.5 or abs(vY) > 0.5):
        v =  math.sqrt( math.pow( vX , 2) + math.pow( vY , 2))
        self.myMusicPlayer.playNote( vol = (v / 100 ), fadeout = int(v * 100) )

Here is the complete code for this collision ball:

import math
from JMRPiFoundations.Skeleton.RPiSparkModule import RPiSparkModule
from Ball import Ball
from MusicNote import MusicNote

class BallBox(RPiSparkModule):
    ball = None
    damping = None
    myMusicPlayer = None

    def _drawVel(self):
        self.RPiSpark.Screen.Canvas.rectangle( (2, 2, 38, 16), 0, 0 )
        self.RPiSpark.Screen.write("DIS:{:1d}".format( self.damping ), xy=(0,4))

    def _changeDam(self, offsetVel):
        """
        Change damping of ball move
        offsetVel can be > 0 to increase damping or < 0 to reduce damping
        damping is limited between 0 and 9, default: 3
        """
        self.damping += offsetVel
        if self.damping < 0:
            self.damping = 0

        if self.damping > 9:
            self.damping = 9

    def onKeyButtonUp(self, channel):
        # Press SW_A to reduce damping
        if channel == self.RPiSparkConfig.BUTTON_ACT_A:
           self._changeDam(-1)
           return

        # Press SW_B to increase damping
        if channel == self.RPiSparkConfig.BUTTON_ACT_B:
           self._changeDam(1)
           return

    def setup(self):
        self.damping = 3
        self.ball = Ball(64, 32, 5)
        # setup all key buttons to INT mode, same time query work fine
        self.initKeyButtons("INT")
        # Open accel
        self.RPiSpark.Attitude.open() #.openWith(temp=True, accel=True, gyro=True)
        self.myMusicPlayer = MusicNote()

        self.RPiSpark.Audio.on()

    def run(self):

        vX = 0
        vY = 0
        fv = -3
        collideXY = 0
        lastCollideXY = 0

        # Play background music
        self.myMusicPlayer.playBgMusic()

        while True:
            # Check exit key status ( JOY_UP + SW_A )
            if self.readExitButtonStatus():
                break;

            # Get Accel data from attitude sensor
            accelData = self.RPiSpark.Attitude.getAccelData()

            vX += accelData["x"]
            vY += accelData["y"]

            collideXY = self.ball.move( -vX, vY )

            if collideXY > 0:
                if collideXY in [1,2,5,6,9,10]:
                    vX += fv if vX > 0 else -fv
                    if abs(vX)<0.5: vX = 0
                    vX = -vX

                if collideXY in [4,8,5,6,9,10]:
                    vY += fv if vY > 0 else -fv
                    if abs(vY)<0.5: vY = 0
                    vY = -vY

                if collideXY in [1,2,4,8]:
                    if (lastCollideXY != collideXY) and (abs(vX) > 0.5 or abs(vY) > 0.5):
                        v =  math.sqrt( math.pow( vX , 2) + math.pow( vY , 2))
                        self.myMusicPlayer.playNote( vol = (v / 100 ), fadeout = int(v * 100) )

            lastCollideXY = collideXY

            # Move the ball up
            if self.readKeyButton(self.RPiSparkConfig.BUTTON_JOY_UP):
                self.ball.move(0, -self.damping)

            # Move the ball down
            if self.readKeyButton(self.RPiSparkConfig.BUTTON_JOY_DOWN):
                self.ball.move(0, self.damping)

            # Move the ball left
            if self.readKeyButton(self.RPiSparkConfig.BUTTON_JOY_LEFT):
                self.ball.move(-self.damping, 0)

            # Move the ball right
            if self.readKeyButton(self.RPiSparkConfig.BUTTON_JOY_RIGHT):
                self.ball.move(self.damping, 0)

            # Move the ball to center of screen
            if self.readKeyButton(self.RPiSparkConfig.BUTTON_JOY_OK):
                self.ball.reset()

            # Drawing the ball on the screen
            self.RPiSpark.Screen.clear()
            self._drawVel()
            self.RPiSpark.Screen.Canvas.ellipse( self.ball.getXY(), 1, 1 )
            self.RPiSpark.Screen.refresh()

        self.releaseKeyButtons()
        self.myMusicPlayer.stop()
        self.RPiSpark.Audio.off()
        print("BallBox is done.")

Save as BallBox_9_2.py and execute the following command in the terminal:

$> rspk BallBox_9_2 -f

At this time, you can control the movement of the ball by changing the attitude of RPi-Spark, and you will find that the sound effect and trajectory of the collision are close to the actual elastic collision.


 

Was this article helpful?

YES     |     NO

 

Enjoying the project? Spotted a mistake? Any opinions on the website? Let us know!