Logo Pending


Priorities Revisited

I just spent way too long drawing little hexagons. Here’s why.

As you know by now, SCI0 up to SCI11 use vector-based priority and control screens, while SCI2 introduced bitmap-based priority screens while also removing the control screen entirely. That means when I render a background for The Dating Pool, I have to trace out everything you can stand behind, by hand, as vectors. And a while back I replaced the simple railing on the space station scenes with hexagons, so I had to re-vector the priority screen to match.

I didn’t draw any hexagons where the booths are because you can’t stand close enough for it to matter. Saves a lotta work for me. That’s still a lot of Line and Fill commands though. And that’s just one screen up there. There’s three.

Here’s what it’d look look if we targeted SCI2, hypothetically:

Much easier to produce, perhaps. I could just load it into my editor of choice, select everything that’d be closer, and cut that out onto a new layer. Rinse and repeat. And despite appearances here, the priority layers wouldn’t all be the full screen size either. They’d actually only be… 320×17 pixels for the one and 320×22 pixels for the other. Could be even smaller if I cut the booth layer into three separate pieces, perhaps.

Note that the background layer is completely missing the colors from the railing and booth layers. Why compress that twice or more after all?

[ , ] 2 Comments on Priorities Revisited

Perspective is a tricky thing

This topic was suggested, more or less, by Phil Fortier.

What do these screenshots from DoomLeisure Suit Larry 3, and Secret of Monkey Island have in common?

Their perspective. Every single wall is a straight line. I put Doom there to show it’s not just adventure games, and Monkey Island because the arcs end in straight lines, but otherwise they all have the same perspective. Don’t believe your eyes? Here, let me spell it out for you:

This is one-point perspective, where lines converge to a single point.

Here’s a Youtube video I picked out at random from my search results while I ensured I wasn’t pulling crap out of my ass. You’ll notice a hallway like that could do well as an adventure game background.

They’re also a pain in the ass when you render your game’s backgrounds with a program that doesn’t do 1PP, like I do. I mean, I could use this copy of 3D Studio Max that I have collecting dust over here, but all my prefabs are in Daz Studio? So I gotta fake it somehow. Very carefully align the camera so the walls point straight up.

In this old version of Alhor’s Garage in The Dating Pool, the walls are not straight. So I went back and tweaked the camera along with a few other details.

I feel much better about this version. But for other scenes, to get enough floor space in view, I have to pull back the camera drastically. Normally you’d increase the floor space by angling the point of view down. I’m sure you can agree that in Chairman Kenneth’s office, the camera is pretty far up. If I tried to reproduce that image in Daz, I’d get diagonal walls. So how do you fix that?

There’s practically no floor space here! If I used this, the main character would have a line to move along, and if other characters were to try and pass there’d be almost no space to show it. Moving the camera up mostly increases the ceiling space…

And of course you could fake it by tilting the walls back to compensate.

Or you can just say fuck it and deem the perspective distortion negligible after downsampling.

*sigh*

I seriously wish I had the means to acquire some nicely painted backgrounds, even after years of demos with rendered ones.

[ , , , , , ] Leave a Comment

Skip a bit, brother

Ah yes. The skip button. You don’t see those often in most of the old Sierra adventure games, and to be honest I’m not interested enough in the later ones to check. Sue me. But how do they work?
As usual, let’s look at the scripts.

First, we have Leisure Suit Larry 5 – Passionate Patti does Pittsburgh, which shares its skip system with Freddy Pharkas Frontier Pharmacist. The only notable difference between the two is that, being an SCI11 game, the latter uses Messages instead of Text resources. This system has two dedicated parts to it, plus how the current scene reacts:

