Ingame Menu

386 views
Skip to first unread message

margaret laroche

unread,
Jan 15, 2014, 7:18:05 AM1/15/14
to mel...@googlegroups.com
Hi! I'm learning so much here! :D

However I wanna something since I'm not really that good in programming.

I wanna make an ingame menu that have two tab, one show up item inventory and another show player status.

I wonder what simple way would be the best to do this?

Currently I'm thinking about using another ScreenObject to make the ingame menu, so when player click on menu Button, it will change screen into the this screenobject...
and then in this screenObject, i will create two button, and it will show up the data (through draw() method) according to the button...

The player status one I can make it... but, how do I make the item inventory? I have ten type of item that the player could collect, and on screen the player only could see for example up tp 6 item, so there's 4 item missing. How do I make it scrollable? Should I create another div in the canvas div and create a table to list these item?

I probably put these item on an array to make it easier to manage, so if player get an item, I could add it to the array or if the player use an item until it's 0, i could splice it and remove it from the inventory....

I'm sorry if this is a bad question, but I can't find any tutorial or example of creating this kind of in game menu....

Aaron McLeod

unread,
Jan 15, 2014, 7:57:26 AM1/15/14
to mel...@googlegroups.com
Dont change to a different screen object for this, as changing state removes objects from the game world. If you set them to persistent, they'll stay, but then you also have to do a lot more manual cleanup. 

Instead, I would just have a separate object extending renderable, that manages two other objects and two buttons. The two are for each tab, and the buttons correspond to them. Simply setup the tab buttons as  GUI_Object that invokes a function to load its object. The renderable then would simply draw the active one. From there, simply do event registration on the inventory items, and so forth. Just be sure that you remove and add events appropriately as you switch tabs, and close the menu.




--
You received this message because you are subscribed to the Google Groups "melonJS - A lightweight HTML5 game engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to melonjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Aaron McLeod
http://agmprojects.com

Jay Oster

unread,
Jan 15, 2014, 2:34:59 PM1/15/14
to mel...@googlegroups.com
It should also be pointed out that the updateWhenPaused property is designed for pause-menu UIs. The GUI_Object that Aaron mentioned should use this property, so that you can pause the game, show the menu interface, and allow the menu to animate and perform any other updates you like.

Aaron McLeod

unread,
Jan 15, 2014, 2:37:29 PM1/15/14
to mel...@googlegroups.com
Which reminds me. We should make GUI_Object a little more friendly for re-using the same object. I ended up writing my own renderable, so i could initialize and tear down the event handling when i wanted to: https://github.com/agmcleod/snowballeffect/commit/c53fbbadf6e43e76c445d37edc8b78b40efb68c5#diff-e0685cdb8897f26a83bf674a9bd9ce30L1

Or maybe the solution is just to do what i did with the sprite object.

ayakashi.a...@gmail.com

unread,
Jan 15, 2014, 4:53:18 PM1/15/14
to mel...@googlegroups.com
Thank you for your input! Did you mean like this?

var InGameMenu = me.Renderable.extend({
   init: function(){
          this.playerTabBtn = new Button();
          this.invTabBtn = new Button();

          this.playerTabMenu = new PlayerTab(){};
          this.invTabMenu = new InventoryTab(){};

          this.playerTabBtn.onClick = function(){
                me.game.world.addChild(this.playerTabMenu);
          }
          this.invTabBtn.onClick = function(){
                me.game.world.addChild(this.invTabMenu);
          }
   }

   update: function(){
          return true;
   }
   
});

var PlayerTab = me.Renderable.extend({
   //draw info about player data - name, image, hp
});

var InventoryTab = me.Renderable.extend({
   //draw inventory data - read from array of items and draw it
});

var Button = me.GUI_Object.extend({});

so I don't need another div? How do I make the inventory scrollable? 

Jay Oster

unread,
Jan 15, 2014, 6:27:00 PM1/15/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Using HTML for scrollable elements is the "easy" way. It can be done with the least amount of code. Or you could use a library like Zebra, which looks like a ridiculously heavy download for UI within the canvas... http://zebra.gravitysoft.org/

margaret laroche

