[I6] Are scalable graphics possible in a Glulx game?

The routines in Counterfeit Monkey rely on floating point division. For example: ideal-width / 0.8395. As I’ve said before, there is no floating point division in Inform 6. You can’t even enter a floating point number.

You don’t say which interpreters you’re testing with, but changing the height of a “winmethod_Fixed” graphics window definitely does work in the interpreters I’ve been involved with: I am sure as that’s the sort of thing I’ve tested. What I can’t offer you is an Inform 6 example, but unless your interpreter is bugged, it is possible to do that. The most likely cause is that you haven’t called the function in quite the right way, but without an example to demonstrate it’s hard to be sure.

As for floating point support, well, there are two approaches. Floating point support is available in the interpreters, if not the Inform 6 language, so you could call the floating point opcodes directly from Inform 6. It’s slightly tricky, but not impossible. The Glulx specification details what the floating point opcodes are and what they do: with them you can turn integers into floating point, do floating point maths, and turn the result back into integer form.

To be honest, though, I’d take the simplest approach and scale everything I needed floating point for by (say) 1000: since with Glulx you’ve got 32-bit integer arithmetic that should be fine for all reasonable values. So if I had a picture with width 300 and height 200, I’d say the aspect ratio was (width*1000)/height = 1500. Then if I knew the height of my window was 300, I’d work out the width as (height*ratio)/1000 = (300*1500)/1000 = 450. It’s basically just crude fixed point maths.

1 Like

I’ve just remembered that floating point constants are supported from Inform 6.32: see the release notes. Floating point maths is not included in the language, but you can at least express constants and call the floating point opcodes.

Zarf wrote some unit tests for all this:
https://eblong.com/zarf/glulx/floatconsttest.inf
https://eblong.com/zarf/glulx/glulxercise.inf

3 Likes

Ooh, you’re right. I don’t think I mentioned that. I’m using Windows Glulxe 0.5.4.150 on Windows 7. You should know it well. :grin:

I didn’t know about the Glulx floating point opcodes. I’ve never needed them before.

I’ve actually done something similar to what you mentioned to maintain the aspect ratio. As I know the aspect ratio is 4:3, I use something like (width * 3) / 4 to get the height, print the calculated values on screen and check with a calculator. The numbers are right.

As this topic seems to have generated a bit of interest in the community, I might dig into it a bit more when time permits. I don’t like to let something like this beat me.

I just read a bit more of your reply that I missed first time around. I was particularly interested in the “measuring window” to get the full UI window size. I had an idea like that myself while trying to get to sleep the other night. Then forgot about it the next day. I was calling it a “dummy window” with 0% width and 100% height (for vertical dimensions) or 100% width and 0% height (for horizontal dimensions). I might try that. Alternatively, there might be a way to get the dimensions of the root window.

Since your interpreter is using the Glk library I wrote, I’d better demonstrate that changing the window size works:

Include "infglk.h";

[ Main txtWin gfxWin pairWin;

  @setiosys 2 0; ! select Glk I/O system
  txtWin = glk_window_open(0,0,0,wintype_TextBuffer,0);
  glk_set_window(txtWin);
  print "Hello!^This is a test of changing a graphics window's height...^";

  gfxWin = glk_window_open(txtWin,winmethod_Fixed+winmethod_Above,1,wintype_Graphics,1);
  pairWin = glk_window_get_parent(gfxWin);

  glk_request_timer_events(1000);

  while (1)
  {
    glk_window_set_arrangement(pairWin,winmethod_Fixed+winmethod_Above,100,0);
    glk_window_fill_rect(gfxWin,$00ff0000,0,0,100,100);
    waitForTimer();

    glk_window_set_arrangement(pairWin,winmethod_Fixed+winmethod_Above,200,0);
    glk_window_fill_rect(gfxWin,$0000ff00,0,0,100,200);
    waitForTimer();
  }
];

Array gg_event --> 4;

[ waitForTimer;

  while (1)
  {
    glk_select(gg_event);
    if (gg_event-->0 == evtype_Timer)
      return;
  }
];

This only uses “infglk.h”, a header auto-generated from the Glk C header. The most up-to-date version comes from https://raw.githubusercontent.com/erkyrath/glk-dev/master/dispatch_dump/infglk.h

When the timer triggers, every second, it causes the graphics window to oscillate in height between 100 and 200 pixels. In writing this I can guess what caught you out: glk_window_set_arrangement() applies to the pair window that represents the splitting of the window, not to the graphics window itself.

1 Like

I think you’re exactly right. As soon as I saw your reference to pairWin (an abbreviation of a term that zarf uses to describe the parent window), I scanned your code to find:

pairWin = glk_window_get_parent(gfxWin);

I then searched the Glk spec for glk_window_get_parent and found what I needed. It was in there all the time, it just wasn’t explained very well and wasn’t where I’d expect to find it. So, I need to resize the parent (the paired window), not the child (the key window), even though it was the opening of the child window that originally set the size constraints. It makes sense in a weird sort of way. Now I’m excited. Thanks David.

It’s not quite like that. Say you initially start with a single window A. When you want to carve off a new window B from that, what actually happens is that you get three windows – the new “pair window” P1 (which is exactly the same size as A used to be) and two “real windows” A and B, which are now children of P1, and (usually, but not always) one of which is the key window of P1.

You put content into A and B but it’s P1 that actually stores the “arrangement”. And if you further subdivide B, for example, then you might get P1 -> { A, P2 -> { B, C } }.

Or at least this is my understanding, anyway, having read this stuff for the first time myself last week. :wink:

Historically speaking, text-graphic IF tackled the much worse diversity in graphics of the 8 and 16 bit era either using vector graphics (e.g. quill/illustrator, GAC) or a master format easily convertible to the variety of graphic capabilities of the 8 and 16 bit video output. (ex. Magnetic scrolls)

Today we have open and free formats for both solutions (svg and png), and the core logic of IF programming is having an high-level language mated to a parser library for a virtual machine, the latter specialised for IF.

said that, the ideal handling of the issue ought to be leaving to the 'terp the low-level handling of .svg and/or .png files and having the library handling the selection of the appropriate picture and placement, the ideal final result, from the IF author’s perspective, should be having, say handling the picture like an object’s description (following the ancient saying “a picture is worth thousand words”), in the I6 case, having something like:

with image white_house

where white_house points to the picture inside the blorb bundle.

Best regards from Italy,
dott. Piergiorgio.

Those sorts of things do exist – for example over in I7 you can just include the “Location Images” extension and everything just works as if by magic.

Still, people who want to put the time and effort into putting images in their stories in the first place often want to have finer control over placing multiple images in specific locations or specific layouts, and at that point you often have to drill down into the finer details of Glk.

But either way, that sort of suggestion is entirely off-topic in this thread.

The image property is a great idea, but I also have many changeable images and some cut scenes, so the image property would need to be a routine and you still need to be able to change that image within your code. I’m sure you can do that in I7, just as you can in I6. It’s actually quite easy.

Oh, and you have to do it in such a way that your images are still correct after restart, restore and undo.