Responsive Bootstrap and JQuery Game Template for Mobile

For mobile web app templates, Jquery Mobile has been a popular choice but it comes with its own set of issues when we have multiple pages in the game since it makes ajax calls to load the pages and if there are specific things which are required to be handled on each page then it becomes even more complex to handle those scenarios. The alternate is to have a simple Bootstrap and JQuery based template with multiple pages which is simple and works just like a website. The problem here is that the pages are loaded again and again whenever we navigate from one page to another. This is not an ideal scenario for mobile web apps since all external libraries are required to be initialized on all pages which is not required and unnecessary work for processor. For example, if you compiled your web app using PhoneGap and are using a plugin to play audio. You need to initialized the audio plugin on all pages wherever you need to use the plugin. In ideal scenario, the plugin should only be initialized once when app is first opened and should be available on all pages of your app which is why the preferred approach on mobile is to have single HTML file.

In this alternate approach we use a single page and show/hide the sections where each section contains a page. This is pretty much how JQuery Mobile works but in a more elementary way giving you full control over everything you need to handle.

First we will define and initialize  a helper class to manage storage to keep track of config changes and other game related data using browser/mobile cache

function LocalStorageManager() {
    this.gameConfigKey = "my-gameConfig";
    this.gameParamsKey = "my-gameParams";
    var supported = this.localStorageSupported();
    this.storage = supported ? window.localStorage : window.fakeStorage;
}

LocalStorageManager.prototype = {
    localStorageSupported: function () {
        var testKey = "test";
        try {
            var storage = window.localStorage;
            storage.setItem(testKey, "1");
            storage.removeItem(testKey);
            return true;
        } catch (error) {
            return false;
        }
    },
    getGameParams: function () {
        var paramsJSON = this.storage.getItem(this.gameParamsKey);
        return paramsJSON ? JSON.parse(paramsJSON) : { };
    },
    setGameParams: function (gameParams) {
        this.storage.setItem(this.gameParamsKey, JSON.stringify(gameParams));
    },
    clearGameParams: function () {
        this.storage.removeItem(this.gameParamsKey);
    },
    getGameConfig: function () {
        var configJSON = this.storage.getItem(this.gameConfigKey);
        return configJSON ? JSON.parse(configJSON) : { playSounds: true };
    },
    setGameConfig: function (gameConfig) {
        this.storage.setItem(this.gameConfigKey, JSON.stringify(gameConfig));
    },
    clearGameConfig: function () {
        this.storage.removeItem(this.gameConfigKey);
    },
};
var localStorageManager = new LocalStorageManager();

Let us now look at the HTML code

<!DOCTYPE html>
<html>
<head>
    <title>Game Template</title>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=no">
    <style>
        /* following two viewport lines are equivalent to meta viewport statement above, and is needed for Windows */
        /* see http://www.quirksmode.org/blog/archives/2014/05/html5_dev_conf.html and http://dev.w3.org/csswg/css-device-adapt/ */
        @-ms-viewport { width: 100vw ; min-zoom: 100% ; zoom: 100% ; }          @viewport { width: 100vw ; min-zoom: 100% zoom: 100% ; }
        @-ms-viewport { user-zoom: fixed ; min-zoom: 100% ; }                   @viewport { user-zoom: fixed ; min-zoom: 100% ; }
        /*@-ms-viewport { user-zoom: zoom ; min-zoom: 100% ; max-zoom: 200% ; }   @viewport { user-zoom: zoom ; min-zoom: 100% ; max-zoom: 200% ; }*/
    </style>

    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/custom.css">
    <link rel="stylesheet" href="css/jquery-confirm.min.css">
    <script src="js/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script src="js/jquery-confirm.min.js"></script>
    <script src="js/storage.js"></script>

    <script src="js/init-app.js"></script>	
