Tweak scrolly tile
diff --git a/examples/scrolly-tile/scrolly-tile.cpp b/examples/scrolly-tile/scrolly-tile.cpp
index 9ffb3d6..e5d7533 100644
--- a/examples/scrolly-tile/scrolly-tile.cpp
+++ b/examples/scrolly-tile/scrolly-tile.cpp
@@ -4,7 +4,7 @@
 

 using namespace blit;

 

-#define __AUDIO__

+//#define __AUDIO__

 

 #define SCREEN_W 160

 #define SCREEN_H 120

@@ -39,7 +39,7 @@
 #define RANDOM_TYPE_HRNG 0

 #define RANDOM_TYPE_PRNG 1

 

-#define PASSAGE_COUNT 5

+uint8_t passage_count = 3;

 

 // Number of times a player can jump sequentially

 // including mid-air jumps and the initial ground

@@ -95,7 +95,15 @@
 // back to those still active.

 uint16_t linked_passage_mask = 0;

 

-uint8_t passages[PASSAGE_COUNT] = {0};

+

+struct Passage {

+    int8_t x;

+    int8_t direction;

+    uint8_t width;

+    bool enabled;

+};

+

+std::vector<Passage> passages;

 

 // Keep track of game state

 enum enum_state {

@@ -236,65 +244,63 @@
 

 uint16_t generate_new_row_mask() {

     uint16_t new_row_mask = 0x0000;

-    uint8_t passage_width = floorf(((sinf(current_row / 10.0f) + 1.0f) / 2.0f) * PASSAGE_COUNT);

+    bool passage_ended = false;

 

-    // Cut our consistent winding passage through the level

-    // by tracking the x coord of our passage we can ensure

-    // that it's always navigable without having to reject

-    // procedurally generated segments

-    for(auto p = 0; p < PASSAGE_COUNT; p++){

-        if(p > passage_width) {

-            continue;

+    uint8_t passage_idx = 0;

+    int8_t x2 = passages[0].x;

+

+    for(Passage& passage : passages) {

+        uint8_t actions = get_random_number() & 0xff;

+

+        if (actions & 0b00111110) {

+            passage.direction = actions & 0b1 ? -1 : 1;

         }

-        // Controls how far a passage can snake left/right

-        uint8_t turning_size = get_random_number() % 7;

-

-        new_row_mask |= (0x8000 >> passages[p]);

-

-        // At every new generation we choose to branch a passage

-        // either left or right, or let it continue upwards.

-        switch(get_random_number() % 3){

-            case 0: // Passage goes right

-                while(turning_size--){

-                    if(passages[p] < TILES_X - 2){

-                        passages[p] += 1;

-                    }

-                    new_row_mask |= (0x8000 >> passages[p]);

-                }

-                break;

-            case 1: // Passage goes left

-                while(turning_size--){

-                    if(passages[p] > 1){

-                        passages[p] -= 1;

-                    }

-                    new_row_mask |= (0x8000 >> passages[p]);

-                }

-                break;

+        else {

+            passage.direction = 0;

         }

-    }

 

-    // Whenever we have a narrowing of our passage we must check

-    // for orphaned passages and link them back to the ones still

-    // available, to avoid the player going up a tunnel that ends

-    // abruptly :(

-    // This routine picks a random passage from the ones remaining

-    // and routes every orphaned passage to it.

-    if(passage_width < last_passage_width) {

-        uint8_t target_passage = get_random_number() % (passage_width + 1);

-        uint8_t target_p_x = passages[target_passage];

+        if (actions & 0b10000000) {

+            passage.width = ceilf(((sinf(current_row / 10.0f) + 1.0f) / 2.0f) * 3);

+        }

 

-        for(auto i = passage_width; i < last_passage_width + 1; i++){

-            new_row_mask |= (0x8000 >> passages[i]);

-

-            int8_t direction = (passages[i] < target_p_x) ? 1 : -1;

-    

-            while(passages[i] != target_p_x) {

-                passages[i] += direction;

-                new_row_mask |= (0x8000 >> passages[i]);

+        if (actions & 0b01000000) {

+            if(passage_idx > 0) {

+                passage.enabled = !passage.enabled;

+                passage_ended = !passage.enabled;

             }

         }

+        

+        int8_t x1 = passage.x;

+

+        if(passage.enabled) {

+            passage.x += passage.direction * passage.width;

+            if(passage.x < 0) passage.x = 0;

+            if(passage.x > 15) passage.x = 15;

+            x2 = passage.x;

+        }

+        if(passage.enabled | passage_ended) {

+            if(x1 < x2) {

+                for(auto px = x1; px <= x2; px++) {

+                    new_row_mask |= (0x8000 >> px) & 0xffff;

+                }

+            }

+            else if(x1 > x2)

+            {

+                for(auto px = x2; px <= x1; px++) {

+                    new_row_mask |= (0x8000 >> px) & 0xffff;

+                }

+            }

+            else {

+                    new_row_mask |= (0x8000 >> x1) & 0xffff;

+            }

+        }

+        passage_idx += 1;

     }

-    last_passage_width = passage_width;

+

+   if(new_row_mask == 0xffff && (current_row & 0b11) == 0) {

+       new_row_mask = get_random_number() & 0xffff;

+        new_row_mask |= (0x8000 >> x2);

+   }

 

     current_row++;

     return ~new_row_mask;

@@ -377,9 +383,31 @@
     water_level = 0;

     last_passage_width = 0;

     current_row = 0;

+    passages.clear();

+    passage_count = 1 + (get_random_number() % 6);

 

-    for(auto x = 0; x < 5; x++) {

-        passages[x] = (get_random_number() % 14) + 1;

+    for(auto i = 0u; i < passage_count; i++) {

+        int8_t direction = 0;

+

+        switch(get_random_number() & 0b11) {

+            case 0:

+                direction = -1;

+                break;

+            case 1:

+                direction = 1;

+                break;

+            default:

+                direction = 0;

+        }

+

+        int8_t x = get_random_number() & 0xf;

+

+        passages.push_back(Passage{

+            .x = 10,

+            .direction = direction,

+            .width = 1,

+            .enabled = true

+        });

     }

 

     // Use update_tiles to create the initial game state

@@ -623,11 +651,11 @@
             case near_wall_left:

             case near_wall_right:

                 if ((buttons & Button::DPAD_LEFT) && (player_state == wall_left || player_state == near_wall_left)){

-                    player_velocity.y *= 0.5f;

+                    player_velocity.y *= 0.6f;

                     break;

                 }

                 if ((buttons & Button::DPAD_RIGHT) && (player_state == wall_right || player_state == near_wall_right)){

-                    player_velocity.y *= 0.5f;

+                    player_velocity.y *= 0.6f;

                     break;

                 }

                 // Fall through to air friction