Take animation, text and menus to a separate UI module

This commit is contained in:
Tissevert 2018-11-20 15:56:28 +01:00
parent 2eecc2c7fb
commit 865f7ce83e
5 changed files with 120 additions and 89 deletions

View file

@ -1,4 +1,4 @@
function Automaton(async, buttons, dom, messaging, screen, session) {
function Automaton(async, dom, messaging, screen, session, ui) {
var menus = {
start: {
entries: [
@ -27,67 +27,6 @@ function Automaton(async, buttons, dom, messaging, screen, session) {
// console.log(game);
//});
function animation(frames) {
var frameCounter = 0;
var scheduled;
var step = function() {
if(frameCounter < frames.length) {
scheduled = null;
frames[frameCounter].action();
if(frames[frameCounter].delay != undefined) {
scheduled = setTimeout(step, frames[frameCounter].delay);
}
frameCounter++
}
};
return {
run: step,
skip: function() { if(scheduled != undefined) { clearTimeout(scheduled); } }
};
}
function text(message) {
var characters = message.split('');
var frames = [];
var ready = false;
var append = function(c) { return function() { screen.appendText(c); }; };
for(var i = 0; i < characters.length; i++) {
frames.push({action: append(characters[i]), delay: 50});
}
frames.push({action: function() { ready = true; screen.markAsRead(); }, delay: null});
var remote = animation(frames);
return function(f) {
buttons.push({
'A': function() {
if(ready) {
f();
} else {
remote.skip();
screen.text(message);
ready = true;
}
}
});
screen.text('');
remote.run();
};
}
function menu(config) {
var cursor = 0;
var m = screen.menu(config.entries);
var sync = function() { screen.select(cursor); };
var mapping = {
'Up': function() { cursor = Math.max(0, cursor - 1); sync(); },
'Down': function() { cursor = Math.min(config.entries.length - 1, cursor + 1); sync(); },
'A': function() { config.entries[cursor].action(); }
};
if(config.cancel != undefined) {
mapping['B'] = function() { buttons.pop(); screen.clear(m); config.cancel(); }
}
buttons.push(mapping);
}
function run() {
intro();
}
@ -95,31 +34,24 @@ function Automaton(async, buttons, dom, messaging, screen, session) {
function intro() {
var title = dom.make('p', {textContent: "P O K E M O N", class: 'title'});
var subtitle = dom.make('p', {textContent: "< press start >", class: 'subtitle'});
var remote = animation([
{action: function() {}, delay: 500},
{action: function() { screen.show(title); }, delay: 1000},
{action: function() { screen.show(subtitle); }, delay: null}
]);
buttons.map({
'B': function() { remote.skip(); intro() },
'Start': function() {
remote.skip();
screen.frame(2);
screen.clear();
menu(menus.start);
}
});
screen.frame(1);
screen.clear();
remote.run();
ui.frame('Intro');
async.run(
ui.cinematic([
{action: function() {}, delay: 500},
{action: function() { screen.show(title); }, delay: 1000},
{action: function() { screen.show(subtitle); }, delay: null}
], {
'B': intro,
'Start': function() { ui.frame('StartMenu'); ui.menu(menus.start); }
})
);
}
function newGame() {
screen.frame(3);
screen.clear();
ui.frame('GameInit');
async.run(
text("Bonjour ! Bienvenue dans le monde merveilleux des pokémons !"),
text("Pour certains, les pokemons sont des amis. Pour d'autres, ils sont une ressource. "),
ui.text("Bonjour ! Bienvenue dans le monde merveilleux des pokémons !"),
ui.text("Pour certains, les pokemons sont des amis. Pour d'autres, ils sont une ressource. Pour ma part, hé bien l'étude des pokémons est ma passion et mon métier."),
);
}
}

View file

@ -10,6 +10,7 @@
<script src="screen.js"></script>
<script src="buttons.js"></script>
<script src="messaging.js"></script>
<script src="ui.js"></script>
<script src="automaton.js"></script>
<link rel="stylesheet" href="screen.css" type="text/css"/>
</head>

View file

@ -5,7 +5,8 @@ window.addEventListener('load', function() {
screen = Screen(dom);
session = Session();
buttons = Buttons(session);
automaton = Automaton(async, buttons, dom, messaging, screen, session);
ui = UI(buttons, screen);
automaton = Automaton(async, dom, messaging, screen, session, ui);
messaging.start();
automaton.run();

View file

@ -54,27 +54,27 @@ ul.menu .selected:before {
}
/* 1st frame */
#screen.frame1 * {
#screen.frameIntro * {
position: absolute;
}
#screen.frame1 p {
#screen.frameIntro p {
width: 100%;
text-align: center;
margin: 0;
transform: translateY(-50%);
}
#screen.frame1 .title {
#screen.frameIntro .title {
font-size: 2em;
top: 50%;
}
#screen.frame1 .subtitle {
#screen.frameIntro .subtitle {
top: 75%;
}
/* 2nd frame */
#screen.frame2 ul {
#screen.frameStartMenu ul {
width: 7em;
}

97
src/ui.js Normal file
View file

@ -0,0 +1,97 @@
function UI(buttons, screen) {
return {
animation: animation,
cinematic: cinematic,
frame: frame,
menu: menu,
text: text
};
function animation(frames) {
var frameCounter = 0;
var scheduled;
var step = function() {
if(frameCounter < frames.length) {
scheduled = null;
frames[frameCounter].action();
if(frames[frameCounter].delay != undefined) {
scheduled = setTimeout(step, frames[frameCounter].delay);
}
frameCounter++
}
};
return {
run: step,
pause: function() { if(scheduled != undefined) { clearTimeout(scheduled); } }
};
}
function cinematic(frames, controls) {
var remote = animation(frames);
var mapping = {};
for(var key in controls) {
mapping[key] = function() {
buttons.pop();
remote.pause();
controls[key]();
};
}
return function(f) {
buttons.push(mapping);
remote.run();
f();
};
}
function frame(id) {
screen.clear();
screen.frame(id);
}
function menu(config) {
var cursor = 0;
var m = screen.menu(config.entries);
var sync = function() { screen.select(cursor); };
var mapping = {
'Up': function() { cursor = Math.max(0, cursor - 1); sync(); },
'Down': function() { cursor = Math.min(config.entries.length - 1, cursor + 1); sync(); },
'A': function() { config.entries[cursor].action(); }
};
if(config.cancel != undefined) {
mapping['B'] = function() { buttons.pop(); screen.clear(m); config.cancel(); }
}
buttons.push(mapping);
}
function textScreen(message) {
var characters = message.split('');
var frames = [];
var ready = false;
var append = function(c) { return function() { screen.appendText(c); }; };
for(var i = 0; i < characters.length; i++) {
frames.push({action: append(characters[i]), delay: 50});
}
frames.push({action: function() { ready = true; screen.markAsRead(); }, delay: null});
var remote = animation(frames);
return function(f) {
buttons.push({
'A': function() {
if(ready) {
f();
} else {
remote.pause();
screen.text(message);
ready = true;
}
}
});
screen.text('');
remote.run();
};
}
function text(message) {
return textScreen(message);
}
}