</head>
<body>
<div id="page1" style="display: none;">
    <div class="container-fluid">
        <div class="row">
            <div class="col-xs-12">
                <img id="logo" class="img-responsive margin-auto" src="images/logo.png" alt="logo" />
			</div>
		</div>
		<div class="row">
            <div class="col-xs-12">
				<div class="hot-container">
					<a href="#" onclick="openPage(3)" class="btn btn-green">Play</a>
				</div>	
				<div class="hot-container">
					<a href="#" onclick="openPage(2)" class="btn btn-red">Rules</a>
				</div>	
				<div class="hot-container">
					<a href="#" class="btn btn-voilet">Leaderboard</a>
				</div>	
				<div class="hot-container">
					<a href="#" class="btn btn-blue">Rate it</a>
				</div>	
				<div class="hot-container">
					<a href="#" class="btn btn-blue">Share</a>
				</div>	
            </div>
        </div>
    </div>
</div>

<div id="page2" style="display: none;">
<div class="container-fluid">
        <div class="row">
            <div class="col-xs-2"><a href="#" onclick="openPage(1)"><span class="glyphicon glyphicon-circle-arrow-left"></span></a></div>
            <div class="col-xs-8">
                <p class="select-head">How to Play?</p>
            </div>
            <div class="col-xs-12">
                <div id="player-instructions" class="player-inst">
                    <h4>GAMEPLAY</h4>
                    <p>
                        Your Game Description!!
                    </p>
                </div>
            </div>
        </div>
    </div>
</div>

<div id="page3" style="display: none;">
    <div class="container-fluid">
        <div id="gametable" style="margin:auto;">
			<div class="row" style="margin-top:10px;">
				<div class="col-xs-2" class="margin-auto" style="height:40px;/*background-color:rgba(255, 255, 255, 0.5);*/">
					 <a href="#" onclick="openPage(1)"><span class="glyphicon glyphicon-home"></span></a>
				</div>
				<div class="col-xs-2" class="margin-auto" style="height:40px;">
					 <a id="newbutton" href="#"><span class="glyphicon glyphicon-repeat"></span></a>
				</div>
				<div class="col-xs-5" class="margin-auto" style="height:40px;">
				</div>
				<div class="col-xs-2" class="margin-auto" style="height:40px;">
					 <a href="#" id="audiobutton"><span class="glyphicon glyphicon-volume-up"></span></a>
				</div>
			</div>	
			<div class="row">
				<div class="col-xs-12" id="gamearea">
				<br/><br/>My Game
				</div>
			</div>
        </div>
    </div>
    <!-- /page -->
</div>

<!-- Game Code -->
<script src="js/game.js"></script>

<script>
var pageCount = 3;
function openPage(id){
	var gameParams = localStorageManager.getGameParams();
	gameParams.currentPage = gameParams.currentPage? id: 1;
	localStorageManager.setGameParams(gameParams);
	for(var i = 1; i <= pageCount; i++){
		$('#page'+i).hide();		
	}
	$('#page'+id).show();
}
function openGame(id){
	var gameParams = localStorageManager.getGameParams();
	gameParams.currentPage = id;
	localStorageManager.setGameParams(gameParams);
	for(var i = 1; i <= pageCount; i++){
		$('#page'+i).hide();		
	}
	$('#page'+id).show();

	startGame();
	
    var config = localStorageManager.getGameConfig();
    if (config && config.playSounds){
		$('#audiobutton span').removeClass("glyphicon-volume-off");
        $('#audiobutton span').addClass("glyphicon-volume-up");     
    } else {
        $('#audiobutton span').removeClass("glyphicon-volume-up");
        $('#audiobutton span').addClass("glyphicon-volume-off");         
    }
}

$(window).on('load', function () {
	var gameParams = localStorageManager.getGameParams();
	if(!gameParams.currentPage){
		gameParams.currentPage = 1;
	}
	
	if(gameParams.currentPage == 3){
		openGame(gameParams.currentPage);
	} else {
		openPage(gameParams.currentPage);
	}
	localStorageManager.setGameParams(gameParams);
	attachEvents();
});
</script>

</body>
</html>

We have defined all pages in its own DIV and set display to none for all DIVs. When we load the app for the first time, current page id can be set to the first page and saved to the cache. For all further visits we will set it to the last opened page id and then load that page.

There are two different methods for opening the page; OpenPage and OpenGame; OpenPage is a general purpose page redirect with no additional handling whereas OpenGame might need some additional work so we have separate methods to handle these scenarios. You can define additional pages and respective methods.

The template can be downloaded from github


Leave A Comment

Your email address will not be published.