mirror of
https://github.com/Michatec/MiniFaceBook.git
synced 2026-03-31 23:46:30 +02:00
Secret Page removed.
This commit is contained in:
5
main.py
5
main.py
@@ -229,11 +229,6 @@ def not_found(error):
|
|||||||
return redirect(url_for('post.feed'))
|
return redirect(url_for('post.feed'))
|
||||||
return render_template('index.html'), 200
|
return render_template('index.html'), 200
|
||||||
|
|
||||||
@app.route('/secret')
|
|
||||||
@login_required
|
|
||||||
def secret():
|
|
||||||
return render_template('secret.html')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
serve(app, host="0.0.0.0", port=80, threads=12)
|
serve(app, host="0.0.0.0", port=80, threads=12)
|
||||||
|
|||||||
@@ -1,294 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% block title %}{{ _('Secret') }}{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<h1>Secret</h1>
|
|
||||||
<canvas width="320" height="640" id="game"></canvas>
|
|
||||||
<script>
|
|
||||||
function getRandomInt(min, max) {
|
|
||||||
min = Math.ceil(min);
|
|
||||||
max = Math.floor(max);
|
|
||||||
|
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate a new tetromino sequence
|
|
||||||
// @see https://tetris.fandom.com/wiki/Random_Generator
|
|
||||||
function generateSequence() {
|
|
||||||
const sequence = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'];
|
|
||||||
|
|
||||||
while (sequence.length) {
|
|
||||||
const rand = getRandomInt(0, sequence.length - 1);
|
|
||||||
const name = sequence.splice(rand, 1)[0];
|
|
||||||
tetrominoSequence.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the next tetromino in the sequence
|
|
||||||
function getNextTetromino() {
|
|
||||||
if (tetrominoSequence.length === 0) {
|
|
||||||
generateSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = tetrominoSequence.pop();
|
|
||||||
const matrix = tetrominos[name];
|
|
||||||
|
|
||||||
// I and O start centered, all others start in left-middle
|
|
||||||
const col = playfield[0].length / 2 - Math.ceil(matrix[0].length / 2);
|
|
||||||
|
|
||||||
// I starts on row 21 (-1), all others start on row 22 (-2)
|
|
||||||
const row = name === 'I' ? -1 : -2;
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: name, // name of the piece (L, O, etc.)
|
|
||||||
matrix: matrix, // the current rotation matrix
|
|
||||||
row: row, // current row (starts offscreen)
|
|
||||||
col: col // current col
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotate an NxN matrix 90deg
|
|
||||||
// @see https://codereview.stackexchange.com/a/186834
|
|
||||||
function rotate(matrix) {
|
|
||||||
const N = matrix.length - 1;
|
|
||||||
const result = matrix.map((row, i) =>
|
|
||||||
row.map((val, j) => matrix[N - j][i])
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if the new matrix/row/col is valid
|
|
||||||
function isValidMove(matrix, cellRow, cellCol) {
|
|
||||||
for (let row = 0; row < matrix.length; row++) {
|
|
||||||
for (let col = 0; col < matrix[row].length; col++) {
|
|
||||||
if (matrix[row][col] && (
|
|
||||||
// outside the game bounds
|
|
||||||
cellCol + col < 0 ||
|
|
||||||
cellCol + col >= playfield[0].length ||
|
|
||||||
cellRow + row >= playfield.length ||
|
|
||||||
// collides with another piece
|
|
||||||
playfield[cellRow + row][cellCol + col])
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// place the tetromino on the playfield
|
|
||||||
function placeTetromino() {
|
|
||||||
for (let row = 0; row < tetromino.matrix.length; row++) {
|
|
||||||
for (let col = 0; col < tetromino.matrix[row].length; col++) {
|
|
||||||
if (tetromino.matrix[row][col]) {
|
|
||||||
|
|
||||||
// game over if piece has any part offscreen
|
|
||||||
if (tetromino.row + row < 0) {
|
|
||||||
return showGameOver();
|
|
||||||
}
|
|
||||||
|
|
||||||
playfield[tetromino.row + row][tetromino.col + col] = tetromino.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for line clears starting from the bottom and working our way up
|
|
||||||
for (let row = playfield.length - 1; row >= 0; ) {
|
|
||||||
if (playfield[row].every(cell => !!cell)) {
|
|
||||||
|
|
||||||
// drop every row above this one
|
|
||||||
for (let r = row; r >= 0; r--) {
|
|
||||||
for (let c = 0; c < playfield[r].length; c++) {
|
|
||||||
playfield[r][c] = playfield[r-1][c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
row--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tetromino = getNextTetromino();
|
|
||||||
}
|
|
||||||
|
|
||||||
// show the game over screen
|
|
||||||
function showGameOver() {
|
|
||||||
cancelAnimationFrame(rAF);
|
|
||||||
gameOver = true;
|
|
||||||
|
|
||||||
context.fillStyle = 'black';
|
|
||||||
context.globalAlpha = 0.75;
|
|
||||||
context.fillRect(0, canvas.height / 2 - 30, canvas.width, 60);
|
|
||||||
|
|
||||||
context.globalAlpha = 1;
|
|
||||||
context.fillStyle = 'white';
|
|
||||||
context.font = '36px monospace';
|
|
||||||
context.textAlign = 'center';
|
|
||||||
context.textBaseline = 'middle';
|
|
||||||
context.fillText('GAME OVER!', canvas.width / 2, canvas.height / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
const canvas = document.getElementById('game');
|
|
||||||
const context = canvas.getContext('2d');
|
|
||||||
const grid = 32;
|
|
||||||
const tetrominoSequence = [];
|
|
||||||
|
|
||||||
// keep track of what is in every cell of the game using a 2d array
|
|
||||||
// tetris playfield is 10x20, with a few rows offscreen
|
|
||||||
const playfield = [];
|
|
||||||
|
|
||||||
// populate the empty state
|
|
||||||
for (let row = -2; row < 20; row++) {
|
|
||||||
playfield[row] = [];
|
|
||||||
|
|
||||||
for (let col = 0; col < 10; col++) {
|
|
||||||
playfield[row][col] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// how to draw each tetromino
|
|
||||||
// @see https://tetris.fandom.com/wiki/SRS
|
|
||||||
const tetrominos = {
|
|
||||||
'I': [
|
|
||||||
[0,0,0,0],
|
|
||||||
[1,1,1,1],
|
|
||||||
[0,0,0,0],
|
|
||||||
[0,0,0,0]
|
|
||||||
],
|
|
||||||
'J': [
|
|
||||||
[1,0,0],
|
|
||||||
[1,1,1],
|
|
||||||
[0,0,0],
|
|
||||||
],
|
|
||||||
'L': [
|
|
||||||
[0,0,1],
|
|
||||||
[1,1,1],
|
|
||||||
[0,0,0],
|
|
||||||
],
|
|
||||||
'O': [
|
|
||||||
[1,1],
|
|
||||||
[1,1],
|
|
||||||
],
|
|
||||||
'S': [
|
|
||||||
[0,1,1],
|
|
||||||
[1,1,0],
|
|
||||||
[0,0,0],
|
|
||||||
],
|
|
||||||
'Z': [
|
|
||||||
[1,1,0],
|
|
||||||
[0,1,1],
|
|
||||||
[0,0,0],
|
|
||||||
],
|
|
||||||
'T': [
|
|
||||||
[0,1,0],
|
|
||||||
[1,1,1],
|
|
||||||
[0,0,0],
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
// color of each tetromino
|
|
||||||
const colors = {
|
|
||||||
'I': 'cyan',
|
|
||||||
'O': 'yellow',
|
|
||||||
'T': 'purple',
|
|
||||||
'S': 'green',
|
|
||||||
'Z': 'red',
|
|
||||||
'J': 'blue',
|
|
||||||
'L': 'orange'
|
|
||||||
};
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
let tetromino = getNextTetromino();
|
|
||||||
let rAF = null; // keep track of the animation frame so we can cancel it
|
|
||||||
let gameOver = false;
|
|
||||||
|
|
||||||
// game loop
|
|
||||||
function loop() {
|
|
||||||
rAF = requestAnimationFrame(loop);
|
|
||||||
context.clearRect(0,0,canvas.width,canvas.height);
|
|
||||||
|
|
||||||
// draw the playfield
|
|
||||||
for (let row = 0; row < 20; row++) {
|
|
||||||
for (let col = 0; col < 10; col++) {
|
|
||||||
if (playfield[row][col]) {
|
|
||||||
const name = playfield[row][col];
|
|
||||||
context.fillStyle = colors[name];
|
|
||||||
|
|
||||||
// drawing 1 px smaller than the grid creates a grid effect
|
|
||||||
context.fillRect(col * grid, row * grid, grid-1, grid-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw the active tetromino
|
|
||||||
if (tetromino) {
|
|
||||||
|
|
||||||
// tetromino falls every 35 frames
|
|
||||||
if (++count > 35) {
|
|
||||||
tetromino.row++;
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
// place piece if it runs into anything
|
|
||||||
if (!isValidMove(tetromino.matrix, tetromino.row, tetromino.col)) {
|
|
||||||
tetromino.row--;
|
|
||||||
placeTetromino();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.fillStyle = colors[tetromino.name];
|
|
||||||
|
|
||||||
for (let row = 0; row < tetromino.matrix.length; row++) {
|
|
||||||
for (let col = 0; col < tetromino.matrix[row].length; col++) {
|
|
||||||
if (tetromino.matrix[row][col]) {
|
|
||||||
|
|
||||||
// drawing 1 px smaller than the grid creates a grid effect
|
|
||||||
context.fillRect((tetromino.col + col) * grid, (tetromino.row + row) * grid, grid-1, grid-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// listen to keyboard events to move the active tetromino
|
|
||||||
document.addEventListener('keydown', function(e) {
|
|
||||||
if (gameOver) return;
|
|
||||||
|
|
||||||
// left and right arrow keys (move)
|
|
||||||
if (e.which === 37 || e.which === 39) {
|
|
||||||
const col = e.which === 37
|
|
||||||
? tetromino.col - 1
|
|
||||||
: tetromino.col + 1;
|
|
||||||
|
|
||||||
if (isValidMove(tetromino.matrix, tetromino.row, col)) {
|
|
||||||
tetromino.col = col;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// up arrow key (rotate)
|
|
||||||
if (e.which === 38) {
|
|
||||||
const matrix = rotate(tetromino.matrix);
|
|
||||||
if (isValidMove(matrix, tetromino.row, tetromino.col)) {
|
|
||||||
tetromino.matrix = matrix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// down arrow key (drop)
|
|
||||||
if(e.which === 40) {
|
|
||||||
const row = tetromino.row + 1;
|
|
||||||
|
|
||||||
if (!isValidMove(tetromino.matrix, row, tetromino.col)) {
|
|
||||||
tetromino.row = row - 1;
|
|
||||||
|
|
||||||
placeTetromino();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tetromino.row = row;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// start the game
|
|
||||||
rAF = requestAnimationFrame(loop);
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
||||||
Reference in New Issue
Block a user