As part of a university course, we should realize a digital escape room to teach some content applying gamification. However most digital escape rooms out there are just point and click adventures, which seemed a bit too boring to us. So we decided that we want to also implement some small minigames to keep the players engaged. These minigames should only be really small 2D games and puzzles, each not being graphically or gameplay wise more complex than little arcade games like snake.
The important thing would be, that these games should be able to communicate with the frontend application, as the scores and decisions in these minigames should affect the other content.
Any help is appreciated. It is not fixed yet, but we plan to implement the backend as a SpringBoot application and the frontend using Angular, as we are most familiar with these technologies and have limited time. So it would be even better if your ideas would work out in an Angular application. Compatibility with mobile devices would be a huge plus.
Does anyone have experience with this? I have some experience in game development using unity, but we thought about some smaller, easier javascript library like pixijs, which could be picked up more easily during this project by us all and does not have a loading screen for each game like the free unity license has.
Thanks in advance!
I already did some research, but did not find anything that is really suitable, such that it is simple to create small games, having not a loading screen for each game and that it is open to provide data outside the WebGl component.
Tad's Basic Game Objects can make quick games easily, and as long as you can create the div structure (shown below) it should be able to plug into any html. (you don't need webgl to make small mini games)
The best way to do it would be to actually just change the specifics of one single instance of a game. I think both Phaser and Pixi have options for not using webgl, but they use it by default, and are by default set up for more advanced games. Tabageos is all tile based and set up for basic quickly made games, and is really just a set of classes instead of a full framework, but has one framework class, the GameSkeleton class.
Here is an example of changing from platformer to top down maze by just changing a few properties and resting the game:
(this example should also run on mobile, a touch controller will try to show under the game, one would have to expand and zoom the area, otherwise use wasd to move)
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tabageos/tabageos/tbgs_min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/tabageos/tabageos/ControllerPad.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/tabageos/tabageos/ControllerPad.css">
<div id="container" style="position:relative;width:168x;">
<div id="root" style="position:relative;width:168px;height:144px;top:0px;left:0px;"> </div>
<div id="controller" > </div>
</div>
<div id="game1" style="width:50px;height:50px;border:thin solid black;cursor:pointer"> game1 </div>
<div id="game2" style="width:50px;height:50px;border:thin solid black;cursor:pointer"> game2 </div>
<script type="text/javascript">
let currentGameScene = null;
let gameColorValues = null;
let topDown = 0;
const baseGameCode = (function() {
function QuickGame() {
var specs = {gWidth:336, gHeight:144, controllerDivId:"controller", gameScale:0, gameLoop:this.loop, initializationSpecifics:this.setup}
tabageos.GameSkeleton.call(this, specs);
}
QuickGame.prototype = Object.create(tabageos.GameSkeleton.prototype);
QuickGame.prototype.setup = function() {
this.startButton.innerHTML = topDown ? "Game 2 Start" : "Game 1 Start";
this.player = new tabageos.BasicNinja(16,32,16,16, currentGameScene,null,1,0,16,16,currentGameScene.length,currentGameScene[0].length,0);
this.player._directCanvasObject = this.charLayer;
this.player._autoAnimate = 1;
this.player._jumps = topDown ? 0 : 1;
this._cameraType = 1;
var cValues = gameColorValues;
tabageos.BlitMath.drawSquaresFromPattern(this.display, currentGameScene, 16, 16, cValues);
this.removeHUD();
};
QuickGame.prototype.loop = function(){ var cb = this.controller.buttons;
this.player.move(cb.left,cb.right, cb.up || cb.a, cb.down);
};
new QuickGame();
});
document.getElementById("game1").addEventListener("click", selectGame, false);
document.getElementById("game2").addEventListener("click", selectGame, false);
function selectGame(e) {
var values1 = {1:"#6495ed",0:"#FFFFFF", 2:"#212121"};
var values2 = {1:"#640000",0:"#FFFFFF", 2:"#6495ed"};
var scene2 = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1],
[1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,2,1],
[1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1],
[1,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
var scene = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1],
[1,2,2,2,0,0,0,0,0,1,0,0,1,0,0,0,0,2,2,2,1],
[1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
if(e.target.id == "game1") {
currentGameScene = scene; gameColorValues = values1; topDown = 0;
if(!tabageos.GameSkeleton.game) {
baseGameCode();
} else {
tabageos.GameSkeleton.game.fullResetToTitle();
}
}
if(e.target.id == "game2") {
currentGameScene = scene2; gameColorValues = values2; topDown = 1;
if(!tabageos.GameSkeleton.game) {
baseGameCode();
} else {
tabageos.GameSkeleton.game.fullResetToTitle();
}
}
};
</script>