// © Головин Г.Г., Визуализация игрового процесса, 2023 'use strict'; // размер клеточки, отступ const size = 30, gap = 2; // массив статусов игры const statuses = ["ИГРА","УРОВЕНЬ","ПАУЗА","ЗАВЕРШЕНО"]; // массив цветов для фигур const colors = [ 'rgba(240,240,240,1)', 'rgba(150,0,0,1)', 'rgba(0,0,150,1)', 'rgba(150,150,0,1)', 'rgba(0,150,150,1)', 'rgba(0,150,0,1)', 'rgba(150,0,150,1)', 'rgba(150,80,80,1)']; // прозрачность фигур colors.setDefault = function() { this.alpha = 0; } colors.setDefault(); // получаем цвет, добавляем прозрачность только фигурам colors.get = function(...numbers) { for (let num of numbers) if (num <= 0) return this[0]; else if (num < colors.length) return this[num].replace('1)', (100-this.alpha)/100 + ')'); return this[0]; } // массив для кубиков let field3D = []; // центральная точка для поворотов const t0 = {}; t0.reCalc = function() { this.x = columns*(size+gap)/2; this.y = rows*(size+gap); this.z = (size+gap)*2; }; t0.reCalc(); // угол поворота игрового поля с кубиками let deg={}; deg.setDefault = function() { this.x=-1; this.y=0; this.z=0; }; deg.setDefault(); // параллельная проекция: центр и экран наблюдателя let d1 = 600, tv1={}; tv1.reCalc = function() { this.x=columns*(size+gap)/2; this.y=(size+gap)*2; this.z=(size+gap)*2; d1 = Math.max(rows,columns)*(size+gap); } tv1.reCalc(); // перспективная проекция: центр и экран наблюдателя let d2 = 600, tv2 = {}; tv2.reCalc = function() { this.x = columns*(size+gap)/2; this.y = rows*(size+gap)/2; this.z = (size+gap)*2; this.show=false; d2 = Math.max(rows,columns)*(size+gap); }; tv2.reCalc(); // стакан с игрой const container = {}; container.canvas = document.getElementById('container'); container.context = container.canvas.getContext('2d'); container.changeSize = function() { this.canvas.width = columns*size+(columns+1)*gap; this.canvas.height = rows*size+(rows+1)*gap; }; container.changeSize(); // перетаскивание центральной точки мышью container.msBtnPressed = false; container.canvas.onmouseup = ()=> container.msBtnPressed=false; container.canvas.onmousedown = (caller)=> { container.msBtnPressed=true; container.canvas.onmousemove(caller); } container.canvas.onmousemove = (caller)=> { if (vol==VOLUME.PERSPECTIVE && container.msBtnPressed && tv2.show) { tv2.x = caller.offsetX; tv2.y = caller.offsetY; repaint(false); refreshParams(); } } // следующая фигура const next = {}; next.canvas = document.getElementById('next'); next.context = next.canvas.getContext('2d'); next.changeSize = function() { this.canvas.width = 2*size+3*gap; this.canvas.height = 4*size+5*gap; }; next.changeSize(); // состояние игры const statusView = {}; statusView.level = document.getElementById('levelView'); statusView.score = document.getElementById('scoreView'); statusView.nextLevel = document.getElementById('nextLevelView'); statusView.speed = document.getElementById('speedometer') statusView.status = document.getElementById('statusView'); statusView.refresh = function() { this.level.innerText = level; this.score.innerText = score; this.nextLevel.innerText = nextLevel; this.speed.value = speedometer(); this.status.innerText = statuses[status]; } // обновление изображения function repaint(refresh3D=true) { // состояние игры statusView.refresh(); // стакан с игрой if (vol==VOLUME.FLAT) { drawCells(container.canvas, container.context, field, currentFigure.type); } else { if (refresh3D || field3D.length==0) prepare3D(); repaint3D(); } // следующая фигура drawCells(next.canvas, next.context, nextFigure.shape); } // рисуем массив клеточек function drawCells(canvas, context, array, color) { // очищаем весь холст целиком context.clearRect(0, 0, canvas.width, canvas.height); // обходим массив, рисуем клеточки for (let y=0; y b.dist-a.dist); // удаляем смежные стенки между соседними кубиками for (let i=0, j=1; iMath.abs(b.dist-a.dist)>size ? b.dist-a.dist : b.clock-a.clock); // обновляем стакан с игрой drawCubes(container.canvas, container.context, proj); // центральная точка перспективной проекции if (vol==VOLUME.PERSPECTIVE && tv2.show) centerPoint(container.context); } // обходим массив, рисуем грани по точкам function drawCubes(canvas, context, array) { // очищаем весь холст целиком context.clearRect(0, 0, canvas.width, canvas.height); // рисуем только видимые грани const visible = function(face) { // если есть хотя бы одна точка, которую можно нарисовать for (let j = 0; j < face.length; j++) if (face[j].x>-size && face[j].x-size && face[j].y