Help with UI/HUD implementation [solved]

Hello everyone!

I am working on an rpg and I have alot of objects, npcs and even spells and inventory for the player to manage. The screen easily clutters to the point were you cant see or klick the verbs of exits and objects in the same room. see screenshot:

https://cdn1.imggmi.com/uploads/2018/10/12/c3432005d1264fd02ed8302957361954-full.png

What id like the UI to look like is (in descending order):

  • right: Basic Actions, Compass, Places and Objects
  • left: Status(Health&conditions), SpecialSkills&MagicSpells, Inventory, (Attributes+combat stats if space)

i "attemped" a screenshot in paint of the result that id like to have :)

https://cdn1.imggmi.com/uploads/2018/10/12/79c2905dfbed7f611d16a6646fa4d18e-full.png

my user interface script is:

JS.setCommands ("Look;Wait;Perception;Memory;Status;Lore")
JS.setCss ("#txtCommandDiv", "position:fixed;bottom:10px")
JS.setCss ("#gameContent", "margin-bottom:70px;")

and startscript:

CombatInitialise
JS.setCustomStatus ("")

also im using the combat, conv and shop libraries

I´m pretty sure i copied this from someone and was super happy it worked. I have no idea to move a tab like the inventory to the left side of the screen...

Any Ideas or leads to tutorials or documentation?


I also found another turnscript:

  <turnscript>
    <enabled />
    <script><![CDATA[
      if (ArmourTooHeavy()) {
        x = "</br>Your armour is slowing you down"
      }
      else {
        x = ""
      }
      if (player.hitpoints >= CalcFullHits() * 0.75 ) {
        s = "Health "+ player.hitpoints + " / " + CalcFullHits() + "</br>You feel fine" + x
      }
      else if (player.hitpoints >= CalcFullHits() * 0.25) {
        s = "Health "+ player.hitpoints + " / " + CalcFullHits() + "</br>You are wounded" + x
      }
      else {
        s = "Health "+ player.hitpoints + " / " + CalcFullHits() + "</br>You are near death" + x
      }
      JS.setCustomStatus (s)
      JS.scrollToEnd ()
    ]]></script>
  </turnscript>

sorry for double post


Hey there,

I'm not sure (at all) but the only way I can see it being done is by diving deep into the css ocean and alter the placement of each individual pane based on it's id.
I think it's possible, I think it'd look nice and I also think it'd be quite the hassle.

(I highly recommend checking out the StylesheetLib (by Soongames) to make it easier to alter the css in depth)

EDIT:
I know it's indeed possible to move the panes to the left side (that's how I've got my next project set up)

Click here for screenshot

.... I'm just not sure how to make a couple of panes move one way, and the others another way.

It shouldn't be that hard with some javascript.

My first thought is to remove the contents of the sidebar, clone it, then put the contents back.

var paneContents = $('#gamePanesRunning').children().appendTo('body');
var leftpane = $('#gamePanes').clone().attr('id', 'leftPanes').css({INSERT STYLE STUFF HERE});
paneContents.each(function () {
  $(this).appendTo(($(this).is('PANES TO GO ON THE LEFT') ? leftPanes : $('#gamePanes')).children('#gamePanesRunning'));
});
leftpane.children('#gamePanesRunning').attr('id', 'leftPanesRunning');
leftpane.children('#gamePanesFinished').attr('id', 'leftPanesFinished');
leftpane.insertBefore('#gamePanes');

