nice puzzle game

Dependencies:   PokittoLib

Revision:
3:f6302af708a4
Parent:
0:3c929189abce
--- a/main.cpp	Wed Oct 18 14:48:38 2017 +0000
+++ b/main.cpp	Sun Nov 18 14:37:27 2018 +0000
@@ -2,8 +2,13 @@
 #include "Pokitto.h"
 #include "sens_levs.h"
 #include "gfx.h"
+#include "Synth.h"
+#include "sound.h"
+#include "snd.h"
+#include "tune.h"
 
 Pokitto::Core game;
+Pokitto::Sound snd_;
 
 #define OFF_X 2
 #define OFF_Y 42
@@ -33,26 +38,48 @@
 byte gameMode;
 unsigned int myInt=0;
 byte scroller=0;
-char musicName[] = "sensitiv.raw";
+//char musicName[] = "sensitiv.snd";
 int lives;
 
 uint32_t myDelay;
 uint32_t tempTime;
 
+typedef struct{
+    bool playSample;
+    int soundPoint;
+    const uint8_t *currentSound;
+    int currentSoundSize;
+    int volume;
+    int speed;
+    int repeat;
+} sampletype;
+
+sampletype snd[4]; // up to 4 sounds at once?
+int oldQuart;
+
+uint32_t nextBufferIndexToFill = 0;
+uint32_t nextT = 0;
+uint32_t oldBufIndex=0;
+
+int currentLine=0;
+int mytick=0;
+int pattern=0; 
+int oldBufNum = 0;
+
 // explosion
 uint8_t expX[EXPLODESPRITES], expY[EXPLODESPRITES], expF[EXPLODESPRITES], expU[EXPLODESPRITES];
 uint8_t explode = 0;
 
 void rumbleOn(){
-    DigitalOut outPin(P0_13);
-    DigitalOut inPin(P0_11);
-    inPin=0;
+    DigitalOut outPin(EXT0);
+    //DigitalOut inPin(P0_11);
+    //inPin=0;
     outPin=1;
 }
 void rumbleOff(){
-    DigitalOut outPin(P0_13);
-    DigitalOut inPin(P0_11);
-    inPin=0;
+    DigitalOut outPin(EXT0);
+    //DigitalOut inPin(P0_11);
+    //inPin=0;
     outPin=0;
 }
 
@@ -102,10 +129,100 @@
    return var;
 }
 
+/**********[Sound]*********************************************************/
+
+
+Ticker sounder;
+Ticker sounder1;
+
+// note_speed << octave. = speed to play sample
+int note_speed[]={ 27,30,16,18,20,21,24,     29,0 ,17,19,0 ,23,25};
+//                 A  B  C  D  E  F  G       A# B# C# D# E# F# G#
+
+
+uint8_t playSound(int channel, const unsigned char *sound, uint16_t soundSize, int volume = 255, int speed=255, int repeat=0){
+
+    snd[channel].currentSound = sound;
+    snd[channel].currentSoundSize = (soundSize*255)/speed;
+    snd[channel].soundPoint = 0;
+    snd[channel].playSample = 1;
+    snd[channel].volume = volume;
+    snd[channel].speed = speed;
+    snd[channel].repeat = repeat;
+
+    return channel;
+}
+
+uint8_t mixSound(int samplePos)
+{
+    int temp = 0;
+    int ss[4];
+
+    for(int s=0; s<4; s++){
+        ss[s] = (snd[s].currentSound[(snd[s].soundPoint*snd[s].speed)>>8]*snd[s].volume>>8) * snd[s].playSample;
+        ++snd[s].soundPoint;
+        if(snd[s].soundPoint >= snd[s].currentSoundSize){
+            if(snd[s].repeat){
+                snd[s].soundPoint=0;
+            }else{
+                snd[s].playSample=0;
+                snd[s].soundPoint=0;
+            }
+        }
+     }    
+
+
+//    temp = (ss[0] + ss[1] + ss[2] + ss[3]) - (ss[0] * ss[1] * ss[2] * ss[3]);
+    temp = ((127 - ss[0] + ss[1] + ss[2] + ss[3])/4)+127;
+    
+    return temp;
+}
+
+void update_tune(){
+
+    char pat = my_pattern[pattern];
+
+    for(int t=0; t<4; t++){
+        char note =       tune[pat][currentLine][t][0];
+        char octave =     tune[pat][currentLine][t][1];
+        int volume =     tune[pat][currentLine][t][2] << 2;
+        char instrument = tune[pat][currentLine][t][3];
+                    
+        if(note > 0){
+            
+            int speed = (note_speed[note-1] << octave) >> 2;
+                        
+            switch(instrument){
+                case 1:
+                    playSound(t, s_01, sizeof(s_01), volume, speed, sampleRepeat[0]);
+                break;
+                case 2:
+                    playSound(t, s_02, sizeof(s_02), volume, speed, sampleRepeat[1]);
+                break;
+                case 3:
+                    playSound(t, s_03, sizeof(s_03), volume, speed, sampleRepeat[2]);
+                break;
+                case 4:
+                    playSound(t, s_04, sizeof(s_04), volume, speed, sampleRepeat[3]);
+                break;
+            }
+        }
+                            
+        snd[t].volume = volume;
+                
+    }
+ 
+    if(currentLine++==63){
+        currentLine=0;
+        if(pattern++==sizeof(my_pattern))pattern=0;
+    }
+}
+
 /**************************************************************************/
 
