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:
Fri Jan 02 01:55:12 2015 +0000
Revision:
5:a758c7d4da03
Child:
12:1394b0c6e8b0
Tweaked graphics

Who changed what in which revision?

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