Blocking problem

Started by markbilly, Mon 24/10/2011 15:03:29

Previous topic - Next topic

markbilly

Hi,

I have this function, which I want to be able to repeat in a loop. It needs to do its thing without blocking - so the player can click on things at the same time.

Basically all it's doing is moving a line of text down the page - 1 pixel every second - until it gets to a certain y value.

This is the code I tried to write so it didn't block:
Code: ags

function ScrollSentence(int speed = 40)
{
  int timer = 0;
  sentence = Overlay.CreateTextual(134, 36, 80, Game.SpeechFont, 15, "Sentence 1");
  while (sentence.Y < 108) {
      timer++;
      if (timer == speed) {
        sentence.Y++;
        timer = 0;
      }
  }
  sentence.Remove();
}


Except that doesn't work just locks the game up. The only way to fix it is to add a Wait(1) - but that destroys the point.

Code: ags

function ScrollSentence(int speed)
{
  int timer = 0;
  //determine what "sentence one" from lists
  sentence = Overlay.CreateTextual(134, 36, 80, Game.SpeechFont, 15, "Sentence 1");
  while (sentence.Y < 108) {
      timer++;
      if (timer == 40) {
        sentence.Y++;
        timer = 0;
      }
      Wait(1);
  }
  sentence.Remove();
}


Help - this is integral to getting the game working! Thanks, Mark.
 

Khris

You need to restructure everything; it'll never work that way. You need global variables and the moving has to be done inside repeatedly_execute.

Code: ags
Overlay*sentence;
int overlay_speed, overlay_timer;

void ScrollSentence(int speed, String message) {

  sentence = Overlay.CreateTextual(134, 36, 80, Game.SpeechFont, 15, message);
  overlay_speed = speed;
  overlay_timer = 0;
}

// inside repeatedly_execute

  if (sentence.Valid) {
    overlay_timer++;
    if (overlay_timer >= overlay_speed) {
      sentence.Y++;
      overlay_timer = 0;
      if (sentence.Y == 108) sentence.Remove();
    }
  }

markbilly

#2
OK, that makes sense!

Yep, it works. For now at least ;) Thanks, Khris.

EDIT: Scrub that! Now if I try and use the function in a loop itself, the game hangs.
 

Khris

I didn't test this but you're not supposed to call ScrollSentence in a loop.
If you want multiple lines scrolling independently, that requires a bit more work.

Currently, if you call the function a second time while there's already an overlay on the screen, what should happen is the first one simply disappears. Like I said I didn't test this though.

The basic idea for multiple lines is to use an array of Overlays and deal with them one after another in rep_ex.
Ideally though the game would use just one Overlay, putting its graphic together using a DynamicSprite and .DrawString.

markbilly

OK, well basically what I want to do is have three Overlays scrolling down a "page". When each of them reaches the bottom, they need to be created back at the top again. Repeat.

The way I'm looking at it now, I think this is impossible in AGS.

?
 

Calin Leafshade

certainly not impossible, my friend!

Khris! sort the gentleman out!

I would but I am currently naked and need to get dressed.

Do excuse the state of my penis, i'm just so happy to see all of you.

Khris

LOL @ Calin ;D

Why would it be impossible...?

Try this:
Code: ags
Overlay*sentence[3];
int overlay_speed, overlay_timer;

void ScrollSentence(int speed) {

  sentence[0] = Overlay.CreateTextual(134, 36, 80, Game.SpeechFont, 15, "Text 1");
  sentence[1] = Overlay.CreateTextual(134, 56, 80, Game.SpeechFont, 15, "Text 2");
  sentence[2] = Overlay.CreateTextual(134, 76, 80, Game.SpeechFont, 15, "Text 3");
  overlay_speed = speed;
  overlay_timer = 0;
}

// inside repeatedly_execute

  if (sentence[0].Valid) {
    overlay_timer++;
    if (overlay_timer >= overlay_speed) {
      overlay_timer = 0;
      int i;
      while (i < 3) {
        sentence[i].Y++;
        if (sentence[i].Y == 108) sentence[i].Y = 36;
        i++;
      }
    }
  }

