What is causing Phylactere script to choose blue rather than translucent black?

Started by bx83, Fri 20/10/2017 07:33:19

Previous topic - Next topic

bx83

I'm using the Phylactere script to render speech which is normally used by Speak; and it works very well.
For my speechbubble background, I've chosen a translucent black; however, when it comes into contact with the black of a game background, it turns blue....? Why is it doing this?
Check this:


Here is my code:

Code: ags

// Require: AGS 3

Phylactere_Param phylactere;
export phylactere;

int Phylactere_col_r;
int Phylactere_col_g;
int Phylactere_col_b;

function game_start() {
  /* ------------- PARAMETRAGE --------------- */
  phylactere.background_color = 65535;
  phylactere.is_transparent = true;
  phylactere.outline_color = 0;
  phylactere.speed = 35;
  phylactere.transparency = 30;
  phylactere.transparency_red = 0;
  phylactere.transparency_green = 0;
  phylactere.transparency_blue = 0;
  phylactere.width = 300;
  phylactere.distance_from_head = 6;
  phylactere.view_speed = 5;
  phylactere.ajust_htext = 5;
  phylactere.skip_mode = eSkipKeyOrClick;
  /* ------------------------------------------ */
  
}

function getRVG(int color) {
  int c = color;
  if (c == -1) c = 63519;
  int cc = c / 2048;
  int cr , cg, cb;
  cr = cc * 8;
  c = c - (cc * 2048);
  cc = c / 64;
  cg = (cc * 8);
  c = c - (cc * 64);
  if (cg > 0) {
    cg += 4;
    c -= 32;
  }
  cb = c * 8;
  if (cb < 0) {
    if (cg > 4) cg -= 4;
    cb = 256 + cb;
  }
  Phylactere_col_r = ((cr * phylactere.transparency) + (phylactere.transparency_red * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_r > 255) Phylactere_col_r = 255;
  if (Phylactere_col_r < 0) Phylactere_col_r = 0;
  Phylactere_col_g = ((cg * phylactere.transparency) + (phylactere.transparency_green * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_g > 255) Phylactere_col_g = 255;
  if (Phylactere_col_g < 0) Phylactere_col_g = 0;
  Phylactere_col_b = ((cb * phylactere.transparency) + (phylactere.transparency_blue * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_b > 255) Phylactere_col_b = 255;
  if (Phylactere_col_b < 0) Phylactere_col_b = 0;
}

function Phylactere(this Character* , String str,  PhylactereQueueMode mode) {
 
  String speechnum;
 
  if (str.IndexOf("&") != -1) {
    speechnum = str.Substring(str.IndexOf("&"), str.IndexOf(" ")+1);
    str = str.Substring(str.IndexOf(" "), str.Length-1);
  } else {
    str = str.Copy();
  }

  
  if (IsTranslationAvailable()) str = GetTranslation(str);
 
  String GQueue[20]; // Dessin de la Queue (X = Contour, O = Fond)
  int queue_height = 0;
 
  if (mode == ePhylactereTalking) {
    GQueue[01] = "OOOOOOOO";
    GQueue[02] = "XOOOOOXX";
    GQueue[03] = "XOOOOX  ";
    GQueue[04] = "XOOOOX  ";
    GQueue[05] = " XOOOX  ";
    GQueue[06] = " XOOOX  ";
    GQueue[07] = "  XOOOX ";
    GQueue[08] = "   XOOOX";
    GQueue[09] = "    XXX ";
    queue_height = 9;
  }

  if (mode == ePhylactereThinking) {
    GQueue[01] = "        ";
    GQueue[02] = "        ";
    GQueue[03] = "  XX    ";
    GQueue[04] = " XOOX   ";
    GQueue[05] = "XOOOOX  ";
    GQueue[06] = "XOOOOX  ";
    GQueue[07] = " XOOX   ";
    GQueue[08] = "  XX    ";
    GQueue[09] = "        ";
    GQueue[10] = "    XX  ";
    GQueue[11] = "   XOOX ";
    GQueue[12] = "   XOOX ";
    GQueue[13] = "    XX  ";
    queue_height = 13;
  }
  
  // Controle des parametres
  if (phylactere.transparency < 0) phylactere.transparency = 0;
  if (phylactere.transparency > 100) phylactere.transparency = 100;
  if (phylactere.transparency_red < 0) phylactere.transparency_red = 0;
  if (phylactere.transparency_red > 255) phylactere.transparency_red = 255;
  if (phylactere.transparency_green < 0) phylactere.transparency_green = 0;
  if (phylactere.transparency_green > 255) phylactere.transparency_green = 255;
  if (phylactere.transparency_blue < 0) phylactere.transparency_blue = 0;
  if (phylactere.transparency_blue > 255) phylactere.transparency_blue = 255;
  if ((phylactere.skip_mode != eSkipTimer) && (phylactere.skip_mode != eSkipKeyOrClick) && (phylactere.skip_mode != eSkipOnlyKeyOrClick)) phylactere.skip_mode = eSkipTimer;

  // Arrêt du personnage si en mouvement
  if (phylactere.is_transparent) {
    if (this.Moving) this.StopMoving();
  }
  int char_x = this.x;
  int char_y = this.y;
  int view_x = GetViewportX();
  int view_y = GetViewportY();

  // Création de la surface
  DynamicSprite *screen = DynamicSprite.CreateFromBackground();
  DrawingSurface *surface = screen.GetDrawingSurface();
  surface.Clear();
  int screen_width = surface.Width;
  int screen_height = surface.Height;

  // Lance l'animation "Speech"
  if (this.SpeechView > 0) {
    if (mode != ePhylactereThinking) {
      this.LockView(this.SpeechView);
      this.Animate(this.Loop, phylactere.view_speed , eRepeat, eNoBlock);
    }
  }

  // Recupération de la hauteur du personnage
  ViewFrame *char_frame = Game.GetViewFrame(this.View , this.Loop, this.Frame);
  int char_height = FloatToInt(IntToFloat(Game.SpriteHeight[char_frame.Graphic]) * IntToFloat(this.Scaling) / 100.0);
  
  // Découpage de la phrase
  String line[101];
  int line_width[101];
  int line_height[101];
  int nb_lines = 0;
  String tmp_line = str.Substring(0, 1);
  String tmp_line2 = "";
  int ind_str = 1;
  int width_max = 0;
  int height_max = 0;
  while ((ind_str < str.Length) && (nb_lines < 99)) {
    tmp_line2 = tmp_line.AppendChar(str.Chars[ind_str]);
    if (GetTextWidth(tmp_line2, Game.SpeechFont) > phylactere.width) {
      int seek_blank = tmp_line.Length - 1;
      while (seek_blank > 0 && tmp_line.Chars[seek_blank] != ' ') {
        seek_blank--;
      }
      if (seek_blank > 0) {
        tmp_line2 = tmp_line.Substring(seek_blank + 1 , tmp_line.Length - seek_blank);
        tmp_line2 = tmp_line2.AppendChar(str.Chars[ind_str]);
        tmp_line = tmp_line.Substring(0, seek_blank);
      } else {
        tmp_line2 = "";
        tmp_line2 = tmp_line2.AppendChar(str.Chars[ind_str]);
      }
      nb_lines++;
      line[nb_lines] = tmp_line;
      line_width[nb_lines] = GetTextWidth(line[nb_lines], Game.SpeechFont);
      line_height[nb_lines] = GetTextHeight(line[nb_lines], Game.SpeechFont, screen_width);
      if (line_width[nb_lines] > width_max) width_max = line_width[nb_lines];
      height_max = height_max + line_height[nb_lines];
    }
    tmp_line = tmp_line2;
    tmp_line2 = "";
    ind_str++;
  }
  nb_lines++;
  line[nb_lines] = tmp_line;
  line_width[nb_lines] = GetTextWidth(line[nb_lines], Game.SpeechFont);
  line_height[nb_lines] = GetTextHeight(line[nb_lines], Game.SpeechFont, screen_width);
  if (line_width[nb_lines] > width_max) width_max = line_width[nb_lines];
  height_max = height_max + line_height[nb_lines];

  // Calcul positions du texte
  int texte_x = char_x - (width_max / 2) - GetViewportX();
  int texte_y = char_y - char_height - height_max - GetViewportY() - queue_height - phylactere.distance_from_head;
  if (texte_x < 0) texte_x = 0;
  if (texte_y < 0) texte_y = 0;
  if (texte_x + width_max + GetViewportX() > screen_width) texte_x = screen_width - width_max - GetViewportX();
  
  // Calcul positions de la bulle
  int bulle_x1 = texte_x - 5;
  int bulle_y1 = texte_y - 9 + phylactere.ajust_htext;    //CHEAT, set to 1
  int bulle_x2 = texte_x + width_max + 5;
  int bulle_y2 = texte_y + height_max + phylactere.ajust_htext;
  
  // ---- Bulle ----
  DrawingSurface* background_surface;
  DynamicSprite* background_sprite;
  
  if (phylactere.is_transparent) {
    bool mouse_visible_before = Mouse.Visible;
    if (mouse_visible_before) Mouse.Visible = false;
    //Wait(1);
    background_sprite = DynamicSprite.CreateFromScreenShot();
    if (mouse_visible_before) Mouse.Visible = true;
    background_surface = background_sprite.GetDrawingSurface();
    int by = bulle_y1;
    int bx;
    while (by <= bulle_y2) {
      bx = bulle_x1;
      while (bx <= bulle_x2) {
        int col = background_surface.GetPixel(bx, by);
        getRVG(col);
        surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
        surface.DrawPixel(bx, by);
        bx++;
      }
      by++;
    }
    
    bx = bulle_x1 - 1;
    by = bulle_y1 + 1;
    while (by <= bulle_y2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x2 + 1;
    by = bulle_y1 + 1;
    while (by <= bulle_y2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x1 + 1;
    by = bulle_y1 - 1;
    while (bx <= bulle_x2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

    bx = bulle_x1 + 1;
    by = bulle_y2 + 1;
    while (bx <= bulle_x2 - 1) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

    bx = bulle_x1 - 2;
    by = bulle_y1 + 3;
    while (by <= bulle_y2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x2 + 2;
    by = bulle_y1 + 3;
    while (by <= bulle_y2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      by++;
    }

    bx = bulle_x1 + 3;
    by = bulle_y1 - 2;
    while (bx <= bulle_x2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

    bx = bulle_x1 + 3;
    by = bulle_y2 + 2;
    while (bx <= bulle_x2 - 3) {
      int col = background_surface.GetPixel(bx, by);
      getRVG(col);
      surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
      surface.DrawPixel(bx, by);
      bx++;
    }

  } else {
    surface.DrawingColor = phylactere.background_color;
    surface.DrawRectangle(bulle_x1 , bulle_y1 ,  bulle_x2 ,  bulle_y2);
    surface.DrawLine(bulle_x1 - 1, bulle_y1 + 1 ,  bulle_x1 - 1 ,  bulle_y2 - 1);
    surface.DrawLine(bulle_x2 + 1, bulle_y1 + 1 ,  bulle_x2 + 1 ,  bulle_y2 - 1);
    surface.DrawLine(bulle_x1 + 1 ,  bulle_y1 - 1 ,  bulle_x2 - 1 ,  bulle_y1 - 1);
    surface.DrawLine(bulle_x1 + 1 ,  bulle_y2 + 1 ,  bulle_x2 - 1 ,  bulle_y2 + 1);
    surface.DrawLine(bulle_x1 - 2, bulle_y1 + 3 ,  bulle_x1 - 2 ,  bulle_y2 - 3);
    surface.DrawLine(bulle_x2 + 2, bulle_y1 + 3 ,  bulle_x2 + 2 ,  bulle_y2 - 3);
    surface.DrawLine(bulle_x1 + 3 ,  bulle_y1 - 2 ,  bulle_x2 - 3 ,  bulle_y1 - 2);
    surface.DrawLine(bulle_x1 + 3 ,  bulle_y2 + 2 ,  bulle_x2 - 3 ,  bulle_y2 + 2);
  }

  // ---- Contours ----
  surface.DrawingColor = phylactere.outline_color;
  surface.DrawLine(bulle_x1 - 3, bulle_y1 + 3 ,  bulle_x1 - 3 ,  bulle_y2 - 3);
  surface.DrawLine(bulle_x2 + 3, bulle_y1 + 3 ,  bulle_x2 + 3 ,  bulle_y2 - 3);
  surface.DrawLine(bulle_x1 + 3 ,  bulle_y1 - 3 ,  bulle_x2 - 3 ,  bulle_y1 - 3);
  surface.DrawLine(bulle_x1 + 3 ,  bulle_y2 + 3 ,  bulle_x2 - 3 ,  bulle_y2 + 3);
  
  //---- Angle supérieur gauche ----
  surface.DrawPixel(bulle_x1 - 2 , bulle_y1 + 2);
  surface.DrawPixel(bulle_x1 - 2 , bulle_y1 + 1);
  surface.DrawPixel(bulle_x1 - 1 , bulle_y1);
  surface.DrawPixel(bulle_x1 , bulle_y1 - 1);
  surface.DrawPixel(bulle_x1 + 1 , bulle_y1 - 2);
  surface.DrawPixel(bulle_x1 + 2 , bulle_y1 - 2);

  //---- Angle supérieur droit ----
  surface.DrawPixel(bulle_x2 + 2 , bulle_y1 + 2);
  surface.DrawPixel(bulle_x2 + 2 , bulle_y1 + 1);
  surface.DrawPixel(bulle_x2 + 1 , bulle_y1);
  surface.DrawPixel(bulle_x2 , bulle_y1 - 1);
  surface.DrawPixel(bulle_x2 - 1 , bulle_y1 - 2);
  surface.DrawPixel(bulle_x2 - 2 , bulle_y1 - 2);

  //---- Angle inférieur gauche ----
  surface.DrawPixel(bulle_x1 - 2 , bulle_y2 - 2);
  surface.DrawPixel(bulle_x1 - 2 , bulle_y2 - 1);
  surface.DrawPixel(bulle_x1 - 1 , bulle_y2);
  surface.DrawPixel(bulle_x1 , bulle_y2 + 1);
  surface.DrawPixel(bulle_x1 + 1 , bulle_y2 + 2);
  surface.DrawPixel(bulle_x1 + 2 , bulle_y2 + 2);

  //---- Angle inférieur droit ----
  surface.DrawPixel(bulle_x2 + 2 , bulle_y2 - 2);
  surface.DrawPixel(bulle_x2 + 2 , bulle_y2 - 1);
  surface.DrawPixel(bulle_x2 + 1 , bulle_y2);
  surface.DrawPixel(bulle_x2 , bulle_y2 + 1);
  surface.DrawPixel(bulle_x2 - 1 , bulle_y2 + 2);
  surface.DrawPixel(bulle_x2 - 2 , bulle_y2 + 2);
  
  // ---- Queue ----
  int char_dir = this.Loop; // 0=bas , 1=gauche, 2=droite, 3=haut
  int qy = bulle_y2 + 3;
  int qx;
  if ((char_dir == 1) || (char_dir == 0)) {
    qx = char_x - 10 - GetViewportX();
  } else {
    qx = char_x + 10 - GQueue[1].Length - GetViewportX();
  }
  int j = 1;
  while (j <= queue_height) {
    int i = 0; 
    while (i < GQueue[j].Length) {
      bool visible = false;
      if (GQueue[j].Chars[i] == 'X') {
        surface.DrawingColor = phylactere.outline_color;
        visible = true;
      }
      if (GQueue[j].Chars[i] == 'O') {
        if (phylactere.is_transparent) {
          int col;
          if ((char_dir == 1) || (char_dir == 0)) {
            col = background_surface.GetPixel(qx + i ,  qy + j - 1);
          } else {
            col = background_surface.GetPixel(qx + GQueue[j].Length - i ,  qy + j - 1);
          }
          getRVG(col);
          surface.DrawingColor = Game.GetColorFromRGB(Phylactere_col_r, Phylactere_col_g, Phylactere_col_b);
        } else {
          surface.DrawingColor = phylactere.background_color;
        }
        visible = true;
      }
      if (visible) {
        if ((char_dir == 1) || (char_dir == 0)) {
          surface.DrawPixel(qx + i ,  qy + j - 1);
        } else {
          surface.DrawPixel(qx + GQueue[j].Length - i ,  qy + j - 1);
        }
      }
      i++; 
    }
    j++;
  }
  if (phylactere.is_transparent) {
    background_surface.Release();
    background_sprite.Delete();
  }

  // Texte
  surface.DrawingColor = this.SpeechColor;
  int ii = 0;
  int jj = 0;
  while (ii < nb_lines) {
    ii++;
    surface.DrawString(texte_x + (width_max - line_width[ii]) / 2 , texte_y + jj , Game.SpeechFont ,  line[ii]); 
    jj = jj + line_height[ii]; 
  }

  // Affichage de la bulle
  int pos_x = bulle_x1 - 4;
  if (pos_x < 0) pos_x = 0;
  int pos_y = bulle_y1 - 4;
  if (pos_y < 0) pos_y = 0;
  int lng_x = bulle_x2 + 4;
  int lng_y = bulle_y2 + 4 + queue_height;
  
  if (lng_x >= screen_width) lng_x = screen_width - 1;
  if (lng_y >= screen_height) lng_y = screen_height - 1;

  DynamicSprite* ds = DynamicSprite.CreateFromDrawingSurface(surface, pos_x, pos_y, lng_x - pos_x + 1 ,  lng_y - pos_y + 1);
  surface.Release();
  Overlay* bulle = Overlay.CreateGraphical(pos_x, pos_y, ds.Graphic, true);

  // Attente
  int tempo = FloatToInt(IntToFloat(str.Length) * IntToFloat(phylactere.speed) / 10.0);
  if (tempo < 40) tempo = 40;
  bool stop = false;
  
  if (speechnum != null) {
    this.SaySync(speechnum.Append(str));  
    this.Say(speechnum);                  //speak the line
  }
  
  if (speechnum==null) {  
    while (!stop){
      if (!phylactere.is_transparent) {
        bulle.Remove();
        int nx = pos_x + (this.x - char_x) - (GetViewportX() - view_x);
        int ny = pos_y + (this.y - char_y) - (GetViewportY() - view_y);
        bulle = Overlay.CreateGraphical(nx, ny, ds.Graphic, true);
      }
      if (phylactere.skip_mode != eSkipOnlyKeyOrClick) tempo--;
      if (phylactere.skip_mode == eSkipKeyOrClick) {
        int wm = WaitMouseKey(1);
        if (wm == 1) stop = true;
      }
      if (phylactere.skip_mode == eSkipTimer) {
        Wait(1);
      }
      if (tempo == 0) stop = true;
    }
  }
  
  // Efface la bulle
  ds.Delete();
  screen.Delete();
  bulle.Remove();
  
  // Arrete l'animation Speech
  if (this.SpeechView > 0) {
    if (mode != ePhylactereThinking) {
      this.UnlockView();
    }
  }
  Wait(1);
    
}


As you can see I've only changed about 5 lines of code to integrate in the numbered speech system, but I thought I should post all.

You can get Phylactere here.

Snarky


Khris

This is not really a bug but more of a known issue; AGS uses the first 32 colors slots for a fixed palette of EGA colors and greyscale tones.
Which means Game.GetColorFromRGB() will yield unexpected results for values like 0,0,B.
The fix is to make sure that either Red or Green are at least 8.

Replace line 50 of the snippet with:
Code: ags
  if (Phylactere_col_r < 8) Phylactere_col_r = 8;

bx83

It doesn't entirely work, just changes the blue to a darker tone. Also doesn't make a difference if I replace line 4 with '16' or lines 7 and 10 with '8' or '16'.

Code: ags

  Phylactere_col_r = ((cr * phylactere.transparency) + (phylactere.transparency_red * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_r > 255) Phylactere_col_r = 255;
  //if (Phylactere_col_r < 0) Phylactere_col_r = 0;
  if (Phylactere_col_r < 8) Phylactere_col_r = 8;
  Phylactere_col_g = ((cg * phylactere.transparency) + (phylactere.transparency_green * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_g > 255) Phylactere_col_g = 255;
  if (Phylactere_col_g < 0) Phylactere_col_g = 0;
  Phylactere_col_b = ((cb * phylactere.transparency) + (phylactere.transparency_blue * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_b > 255) Phylactere_col_b = 255;
  if (Phylactere_col_b < 0) Phylactere_col_b = 0;




I'm using AGS 3.4 r4.

Crimson Wizard

What if you do same replacement for Phylactere_col_g as well?

E: BTW, it is interesting to note that these glitches are appearing precisely over the dark cave wall background. May it be worth to report this issue to module's author, giving the piece of your background to help reproduce it?

Snarky

Hmm... so Phylactere "fakes" transparency by manually calculating the color of every pixel from combining the background with the overlay, and drawing that pixel-by-pixel. Yikes!

If using an overlay rather than a GUI isn't a major priority for some reason, you could just replace all of this with a semi-transparent GUI (or two GUIs, one for the speech bubble and one for the text, because of the antialising problems you get with text on transparent GUIs). It should be a lot faster, and you won't have these color artifacts.

Crimson Wizard

Quote from: Snarky on Fri 20/10/2017 16:51:29
Hmm... so Phylactere "fakes" transparency by manually calculating the color of every pixel from combining the background with the overlay, and drawing that pixel-by-pixel. Yikes!

I think the module was made at times when AGS did not have correct alpha transparency support for overlays. Someone might remake it to make a use of built-in AGS translucency.

bx83

Here's my code, still doesn't work, and get's the dark blue in the second picture:

Code: ags

function getRVG(int color) {
  int c = color;
  if (c == -1) c = 63519;
  int cc = c / 2048;
  int cr , cg, cb;
  cr = cc * 8;
  c = c - (cc * 2048);
  cc = c / 64;
  cg = (cc * 8);
  c = c - (cc * 64);
  if (cg > 0) {
    cg += 4;
    c -= 32;
  }
  cb = c * 8;
  if (cb < 0) {
    if (cg > 4) cg -= 4;
    cb = 256 + cb;
  }
  Phylactere_col_r = ((cr * phylactere.transparency) + (phylactere.transparency_red * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_r > 255) Phylactere_col_r = 255;
  if (Phylactere_col_r < 8) Phylactere_col_r = 8;
  Phylactere_col_g = ((cg * phylactere.transparency) + (phylactere.transparency_green * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_g > 255) Phylactere_col_g = 255;
  if (Phylactere_col_g < 8) Phylactere_col_g = 8;
  Phylactere_col_b = ((cb * phylactere.transparency) + (phylactere.transparency_blue * (100 - phylactere.transparency))) / 100;
  if (Phylactere_col_b > 255) Phylactere_col_b = 255;
  if (Phylactere_col_b < 8) Phylactere_col_b = 8;
}


Not sure about a GUI or Overlay... How would I....?

bx83


Monsieur OUXX

I'm almost sure the answer is in the source code of the Trublu module : http://www.adventuregamestudio.co.uk/forums/index.php?topic=43966
Check out what corner cases monkey0506 is dealing with, and you'll see how to avoid fualty RGB combinations.


PS: just to be sure: is your game 16-bits or 32-bits? On a related note : Did you start your game directly from a demo game that was 16-bits and did you change it to 32-bits? If yes, then you should export the phylactere sprite and re-import it! Moving directly from 16-bits games to 32-games and keeping the original sprites as-is is never a good idea.

 

bx83


Monsieur OUXX

Quote from: bx83 on Mon 23/10/2017 10:57:39
32 bit all the way.
Export the phylactere sprite...?
If it was 32-bits all the way, then you don't need to do that. But still, my comment about studying the flaws of RGB handling (by studying the Trublu code and related discussions) should help if not everything useful has already been said here.
 

Crimson Wizard

If you are using 32-bit game, my suggestion is actually to make Phylactere create DynamicSprite without transparency handling first, then clone it to new sprite with transparency using DrawImage, and use that clone for Overlay. Thus it will use built-in AGS translucency feature instead of calculating it itself.

Or use Snarky's suggestion about GUI:
Quote from: Snarky on Fri 20/10/2017 16:51:29
If using an overlay rather than a GUI isn't a major priority for some reason, you could just replace all of this with a semi-transparent GUI (or two GUIs, one for the speech bubble and one for the text, because of the antialising problems you get with text on transparent GUIs). It should be a lot faster, and you won't have these color artifacts.

SMF spam blocked by CleanTalk