+
 void new2BitTile(int x1, int y1, int wide, int high, int tile, const uint16_t *gfx, int palNumber){
-
+// for drawing level tiles
     uint16_t tileBuffer[wide*high];
 
     uint8_t pix;
@@ -116,10 +233,10 @@
     for(int y=0; y<high; y++){
         for(int x=0; x<quartWide; x++){
             pic = gfx[(tile*quartWide*high)+(x+quartWide*y)];
-            pix = (pic >> 6)&3; tileBuffer[y+high*(  x*4)]=_pal[_miniPal[palNo+pix]];
-            pix = (pic >> 4)&3; tileBuffer[y+high*(1+x*4)]=_pal[_miniPal[palNo+pix]];
-            pix = (pic >> 2)&3; tileBuffer[y+high*(2+x*4)]=_pal[_miniPal[palNo+pix]];
-            pix = pic &3;       tileBuffer[y+high*(3+x*4)]=_pal[_miniPal[palNo+pix]];
+            pix = (pic >> 6)&3; tileBuffer[y*high+(  x*4)]=_pal[_miniPal[palNo+pix]];
+            pix = (pic >> 4)&3; tileBuffer[y*high+(1+x*4)]=_pal[_miniPal[palNo+pix]];
+            pix = (pic >> 2)&3; tileBuffer[y*high+(2+x*4)]=_pal[_miniPal[palNo+pix]];
+            pix = pic &3;       tileBuffer[y*high+(3+x*4)]=_pal[_miniPal[palNo+pix]];
         }
     }
 
@@ -195,10 +312,10 @@
     for(int y=0; y<high; y++){
         for(int x=0; x<quartWide; x++){
             pic = gfx[(tile*quartWide*high)+(x+quartWide*y)];
-            pix = (pic >> 6)&3; if(pix != transparentColor){tileBuffer[y+high*(  x*4)]=numbers_pal[pix];}else{tileBuffer[y+high*(  x*4)]=palReplace;}
-            pix = (pic >> 4)&3; if(pix != transparentColor){tileBuffer[y+high*(1+x*4)]=numbers_pal[pix];}else{tileBuffer[y+high*(1+x*4)]=palReplace;}
-            pix = (pic >> 2)&3; if(pix != transparentColor){tileBuffer[y+high*(2+x*4)]=numbers_pal[pix];}else{tileBuffer[y+high*(2+x*4)]=palReplace;}
-            pix = pic &3;       if(pix != transparentColor){tileBuffer[y+high*(3+x*4)]=numbers_pal[pix];}else{tileBuffer[y+high*(3+x*4)]=palReplace;}
+            pix = (pic >> 6)&3; if(pix != transparentColor){tileBuffer[y*high+(  x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(  x*4)]=palReplace;}
+            pix = (pic >> 4)&3; if(pix != transparentColor){tileBuffer[y*high+(1+x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(1+x*4)]=palReplace;}
+            pix = (pic >> 2)&3; if(pix != transparentColor){tileBuffer[y*high+(2+x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(2+x*4)]=palReplace;}
+            pix = pic &3;       if(pix != transparentColor){tileBuffer[y*high+(3+x*4)]=numbers_pal[pix];}else{tileBuffer[y*high+(3+x*4)]=palReplace;}
         }
     }
 
@@ -326,18 +443,18 @@
     }
 
     game.display.directRectangle(OFF_X,0,218,40,_pal[10]);
-    game.display.directRectangle(OFF_X,0,218,0,_pal[4]);
-    game.display.directRectangle(OFF_X,1,218,1,_pal[10]);
-    game.display.directRectangle(OFF_X,2,218,2,_pal[15]);
-    game.display.directRectangle(OFF_X,3,218,3,_pal[15]);
-    game.display.directRectangle(OFF_X,4,218,4,_pal[10]);
-    game.display.directRectangle(OFF_X,5,218,5,_pal[4]);
-    game.display.directRectangle(OFF_X,36,218,36,_pal[4]);
-    game.display.directRectangle(OFF_X,37,218,37,_pal[10]);
-    game.display.directRectangle(OFF_X,38,218,38,_pal[15]);
-    game.display.directRectangle(OFF_X,39,218,39,_pal[15]);
-    game.display.directRectangle(OFF_X,40,218,40,_pal[10]);
-    game.display.directRectangle(OFF_X,41,218,41,_pal[4]);
+    game.display.directRectangle(OFF_X,0,218,1,_pal[4]);
+    game.display.directRectangle(OFF_X,1,218,2,_pal[10]);
+    game.display.directRectangle(OFF_X,2,218,3,_pal[15]);
+    game.display.directRectangle(OFF_X,3,218,4,_pal[15]);
+    game.display.directRectangle(OFF_X,4,218,5,_pal[10]);
+    game.display.directRectangle(OFF_X,5,218,6,_pal[4]);
+    game.display.directRectangle(OFF_X,36,218,37,_pal[4]);
+    game.display.directRectangle(OFF_X,37,218,38,_pal[10]);
+    game.display.directRectangle(OFF_X,38,218,39,_pal[15]);
+    game.display.directRectangle(OFF_X,39,218,40,_pal[15]);
+    game.display.directRectangle(OFF_X,40,218,41,_pal[10]);
+    game.display.directRectangle(OFF_X,41,218,42,_pal[4]);
 
 
     // pause if any buttons held
@@ -386,14 +503,41 @@
                     }
                     if(x>0){if(curLev[((y) * LEVWIDTH) + (x-1)]){ tile += 4; }}
                     new2BitTile(OFF_X+x*tileSize, OFF_Y+y*tileSize, tileSize, tileSize, shaddow[tile], gbTiles, shaddow[tile]);
+
+                    for (int t = 0; t < EXPLODESPRITES; t++) {
+                        if (expU[t] == 1) {
+                            if(expX[t]==x && expY[t]==y){
+                                draw4BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, expF[t], 8, explode_tiles);
+                            }
+                        }
+                    }
+
                 }else{
                     // all other tiles
                     new2BitTile(OFF_X+x*tileSize, OFF_Y+y*tileSize, tileSize, tileSize, curLev[tn], gbTiles, curLev[tn]);
                 }
             }
