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:
Mon Feb 16 03:46:57 2015 +0000
Revision:
16:f9227904afc4
Parent:
13:0900880bde68
Added a 4th game screen

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