unread,
Jan 16, 2014, 7:43:18 PM1/16/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Hello, I tried making it like this: 

var InGameMenu = me.Renderable.extend({
    init: function(x, y){

        this.parent(new me.Vector2d(x, y), 0, 0);

        this.x = x;
        this.y = y;
    
        //create Button
        this.playerTabBtn = new Button(200,200, "playerTab", "playerTab", 64, 64);
        this.invTabBtn = new Button(200,200, "invTab", "invTab", 64, 64);

        me.game.world.addChild(this.playerTabBtn);
        me.game.world.addChild(this.invTabBtn);

        //this.playerTabMenu = new PlayerTab();
        //this.invTabMenu = new InventoryTab();

        //this.playerTabBtn.onClick = function(){
        //    me.game.world.addChild(this.playerTabMenu);
        //}
        //this.invTabBtn.onClick = function(){
        //    me.game.world.addChild(this.invTabMenu);
        //}
    },

    update: function(){
        return true;
    },

    draw: function(context){
        //create a black rectangle as the ingame menu background
        context.fillStyle = "#000000";
        context.fillRect(0, 0, 860, 380);

        return true;
    }
   
});

and I add the menu button inside the HUD container

game.HUD = game.HUD || {}; 
game.HUD.Container = me.ObjectContainer.extend({ 

init: function() {
this.parent();
this.isPersistent = true;
this.collidable = false;
this.z = Infinity;

this.status = new game.HUD.statusBar(0, 0);
this.addChild(this.status);

this.bindW = false;
this.bindA = false;
this.bindS = false;
this.bindD = false;

this.control = new game.HUD.controlPad(20, 350);
this.addChild(this.control);

this.menuBtn = new game.HUD.menuButton(800, 300);
this.addChild(this.menuBtn);

this.atkBtn = new game.HUD.attackButton(750, 360);
this.addChild(this.atkBtn);

   //this.menuBar = new game.HUD.menuBar(200, 80);
   //this.addChild(this.menuBar);
}
});

and this is the menu button:

game.HUD.menuButton = me.Renderable.extend({
    init: function (x, y) {
        this.parent(new me.Vector2d(x, y), 0, 0); // (size does not matter here)
        
        this.x = x;
        this.y = y;

        //check if the mouse is already binded with key M
        this.keyMBinded = false;

        this.floating = true; // make sure we use screen coordinates
        this.menuBtnImage = me.loader.getImage("menuBtnNorm");

        this.ingameMenu = new InGameMenu(0,0);
    },

    update: function () {

        if (me.input.mouse.pos.x >= this.x && me.input.mouse.pos.x <= (this.x + this.menuBtnImage.width) && me.input.mouse.pos.y >= this.y && me.input.mouse.pos.y <= (this.x + this.menuBtnImage.height)) {
            //console.log("M");
            this.keyMBinded = true;

            me.game.world.addChild(this.ingameMenu);
            console.log("add ingame menu");

            //me.input.bindMouse(me.input.mouse.LEFT, me.input.KEY.M);
        }      

        return true;
    },

    draw: function (context) {        
        //draw menu Button
        context.drawImage(this.menuBtnImage, this.x, this.y);
        return true;
    }
});

However, the button I set in IngameMenu was drawn even before i hovered on the menu button (should be click, but for now i set it to hover for testing purposes). And when I hovered to the Menu Button, the rectangle wasn't drawn (this supposed to be the ingame menu background).

What am I doing wrong? The code is just testing if I could bring up the ingame Menu first (along with the two buttons)....

Jay Oster

unread,
Jan 16, 2014, 7:56:27 PM1/16/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
An object can only be drawn if it has been added to the scene graph. So the condition you are using for "hover" is not working as you expect. And indeed, it looks like there's a typo right here:

me.input.mouse.pos.y <= (this.x + this.menuBtnImage.height)

margaret laroche

unread,
Jan 16, 2014, 9:06:55 PM1/16/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Ah, thanks! I didn't see that...

Okay, I've corrected it. and it seems, because it was renderable, doing this:

this.ingameMenu = new InGameMenu(0, 0);

