Beispiel #1
0
int static possible_downward_moves(RenderBuffer &buffer, int x, int y)
{
    int moves = 0;

    // no moves possible from bottom row
    if (y == 0) {
        return 0;
    }

    if (buffer.GetTempPixel(x-1 < 0 ? x-1+buffer.BufferWi : x-1, y-1) == xlBLACK) {
        moves += 1;
    }
    if (buffer.GetTempPixel(x, y-1) == xlBLACK) {
        moves += 2;
    }
    if (buffer.GetTempPixel(x+1 >= buffer.BufferWi ? x+1-buffer.BufferWi : x+1, y-1) == xlBLACK) {
        moves += 4;
    }

    return moves;
}
Beispiel #2
0
static void set_pixel_if_not_color(RenderBuffer &buffer, int x, int y, xlColor toColor, xlColor notColor, bool wrapx, bool wrapy)
{
    int adjx = x;
    int adjy = y;

    if (x < 0) {
        if (wrapx) {
            adjx += buffer.BufferWi;
        }
        else {
            return;
        }
    }
    else if (x >= buffer.BufferWi) {
        if (wrapx) {
            adjx -= buffer.BufferWi;
        }
        else {
            return;
        }
    }
    if (y < 0) {
        if (wrapy) {
            adjy += buffer.BufferHt;
        }
        else {
            return;
        }
    }
    else if (y >= buffer.BufferHt) {
        if (wrapy) {
            adjy -= buffer.BufferHt;
        }
        else {
            return;
        }
    }

    // strip off alpha when comparing
    if (buffer.GetTempPixel(adjx, adjy).GetRGB() != notColor.GetRGB()) {
        buffer.SetPixel(adjx, adjy, toColor);
    }
}
Beispiel #3
0
void GalaxyEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) {
    int center_x = SettingsMap.GetInt("SLIDER_Galaxy_CenterX");
    int center_y = SettingsMap.GetInt("SLIDER_Galaxy_CenterY");
    int start_radius = SettingsMap.GetInt("SLIDER_Galaxy_Start_Radius");
    int end_radius = SettingsMap.GetInt("SLIDER_Galaxy_End_Radius");
    int start_angle = SettingsMap.GetInt("SLIDER_Galaxy_Start_Angle");
    int revolutions = SettingsMap.GetInt("SLIDER_Galaxy_Revolutions");
    int start_width = SettingsMap.GetInt("SLIDER_Galaxy_Start_Width");
    int end_width = SettingsMap.GetInt("SLIDER_Galaxy_End_Width");
    int duration = SettingsMap.GetInt("SLIDER_Galaxy_Duration");
    int acceleration = SettingsMap.GetInt("SLIDER_Galaxy_Accel");
    bool reverse_dir = SettingsMap.GetBool("CHECKBOX_Galaxy_Reverse");
    bool blend_edges = SettingsMap.GetBool("CHECKBOX_Galaxy_Blend_Edges");
    bool inward = SettingsMap.GetBool("CHECKBOX_Galaxy_Inward");

    if( revolutions == 0 ) return;
    std::vector< std::vector<double> > temp_colors_pct(buffer.BufferWi, std::vector<double>(buffer.BufferHt));
    std::vector< std::vector<double> > pixel_age(buffer.BufferWi, std::vector<double>(buffer.BufferHt));

    double eff_pos = buffer.GetEffectTimeIntervalPosition();
    int num_colors = buffer.palette.Size();
    xlColor color, c_old, c_new;
    HSVValue hsv1;
    double eff_pos_adj = buffer.calcAccel(eff_pos, acceleration);
    double revs = (double)revolutions;

    double pos_x = buffer.BufferWi * center_x/100.0;
    double pos_y = buffer.BufferHt * center_y/100.0;

    double head_duration = duration/100.0;    // time the head is in the frame
    double tail_length = revs * (1.0 - head_duration);
    double color_length = tail_length / num_colors;
    if(color_length < 1.0) color_length = 1.0;


    double tail_end_of_tail = ((revs + tail_length) * eff_pos_adj) - tail_length;
    double head_end_of_tail = tail_end_of_tail + tail_length;

    double radius1 = start_radius;
    double radius2 = end_radius;
    double width1 = start_width;
    double width2 = end_width;

    double step = buffer.GetStepAngle(radius1, radius2);

    for( int x = 0; x < buffer.BufferWi; x++ )
    {
        for( int y = 0; y < buffer.BufferHt; y++ )
        {
            temp_colors_pct[x][y] = 0.0;
            pixel_age[x][y] = 0.0;
        }
    }
    buffer.ClearTempBuf();

    double last_check = (inward ? std::min(head_end_of_tail,revs) : std::max(0.0, tail_end_of_tail) ) + (double)start_angle;

    for( double i = (inward ? std::min(head_end_of_tail,revs) : std::max(0.0, tail_end_of_tail));
        (inward ? i >= std::max(0.0, tail_end_of_tail) : i <= std::min(head_end_of_tail,revs));
        (inward ? i -= step : i += step) )
    {
        double adj_angle = i + (double)start_angle;
        if( reverse_dir )
        {
            adj_angle *= -1.0;
        }
        double color_val = (head_end_of_tail-i) / color_length;
        int color_int = (int)color_val;
        double color_pct = color_val - (double)color_int;
        int color2 = std::min(color_int+1, num_colors-1);
        if( color_int < color2 )
        {
            buffer.Get2ColorBlend(color_int, color2, std::min( color_pct, 1.0), color);
        }
        else
        {
            buffer.palette.GetColor(color2, color);
        }
        HSVValue hsv(color);
        double full_brightness = hsv.value;
        double pct = i/revs;
        double current_radius = radius2 * pct + radius1 * (1.0 - pct);
        double current_width = width2 * pct + width1 * (1.0 - pct);
        double half_width = current_width / 2.0;
        double inside_radius = current_radius - half_width;
        for( double r = inside_radius; ; r += 0.5 )
        {
            if( r > current_radius ) r = current_radius;
            double x1 = buffer.sin(ToRadians(adj_angle)) * r + (double)pos_x;
            double y1 = buffer.cos(ToRadians(adj_angle)) * r + (double)pos_y;
            double outside_radius = current_radius + (current_radius - r);
            double x2 = buffer.sin(ToRadians(adj_angle)) * outside_radius + (double)pos_x;
            double y2 = buffer.cos(ToRadians(adj_angle)) * outside_radius + (double)pos_y;
            double color_pct2 = (r-inside_radius)/(current_radius-inside_radius);
            if( blend_edges )
            {
                if( hsv.value > 0.0 )
                {
                    if ((int)x1 >= 0 && (int)x1 < buffer.BufferWi && (int)y1 >= 0 && (int)y1 < buffer.BufferHt)
                    {
                        buffer.SetTempPixel((int)x1,(int)y1,color);
                        temp_colors_pct[(int)x1][(int)y1] = color_pct2;
                        pixel_age[(int)x1][(int)y1] = adj_angle;
                    }
                    if ((int)x2 >= 0 && (int)x2 < buffer.BufferWi && (int)y2 >= 0 && (int)y2 < buffer.BufferHt)
                    {
                        buffer.SetTempPixel((int)x2,(int)y2,color);
                        temp_colors_pct[(int)x2][(int)y2] = color_pct2;
                        pixel_age[(int)x2][(int)y2] = adj_angle;
                    }
                }
            }
            else
            {
                hsv.value = full_brightness * color_pct2;
                if( hsv.value > 0.0 )
                {
                    buffer.SetPixel(x1,y1,hsv);
                    buffer.SetPixel(x2,y2,hsv);
                }
            }
            if( r >= current_radius ) break;
        }
        // blend old data down into final buffer
        if( blend_edges && ( (inward ? (last_check-adj_angle) : (adj_angle-last_check)) >= 90.0) )
        {
            for( int x = 0; x < buffer.BufferWi; x++ )
            {
                for( int y = 0; y < buffer.BufferHt; y++ )
                {
                    if( temp_colors_pct[x][y] > 0.0 && ((inward ? (pixel_age[x][y]-adj_angle) : (adj_angle-pixel_age[x][y])) >= 180.0) )
                    {
                        buffer.GetTempPixel(x,y,c_new);
                        buffer.GetPixel(x,y,c_old);
                        buffer.Get2ColorAlphaBlend(c_old, c_new, temp_colors_pct[x][y], color);
                        buffer.SetPixel(x,y,color);
                        temp_colors_pct[x][y] = 0.0;
                        pixel_age[x][y] = 0.0;
                    }
                }
            }
            last_check = adj_angle;
        }
    }

    // blend remaining data down into final buffer
    if( blend_edges )
    {
        for( int x = 0; x < buffer.BufferWi; x++ )
        {
            for( int y = 0; y < buffer.BufferHt; y++ )
            {
                if( temp_colors_pct[x][y] > 0.0 )
                {
                    buffer.GetTempPixel(x,y,c_new);
                    buffer.GetPixel(x,y,c_old);
                    buffer.Get2ColorAlphaBlend(c_old, c_new, temp_colors_pct[x][y], color);
                    buffer.SetPixel(x,y,color);
                }
            }
        }
    }

}
Beispiel #4
0
void ShockwaveEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) {
    int center_x = SettingsMap.GetInt("SLIDER_Shockwave_CenterX", 0);
    int center_y = SettingsMap.GetInt("SLIDER_Shockwave_CenterY", 0);
    int start_radius = SettingsMap.GetInt("SLIDER_Shockwave_Start_Radius", 0);
    int end_radius = SettingsMap.GetInt("SLIDER_Shockwave_End_Radius", 0);
    int start_width = SettingsMap.GetInt("SLIDER_Shockwave_Start_Width", 0);
    int end_width = SettingsMap.GetInt("SLIDER_Shockwave_End_Width", 0);
    int acceleration = SettingsMap.GetInt("SLIDER_Shockwave_Accel", 0);
    bool blend_edges = SettingsMap.GetBool("CHECKBOX_Shockwave_Blend_Edges");

    std::vector< std::vector<double> > temp_colors_pct(buffer.BufferWi, std::vector<double>(buffer.BufferHt));
    double eff_pos = buffer.GetEffectTimeIntervalPosition();
    int num_colors = buffer.palette.Size();
    if( num_colors == 0 )
        num_colors = 1;
    xlColor color, c_old, c_new;
    double eff_pos_adj = buffer.calcAccel(eff_pos, acceleration);

    double blend_pct = 1.0 / (num_colors-1);
    double color_pct1 = eff_pos_adj / blend_pct;
    int color_index = (int)color_pct1;
    blend_pct = color_pct1 - (double)color_index;
    buffer.Get2ColorBlend(color_index, std::min(color_index+1,num_colors-1), std::min( blend_pct, 1.0), color);

    double pos_x = buffer.BufferWi * center_x/100.0;
    double pos_y = buffer.BufferHt * center_y/100.0;

    double radius1 = start_radius;
    double radius2 = end_radius;
    double radius_center = radius1 + (radius2 - radius1) * eff_pos_adj;
    double half_width = (start_width + (end_width - start_width) * eff_pos_adj) / 2.0;
    radius1 = radius_center - half_width;
    radius2 = radius_center + half_width;

    double step = buffer.GetStepAngle(radius1, radius2);

    for( int x = 0; x < buffer.BufferWi; x++ )
    {
        for( int y = 0; y < buffer.BufferHt; y++ )
        {
            temp_colors_pct[x][y] = 0.0;
        }
    }
    buffer.ClearTempBuf();

    for( double current_angle = 0.0; current_angle <= 360.0; current_angle += step )
    {
        for( double r = std::max(0.0, radius1); r <= radius2; r += 0.5 )
        {
            double x1 = buffer.sin(ToRadians(current_angle)) * r + (double)pos_x;
            double y1 = buffer.cos(ToRadians(current_angle)) * r + (double)pos_y;

            if( blend_edges )
            {
                double color_pct = 1.0 - std::abs(r-radius_center)/half_width;
                if( color_pct > 0.0 )
                {
                    if (x1 >= 0 && x1 < buffer.BufferWi && y1 >= 0 && y1 < buffer.BufferHt)
                    {
                        if (buffer.allowAlpha) {
                            color.alpha = 255.0 * color_pct;
                            buffer.SetPixel((int)x1,(int)y1,color);
                        } else {
                            temp_colors_pct[(int)x1][(int)y1] = color_pct;
                            buffer.SetTempPixel((int)x1,(int)y1,color);
                        }
                    }
                }
            }
            else
            {
                buffer.SetPixel((int)x1,(int)y1,color);
            }
        }
    }

    // blend element data into final buffer
    if( blend_edges && !buffer.allowAlpha )
    {
        for( int x = 0; x < buffer.BufferWi; x++ )
        {
            for( int y = 0; y < buffer.BufferHt; y++ )
            {
                if( temp_colors_pct[x][y] > 0.0 )
                {
                    buffer.GetTempPixel(x,y,c_new);
                    buffer.GetPixel(x,y,c_old);
                    buffer.Get2ColorAlphaBlend(c_old, c_new, temp_colors_pct[x][y], color);
                    buffer.SetPixel(x,y,color);
                    temp_colors_pct[x][y] = 0.0;
                }
            }
        }
    }
}
Beispiel #5
0
void SnowflakesEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) {

    int Count = SettingsMap.GetInt("SLIDER_Snowflakes_Count", 5);
    int SnowflakeType = SettingsMap.GetInt("SLIDER_Snowflakes_Type", 1);
    int sSpeed = SettingsMap.GetInt("SLIDER_Snowflakes_Speed", 10);
    std::string falling = SettingsMap.Get("CHOICE_Falling", "Driving");

    int i,n,x,x0,y0,y,check,delta_y;
    xlColor color1,color2, color3;
    bool wrapx = false; // set to true if you want snowflakes to draw wrapped around when near edges in the accumulate effect.


    SnowflakesRenderCache *cache = (SnowflakesRenderCache*)buffer.infoCache[id];
    if (cache == nullptr) {
        cache = new SnowflakesRenderCache();
        buffer.infoCache[id] = cache;
    }

    int &LastSnowflakeCount = cache->LastSnowflakeCount;
    int &LastSnowflakeType = cache->LastSnowflakeType;
    int &effectState = cache->effectState;
    std::string& LastFalling = cache->LastFalling;

    buffer.palette.GetColor(0, color1);
    buffer.palette.GetColor(1, color2);

    if (buffer.needToInit ||
        Count != LastSnowflakeCount ||
        SnowflakeType != LastSnowflakeType ||
        falling != LastFalling) {

        // initialize
        buffer.needToInit = false;
        LastSnowflakeCount=Count;
        LastSnowflakeType=SnowflakeType;
        LastFalling = falling;
        buffer.ClearTempBuf();
        effectState = 0;

        // place Count snowflakes
        for (n=0; n < Count; n++) {

            delta_y=buffer.BufferHt/4;
            y0=(n % 4)*delta_y;

            if (y0+delta_y > buffer.BufferHt) delta_y = buffer.BufferHt-y0;
            if (delta_y<1) delta_y=1;

            // find unused space
            for (check=0; check < 20; check++)
            {
                x=rand() % buffer.BufferWi;
                y=y0 + (rand() % delta_y);
                if (buffer.GetTempPixel(x,y) == xlBLACK) {
                    effectState++;
                    break;
                }
            }

            // draw flake, SnowflakeType=0 is random type
            switch (SnowflakeType == 0 ? rand() % 5 : SnowflakeType-1)
            {
                case 0:
                    // single node
                    if(falling != "Driving") {
                        buffer.SetTempPixel(x, y, color1, 0);
                    }
                    else {
                        buffer.SetTempPixel(x, y, color1);
                    }
                    break;
                case 1:
                    // 5 nodes
                    if (x < 1) x+=1;
                    if (y < 1) y+=1;
                    if (x > buffer.BufferWi-2) x-=1;
                    if (y > buffer.BufferHt-2) y-=1;
                    if(falling != "Driving") {
                        buffer.SetTempPixel(x,y,color1, 1);
                    }
                    else {
                        buffer.SetTempPixel(x,y,color1);
                        buffer.SetTempPixel(x-1,y,color2);
                        buffer.SetTempPixel(x+1,y,color2);
                        buffer.SetTempPixel(x,y-1,color2);
                        buffer.SetTempPixel(x,y+1,color2);
                    }
                    break;
                case 2:
                    // 3 nodes
                    if (x < 1) x+=1;
                    if (y < 1) y+=1;
                    if (x > buffer.BufferWi-2) x-=1;
                    if (y > buffer.BufferHt-2) y-=1;
                    if(falling != "Driving")
                    {
                        buffer.SetTempPixel(x,y,color1, 2);
                    }
                    else
                    {
                        buffer.SetTempPixel(x,y,color1);
                        if (rand() % 100 > 50)      // % 2 was not so random
                        {
                            buffer.SetTempPixel(x-1,y,color2);
                            buffer.SetTempPixel(x+1,y,color2);
                        }
                        else
                        {
                            buffer.SetTempPixel(x,y-1,color2);
                            buffer.SetTempPixel(x,y+1,color2);
                        }
                    }
                    break;
                case 3:
                    // 9 nodes
                    if (x < 2) x+=2;
                    if (y < 2) y+=2;
                    if (x > buffer.BufferWi-3) x-=2;
                    if (y > buffer.BufferHt-3) y-=2;
                    if(falling != "Driving") {
                        buffer.SetTempPixel(x, y, color1, 3);
                    }
                    else {
                        buffer.SetTempPixel(x, y, color1);
                        for (i=1; i<=2; i++)
                        {
                            buffer.SetTempPixel(x-i,y,color2);
                            buffer.SetTempPixel(x+i,y,color2);
                            buffer.SetTempPixel(x,y-i,color2);
                            buffer.SetTempPixel(x,y+i,color2);
                        }
                    }
                    break;
                case 4:
                    // 13 nodes
                    if (x < 2) x+=2;
                    if (y < 2) y+=2;
                    if (x > buffer.BufferWi-3) x-=2;
                    if (y > buffer.BufferHt-3) y-=2;
                    if(falling != "Driving") {
                        buffer.SetTempPixel(x, y, color1, 4);
                    }
                    else {
                        buffer.SetTempPixel(x, y, color1);
                        buffer.SetTempPixel(x-1,y,color2);
                        buffer.SetTempPixel(x+1,y,color2);
                        buffer.SetTempPixel(x,y-1,color2);
                        buffer.SetTempPixel(x,y+1,color2);

                        buffer.SetTempPixel(x-1,y+2,color2);
                        buffer.SetTempPixel(x+1,y+2,color2);
                        buffer.SetTempPixel(x-1,y-2,color2);
                        buffer.SetTempPixel(x+1,y-2,color2);
                        buffer.SetTempPixel(x+2,y-1,color2);
                        buffer.SetTempPixel(x+2,y+1,color2);
                        buffer.SetTempPixel(x-2,y-1,color2);
                        buffer.SetTempPixel(x-2,y+1,color2);
                    }
                    break;
                case 5:
                    // 45 nodes (not enabled)
                    break;
            }
        }
    }

    // move snowflakes
    int movement = (buffer.curPeriod - buffer.curEffStartPer) * sSpeed * buffer.frameTimeInMs / 50;
    int new_x,new_y,new_x2,new_y2;
    int starty = 0;
    if (falling == "Falling & Accumulating")
    {
        starty = 1;
    }

    bool driving = falling == "Driving";
    for (x=0; x<buffer.BufferWi; x++) {
        new_x = (x+movement/20) % buffer.BufferWi; // CW
        new_x2 = (x-movement/20) % buffer.BufferWi; // CCW
        if (new_x2 < 0) new_x2 += buffer.BufferWi;

        for (y=starty; y<buffer.BufferHt; y++) {
            if (!driving) {

                // this controls the speed by skipping movement when slow
                if (((buffer.curPeriod-buffer.curEffStartPer) * (sSpeed+1)) / 30 != ((buffer.curPeriod-buffer.curEffStartPer-1) * (sSpeed + 1)) / 30)
                {
                    // if there is a flake to move
                    buffer.GetTempPixel(x, y, color3);
                    if (color3 != xlBLACK) {

                        // check where we can move to?
                        int moves = possible_downward_moves(buffer, x, y);
                        x0 = x;

                        //we have something to move
                        // randomly move the flake left or right
                        if (moves > 0 || (falling == "Falling" && y == 0))
                        {
                            switch(rand() % 5)
                            {
                                case 0:
                                    if (moves & 1) {
                                        x0 = x - 1;
                                    }
                                    else {
                                        if (moves & 2) {
                                            x0 = x;
                                        }
                                        else {
                                            x0 = x + 1;
                                        }
                                    }
                                    break;
                                case 1:
                                    if (moves & 4) {
                                        x0 = x + 1;
                                    }
                                    else {
                                        if (moves & 2) {
                                            x0 = x;
                                        }
                                        else {
                                            x0 = x - 1;
                                        }
                                    }
                                    break;
                                default:  //down more often then left/right to look less "jittery"
                                    if (moves & 2) {
                                        x0 = x;
                                    }
                                    else if ((moves & 5) == 4) {
                                        x0 = x + 1;
                                    }
                                    else if ((moves & 5) == 1) {
                                        x0 = x - 1;
                                    }
                                    else {
                                        switch(rand() % 2)
                                        {
                                            case 0:
                                                x0 = x+1;
                                                break;
                                            default:
                                                x0 = x-1;
                                                break;
                                        }
                                    }
                                    break;
                            }

                            // handle wrap around
                            if (x0 < 0) {
                                x0 += buffer.BufferWi;
                            }
                            else if (x0 >= buffer.BufferWi) {
                                x0 -= buffer.BufferWi;
                            }

                            // and move it down
                            y0 = y - 1;

                            buffer.SetTempPixel(x, y, xlBLACK);
                            if (y0 >= 0)
                            {
                                // move the flake down
                                buffer.SetTempPixel(x0, y0, color3);

                                if (falling == "Falling & Accumulating")
                                {
                                    int nextmoves = possible_downward_moves(buffer, x0, y0);
                                    if (nextmoves == 0) {
                                        // we cant move any further so we can add one at the top
                                        effectState--;
                                    }
                                }
                            }
                            else
                            {
                                // falling should always be just falling ... never accumulate
                                effectState--;
                            }
                        }
                    }
                }
            } else {
                new_y = (y+movement/10) % buffer.BufferHt;
                new_y2 = (new_y+buffer.BufferHt/2) % buffer.BufferHt;
                buffer.GetTempPixel(new_x,new_y,color1);
                if (color1 == xlBLACK) buffer.GetTempPixel(new_x2,new_y2,color1);                // strip off the alpha channel
                buffer.SetPixel(x, y, color1);
            }
        }
    }

    if (!driving)
    {
        // add new flakes to the top
        check = 0;
        int placedFullCount = 0;
        while (effectState < Count && check < 20) {
            // find unused space
            x=rand() % buffer.BufferWi;
            if (buffer.GetTempPixel(x, buffer.BufferHt-1) == xlBLACK) {
                effectState++;
                buffer.SetTempPixel(x, buffer.BufferHt-1, color1, SnowflakeType == 0 ? rand() % 5 : SnowflakeType-1);

                int nextmoves = possible_downward_moves(buffer, x, buffer.BufferHt-1);
                if (nextmoves == 0) {
                    //the placed pixel fills the column, make sure we note that so we can place
                    //another snowflake
                    placedFullCount++;
                }
            }
            check++;
        }
        effectState -= placedFullCount;

        // paint my current state
        for (int y=0; y < buffer.BufferHt; y++) {
            for (int x=0; x < buffer.BufferWi; x++) {

                buffer.GetTempPixel(x, y, color3);
                if (color3 != xlBLACK)
                {
                    // draw flake, SnowflakeType=0 is random type
                    switch (color3.Alpha())
                    {
                        case 0:
                            // single node
                            buffer.SetPixel(x, y, color1);
                            break;
                        case 1:
                            // 5 nodes
                            buffer.SetPixel(x,y,color1);
                            set_pixel_if_not_color(buffer, x-1, y, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x+1, y, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x, y-1, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x, y+1, color2, color1, wrapx, false);
                            break;
                        case 2:
                        {
                            // 3 nodes
                            buffer.SetPixel(x,y,color1);
                            bool isAtBottom = true;
                            for (int yt = 0; yt < y - 1; yt++) {
                                if (buffer.GetTempPixel(x, yt) == xlBLACK) {
                                    isAtBottom = false;
                                    break;
                                }
                            }

                            // when flake has settled always paint it horizontally
                            if (isAtBottom)
                            {
                                set_pixel_if_not_color(buffer, x-1, y, color2, color1, wrapx, false);
                                set_pixel_if_not_color(buffer, x+1, y, color2, color1, wrapx, false);
                            }
                            else {
                                if (rand() % 100 > 50)      // % 2 was not so random
                                {
                                    set_pixel_if_not_color(buffer, x-1, y, color2, color1, wrapx, false);
                                    set_pixel_if_not_color(buffer, x+1, y, color2, color1, wrapx, false);
                                }
                                else
                                {
                                    set_pixel_if_not_color(buffer, x, y-1, color2, color1, wrapx, false);
                                    set_pixel_if_not_color(buffer, x, y+1, color2, color1, wrapx, false);
                                }
                            }
                        }
                            break;
                        case 3:
                            // 9 nodes
                            buffer.SetPixel(x,y,color1);
                            for (i=1; i<=2; i++)
                            {
                                set_pixel_if_not_color(buffer, x-i, y, color2, color1, wrapx, false);
                                set_pixel_if_not_color(buffer, x+i, y, color2, color1, wrapx, false);
                                set_pixel_if_not_color(buffer, x, y-i, color2, color1, wrapx, false);
                                set_pixel_if_not_color(buffer, x, y+i, color2, color1, wrapx, false);
                            }
                            break;
                        case 4:
                            // 13 nodes
                            buffer.SetPixel(x,y,color1);
                            set_pixel_if_not_color(buffer, x-1, y, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x+1, y, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x, y+1, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x, y-1, color2, color1, wrapx, false);

                            set_pixel_if_not_color(buffer, x-1, y+2, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x+1, y+2, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x-1, y-2, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x+1, y-2, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x+2, y-1, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x+2, y+1, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x-2, y-1, color2, color1, wrapx, false);
                            set_pixel_if_not_color(buffer, x-2, y+1, color2, color1, wrapx, false);
                            break;
                        case 5:
                            // 45 nodes (not enabled)
                            break;
                    }
                }
            }
        }
    }
}