Platform game written for the GHI/OutrageousCircuits RETRO game device. Navigate the caves collecting all the pickups and avoiding the creatures and haunted mine carts that patrol the caves. Oh and remember to watch out for the poisonous plants... This game demonstrates the ability to have multiple animated sprites where the sprites can overlap the background environment. See how the player moves past the fence and climbs the wall in the 3rd screen.

Dependencies:   mbed

Committer:
taylorza
Date:
Sat Dec 27 23:24:30 2014 +0000
Revision:
3:a93fe5f207f5
Working before fixed point audio

Who changed what in which revision?

UserRevisionLine numberNew contents of line
taylorza 3:a93fe5f207f5 1 #include "mbed.h"
taylorza 3:a93fe5f207f5 2 #include "SoundBlock.h"
taylorza 3:a93fe5f207f5 3 #include "SoundChannel.h"
taylorza 3:a93fe5f207f5 4
taylorza 3:a93fe5f207f5 5 SoundChannel::SoundChannel() :
taylorza 3:a93fe5f207f5 6 _state(4)
taylorza 3:a93fe5f207f5 7 {
taylorza 3:a93fe5f207f5 8 }
taylorza 3:a93fe5f207f5 9
taylorza 3:a93fe5f207f5 10 void SoundChannel::play(const SoundBlock soundBlocks[], int count)
taylorza 3:a93fe5f207f5 11 {
taylorza 3:a93fe5f207f5 12 _soundBlocks = soundBlocks;
taylorza 3:a93fe5f207f5 13 _count = count;
taylorza 3:a93fe5f207f5 14 _index = 0;
taylorza 3:a93fe5f207f5 15 _state = 0;
taylorza 3:a93fe5f207f5 16 }
taylorza 3:a93fe5f207f5 17
taylorza 3:a93fe5f207f5 18 bool SoundChannel::update(bool &pinState)
taylorza 3:a93fe5f207f5 19 {
taylorza 3:a93fe5f207f5 20 switch(_state)
taylorza 3:a93fe5f207f5 21 {
taylorza 3:a93fe5f207f5 22 case 0 :
taylorza 3:a93fe5f207f5 23 startSoundBlock();
taylorza 3:a93fe5f207f5 24 break;
taylorza 3:a93fe5f207f5 25
taylorza 3:a93fe5f207f5 26 case 3 : // Stop sound
taylorza 3:a93fe5f207f5 27 pinState = _pinState = false;
taylorza 3:a93fe5f207f5 28 _state = 4;
taylorza 3:a93fe5f207f5 29 return true;
taylorza 3:a93fe5f207f5 30
taylorza 3:a93fe5f207f5 31 case 4 : // No sound
taylorza 3:a93fe5f207f5 32 return false;
taylorza 3:a93fe5f207f5 33 }
taylorza 3:a93fe5f207f5 34
taylorza 3:a93fe5f207f5 35 if (updateCounters())
taylorza 3:a93fe5f207f5 36 {
taylorza 3:a93fe5f207f5 37 switch(_currentSoundBlock.getToneType())
taylorza 3:a93fe5f207f5 38 {
taylorza 3:a93fe5f207f5 39 case SoundBlock::Tone : updateTone(); pinState = _pinState; return true;
taylorza 3:a93fe5f207f5 40 case SoundBlock::Noise : updateNoise(); pinState = _pinState; return true;
taylorza 3:a93fe5f207f5 41 case SoundBlock::Pause : return false;
taylorza 3:a93fe5f207f5 42 }
taylorza 3:a93fe5f207f5 43 }
taylorza 3:a93fe5f207f5 44
taylorza 3:a93fe5f207f5 45 return false;
taylorza 3:a93fe5f207f5 46 }
taylorza 3:a93fe5f207f5 47
taylorza 3:a93fe5f207f5 48 void SoundChannel::updateTone()
taylorza 3:a93fe5f207f5 49 {
taylorza 3:a93fe5f207f5 50 switch(_state)
taylorza 3:a93fe5f207f5 51 {
taylorza 3:a93fe5f207f5 52 case 1: // High
taylorza 3:a93fe5f207f5 53 {
taylorza 3:a93fe5f207f5 54 _pinState = true;
taylorza 3:a93fe5f207f5 55 _pitchHighCounter -= FP_SCALE;
taylorza 3:a93fe5f207f5 56 if (_pitchHighCounter <= 0)
taylorza 3:a93fe5f207f5 57 {
taylorza 3:a93fe5f207f5 58 _pinState = false;
taylorza 3:a93fe5f207f5 59 _pitchHighCounter += _basePitchHighCount;
taylorza 3:a93fe5f207f5 60 _state = 2;
taylorza 3:a93fe5f207f5 61 }
taylorza 3:a93fe5f207f5 62 }
taylorza 3:a93fe5f207f5 63 break;
taylorza 3:a93fe5f207f5 64
taylorza 3:a93fe5f207f5 65 case 2: // Low
taylorza 3:a93fe5f207f5 66 {
taylorza 3:a93fe5f207f5 67 _pinState = false;
taylorza 3:a93fe5f207f5 68 _pitchLowCounter -= FP_SCALE;
taylorza 3:a93fe5f207f5 69 if (_pitchLowCounter <= 0)
taylorza 3:a93fe5f207f5 70 {
taylorza 3:a93fe5f207f5 71 _pinState = true;
taylorza 3:a93fe5f207f5 72 _pitchLowCounter += _basePitchLowCount;
taylorza 3:a93fe5f207f5 73 _state = 1;
taylorza 3:a93fe5f207f5 74 }
taylorza 3:a93fe5f207f5 75 }
taylorza 3:a93fe5f207f5 76 break;
taylorza 3:a93fe5f207f5 77 }
taylorza 3:a93fe5f207f5 78 }
taylorza 3:a93fe5f207f5 79
taylorza 3:a93fe5f207f5 80 void SoundChannel::updateNoise()
taylorza 3:a93fe5f207f5 81 {
taylorza 3:a93fe5f207f5 82 switch(_state)
taylorza 3:a93fe5f207f5 83 {
taylorza 3:a93fe5f207f5 84 case 1: // High/Low
taylorza 3:a93fe5f207f5 85 {
taylorza 3:a93fe5f207f5 86 _pitchHighCounter -= FP_SCALE;
taylorza 3:a93fe5f207f5 87 if (_pitchHighCounter <= 0)
taylorza 3:a93fe5f207f5 88 {
taylorza 3:a93fe5f207f5 89 _pinState = (SoundChannel::lfsr_rand() & 1) == 1;
taylorza 3:a93fe5f207f5 90 _pitchHighCounter += _basePitchHighCount;
taylorza 3:a93fe5f207f5 91 }
taylorza 3:a93fe5f207f5 92 }
taylorza 3:a93fe5f207f5 93 break;
taylorza 3:a93fe5f207f5 94 }
taylorza 3:a93fe5f207f5 95 }
taylorza 3:a93fe5f207f5 96
taylorza 3:a93fe5f207f5 97 void SoundChannel::startSoundBlock()
taylorza 3:a93fe5f207f5 98 {
taylorza 3:a93fe5f207f5 99 _currentSoundBlock = _soundBlocks[_index];
taylorza 3:a93fe5f207f5 100
taylorza 3:a93fe5f207f5 101 _stepCounter = _currentSoundBlock.getStepCount();
taylorza 3:a93fe5f207f5 102 _stepDurationCounter = _currentSoundBlock.getStepDuration();
taylorza 3:a93fe5f207f5 103 _pitchOffset = 0;
taylorza 3:a93fe5f207f5 104 _dutyOffset = 0;
taylorza 3:a93fe5f207f5 105 updateAudioCounters();
taylorza 3:a93fe5f207f5 106 _state = 1;
taylorza 3:a93fe5f207f5 107 }
taylorza 3:a93fe5f207f5 108
taylorza 3:a93fe5f207f5 109 bool SoundChannel::updateCounters()
taylorza 3:a93fe5f207f5 110 {
taylorza 3:a93fe5f207f5 111 --_stepDurationCounter;
taylorza 3:a93fe5f207f5 112 if (_stepDurationCounter == 0)
taylorza 3:a93fe5f207f5 113 {
taylorza 3:a93fe5f207f5 114 --_stepCounter;
taylorza 3:a93fe5f207f5 115 if (_stepCounter == 0)
taylorza 3:a93fe5f207f5 116 {
taylorza 3:a93fe5f207f5 117 ++_index;
taylorza 3:a93fe5f207f5 118 if (_index == _count)
taylorza 3:a93fe5f207f5 119 {
taylorza 3:a93fe5f207f5 120 _state = 3;
taylorza 3:a93fe5f207f5 121 return false;
taylorza 3:a93fe5f207f5 122 }
taylorza 3:a93fe5f207f5 123 else
taylorza 3:a93fe5f207f5 124 {
taylorza 3:a93fe5f207f5 125 _state = 0;
taylorza 3:a93fe5f207f5 126 }
taylorza 3:a93fe5f207f5 127 }
taylorza 3:a93fe5f207f5 128 else
taylorza 3:a93fe5f207f5 129 {
taylorza 3:a93fe5f207f5 130 int16_t pitchSlide = _currentSoundBlock.getPitchSlide();
taylorza 3:a93fe5f207f5 131 int8_t dutySlide = _currentSoundBlock.getDutySlide();
taylorza 3:a93fe5f207f5 132 if ( pitchSlide != 0 || dutySlide != 0)
taylorza 3:a93fe5f207f5 133 {
taylorza 3:a93fe5f207f5 134 _pitchOffset += pitchSlide;
taylorza 3:a93fe5f207f5 135 _dutyOffset += dutySlide;
taylorza 3:a93fe5f207f5 136 updateAudioCounters();
taylorza 3:a93fe5f207f5 137 }
taylorza 3:a93fe5f207f5 138
taylorza 3:a93fe5f207f5 139 _stepDurationCounter = _currentSoundBlock.getStepDuration();
taylorza 3:a93fe5f207f5 140 }
taylorza 3:a93fe5f207f5 141 }
taylorza 3:a93fe5f207f5 142 return true;
taylorza 3:a93fe5f207f5 143 }
taylorza 3:a93fe5f207f5 144
taylorza 3:a93fe5f207f5 145 void SoundChannel::updateAudioCounters()
taylorza 3:a93fe5f207f5 146 {
taylorza 3:a93fe5f207f5 147 float pitch = _currentSoundBlock.getPitch(_pitchOffset);
taylorza 3:a93fe5f207f5 148 float ph = pitch * ((float)_currentSoundBlock.getDuty(_dutyOffset) / 256.0f);
taylorza 3:a93fe5f207f5 149 float pl = pitch - ph;
taylorza 3:a93fe5f207f5 150 _basePitchHighCount = (uint32_t)(ph * FP_SCALE);
taylorza 3:a93fe5f207f5 151 _basePitchLowCount = (uint32_t)(pl * FP_SCALE);
taylorza 3:a93fe5f207f5 152 _pitchHighCounter = _basePitchHighCount;
taylorza 3:a93fe5f207f5 153 _pitchLowCounter = _basePitchLowCount;
taylorza 3:a93fe5f207f5 154 }
taylorza 3:a93fe5f207f5 155
taylorza 3:a93fe5f207f5 156 uint16_t SoundChannel::lfsr_rand()
taylorza 3:a93fe5f207f5 157 {
taylorza 3:a93fe5f207f5 158 static uint16_t lfsr = 0xACE1u;
taylorza 3:a93fe5f207f5 159 lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u);
taylorza 3:a93fe5f207f5 160 return lfsr;
taylorza 3:a93fe5f207f5 161 }