In that code, the string 'PANES TO GO ON THE LEFT' might be replaced with '#inventoryLabel,#inventoryAccordion,#customStatusPane'
and {INSERT STYLE STUFF HERE} will be whatever style attributes you want to position your new sidebar where you want it (I think CheeseMyBaby probably knows this better than I do; I'm not good at layout). A simple example might be {position: 'fixed', left: '0px', top: '0px'}

I've tried this (entering in the javascript console on a random game), and it seems to work fine. But sometimes it seems to mess about with pane visibility, so you'd have to do:

$('#leftPanesRunning').show();
$('#leftPanesFinished').hide();

The rest is just messing about with the CSS to make it look right. It does mean that you'll now have to make sure that any style changes are made to both #gamePanes and #leftPanes.

Making this work on mobile… not sure what you'd want to do with it there.


Wow, thanks for the detailed reply.

Unfortunately i can´t find out how to put the example of the java script you supplied:

var paneContents = $('#gamePanesRunning').children().appendTo('body');
var leftpane = $('#gamePanes').clone().attr('id', 'leftPanes').css({INSERT STYLE STUFF HERE});
paneContents.each(function () {
  $(this).appendTo(($(this).is('#inventoryLabel,#inventoryAccordion,#customStatusPane') ? leftPanes : $('#gamePanes')).children('#gamePanesRunning'));
});
leftpane.children('#gamePanesRunning').attr('id', 'leftPanesRunning');
leftpane.children('#gamePanesFinished').attr('id', 'leftPanesFinished');
leftpane.insertBefore('#gamePanes');

into a test game code:

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="new">
    <gameid>f8f2a639-f9dd-43d8-ba0f-cac52a418d8f</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <customstatuspane />
    <commandpane />
    <start type="script">
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
</asl>

Just putting it in the start script throws errors. I realise this is probably a pretty basic question...


I believe there's a way to put in javascript in the desktop editor. I think it has to be included in the game as a separate file.

In the web editor (which I have to work with as I'm a linux user, so can't run Quest on my laptop), you have to go about it in a slightly awkward way: wrapping the javascript in an eval call. In this case, you would put this in your UI initialisation script (if you put it in the start script, loading a saved game would put the panes back in their original places).

A Quest script that calls the javascript:

JS.eval ("(function () {var paneContents = $('#gamePanesRunning').children().appendTo('body');var leftpane = $('#gamePanes').clone().attr('id', 'leftPanes').css({position: 'fixed', left: '0px', top: '0px'});paneContents.each(function () {$(this).appendTo(($(this).is('#inventoryLabel,#inventoryAccordion,#customStatusPane') ? leftPanes : $('#gamePanes')).children('#gamePanesRunning'));});leftpane.children('#gamePanesRunning').attr('id', 'leftPanesRunning');leftpane.children('#gamePanesFinished').attr('id', 'leftPanesFinished');leftpane.insertBefore('#gamePanes');})();")

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="new">
    <gameid>f8f2a639-f9dd-43d8-ba0f-cac52a418d8f</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <customstatuspane />
    <commandpane />
    <start type="script">
    </start>
    <attr name="feature_advancedwearables" type="boolean">false</attr>
    <feature_advancedscripts />
    <inituserinterface type="script">
      JS.eval ("(function () {var paneContents = $('#gamePanesRunning').children().appendTo('body');var leftpane = $('#gamePanes').clone().attr('id', 'leftPanes').css({position: 'fixed', left: '0px', top: '0px'});paneContents.each(function () {$(this).appendTo(($(this).is('#inventoryLabel,#inventoryAccordion,#customStatusPane') ? leftPanes : $('#gamePanes')).children('#gamePanesRunning'));});leftpane.children('#gamePanesRunning').attr('id', 'leftPanesRunning');leftpane.children('#gamePanesFinished').attr('id', 'leftPanesFinished');leftpane.insertBefore('#gamePanes');})();")
    </inituserinterface>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
</asl>

results in the panes being displayed on the bottom of the screen:

https://cdn1.imggmi.com/uploads/2018/10/16/46a28e81f62b57f39c50b0025c596dc9-full.png


Sorry, think that's a careless typo. In the JS, the part "? leftPanes :" in the middle should be "? leftpane :". Must have messed up when copying it over to the forum.


Thanks alot for the help. I´m able to move #compassLabel,#compassAccordion,#customStatusPane to the left. Moving tabs with changing content (#commandPane,#inventoryLabel,#inventoryAccordion) requires better css, because the window just resized waaay into the text-field, if there is an item with a long name in your inventory. Since moving the status bar and compass to the left frees up a lot of space, I can live with that.

My current problem however is, that if i run this code:

JS.eval ("(function () {var paneContents = $('#gamePanesRunning').children().appendTo('body');var leftpane = $('#gamePanes').clone().attr('id', 'leftPanes').css({position: 'fixed', left: '0px', top: '0px'});paneContents.each(function () {$(this).appendTo(($(this).is('#compassLabel,#compassAccordion,#customStatusPane') ? leftpane : $('#gamePanes')).children('#gamePanesRunning'));});leftpane.children('#gamePanesRunning').attr('id', 'leftPanesRunning');leftpane.children('#gamePanesFinished').attr('id', 'leftPanesFinished');leftpane.insertBefore('#gamePanes');})();")

in any game, I get a:

Game Over
This game has finished

constantly displayed below the last pane on the left side - in this case the compass. Even though the game is still runing and the interface works fine. Maybe it has something to do with the thing that happens when you end a game: The panes dissappear and "Game Over. This game has finished" gets displayed... Any way to get rid of it? It could confuse the player a bit :)