(instance icon5 of IconI
  ; ...
  (method (select)
    (return
      (if (and gFFRoom (super select: &rest))
        ; That is, if we had a gFFRoom set and the usual response to a button click was true.
        (gIconBar hide:)
        (if (Print "Do you really want to skip ahead?" #title "Fast Forward" #button "Yes" 1 #button "Oops" 0)
          (if (== gFFRoom 1000)
            ; In this case, we want to cue something.
            (if (IsObject gFFScript)
              (gFFScript cue:)
              (SetFFRoom 0)
            else
              (Print "ERROR: Object passed to SetFFRoom isn't an object you silly person!")
            )
          else
            ; In the *other* case, we just want to go somewhere.
            ; This option is good for larger cutscenes.
            (gRoom newRoom: gFFRoom)
            (= gFFRoom (+ gFFRoom 1000))
            ; ... I'm... not entirely sure what that was for.
          )
        )
      else
        (return 0)
      )
    )
  )
)
 
(procedure (SetFFRoom room script)
  (if (not room)
    (= gFFRoom 0)
    (= gFFScript null)
    (gIconBar disable: 5)
  else
    (= gFFRoom room)
    (if (and (> argc 1) (== room 1000))
      (= gFFScript script)
    )
    (gIconBar enable: 5)
  )
)

Call SetFFRoom with anything but 1000, and you set up a skip to another room. Call it with “room” 1000 and a cue-able object otherwise. Pretty simple, I don’t think I need to bother with a practical example.

Incidentally, this makes one of the examples of a non-standard procedure whose name is absolutely certain.

On to Leisure Suit Larry 6 – Shape Up or Slip Out. This is the low-res SCI11 version, but I sincerely doubt the SCI2 version is much different. It has only one shared part, the icon, without a setup procedure. Note that icon5 is exported as ScriptID 0 8, hence the references throughout.

(instance icon5 of BarIconI
  ; ...
  (method (doit &tmp theTarget)
    (cond 
      ((not gSkipTarget)
        ; Don't do anything if no skip was set up.
        0
      )
      ((not (IsObject gSkipTarget))
        ; Skip target is a number, so a room.
        (gButtonBar disable: (ScriptID 0 8)) ; icon5 that is.
        (= theTarget gSkipTarget)
        (= gSkipTarget null)
        (gRoom newRoom: theTarget)
      )
      (else
        ; Skip target is something to cue.
        (gButtonBar disable: (ScriptID 0 8))
        (= theTarget gSkipTarget)
        (= gSkipTarget null)
        (theTarget cue:)
      )
    )
  )
)

As an example, here’s the ladder-climbing sequence with Merrily:

(instance rm260 of LarryRoom
  (properties
    picture 260
    horizon 11
  )
 
  (method (init)
    (super init: &rest)
    (= gSkipTarget gRoom)
    ((ScriptID 0 8) enable:)
    (self setScript: toTower)
    ; ...
  )
 
  (method (cue)
    ; Called when we click the Fast Forward button.
    ((gRoom script?) setScript: forwardScript)
  )
)
 
(instance forwardScript of Script
  (properties)
 
  (method (changeState newState &tmp oldCursor)
    (switchto (= state newState)
      (
        (= cycles 2)
      )
      (
        (= oldCursor gCursor)
        (gGame setCursor: 999)
        (SetCursor 225 87)
        (if
          (Print
            addTitle: "Just Not Into Rubber, Larry?"
            addText: "Do you really want to miss out on what promises to be a unique experience, Larry?"
            addButton: 0 "Oops" 0 35
            addButton: 1 "Yes" 155 35
            init:
          )
          (self cue:)
        else
          (gGame setCursor: oldCursor)
          ; Reset the skip and get rid of this script.
          (= gSkipTarget gRoom)
          (self dispose:)
        )
      )
      (
        ; We chose to skip. Change up our inventory...
        (gEgo get: 40 put: 35 put: 31 put: 20 put: 2)
        (= gSkipTarget null)
        ((ScriptID 0 8) disable:)
        (gGame handsOff: changeScore: 20 174 hideControls:)
        (= cycles 2)
      )
      (
        (SetPort 0)
        (SetPort 0 0 190 320 10 0)
        (Bset 8)
        (gSounds stop:)
        (DrawPic 98 dpOPEN_EDGECENTER) ; Black screen
        (gCast eachElementDo: #hide)
        (= cycles 2)
      )
      (
        (gRoom newRoom: 620) ; Go to your room
      )
    )
  )
)

And then there’s The Dating Pool. It has a simple skip system with a single global, like LSL6, but comes in two parts like LSL5 and FPFP.

(instance SkipIcon of cdIconItem
  (method (select)
    (if gSkip
      ; I *could* ask for confirmation here...
      (gIconBar hide:)
      (if (IsObject gSkip)
        (gSkip cue:)
      else
        (NewRoom gSkip)
      )
      (return true)
    )
  )
)
 
(procedure (SetSkip skip)
  (= gSkip (if argc skip else 0))
  (if gSkip
    ; Unlike LSL6's ButtonBar, an IconBar's IconItem doesn't have enable or disable methods.
    (SkipIcon signal: (| icHIDEBAR icRELEASE icIMMEDIATE))
  else
    ; I could let gIconBar enable or disable the icon but nyeh.
    (SkipIcon signal: (| icHIDEBAR icRELEASE icIMMEDIATE icDISABLED))
  )
)

And an example:

(instance IntroScript of Script
  (method (changeState newState)
    (switchto (= state newState)
      (
        (HandsOff)
        (SetSkip skipScript)
        ; ...
      )
      ; ...
    )
  )
)
 
(instance skipScript of Script
  (method (cue)
    (DrawPic 150 dpFADEOUT)
    ; Put us at place we'd be if we let the cutscene play out.
    (gEgo
      init:
      posn: 90 130
      resetCycler:
      view: 0
      loop: 2
    )
    (gRoom setScript: RoomScript)
  )
)

(Update: I’d changed the skip script in The Dating Pool to use cue instead of doit and allow gSkip to be a room number. And then I forgot to update the example.)

[ , , , , ] Leave a Comment

On SCI Windows – Part 7 – The Dating Pool

It was inevitable, really, that I’d end this series with my own game. The Dating Pool uses a simplified take on BorderWindow, with the ability to change the thickness removed.

could’ve just used a BorderWindow, in fact, with bevelWid and shadowWid both set to 1 and I’d get the exact same result. This exact style was in fact one of the examples I’ve shown back there! But I did not, if only because I use titles sometimes.

(class cdWindow of SysWindow
  (properties
    topBordColor 7
    lftBordColor 6
    rgtBordColor 4
    botBordColor 3
    titleBack 3
    titleColor 255
  )
 
  (method (open &tmp oldPort screens)
    ; The established setup
    (= screens VISUAL)
    (if (!= priority -1) (|= screens PRIORITY))
 
    ; Make room for the edges
    (= lsTop (- top 2))
    (if title (-= lsTop 9))
    (= lsLeft (- left 2))
    (= lsRight (+ right 3))
    (= lsBottom (+ bottom 3))
 
    ; Set our custom style
    (= type 128)
 
    ; Always top priority
    (= priority 15)
    (super open:)
 
    ; Now we draw, on the whole screen.
    (= oldPort (GetPort))
    (SetPort 0)
 
    ; Draw our fill...
    (Graph grFILL_BOX top left bottom right screens back 15)
 
    ; Custom title bar support!
    (if title
      (-= top 9)
      (+= bottom 1)
      (Graph grFILL_BOX top left (+ top 9) right screens botBordColor titleBack)
      (Display title dsCOORD left top dsWIDTH (- right left) dsCOLOR titleColor dsFONT 999 dsMODE alCENTER)
    )
 
    ; Draw the frame
    (Graph grDRAW_LINE (- top 1) (- left 1) (- top 1) right topBordColor priority screens)
    (Graph grDRAW_LINE (- top 1) (- left 1) (- bottom 1) (- left 1) lftBordColor priority screens)
    (Graph grDRAW_LINE (- bottom 1) left (- bottom 1) right botBordColor priority screens)
    (Graph grDRAW_LINE top right (- bottom 2) right rgtBordColor priority screens)
 
    ; Draw our drop shadow
    (Graph grDRAW_LINE bottom (+ left 1) bottom right 0 priority screens)
    (Graph grDRAW_LINE top (+ right 1) bottom (+ right 1) 0 priority screens)
 
    ; Show what we have wrought.
    (Graph grUPDATE_BOX (- top 1) (- left 1) (+ bottom 1) (+ right 1) VISUAL)
    (SetPort oldPort)
  )
)

Eagle-eyed viewers might notice that the color properties are set to various grayscales while the image up top is green. This is simply because the instance of this cdWindow class has those colors. The control panel, in contrast, is tan.

And that’s the end of this series. If you have any other SCI games (preferably SCI11 or earlier) that you’d like to see, drop me a line in the comments below and I’ll see what I can do. Barring any of that though…

[ , , ] 2 Comments on On SCI Windows – Part 7 – The Dating Pool

But why though?

For no good reason I just installed and ran Visual Basic 5.0… on Windows 7.

Unsurprisingly, it runs.

More unsurprisingly, there are issues. For example, the placement/sizing rectangles are unbearably sluggish, and you can’t add components to the toolbox without elevation. I mean, if you want to add, say, ComCtl32, you can check it in the list, but pressing OK just gets you a “can’t access the registry” error. You have to run VB5 as admin to make that work.

These and related issues are why I finally stopped using VB6 back then.

And that’s why the real autorun for my game is made in Visual C++, on a Win98 VM.

[ , , ] Leave a Comment

Evolution of a Title Screen

From day one, the title screen for The Dating Pool has been rendered, with one short intermission. Looking back at my development archives, I felt I should show the unseen. So in the inimitable words of Verka Serduchka… Let’s begin!

The original title screen was a closeup of the main character’s little black book, in what was then planned to be her bedroom. Between the default textures and the book’s cover being edited in post, I honestly can’t remember why I replaced it… but it’s not exactly evocative of a “dating pool”, or any kind of pool, really.

Ah, the original demo release’s title screen. This is actually slightly newer than it should be at this point, with the wine and glass added, but who’s keeping track? Maybe me at best, but I hardly did. Anyway, I’m not gonna hunt down a copy without the wine only to post this version a little later.

At one point I figured the 3D renders could serve as the basis for pixel art redraws. I put hours into this image, only to not use it at all. Honestly, I can’t quite remember why I gave up on that idea. But before the demo was in a playable state, I’d reverted to the render and added the wine. Perhaps it was just to not increase the workload even more, or maybe it was because it didn’t actually help solve some issues with global palettes that I’d hoped it would. Oh well, what’s a few wasted hours when you have this much free time to waste to begin with?

And that brings us to the title screen as it is now. The Itch demo has a slightly earlier version of this screen that’s a bit shinier in silly places, but otherwise it’s the same.

(2018 note: the above paragraph was later outdated by an updated demo release.)

I wonder if should put some animation in this. The old screen had the flickering candles… Anyone?

[ , , ] Leave a Comment

Adventure game background art

Ah, Sierra. You gotta love the beautiful background art in their VGA games. From the cartoony…

…to the outright pretty…

…you have to admit someone was credit to team.

But then there’s games where they seemingly dropped the ball (in my opinion) for whatever style-related reason…

…or simply didn’t do much “background art” at all…

And that makes me feel…

Well, okay, I guess, about using edited Gmod screenshots from Letrune in “The Dating Pool”, turning this…

…into this:

[ , , , , , , ] Leave a Comment

The Dating Pool – One Day Demo

Yes folks, that’s right. It’s a brand-new point-and-click adventure romp!

If you think that looks at all like the classic Sierra interface, you’d be right! This not only looks like a classic Sierra game, it actually runs on the same engine! None of that cheap-ass Adventure Game Studio bullshit here, folks, this is the real deal!

And just in time for New Years Eve, here’s a public preview release: http://helmet.kafuka.org/sci/catdate

Go ahead and try it. If you have any suggestions for the full version, including things you’d change in the part shown in this demo, don’t hesitate – my askbox is open.

(Protip: get DOSBox.)

Update: crash fixed in certain scene, thanks to @iliketurnips for notifying me.

[ , , , ] Leave a Comment