instantly drawn it in the screen. so, I moved it inside the mouse.pos condition and it only appear when I hover!!

strangely though, although the button get drawn correctly, the draw method of ingameMenu itself was never called...


game.HUD.menuButton = me.Renderable.extend({
    init: function (x, y) {
        this.parent(new me.Vector2d(x, y), 0, 0); // (size does not matter here)
        
        this.x = x;
        this.y = y;

        this.keyMBinded = false;

        this.floating = true; // make sure we use screen coordinates
        this.menuBtnImage = me.loader.getImage("menuBtnNorm");

        
    },

    update: function () {

        if (me.input.mouse.pos.x >= this.x && me.input.mouse.pos.x <= (this.x + this.menuBtnImage.width) && me.input.mouse.pos.y >= this.y && me.input.mouse.pos.y <= (this.y + this.menuBtnImage.height)) {
            this.keyMBinded = true;           
            this.ingameMenu = new InGameMenu(0, 0); //got rendered instantly
            console.log("add ingame menu");
        }      

        return true;
    },

    draw: function (context) {
        context.drawImage(this.menuBtnImage, this.x, this.y);
        return true;
    }
});

the ingame menu: (I removed unnecessary parts)

var InGameMenu = me.Renderable.extend({
    init: function(x, y){

        this.parent(new me.Vector2d(x, y), 0, 0);

        this.x = x;
        this.y = y;

        //set up buttons
        this.playerTabBtn = new Button(200,200, "playerTab", "playerTab", 64, 64);
        this.invTabBtn = new Button(264,264, "invTab", "invTab", 64, 64);

        me.game.world.addChild(this.playerTabBtn);
        me.game.world.addChild(this.invTabBtn);
    },

    update: function(){
        return true;
    },

    draw: function(context){
        context.fillStyle = "#000000";
        context.fillRect(0, 0, 860, 380);

        console.log("draw rect");

        return true;
    }
   
});

Jay Oster

unread,
Jan 16, 2014, 11:16:59 PM1/16/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Again, an object can only draw if it is added to the scene graph. Creating an object with the `new` keyword does not add it to the scene.

But I do see something that *is* getting added to the scene when that object is created: TWO OTHER OBJECTS! `playerTabBtn` and `invTabBtn`

You should make your `inGameMenu` extend me.ObjectContainer, and the child objects that it creates must be added to itself with `this.addChild()` in place of `me.game.world.addChild()`. Then when you add `inGameMenu` to the scene graph, its children will be ready to render.

In other words, you can create your `inGameMenu` object at any time you want, and it will not be rendered until added to the scene graph. Any children added to it will also not be rendered until it is added to the scene graph.

margaret laroche

unread,
Jan 17, 2014, 2:09:06 AM1/17/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Ah..., turned out the reason why it's not appearing is because i forgot to set the floating tp true.... GUI_Object is automatically set floating to true, which is why it appears, I guess.

game.GUI = game.GUI || {};
game.GUI.Container = me.ObjectContainer.extend({

    init: function () {
        this.parent();
        this.isPersistent = true;
        this.collidable = false;
        this.z = 25;

        this.bindW = false;
        this.bindA = false;
        this.bindS = false;
        this.bindD = false;

        this.control = new game.GUI.controlPad(20, 350);
        this.addChild(this.control);

        this.menuBtn = new game.GUI.menuButton(800, 300);
        this.addChild(this.menuBtn);

        this.atkBtn = new game.GUI.attackButton(750, 360);
        this.addChild(this.atkBtn);
    }
});

game.GUI.menuButton = me.Renderable.extend({
    init: function (x, y) {
        this.parent(new me.Vector2d(x, y), 0, 0); // (size does not matter here)

        this.x = x;
        this.y = y;

        this.keyMBinded = false;

        this.floating = true; // make sure we use screen coordinates
        this.menuBtnImage = me.loader.getImage("menuBtnNorm");
    },

    update: function () {

        if (me.input.mouse.pos.x >= this.x && me.input.mouse.pos.x <= (this.x + this.menuBtnImage.width) && me.input.mouse.pos.y >= this.y && me.input.mouse.pos.y <= (this.y + this.menuBtnImage.height)) {
            //add ingame Menu to screen
            this.ingame = new game.ingameMenu.Container();
            me.game.world.addChild(this.ingame);
            me.game.sort();

            //me.input.bindMouse(me.input.mouse.LEFT, me.input.KEY.M);
        }

        return true;
    },

    draw: function (context) {
        context.drawImage(this.menuBtnImage, this.x, this.y);
        return true;
    }
});

And this is my ingameMenu

game.ingameMenu = game.ingameMenu || {};
game.ingameMenu.Container = me.ObjectContainer.extend({

    init: function () {
        this.parent();
        this.isPersistent = true;
        this.collidable = false;
        this.z = Infinity;

        console.log("this is ingame init");

        //create the background
        this.menuBG = new game.ingameMenu.BG(0, 0);
        this.addChild(this.menuBG);

        //set up buttons
        this.playerTabBtn = new Button(200, 200, "petTab", "petTab", 64, 64);
        this.invTabBtn = new Button(264, 264, "equipTab", "equipTab", 64, 64);

        this.addChild(this.playerTabBtn);
        this.addChild(this.invTabBtn);

        //document.getElementById("id")
        console.log("this is ingame init end");
    }
});

game.ingameMenu.BG = me.Renderable.extend({
    init: function (x, y) {
        this.parent(new me.Vector2d(x, y), 0, 0); // (size does not matter here)

        this.x = x;
        this.y = y;

        this.keyMBinded = false;

        this.floating = true; // make sure we use screen coordinates

        this.font = new me.Font("Beans", 18, "red");

    },

    update: function () {
        console.log("updating");
        return true;
    },

    draw: function (context) {
        console.log("drw rect");
        this.font.draw(context, "for testing purposes", 400, 250);
        context.fillStyle = "#006600";
        context.fillRect(0, 0, 860, 380);
        return true;
    }
});

since I want to add it when I hover to the menu button, I put the creation and add method of the ingameMenu to the mouse.pos if statement. I tried using this.addChild, but it doesn't support that method, so I use me.game.world.addChild(); instead.

And Jay, you said about using HTML for the scrollable element...
I have created a div inside the <div id="screen"></div> (the canvas) and currently set "display: none".

<div id="screen"> //this is the canvas
        <div id="playerStatus"></div> //tabMenu1
        <div id="playerInventory"> //tabMenu2
               (create a table, add data from Item array, make it scrollable)
        </div>
</div>

So then I just need to get the element id and set its display attribute to normal? so it would appear in the canvas and I add or remove data from the HTML? And then set it to display: none again when I change tab or quit the ingame menu?

Jay Oster

unread,
Jan 17, 2014, 2:18:46 AM1/17/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
That sounds about right. `me.game.world` is the ObjectContainer for the scene. When you want to add something to the scene graph, you usually add it there. When creating other ObjectContainers, you can add children to those, as well. That explains why you could not use `this.addChild()` in the hover condition; `this` is not a reference to an ObjectContainer within that context. So you did the right thing by adding it to the scene graph here, using the `me.game.world` reference.

For the HTML, you should instead use the DOM API to add nodes dynamically, and include CSS to style the elements appropriately. If you currently have jQuery in your project, you should use that, because it makes the DOM stuff much easier to work with. If you are not currently using jQuery, you should check out Zepto.js! Same API, but much much smaller.

And finally, here's a real-world example of using HTML with melonJS (uses jQuery): https://github.com/melonjs/melonJS/issues/276#issuecomment-24123196 And the game that currently uses it: http://zaraka.org/mana_game

margaret laroche

unread,
Jan 17, 2014, 9:44:25 PM1/17/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Hi, thanks for the suggestion. I'm using zepto.js now and still learning about JQuery method of creating/manipulating HTML. 

This is my playerTab menu. This get called when menu button was clicked.

I'm still thinking whether i use a container for each tab, or just make each tab extend Renderables (since I'm using HTML anyway....) But for now, I'm using Container in case I want to add any non HTML object in it....

game.PlayerTab = game.PlayerTab || {};
game.PlayerTab.Container = me.ObjectContainer.extend({

    init: function () {
        this.parent();
        this.isPersistent = true;
        this.collidable = false;
        this.z = Infinity;

        console.log("this is playertab init");

        this.content = new game.PlayerTab.content(0, 0);
        this.addChild(this.content);

        console.log("this is playertab init end");
    }
});

game.PlayerTab.content = me.Renderable.extend({
    init: function (x, y) {
        this.parent(new me.Vector2d(x, y), 0, 0); // (size does not matter here)
        this.floating = true; // make sure we use screen coordinates

        this.x = x;
        this.y = y;

        this.id = "playerStatus";

        //create DOM elements for Player status menu tab
        //create div and its style
        var playerStatusCSS = {
            "background-color": "#006600",
            "height": "420px",
            "width": "600px",
            "border": "solid",
            "border-color": "#FFFF66",
            "border-radius": "25px",
            "padding": "3vh 5vw 3vh 5vw",
            "font-family": "AbscissaBold",
            "font-size": "16pt"
        }

        $('<div id="' + this.id + '"></div>').appendTo('#screen');
        $("#" + this.id).css(playerStatusCSS);
        $("<p />", { text: "Hello", id: "greeting", css: { color: 'darkblue' } }).appendTo("#" + this.id);

    },

    update: function () {
        return true;
    },

    draw: function (context) {
        return true;
    }
});


what i wanna know is: since i use autoscaling (my res is actually 860x480 scaled to 1366x768), how do I make this HTML stuff follow the canvas?

I've tried with fluid design (using percentage and vw/vh). But can I use my actual res. pixels and somehow the HTML get scaled just like the canvas got scaled?

And about this updatewhenPaused, I tried to use it like this: this.updatewhenPaused; in the menu button onClick(). However, I see no difference... the game still playing behind the menu.