Moving tabs with changing content (#commandPane,#inventoryLabel,#inventoryAccordion) requires better css

I'm not that good with appearance/layout stuff (my javascript is better than my CSS), but I think maybe CheeseMyBaby can give you some advice on fixing this. It's probably the same style rules that would apply if you were moving the sidebar to the left, except applied to #leftPanes and #leftPanesRunning instead.

Game Over
This game has finished

I believe I mentioned that. It's because of a slightly weird way some of the CSS is implemented.

By default, there are two sidebars at the right in Quest; gamePanesRunning (which contains various panes) and gamePanesFinished (which contains the game over message). The first one is visible, and the second one hidden, until the game ends, when it shows the finished one and hides the running one.

My script duplicates those, but doesn't explicitly show or hide them. So you'd need to do this jsvascript:

$('#leftPanesRunning').show();
$('#leftPanesFinished').hide();

(from my previous post).

Converting that to Quest code, you get:

JS.eval("$('#leftPanesRunning').show();$('#leftPanesFinished').hide();")

or you could merge it into the previous code, to make:

JS.eval ("(function () {var paneContents = $('#gamePanesRunning').children().appendTo('body');var leftpane = $('#gamePanes').clone().attr('id', 'leftPanes').css({position: 'fixed', left: '0px', top: '0px'});paneContents.each(function () {$(this).appendTo(($(this).is('#compassLabel,#compassAccordion,#customStatusPane') ? leftpane : $('#gamePanes')).children('#gamePanesRunning'));});leftpane.children('#gamePanesRunning').attr('id', 'leftPanesRunning').show();leftpane.children('#gamePanesFinished').attr('id', 'leftPanesFinished').hide();leftpane.insertBefore('#gamePanes');})();")

(not 100% sure that will work)


Screenshot for reference in case someone wants to use this setup:

https://cdn1.imggmi.com/uploads/2018/10/18/2dc049d09feaf7a80bca977f3cc15aad-full.png

Works perfectly. You made my game playable - Amazing help!


Cool stuff, mrangel! Can the panes be easily centered?


In order to center the left/center/right panes together, which element(s) should be adjusted?


Wouldn't centred panes be in the way of the main text? Or do you mean a top/bottom panel?


What I meant was, in Fuchs screenshot, the left/center/right panes are (taken together) left-aligned on the screen. Would it be relatively simple to center-align them, so that there was equal (empty) background space on both left/right ends? Hope that question is clear, thanks.


@DCoder
I think it's easy to move them to the middle. However there's only one "textarea" so in order to avoid the panes hovering above the printed text the textarea needs to be resized and move to either side of the panes. (And I guess that defeats the purpose?).
I guess it's possible to create a second area for output but that's a can of worms I'm not touching with a ten foot pole. =)


Ah… I kind of suck on the CSS positioning.

From a quick look over the code, I think the #gameBorder is centred, and #gameContent is automatically set to 250px smaller than it. So the right panes are inside #gameBorder, but the left ones are stuck onto the side of it.

I think aligning them neatly would be easier in javascript; because there's already JS trying to adjust the width of various panes. Something like:

    $("#gameBorder").css({width: "1100px", "max-width": "100%"});
    var screenWidth = $("#gameBorder").width();
    var gameContentPadding = parseInt($("#gameContent").css("padding-left").replace("px", "")) + parseInt($("#gameContent").css("padding-right").replace("px", ""));
    var promptSpacing = $("#txtCommandPrompt").width() + 5;

    $("#gameContent").width(screenWidth - 450).css("margin-left", "225px");
    $("#txtCommand").width(screenWidth - gameContentPadding - promptSpacing - 450);
    $("#updating").css("margin-left", (screenWidth / 2 - 290) + "px");
    $("#gamePanel").width(screenWidth - 450);
    $("#gridPanel").width(screenWidth - 450);
    $("#gridCanvas").prop("width", screenWidth - 450);
    paper.view.viewSize.width = screenWidth - 450;
    var css = addCSSRule("div#gamePanel img");
    css.style.maxWidth = (screenWidth - 450) + "px";
    var css = addCSSRule("div#divOutput img");
    css.style.maxWidth = (screenWidth - 450) + "px";

    $("#gamePanes").css({top: "24px", right: ((window.innerWidth/2 - screenWidth/2 + 4)+"px")});
    $("#leftPanes").css({top: "24px", left: ((window.innerWidth/2 - screenWidth/2 + 4)+"px")});

(based on the default panesVisible function, which is run when the game panes are shown or hidden. If you want to show/hide panes at some point, you'd also need to override this function to show/hide the left panes too)

Off the top of my head, while I'm half asleep and not yet awake enough to do actual work, so don't rely on this too much)


I'm going to experiment with this code...


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums