diff --git a/TODO.md b/TODO.md index f2396db..753f777 100644 --- a/TODO.md +++ b/TODO.md @@ -1,12 +1,12 @@ ## TODO: +- check min canvas sizes +- game session max quests - sfx - rewrite playMusic() func - add sfx&music loader -- draw button and other elements func - info widget - desktop (landscape) orientation - change quest animation -- button hover animation - make docs/ - make quests editor - make conrova build diff --git a/branch-info.md b/branch-info.md new file mode 100644 index 0000000..1185e42 --- /dev/null +++ b/branch-info.md @@ -0,0 +1,18 @@ +## Переосмысление +> 1. Движок отвечает только за логику +> рисование, кнопок и прочей шелухи на стороне разработчика игры + +Есть три состояние игры +1. LOADING +2. GAME +3. FINISH + +1. **LOADING** - Состояние игры, когда загружаются все ресурсы и происходит инициализация игры. +В этот момент рисуется прогресс-бар с процессом загрузки + +2. **GAME** - Состояние, когда происходит сам игровой процесс. +В этот момент игрок может взаимодействовать с элементами + +3. **FINISH** - тоже игровое состояние, но в этом состоянии отображается результат игры, +В этом состоянии, допустимо нажать **RESTART**, в следствии чего сбрасывается состояние игры +и процесс GAME запускается сначала diff --git a/js/areas.js b/js/areas.js deleted file mode 100644 index ac2f90a..0000000 --- a/js/areas.js +++ /dev/null @@ -1,49 +0,0 @@ -import config from './config.json'; - -import * as Draw from './draw.js' - -/** - * Устанавливает размеры и положение зон для отрисовки - * @param {Object} canvas - * @param {Bool} landscape_orientation текущая ориентация игры - * @param {Image} logoImage логотип - * @return {Object} список зон - */ -export function setAreas(canvas, landscape_orientation, logoImage) { - let areasArray = null; - - let cW = canvas.width; - let cH = canvas.height; - - areasArray = { splash: {}, game: {}, finish: {} }; - - if (!landscape_orientation) { - areasArray.game = { - btnAnswer: { x: 10, y: cH - 340, w: cW - 20, h: 250 }, - labelQuestion: { x: 10, y: cH - 340 - 80, w: cW - 20, h: 70 }, - btnUi: { x: 10, y: cH - 80, w: cW - 20, h: 70 }, - questProgress: { x: 10, y: 10, w: cW - 20, h: 20 }, - } - areasArray.game.questImage = { x: 10, y: areasArray.game.questProgress.y + areasArray.game.questProgress.h + 10, - w: cW - 20, h: areasArray.game.labelQuestion.y - areasArray.game.questProgress.y - (areasArray.game.questProgress.h * 2) }; - - let progressBarHeight = cH - (Draw.getCenterV(cH, logoImage.height) + logoImage.height) > 301 ? - Draw.getCenterV(cH, logoImage.height) + logoImage.height + 70 : cH - 70; - - areasArray.splash = { - border: { x: Draw.getCenterH(cW, config.loaderWidth), y: progressBarHeight, w: config.loaderWidth, h: 20 }, - pointer: { position: 0, direction: true }, - } - - areasArray.finish.labelFinishGameName = { x: 10, y: 60, w: cW - 20, h: 30 }; - areasArray.finish.labelTotalAnswerPercent = { x: 10, y: Draw.getCenterV(cH, 80), w: cW - 20, h: 80 }; - areasArray.finish.labelTotalAnswerRight = { x: 10, y: areasArray.finish.labelTotalAnswerPercent.y - 70, w: cW - 20, h: 60 }; - areasArray.finish.labelTotalInfo = { x: 10, y: areasArray.finish.labelTotalAnswerPercent.y + areasArray.finish.labelTotalAnswerPercent.h + 10, w: cW - 20, h: 90 }; - areasArray.finish.image = { x: 10, y: areasArray.finish.labelFinishGameName.y + areasArray.finish.labelFinishGameName.h + 10, w: cW - 20, h: areasArray.finish.labelTotalAnswerRight.y - 20 - areasArray.finish.labelFinishGameName.y - areasArray.finish.labelFinishGameName.h }; - } - else { - // TODO: add areas for landscape mode - } - - return areasArray; -} \ No newline at end of file diff --git a/js/buttons.js b/js/buttons.js index c0aa9a0..a3a7084 100644 --- a/js/buttons.js +++ b/js/buttons.js @@ -1,5 +1,3 @@ -// функции обработки кнопок - /** * Возвращает координаты позичии курсора * @param {Object} canvas canvas с которого считывается позиция курсора diff --git a/js/config.json b/js/config.json index a4e6be5..6b5c05b 100644 --- a/js/config.json +++ b/js/config.json @@ -3,7 +3,7 @@ "gameVersion": [0, 0, 1], "debug": true, "lang": "en-us", - "loaderWidth": 200, + "loader": {"w": 200, "h": 20}, "colors": { "back": "#2f3542", "strokeSize": 1.5, diff --git a/js/draw.js b/js/draw.js index 43a38a6..eb98642 100644 --- a/js/draw.js +++ b/js/draw.js @@ -1,6 +1,5 @@ -// функции рисоввания - /** + * Очищает область рисования * @param {Object} canvas canvas object * @param {String} color строка с цветом (HEX, либо имя, либо rgba, etc) */ @@ -65,31 +64,6 @@ export function getCenterV(canvasHeight, objectHeight) { return canvasHeight / 2 - objectHeight / 2; } -export function drawGameAreas(context, areas) { - context.strokeStyle = "#ff0000"; - context.lineWidth = 1; - - for (const [key, value] of Object.entries(areas)) { - context.strokeRect(value.x, value.y, value.w, value.h); - } -} - -export function drawInfo(canvas, landscape_orientation) { - let cW = canvas.width; - let cH = canvas.height; - let context = canvas.getContext('2d'); - - console.log("INFO"); - - context.fillStyle = 'rgba(0,0,0,.8)'; - context.fillRect(0, 0, cW, cH); - - // if(!landscape_orientation) { - context.fillStyle = '#000000'; - context.fillRect(80, 80, cW - 160, cH - 160); - // } -} - /** * Рисует полосу прогресса с визуализацией правильных и неправильных ответов * @param {} context diff --git a/js/engine.js b/js/engine.js index eedfcc5..4e661dc 100644 --- a/js/engine.js +++ b/js/engine.js @@ -33,7 +33,6 @@ export function shuffle(array) { } } -// /** * Функция возвращает ориентацию игры в зависимости от размера canvas * @param {Object} canvas canvas object @@ -50,5 +49,5 @@ export function setOrientation(canvas) { 'Set game orientation to landscape' : 'Set game orientation to portrait'); - return landscape_orientation; + return landscape_orientation; // true = land | false = port } diff --git a/js/game.js b/js/game.js index 7ee9df1..c5950e4 100644 --- a/js/game.js +++ b/js/game.js @@ -1,5 +1,3 @@ -// функции игры - import { shuffle } from './engine.js'; /** diff --git a/js/index.js b/js/index.js index 1cc2512..6f49447 100644 --- a/js/index.js +++ b/js/index.js @@ -9,7 +9,6 @@ import * as Engine from './engine.js'; import * as Buttons from './buttons.js'; import * as Draw from './draw.js'; import * as Music from './music.js'; -import * as Areas from './areas.js'; import * as Game from './game.js'; // Engine variables ------------------------------------- @@ -18,15 +17,14 @@ let canvas = null; // canvas id let context = null; // context id let cW = null; // canvas with let cH = null; // canvas height -let landscape_orientation = null; // canvas orientation let game = {}; // main game variable -let areas = null; let images = {}; let buttons = {}; let buttonsUi = {}; let music = {}; // Engine init ------------------------------------------ +// ------------------------------------------------------ window.onload = function() { // set html page language document.documentElement.lang = config.lang; @@ -34,6 +32,13 @@ window.onload = function() { // set html body background-color document.body.style.background = config.colors.back; + game.orientation = null; + game.appearanceAplha = 0; + game.loadedState = false; + game.finish = false; + game.currentQuest = 0; + game.loader = null; + // init canvas id and sizes canvas = document.getElementById('game'); context = canvas.getContext('2d'); @@ -41,14 +46,20 @@ window.onload = function() { cH = canvas.height; if (DEBUG) console.log(`Canvas size ${cW} x ${cH}`); + game.orientation = Engine.setOrientation(canvas); - // set screen orientation by carculate canvas width & height - landscape_orientation = Engine.setOrientation(canvas) - + + // loading Logo image let imageLogo = new Image(); imageLogo.src = "assets/logo.png"; images.logo = imageLogo; + // set game loading progress bar + game.loader = { x: Draw.getCenterH(cW, config.loader.w), + y: cH - config.loader.h - 100 }; + game.loader.pointer = 0; + game.loader.direction = true; + let loadingImages = []; loadingImages.push(gameData.result.notPassed, gameData.result.passed); @@ -65,12 +76,6 @@ window.onload = function() { music.music = new AudioContext() || new webkitAudioContext(); Music.playMusic(config, music.music); - game.showAlpha = null; - game.showInfo = false; - game.loadedState = false; - game.finish = false; - game.currentQuest = 0; - // shuffle quests and first quest answers Engine.shuffle(gameData.questions); gameData.questions.forEach(quest => { @@ -80,9 +85,6 @@ window.onload = function() { // set all quest status 'not answered' gameData.questions.forEach(element => element.status = null); - // set areas sizes - areas = Areas.setAreas(canvas, landscape_orientation, images.logo); - // hover by buttons canvas.addEventListener('mousemove', e => { let mousePos = Buttons.getMousePos(canvas, e); @@ -147,6 +149,7 @@ window.onload = function() { // GameLoop --------------------------------------------- +// ------------------------------------------------------ function gameLoop(timeStamp) { update(); draw(); @@ -155,62 +158,40 @@ function gameLoop(timeStamp) { } // Game update func ------------------------------------- +// ------------------------------------------------------ function update() { - if (game.showAlpha >= 0) { - game.showAlpha -= 0.01; + // appearance effect -------------------------------- + if (game.appearanceAplha >= 0) { + game.appearanceAplha -= 0.01; } if (!game.loadedState) { - if (areas.splash.pointer.position < areas.splash.border.w - 50 && areas.splash.pointer.direction) { - areas.splash.pointer.position += 1; - } - else areas.splash.pointer.direction = false; + if (game.loader.pointer < config.loader.w - 50 && game.loader.direction) + game.loader.pointer += 1; + else game.loader.direction = false; - if (!areas.splash.pointer.direction) { - if (areas.splash.pointer.position <= 0) - areas.splash.pointer.direction = true; + if (!game.loader.direction) { + if (game.loader.pointer <= 0) game.loader.direction = true; - areas.splash.pointer.position -= 1; + game.loader.pointer -= 1; } + + console.log(game.loader.pointer); } + // game --------------------------------------------- if (game.loadedState && !game.finish) { - buttons.answerButton0 = { x: Draw.getCenterH(cW, cW / 1.5), y: 0, w: cW / 1.5, h: 50, data: null }; - buttons.answerButton1 = { x: Draw.getCenterH(cW, cW / 1.5), y: 0, w: cW / 1.5, h: 50, data: null }; - buttons.answerButton2 = { x: Draw.getCenterH(cW, cW / 1.5), y: 0, w: cW / 1.5, h: 50, data: null }; - buttons.answerButton3 = { x: Draw.getCenterH(cW, cW / 1.5), y: 0, w: cW / 1.5, h: 50, data: null }; - - let answerButtonsArray = [buttons.answerButton0, buttons.answerButton1, - buttons.answerButton2, buttons.answerButton3]; - - answerButtonsArray.forEach(function callback(value, index, array) { - if (index == 0) - array[index].y = areas.game.btnAnswer.y; - else - array[index].y = array[index - 1].y + value.h + 15; - }); - - // Update answer buttons label - answerButtonsArray.forEach(function callback(value, index) { - value.data = gameData.questions[game.currentQuest].answer[index]; - }); - - buttonsUi.uiInfo = { x: areas.game.btnUi.x, y: areas.game.btnUi.y, w: areas.game.btnUi.h, h: areas.game.btnUi.h }; - buttonsUi.uiMusic = { x: areas.game.btnUi.w + areas.game.btnUi.x - areas.game.btnUi.h, y: areas.game.btnUi.y, w: areas.game.btnUi.h, h: areas.game.btnUi.h }; - buttonsUi.uiSfx = { x: areas.game.btnUi.w + areas.game.btnUi.x - (areas.game.btnUi.h * 2) - 10, y: areas.game.btnUi.y, w: areas.game.btnUi.h, h: areas.game.btnUi.h }; + // NOTE: put your code here } + // finish game -------------------------------------- if (game.finish) { - delete buttons.answerButton0; - delete buttons.answerButton1; - delete buttons.answerButton2; - delete buttons.answerButton3; - - buttons.btnRestart = { x: Draw.getCenterH(cW, cW / 1.5), y: areas.finish.labelTotalInfo.y + areas.finish.labelTotalInfo.h + 20, w: cW / 1.5, h: 70, data: "Ответить на вопросы заново" }; + // NOTE: put your code here } } // Draw to canvas func ---------------------------------- +// ------------------------------------------------------ function draw() { Draw.clearContext(canvas, config.colors.back); // clean canvas @@ -218,133 +199,27 @@ function draw() { if (!game.loadedState) { context.drawImage(images.logo, Draw.getCenterH(cW, images.logo.width), Draw.getCenterV(cH, images.logo.height)); - context.font = "32px Yanone Kaffeesatz"; - context.textAlign = "center"; - context.fillStyle = "white"; + context.fillStyle = config.colors.buttonFill; + context.strokeStyle = config.colors.buttonStroke; + context.lineWidth = config.colors.strokeSize; - context.fillRect(areas.splash.pointer.position + areas.splash.border.x, areas.splash.border.y, 50, areas.splash.border.h); - context.strokeRect(areas.splash.border.x, areas.splash.border.y, - areas.splash.border.w, areas.splash.border.h); + context.fillRect(game.loader.x + game.loader.pointer, game.loader.y, 50, config.loader.h); + context.strokeRect(game.loader.x, game.loader.y, config.loader.w, config.loader.h); } // render game -------------------------------------- if (!game.finish && game.loadedState) { - // draw progress bar - Draw.drawProgressBar(context, areas.game.questProgress, config.colors, gameData.questions); - - // draw quest image - Draw.placeImage(canvas, areas.game.questImage, - gameData.questions[game.currentQuest].image, config.colors); - - // draw question label - Draw.drawQuestionLabel(canvas, areas.game.labelQuestion, gameData.questions[game.currentQuest].question); - - // draw answer buttons - context.fillStyle = config.colors.buttonFill; - context.strokeStyle = config.colors.buttonStroke; - context.lineWidth = config.colors.strokeSize; - - let answerButtonsArray = [buttons.answerButton0, buttons.answerButton1, - buttons.answerButton2, buttons.answerButton3]; - - answerButtonsArray.forEach(function(btn) { - context.fillRect(btn.x, btn.y, btn.w, btn.h); - context.strokeRect(btn.x, btn.y, btn.w, btn.h); - }); - - // draw answer button label - context.font = "32px Yanone Kaffeesatz"; - context.textAlign = "center"; - context.fillStyle = config.colors.buttonFont; - - answerButtonsArray.forEach(function callback(value) { - context.fillText(value.data, cW / 2, value.y + 35); - }); - - // draw UI buttons - context.fillStyle = config.colors.buttonFill; - context.strokeStyle = config.colors.buttonStroke; - context.lineWidth = config.colors.strokeSize; - - for (const [key, value] of Object.entries(buttonsUi)) { - context.fillRect(value.x, value.y, value.w, value.h); - context.strokeRect(value.x, value.y, value.w, value.h); - } + // NOTE: put your code here } // render result game ------------------------------- if (game.finish) { - // draw game name label - context.font = "32px Yanone Kaffeesatz"; - context.textAlign = "center"; - context.fillStyle = "white"; - - context.fillText(config['gameName'], cW / 2, areas.finish.labelFinishGameName.y + 25); - - /// draw finish game image - let rightAnswer = 0; - gameData.questions.forEach(element => element.status ? rightAnswer += 1 : null); - let rightAnswerPercentage = Math.ceil(rightAnswer / gameData.questions.length * 100); - - let i = new Image(); - if (rightAnswerPercentage >= gameData.result.minRightAnswer) { - i.src = `assets/images/${gameData.result.passed}` - } - else { - i.src = `assets/images/${gameData.result.notPassed}` - } - - context.drawImage(i, Draw.getCenterH(cW, i.width), areas.finish.image.y + areas.finish.image.h - i.height); - - // draw labelTotalAnswerRight - context.font = "50px Yanone Kaffeesatz"; - context.fillText(`Результат: ${rightAnswer} из ${gameData.questions.length} ответов верны`, cW / 2, areas.finish.labelTotalAnswerRight.y + 45); - - - // draw labelTotalAnswerPercent - context.font = "75px Yanone Kaffeesatz"; - context.fillText(`Выполнено на ${rightAnswerPercentage}%`, cW / 2, areas.finish.labelTotalAnswerPercent.y + 65); - - // labelTotalInfo - context.font = "50px Yanone Kaffeesatz"; - let resultInfo = null; - - for (const [key, value] of Object.entries(gameData.answerResult)) { - if (key <= rightAnswerPercentage) { - resultInfo = value; - } - } - - context.fillText(resultInfo, cW / 2, areas.finish.labelTotalInfo.y + 55); - - // draw btnRestart - context.fillStyle = config.colors.buttonFill; - context.strokeStyle = config.colors.buttonStroke; - context.fillRect(buttons.btnRestart.x, buttons.btnRestart.y, buttons.btnRestart.w, buttons.btnRestart.h); - context.strokeRect(buttons.btnRestart.x, buttons.btnRestart.y, buttons.btnRestart.w, buttons.btnRestart.h); - - context.font = "32px Yanone Kaffeesatz"; - context.textAlign = "center"; - context.fillStyle = config.colors.buttonFont; - context.fillText(buttons.btnRestart.data, cW / 2, buttons.btnRestart.y + 43); - } - - // draw game areas ---------------------------------- - if (DEBUG && !game.finish && game.loadedState) { - Draw.drawGameAreas(context, areas.game); - } - else if (DEBUG && game.finish) { - Draw.drawGameAreas(context, areas.finish); + // NOTE: put your code here } // draw alpha animation ----------------------------- - if (game.showAlpha != null) { - context.fillStyle = `rgba(0,0,0,${game.showAlpha})`; + if (game.appearanceAplha != null) { + context.fillStyle = `rgba(0,0,0,${game.appearanceAplha})`; context.fillRect(0, 0, cW, cH); } - - // draw info window [indev] ------------------------- - if (game.showInfo) { - Draw.drawInfo(canvas, landscape_orientation); - } }