game.GUI = game.GUI || {};
game.GUI.Container = me.ObjectContainer.extend({

    init: function () {
        this.parent();
        this.isPersistent = true;
        this.collidable = false;
        this.z = 50;

        this.bindW = false;
        this.bindA = false;
        this.bindS = false;
        this.bindD = false;

        this.control = new game.GUI.controlPad(20, 350);
        this.addChild(this.control);

        this.menuBtn = new Button(800, 300, "menuBtnNorm", "menuBtnClicked");
        this.menuBtn.onClick = function () {
            this.updateWhenPaused; //pause game and open menu
            this.image = me.loader.getImage(this.hoverImage); //change image when clicked
            console.log("menu clicked");

            this.ingame = new game.ingameMenu.Container();
            me.game.world.addChild(this.ingame);

Jay Oster

unread,
Jan 17, 2014, 11:29:52 PM1/17/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Hi,

A few suggestions and ideas:
  • You can put all of the CSS into its own file and link to it from index.html with a <link> element. This will help clean up the code, moving the static styles to a static file. And you can still use the `css` method if you need to do dynamic styles.
  • The renderable size should be set to anything that is non-zero. Ideally, you want it the same size as the DOM element that it hosts. This will allow you to do extra stuff in the update and draw menus if needed.
  • The screen scaling ratio is available in me.sys.scale. Scale the DOM element width/height by this vector like this:
    $element.css({
        "width" : (600 * me.sys.scale.x) + "px",
        "height" : (420 * me.sys.scale.y) + "px"
    });
  • You might also want to run the above snippet inside a WINDOW_ONRESIZE event handler, to rescale the element when the browser window is resized.
  • updateWhenPaused is a boolean property that should be set to true on any objects that you want to remain active while the rest of the game is paused. E.g. set this.updateWhenPaused = true; on the GUI_Container init method (not in the click callback) then pause the game in the button callback with me.state.pause(); to pause the game. The GUI_Container will continue receiving updates.

margaret laroche

unread,
Jan 18, 2014, 4:24:19 AM1/18/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
hi, i'm using zepto.js and i just realized that i got this:

Exception was thrown at line 1539, column 5 in ms-appx://cfc6264e-a4a8-4932-a7bf-7e4cf8f0e857/lib/plugins/zepto.js
0x80004005 - JavaScript runtime error: Unspecified error.

in zepto.js:
// getComputedStyle shouldn't freak out when called
  // without a valid element as argument
  try {
    getComputedStyle(undefined) --> this is where the exception happens
  } catch(e) {
    var nativeGetComputedStyle = getComputedStyle;
    window.getComputedStyle = function(element){
      try {
        return nativeGetComputedStyle(element)
      } catch(e) {
        return null
      }
    }
  }

in the output log. it doesn't hrow an error or anything.., but i just find it a bit troubling... any idea what is that?

If I didn't use any JQuery code and zepto js, no error/exception thrown in the output log....



Anyways, I tried this:

me.event.WINDOW_ONRESIZE = function () {
            $('<div id="' + this.id + '"></div>').appendTo('body');
            $("#" + this.id).css(playerStatusCSS);
            
            $("<p />", { text: "Hello", id: "greeting", css: { color: 'darkblue' } }).appendTo("#" + this.id);
};

but doing so that makes the code inside is skipped. 

And I tried putting the css in the cs file and linked it to the html like you said, but doing so doesn't connect the div with the css style. I have to do it like I write before so the style takes an effect. When I do this, I commented out the $("#" + this.id).css(playerStatusCSS);  part (and of course, without the window.onresize stuff).

oh when i tried to put the $element.css({
    "width" : (600 * me.sys.scale.x) + "px",
    "height" : (420 * me.sys.scale.y) + "px"
});

in my playerStatusCSS, it doesn't work. (my div is 'missing' as if i didn't set a height/width to it).

Could you give me some example how to implement those? Thanks!

Jay Oster

unread,
Jan 18, 2014, 5:58:50 PM1/18/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Are you using Windows Phone? The first one might be a bug in Zepto with Windows Phone? I'm not sure.

The WINDOW_ONRESIZE event is just a constant. You must not assign to it. Instead, use it as a parameter to the me.event.subscribe method:

me.event.subscribe(me.event.WINDOW_ONRESIZE, function () {
    $('<div id="' + this.id + '"></div>').appendTo('body');
    $("#" + this.id).css(playerStatusCSS);

    $("<p />", { text: "Hello", id: "greeting", css: { color: 'darkblue' } }).appendTo("#" + this.id);
});

And the CSS file will work fine, you just need to use proper CSS syntax and selectors. So e.g. for the DOM elements that are created by the code above, your CSS might look like:

#playerStatus p {
    background-color: #006600;
    /* ... */
}

Finally, the $element code I wrote was just pseudocode. You need to use a real jQuery selector. Like $("#" + this.id)

margaret laroche

unread,
Jan 18, 2014, 9:54:08 PM1/18/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Thanks for the reply.

I'm creating winstore apps. If I changed to JQuery turned off the zepto, I get the $ undefined... 

About on resize, it scales automatically when I resize the screen through simulator. 
And the me.sys.scale.x must be set .toString() in the css so it could work. otherwise, the css doesn't read the value (somehow adding + "px" doesn't make it a string).

I tried this for the div style
#playerStatus {
    background-color: #006600;
    /* ... */
}

But it doesn't work. Well, I might've missed to write some code / comment out another.

Jay Oster

unread,
Jan 19, 2014, 6:56:17 PM1/19/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
I do not understand why these things are not working. IE 10 and 11 are supposed to be kind of decent, so I'm surprised to hear you can't get basic HTML/CSS working well on it.

margaret laroche

unread,
Jan 19, 2014, 7:37:23 PM1/19/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
well just like i said, i might've forgot to comment out some codes. and it's true: i set the display: none, so no wonder if it doesn't appear :)

it works fine now. thanks.

anyway, about the updateonPause and me.state.pause();

I've tried this:

game.GUI = game.GUI || {};
game.GUI.Container = me.ObjectContainer.extend({

    init: function () {
        this.parent();
        this.isPersistent = true;
        this.collidable = false;
        this.z = 50;

        this.bindW = false;
        this.bindA = false;
        this.bindS = false;
        this.bindD = false;

        this.control = new game.GUI.controlPad(20, 350);
        this.addChild(this.control);

        this.menuBtn = new Button(800, 300, "menuBtnNorm", "menuBtnClicked");
        this.menuBtn.onClick = function () {
            console.log("menu clicked");            

            this.ingame = new game.ingameMenu.Container();
            me.game.world.addChild(this.ingame);

            me.state.pause();
        };

        this.addChild(this.menuBtn);

        this.atkBtn = new game.GUI.attackButton(750, 360);
        this.addChild(this.atkBtn);

        //pause the game and open menu
        this.updateWhenPaused = true;
    }
});


