xxxxxxxxxx
471
let scene = 1; // Set the initial scene to 1
let keyPressUp = false;
let keyPressDown = false;
let keyPressLeft = false;
let keyPressRight = false;
var shapeList = [
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], // I
[0, 2, 0, 0, 2, 0, 0, 2, 2], // L
[0, 3, 0, 0, 3, 0, 3, 3, 0], // J
[4, 4, 0, 0, 4, 4, 0, 0, 0], // Z
[0, 5, 5, 5, 5, 0, 0, 0, 0], // S
[0, 0, 0, 6, 6, 6, 0, 6, 0], // T
[7, 7, 7, 7], // O
];
var palletteMono = [];
var pallette = [
[255, 255, 255], // 0, void
[255, 224, 0], // 1 Yellow
[255, 32, 0], // 2 Red
[32, 255, 0], // 3 Green
[16, 128, 255], // 4 Blue
[255, 96, 16], // 5 Orange
[0, 196, 255], // 6 Light Blue
[128, 0, 255], // 7 Purple
];
let tetrisCanvas; // Tetris canvas
let tetris; // Tetris game object
function setup() {
createCanvas(540, 960); // Set canvas size to 540x960 pixels
// Initialize Tetris canvas
tetrisCanvas = createGraphics(300, 600); // Create a separate canvas for Tetris
tetrisCanvas.background(0); // Set background color of Tetris canvas
tetrisCanvas.position(120, 180); // Position Tetris canvas within the main canvas
// Initialize Tetris game
tetris = new Tetris(10, 20); // Create Tetris game object
frameRate(60);
palletteMono = [];
for (let i = 0; i < pallette.length; i++) {
let rgb = pallette[i];
let gray = rgb[0] + rgb[1] + rgb[2];
palletteMono[i] = [];
palletteMono[i][0] = 255 * gray;
palletteMono[i][1] = 255 * gray;
palletteMono[i][2] = 255 * gray;
}
}
function draw() {
background(0);
function mainMenu() {
// Display current scene content
if (scene === 1) {
mainMenu();
} else if (scene === 2) {
gameScene();
}
// Transition between scenes
if (transitionProgress > 0) {
transitionProgress -= 0.02; // Adjust the speed of transition
yOffset = height * transitionProgress;
drawTransition();
}
}
function gameScene() {
// Draw game scene background image
image(gameSceneImage, 0, 0, width, height);
// Draw Tetris canvas
image(tetrisCanvas, 120, 180);
}
function keyPressed() {
// Handle key events for Tetris game
tetrisKeyPressed();
}
function keyReleased() {
// Handle key events for Tetris game
tetrisKeyReleased();
}
function tetrisKeyPressed() {
if (keyCode == 32) tetris.pause = !tetris.pause;
if (keyCode == 13) tetris.restart = true;
if (keyCode === UP_ARROW) keyPressUp = true;
if (keyCode === DOWN_ARROW) keyPressDown = true;
if (keyCode === LEFT_ARROW) keyPressLeft = true;
if (keyCode === RIGHT_ARROW) keyPressRight = true;
applyInput(200);
}
function tetrisKeyReleased() {
if (keyCode === UP_ARROW) keyPressUp = false;
if (keyCode === DOWN_ARROW) keyPressDown = false;
if (keyCode === LEFT_ARROW) keyPressLeft = false;
if (keyCode === RIGHT_ARROW) keyPressRight = false;
}
class Tetris {
constructor(nx, ny) {
this.tGrid = new TGrid(nx, ny);
this.timer = new Timer();
this.restartGame();
this.shapeNext = undefined;
this.pickNextShape();
}
restartGame() {
this.tGrid.clearGrid();
this.restart = false;
this.pause = false;
this.gameOver = false;
this.spawn = true;
this.rotate = false;
this.tx = this.ty = 0;
this.level = 1;
this.rowsPerLevel = 5;
this.rowsCompleted = 0;
this.shapesCount = 0;
this.timer.reset(600);
}
pickNextShape() {
this.shapeCurr = this.shapeNext;
var indexNext = parseInt(random(shapeList.length));
this.shapeNext = shapeList[indexNext].slice();
}
update() {
if (this.restart) {
this.restartGame();
}
if (this.pause) {
return;
}
// Spawn new shape
if (this.spawn) {
this.pickNextShape();
this.tGrid.setShape(this.shapeCurr);
this.shapesCount++;
this.spawn = false;
}
// Update level/rows/difficulty
this.level += floor(this.rowsCompleted / this.rowsPerLevel);
this.rowsCompleted %= this.rowsPerLevel;
this.timer.duration = ceil(800 / sqrt(this.level));
// Game over check
this.gameOver = this.tGrid.collision(0, 0);
if (this.gameOver) {
return;
}
// Apply user input: transforms
if (this.rotate) this.tGrid.rotate = true;
if (!this.tGrid.collision(this.tx, 0)) this.tGrid.tx = -1;
if (!this.tGrid.collision(0, this.ty)) this.tGrid.ty = +1;
// Apply game step
if (this.timer.updateStep()) {
if (!this.tGrid.collision(0, 1)) {
if (this.tGrid.ty == 0) {
this.tGrid.sy++;
}
} else {
this.tGrid.splatShape();
this.rowsCompleted += this.tGrid.updateRows();
this.spawn = true;
}
}
// Reset transforms
this.rotate = false;
this.tx = this.ty = 0;
}
display(canvas) {
var off, x, y, w, h, cell;
var canvasW = canvas.width;
var canvasH = canvas.height;
off = 40;
h = canvasH - 2 * off;
w = canvasW - 2 * off;
cell = ceil(Math.min(w / this.tGrid.nx, h / this.tGrid.ny));
w = this.tGrid.nx * cell;
h = this.tGrid.ny * cell;
x = parseInt((canvasW - w) / 2.0);
y = parseInt((canvasH - h) / 2.0);
canvas.strokeWeight(1);
canvas.stroke(0);
canvas. noFill;
canvas.rect(x - 4, y - 4, w + 8, h + 8);
// Game screen
var colors = this.pause || this.gameOver ? palletteMono : pallette;
this.displayGrid(canvas, x, y, w, h, colors);
// Shape preview
{
var _w = x - 2 * off;
var _h = canvasH - 2 * off;
var _y = off;
var _x = off + x + w;
this.displayNextShape(canvas, _x, _y, _w, _h);
}
{
var ty = canvasH / 2 - 150;
var tx1 = x + w + x / 2;
var txtLevel = "LEVEL " + this.level;
var txtProgress = "ROW " + this.rowsCompleted + "/" + this.rowsPerLevel;
var txtShapes = "SHAPE " + this.shapesCount;
canvas.textAlign(CENTER, CENTER);
canvas.noStroke();
// Set text color to white
canvas.fill(0); // White
// Set text size and make it bold
canvas.textSize(24);
canvas.textStyle(BOLD);
canvas.text(txtLevel, tx1, ty);
canvas.textSize(16);
canvas.text(txtProgress, tx1, (ty += 24));
canvas.text(txtShapes, tx1, (ty += 16));
}
// Game status
var txtGameStatus = undefined;
if (this.gameOver) txtGameStatus = "GAME OVER";
if (this.pause) txtGameStatus = "PAUSE";
if (txtGameStatus !== undefined) {
canvas.textSize(30);
canvas.textAlign(CENTER, CENTER);
canvas.noStroke();
canvas.fill(0, 0, 0);
canvas.text(txtGameStatus, canvasW / 2 + 2, canvasH / 2 + 1);
canvas.fill(255, 224, 0);
canvas.text(txtGameStatus, canvasW / 2, canvasH / 2);
}
}
displayGrid(pg, x, y, w, h, pallette) {
var nx = this.tGrid.nx;
var ny = this.tGrid.ny;
var cw = w / nx;
var ch = h / ny;
// BG
pg.noFill();
for (var gy = 0; gy < ny; gy++) {
for (var gx = 0; gx < nx; gx++) {
var cx = x + gx * cw;
var cy = y + gy * ch;
pg.stroke(44);
if ((gx & 1) == 1) {
pg.fill(66);
} else {
pg.fill(77);
}
pg.rect(cx, cy, cw, ch);
}
}
// FG
for (var gy = 0; gy < ny; gy++) {
for (var gx = 0; gx < nx; gx++) {
var cx = x + gx * cw;
var cy = y + gy * ch;
var valGrid = this.tGrid.getGridVal(gx, gy);
if (valGrid > 0) {
pg.stroke(0);
var rgb = pallette[valGrid % pallette.length];
pg.fill(rgb[0], rgb[1], rgb[2]);
pg.rect(cx, cy, cw, ch);
}
}
}
// Shape
var ks = this.tGrid.shapeSize;
var kr = ceil(this.tGrid.shapeSize / 2.0);
for (var ky = 0; ky < ks; ky++) {
for (var kx = 0; kx < ks; kx++) {
var gx = this.tGrid.sx + kx - kr;
var gy = this.tGrid.sy + ky - kr;
var cx = x + gx * cw;
var cy = y + gy * ch;
var valShape = this.tGrid.getShapeVal(kx, ky);
if (valShape != 0) {
pg.stroke(0);
var rgb = pallette[valShape % pallette.length];
pg.fill(rgb[0], rgb[1], rgb[2]);
pg.rect(cx, cy, cw, ch);
}
}
}
}
displayNextShape(pg, x, y, w, h) {
var shape = this.shapeNext;
var shapeSize = parseInt(sqrt(shape.length));
var ks = shapeSize;
var kr = shapeSize / 2.0;
var cw = min(w / 5.0, h / 5.0);
var ch = cw;
for (var ky = 0; ky < ks; ky++) {
for (var kx = 0; kx < ks; kx++) {
var gx = kx - kr;
var gy = ky - kr;
var cx = x + gx * cw + w / 2.0;
var cy = y + gy * ch + h / 2.0;
cx = parseInt(cx);
cy = parseInt(cy);
var valShape = shape[ky * shapeSize + kx];
if (valShape != 0) {
pg.fill(200);
} else {
pg.fill(32);
}
pg.stroke(64);
pg.rect(cx, cy, cw, ch);
}
}
}
}
class Timer {
constructor() {
this.duration = 600;
this.time = 0;
}
reset(duration) {
this.setTime();
this.duration = duration;
}
setTime() {
this.time = millis();
}
getTime() {
return millis() - this.time;
}
updateStep() {
if (this.getTime() >= this.duration) {
this.setTime();
return true;
}
return false;
}
}
class TGrid {
constructor(nx, ny) {
this.nx = nx;
this.ny = ny;
this.grid = [];
this.grid.length = nx * ny;
this.clearGrid();
this.setShape([0]);
}
clearGrid() {
for (var i = 0; i < this.grid.length; i++) {
this.grid[i] = 0;
}
}
isInsideGrid(x, y) {
return x >= 0 && x < this.nx && y >= 0 && y < this.ny;
}
setShape(shape) {
this.shape = shape;
this.shapeSize = parseInt(sqrt(shape.length));
this.sx = ceil(this.nx / 2);
this.sy = ceil(this.shapeSize / 2);
}
getGridVal(x, y) {
if (!this.isInsideGrid(x, y)) {
return -1;
} else {
return this.grid[y * this.nx + x];
}
}
setGridVal(x, y, val) {
this.grid[y * this.nx + x] = val;
}
getShapeVal(x, y) {
return this.shape[y * this.shapeSize + x];
}
rotateShapeDir(CW) {
var size = this.shapeSize;
var cpy = this.shape.slice(0);
if (CW) {
var ib = 0;
for (var a = size - 1; a >= 0; a--) {
for (var b = 0; b < size; b++) {
this.shape[ib++] = cpy[size * b + a];
}
}
} else {
var ib = 0;
for (var a = 0; a < size; a++) {
for (var b = size - 1; b >= 0; b--) {
this.shape[ib++] = cpy[size * b + a];
}
}
}
}
getGridDimX() {
return this.nx;
}
getGridDimY() {
return this.ny;
}
collision(tx, ty) {
var ks = this.shapeSize;
var kr = ks / 2.0;
var nx = this.nx;
var ny = this.ny;
var shape = this.shape;
for (var ky = 0; ky < ks; ky++) {
for (var kx = 0; kx < ks; kx++) {
var gx = this.sx + kx - kr + tx;
var gy = this.sy + ky - kr + ty;
var valShape = this.getShapeVal(kx, ky);
if (valShape != 0) {
if (!this.isInsideGrid(gx, gy)) return true;
if (this.getGridVal(gx, gy) != 0) return true;
}
}
}
return false;
}
updateRows() {
var ny = this.ny;
var nx = this.nx;
var countRows = 0;
for (var gy = 0; gy < ny; gy++) {
var complete = true;
for (var gx = 0; gx < nx; gx++) {
if (this.getGridVal(gx, gy) == 0) {
complete = false;
break;
}
}
if (complete) {
countRows++;
for (var gy2 = gy; gy2 > 0; gy2--) {
for (var gx = 0; gx < nx; gx++) {
this.setGridVal(gx, gy2, this.getGridVal(gx, gy2 - 1));
}
}
for (var gx = 0; gx < nx; gx++) {
this.setGridVal(gx, 0, 0);
}
}
}
return countRows;
}
splatShape() {
var ks = this.shapeSize;
var kr = ks / 2.0;
var nx = this.nx;
var ny = this.ny;
var shape = this.shape;
for (var ky = 0; ky < ks; ky++) {
for (var kx = 0; kx < ks; kx++) {
var gx = this.sx + kx - kr;
var gy = this.sy + ky - kr;
var valShape = this.getShapeVal(kx, ky);
if (valShape != 0) {
this.setGridVal(gx, gy, valShape);
}
}
}
}
}
}