-      }
+
+            // player sprite
+            if(drawPlayer){
+                if(x == px/tileSize){
+                    if(y == py/tileSize){
+                        uint16_t tileBuffer[10];
+                        for(byte y1=0; y1<8; y1++){
+                            int offX = ball[y1][0];
+                            int wide = ball[y1][1];
+                            for(byte x1=0; x1<wide; x1++){
+                                tileBuffer[x1]=_pal[ball[y1][x1+2]];
+                            }
+                            game.display.directTile(OFF_X+px+offX+2, OFF_Y+py+y1+2, OFF_X+px+wide+offX+2, OFF_Y+py+3+y1 , tileBuffer);
+                        }// y
+                    }
+                }
+
+             }//drawplayer
 
 
+      }
     }
 
         // explosions
@@ -404,9 +548,9 @@
 
             stillExploding=1;
             if(expF[t]<=1){
-                new2BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, 1, gbTiles, 1);
+//                new2BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, 1, gbTiles, 1);
             }
-            draw4BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, expF[t], 8, explode_tiles);
+//            draw4BitTile(OFF_X+(expX[t]*tileSize), OFF_Y+expY[t]*tileSize, tileSize, tileSize, expF[t], 8, explode_tiles);
             if (frameNumber % EXPLODESPEED == 0) {
               expF[t]++;
               if (expF[t] == 8) {
@@ -416,19 +560,6 @@
           }
         }
 