however, when I tried that: game paused right after I click on the menu button, and no ingame menu container doesn't show up, but I could still click on the "invisble" button in the ingame menu container and it'll show up its corresponding ingame menu tab just fine. and sometimes, clicking them also would bring the ingameMenu.Container 'appear'. (it took a long time for it to appear and sometimes it doesn't appear at all). But when it does appear, the pause breaks and the game behind the menu is working again....

moving the this.updateWhenPaused = true; to the ingameMenu.Container, makes the me.state.pause() doesn't work.

well I found this: https://groups.google.com/forum/#!topic/melonjs/aFdSDrn6iAA that talk about making the similar menu as me.

and it was suggested to use "overlay" objects and stop the update of position and collision when the object are instantiated. i think the "overlay" objects meant was the one I already make (through objectContainer). or was i wrong?

Jay Oster

unread,
Jan 19, 2014, 8:02:21 PM1/19/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com


On Sunday, January 19, 2014 4:37:23 PM UTC-8, margaret laroche wrote:
well just like i said, i might've forgot to comment out some codes. and it's true: i set the display: none, so no wonder if it doesn't appear :)

it works fine now. thanks.

Ok. ;)
 
anyway, about the updateonPause and me.state.pause();

I've tried this:

...

however, when I tried that: game paused right after I click on the menu button, and no ingame menu container doesn't show up, but I could still click on the "invisble" button in the ingame menu container and it'll show up its corresponding ingame menu tab just fine. and sometimes, clicking them also would bring the ingameMenu.Container 'appear'. (it took a long time for it to appear and sometimes it doesn't appear at all). But when it does appear, the pause breaks and the game behind the menu is working again....

The button will continue to be "clickable" until you either unregister the pointer event on it, or consciously stop the click event handling while the game is paused. These pointer events are fired outside of the control of the game engine (kind of... melonJS could also do the "don't handle event if paused" thing unless the object has updateWhenPaused set.) But, it's still pretty easy to workaround. :)

moving the this.updateWhenPaused = true; to the ingameMenu.Container, makes the me.state.pause() doesn't work.

This is certainly what you are supposed to be doing ... Set this flag on objects you want to continue running when the game is paused. It should have no consequence on the pause state of any other object, unless that's a very serious bug in the engine. I would first point the blame on some part of your code, if this is really happening.

well I found this: https://groups.google.com/forum/#!topic/melonjs/aFdSDrn6iAA that talk about making the similar menu as me.

and it was suggested to use "overlay" objects and stop the update of position and collision when the object are instantiated. i think the "overlay" objects meant was the one I already make (through objectContainer). or was i wrong?

That forum post was made sometime between version 0.9.2 and 0.9.3 -- I guarantee things have changed significantly since then, and the suggestions posted there are no longer as relevant. The ObjectContainer class hadn't even been thought of then. ;) By "overlay" I would think it meant more like the DOM elements you are overlaying on top of the canvas (using CSS). For example, a lot of websites utilize an overlay pattern called a "lightbox" when you click on an image to get a bigger view; the lightbox overlay makes it impossible to interact with the rest of the website until it is closed.

Anyway, I think you're on the right track with using the built-in pause stuff. You just need to familiarize yourself with it. And if you have suggestions on improvements, we would love to hear!

margaret laroche

unread,
Jan 19, 2014, 9:35:04 PM1/19/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
okay, i tried it again and the pause works okay (no change in code).

the problem of  the pause's breaking seems due to the error from my geolocation detection. I'm checking the player's location using the geolocation feature of html5 to implement the weather system, and when it return with some error (error.code =2) and throw the pop up message, the pause just breaks. (it seems it breaks because the game is updating the 'weather').

i set the weather change in play.js. (see below)  and position+getting weather data on window.onload, then check position and get weather changes again every 2 hour. if i the geolocation returned with error, it will randomize the weather, and apply the changes to the screen.

game.PlayScreen = me.ScreenObject.extend({
    init: function () {
        this.parent(true);
        this.updateTime = 120 * 60 * 1000; // 1 sec = 1000ms
    },
    onResetEvent: function () {
        //set Key to return to title
        me.input.bindKey(me.input.KEY.Q, "goTitle");
 
        //loadLevel
        me.levelDirector.loadLevel("darkw1");
 
        //add HUD to screen
        this.HUD = new game.HUD.Container();
        me.game.world.addChild(this.HUD);
        me.game.world.sort();
 
        //add GUI to screen
        this.GUI = new game.GUI.Container();
        me.game.world.addChild(this.GUI);
        me.game.world.sort();
 
        //get update on weather
        setInterval(requestPosition, this.updateTime);
    },
    //function to apply weather to screen
    applyWeather: function () {
        //cek if current weather is rain or snow
        if (game.data.curWeather == "Rain" || game.data.curWeather == "Snow") {
            switch (game.data.prevWeather) {
                case "Rain":
                    game.data.prevWeather = game.data.curWeather;
                    break;
                case "Snow":
                    game.data.prevWeather = game.data.curWeather;
                    break;
                case "Sunny":
                    game.data.prevWeather = game.data.curWeather;
                    this.Rain = new game.Rain.Container();
                    me.game.world.addChild(this.Rain);
                    break;
            }
        } //check if current weather is sunny
        else {
            switch (game.data.prevWeather) {
                case "Rain":
                    game.data.prevWeather = game.data.curWeather;
                    me.game.world.removeChild(this.Rain);
                    break;
                case "Snow":
                    game.data.prevWeather = game.data.curWeather;
                    me.game.world.removeChild(this.Rain);
                    break;
                case "Sunny":
                    game.data.prevWeather = game.data.curWeather;
                    break;
            }
        }
    },
    update: function () {
        //apply weather to screen as needed
        this.applyWeather();
        if (me.input.isKeyPressed('goTitle')) {
            me.save.add({ HP: game.data.HP });
            me.state.change(me.state.STARTMENU);
        }
        return true;
    },
    onDestroyEvent: function () {
        me.audio.stopTrack();
        game.data.prevWeather = "Sunny";
        me.game.world.removeChild(this.HUD);
        me.game.world.removeChild(this.GUI);
        me.input.unbindKey(me.input.KEY.Q);
    }
});

it seems the play.js itself is still working (since it apply the weather changes made after the error). any suggestion how to deal with this? Oh, I set the pop message using the built in WinJS message dialog system, not creating it manually with melonjs/canvas.

me.state.pause() seems to pause the whole game (but the ones with updatewhenPaused), so logically, it would pause the play.js from attempting update, right?

Jay Oster

unread,
Jan 19, 2014, 9:52:48 PM1/19/14
to mel...@googlegroups.com, ayakashi.a...@gmail.com
Be careful; setInterval and setTimeout cannot be paused. v1.0.0. is adding version of these functions to me.timer that can be paused.

margaret laroche

unread,
Jan 22, 2014, 4:42:04 AM1/22/14
to mel...@googlegroups.com
Hi, i wanna ask if JQuery-UI is compatible to use with melonjs?

there's this tabs menu in JQuery-UI that would make making ingame menu easier... (well, at least I think it would).

but somehow I can't make the tabs work even though in JSFiddle it works  (here's the sample http://jsfiddle.net/youkai/E4cCy/2/ ).
in my game, it would only display the list as list (not as tabs like in JSFiddle). I've add JQuery 2.0.3 and JQuery-ui 1.10.3.

Aaron McLeod

unread,
Jan 22, 2014, 7:40:58 AM1/22/14
to mel...@googlegroups.com
With jquery ui, double check the css is getting loaded properly. Really you can use any dom elements and position them ontop or around the canvas. 


--
You received this message because you are subscribed to the Google Groups "melonJS - A lightweight HTML5 game engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to melonjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Reply all
Reply to author
Forward
0 new messages