markbilly

#7
Several years using AGS and I am still a terrible scripter. I learn something new everyday!

I'll try that, Khris. Thanks again. :)

EDIT: You genius! Works a charm!
 

markbilly

OK, so I have tried to change this so the game creates a text overlay every time interval at y = 36, scrolls it down to y = 108 and removes it.

It should cycle through this process, using up a String array speech[] as the text for the Overlay array speech_overlay[]. Obviously I used the Overlay array because several Overlays will be visible at once.

Problem is it gives me a "Invalid overlay ID specified" error.

Code: ags

String speech[18];
Overlay*speech_overlay[18];
int overlay_speed, overlay_timer, overlay_Y_speed, overlay_Y_timer;
int speech_start = 0;

void ScrollSentence(int speed) {

  speech_start = 1;
  overlay_Y_speed = speed;
  overlay_Y_timer = 0;
  overlay_speed = speed;
  overlay_timer = 0;  
}

//in repeatedly_execute

function repeatedly_execute() 
{
  
if (speech_start == 1) {
  overlay_timer++;
  if (overlay_timer >= overlay_speed) {
    int i = 0;
    overlay_timer = 0;
    speech_overlay[0] = Overlay.CreateTextual(134, 36, 80, Game.SpeechFont, 15, speech[0]);
    while (speech_overlay[0].Y < 108) {
      overlay_Y_timer++;
      if (overlay_Y_timer >= overlay_Y_speed) {
        speech_overlay[0].Y++;
        overlay_Y_timer = 0;
        if (speech_overlay[0].Y == 108) speech_overlay[0].Remove();
      }
    i++;
    }
  }
}


This is turning out to be a massive nightmare. :(
 

Khris

Again, you can't do it that way.
That while loop inside rep_ex, even if we fix the error, will block the entire game.

The rep_ex itself IS the only while loop you need.

I'm still not entirely sure what it is you want to do.
I get that you want text to scroll from y = 36 to 108. When is a line added? Arbitrarily throughout the game?

Just tell us what you want the player to see, without using any AGS terms.

markbilly

Sentence 4

Sentence 3

Sentence 2

Sentence 1

...


That, scrolling down the screen between y = 36 and 108. So obviously when Sentence 1, for example, goes off the bottom, Sentence 5 will appear at the top and so on. The sentences are stored as elements in as Strings in speech[].

Sorry, I have been very poor in my explanations - this whole exercise is really frustrating me.  :-[
 

Khris

#11
So there are supposed to be only four sentences on the screen at a time? As in, their Y coords are 18 apart?

Code: ags
Overlay*sentence[18];
int overlay_speed, overlay_timer, overlay_y = 35;
bool run_sequence;

void ScrollSentence(int speed) {

  speech[0] = "...";  // you can set those elsewhere
  speech[1] = "...";
  ...
  overlay_speed = speed;
  overlay_timer = 0;
  run_sequence = true;
}

// inside repeatedly_execute

  if (run_sequence) {
    overlay_timer++;
    if (overlay_timer >= overlay_speed) {
      overlay_timer = 0;
      overlay_y++;     // y coord of sentence[0]
      int i, y;
      while (i < 18) {
        y = overlay_y - i*18;  // calculate overlay's y
        if (y == 36) sentence[i] = Overlay.CreateTextual(134, 36, 80, Game.SpeechFont, 15, speech[i]);
        else if (y > 36 && y < 108) sentence[i].Y = y;
        else if (y == 108) {
          sentence[i].Remove();
          if (i == 17) run_sequence = false;  // last overlay has just been removed
        }
        i++;
      }
    }
  }

markbilly

Thanks for all the help, you'll definitely need a credit at this rate!

Still giving a null pointer reference error.

On this line:
Code: ags

        else if (y > 36 && y < 108) sentence[i].Y = y;
 

Khris

Found the error: in the second line of my code, replace the 36 with a 35.
Otherwise the first overlay's Y starts out at 37 and thus the overlay isn't created.

SMF spam blocked by CleanTalk