-        // player sprite
-        if(drawPlayer){
-            uint16_t tileBuffer[10];
-            for(byte y=0; y<8; y++){
-                int offX = ball[y][0];
-                int wide = ball[y][1];
-                for(byte x=0; x<wide; x++){
-                    tileBuffer[x]=_pal[ball[y][x+2]];
-                }
-                game.display.directTile(OFF_X+px+offX+2, OFF_Y+py+y+2, OFF_X+px+wide+offX+2, OFF_Y+py+3+y , tileBuffer);
-            }// y
-        }//drawplayer
-
 
     print(8, 14, "SCORE  LEV LIVES  HISCORE",0,_pal[10]);
     char text[] = "      ";
@@ -667,39 +798,80 @@
 
 }
 
+void update_buffer(){
+/*
+    // Fill the next buffer if it is not used currently 
+    if((uint32_t)currentBuffer != nextBufferIndexToFill) {
+
+        for(uint32_t t=0; t<BUFFER_SIZE; t++){
+            buffers[nextBufferIndexToFill][t] = mixSound(t);
+        }
+        if(++nextBufferIndexToFill > 3)
+            nextBufferIndexToFill = 0;
+        }
+*/
+    char sndOffset[]={2,3,0,1};
+
+    if((uint32_t)currentBuffer != nextBufferIndexToFill) {
+        for(uint32_t t=0; t<BUFFER_SIZE; t++){
+            nextBufferIndexToFill = currentBuffer;
+            buffers[sndOffset[nextBufferIndexToFill]][t] = mixSound(t);
+        }
+    }
+        
+}
 
 int main(){
+
+
     rumbleOff(); // just in case
 
     game.begin();
     game.display.width = 220; // full size
     game.display.height = 174;
-
+ 
+    // Set global audio variables
+    currentBuffer = 0;
+    currentPtr = buffers[currentBuffer];
+    endPtr = currentPtr + BUFFER_SIZE;
+ 
+    // Init audio stream.
+    pokPlayStream(); // activate stream
     game.sound.ampEnable(true);
-    game.sound.playMusicStream(musicName);
+    game.sound.playMusicStream();
+
 
     gameMode = 0; // titleScreen
     tempTime = game.getTime();
 
+
+    sounder.attach(&update_tune, 0.05);
+    sounder1.attach(&update_buffer, 0.0075);
+
     while (game.isRunning()) {
-
+        //update_buffer();
+    
           // if it is time to update the screen
  //       if (game.update(true)){
 
-            game.sound.updateStream();
+            //game.sound.updateStream();
 
             myPad = updateButtons(myPad);
             UpdatePad(myPad);
 
             frameNumber++;
-            char oldMode = gameMode;
+
+//            if(frameNumber %3 == 0) update_tune(); 
+
+            
+            //char oldMode = gameMode;
             switch(gameMode){
                 case 0:
                     drawTitleScreen();
                     break;
                 case 1:
                     levelNum = 0;
-                    myDelay = 10;
+                    myDelay = 5;
                     titleScreen();
                     break;
                 case 10:
@@ -710,15 +882,15 @@
                     break;
                 case 20:
                     // play levels
-                    myDelay = 30;
+                    myDelay = 15;
                     playLevel();
                     break;
             }
 
         // timing loop
         while(game.getTime()-tempTime < myDelay){
-            refreshDisplay();
         };
+        refreshDisplay();
         tempTime = game.getTime();
 //  } // update
   }