Ключевой элемент игры -- игровой фрейм, через который осуществляется взаимодействия игрока с игрой.
Необходимые возможности:
- инициализация,
- отображение изображения в заданной позиции и очистка, 
- воспроизведение звуков,
- слежение за состоянием контроллеров и проверка текущего состояния.

Так же необходимы объекты для хранения и манипулирования ресурсами:
- картинки,
- аудио-семплы,
- состояние контролла.

Для демонстрации будем использовать javascript c html5, так как у него есть все необходимые возможности и не надо организовывать среду для сборки проекта. Демка проверялась на firefox 52.

   


Для хранения картинок и семплов используем стандартные теги <img> и <audio>.

TODO в дальнейшем лучше перейти на ImageData и AudioBuffer -- для  создания спецэффектов (physics/spec.effects)

??? к сожалению нет способа взаимного преобразования <audio> и AudioBuffer

Состояния контроллов -- либо единственное значение, либо структура с соответствующими полями.

   


Для вывода изображения во фрейме используется метод Canvas -- drawImage(image, x, y), а для очистки --  clearRect(0,0,WIDTH, HEIGHT);

!!! можно использовать стили для размещения в нужной позиции, но для множества мелких повторяющихся изображений это не эффективно

   


Используя <audio> воспроизвести звук можно с помощью метода play().

!!! повторный вызов, до завершения предыдущего, будет проигнорирован, поэтому нужен метод перезагрузки -- load()

!? из-за защиты в браузере, без инициации воспроизведения пользователем, семплы не будут воспроизводиться

TODO необходимо переделать на вывод по каналам, и цикличное воспроизведение

   


Слежение за вводом можно осуществить с помощью запоминания событий от контроллов в ассоциативном массиве -- input[{ctr:va}l]. Проверка состояния -- проверка значения соответствующего контролла -- input[ctr].

!!! Подробнее в (framework/controllers)

   


Для инициализации фрема задаются размеры канвы, отслеживаемые контроллы. При инициализации создается <canvas> заданного размера и устанавливаются обработчики на нужные события -- addEventListener(event, handler()). После инициализации

TODO в дальнейшем добавить инициализацию звуковых каналов

   


Для проверки сделаем демку -- вывод изображения со звуком.

Код:
<html>
<head>
    <meta charset="utf-8">
    <script type="text/javascript">

const WIDTH = 640;
const HEIGHT = 480;


var gp_Inputs = {
};

function gp_input(ctr, val){
    if(gp_Inputs[ctr] !== undefined){
        gp_Inputs[ctr] = val;
    }
}

var gp_CanvasContex;
function gp_draw(image, x, y){
    gp_CanvasContex.drawImage(image, x, y);
}

function gp_clear(){
    gp_CanvasContex.clearRect(0,0,WIDTH, HEIGHT);
}

function gp_play(sound){
    sound.load();
    sound.play();
}


function gp_init(){
    var gp = document.getElementById("gamePanel");

    //init event listeners

    var canvas = document.createElement("canvas");
    canvas.id = "gameCanvas";
    canvas.width = WIDTH;
    canvas.height = HEIGHT;
    canvas.style="background-color:black;";
    gp.appendChild(canvas);
    gp_CanvasContex = canvas.getContext('2d');
}

function main(){
    gp_init();

    //resource load
    document.getElementById('snd1').load();

    gp_clear();
    var x=10,y=10;
    window.setInterval(()=>{
        gp_draw(document.getElementById('img1'),x,y);
        gp_play(document.getElementById('snd1'));

        x+=10;y+=10;
        if(x > WIDTH || y > HEIGHT){
            gp_clear();
            x=10;y=10;
        }
    },1000);

}
    </script>

</head>
<body>
    <button onclick="main();">start</button>
    <div class="gamepanel" id="gamePanel">
        <img id="img1" style="display:none;" src="http://vt.chuvsu.ru/misc/favicon.ico">
        <audio id="snd1" src="http://www.sounds.beachware.com/2illionzayp3may/ovbzl/PIECES.mp3"></audio>
    </div>
</body>
</html>

   


TODO оформить в виде модуля

TODO отделить вывод изображений, звуков, инициализация ресурсов