Last active
May 6, 2019 00:56
-
-
Save y2bd/97fa9e8975c78f69ed9920dcf05593f8 to your computer and use it in GitHub Desktop.
SCRIPT-8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// board specs | |
const BOARD_WIDTH = 10 | |
const BOARD_HEIGHT = 24 | |
const BOARD_X = 0 | |
const BOARD_Y = 0 | |
// board states | |
const EMPTY = 0 | |
const FULL = 1 | |
// blok specs | |
const BLOK_TYPES = 7 | |
const BLOK_SIZE = 4 | |
// game states | |
const CHOOSE = 0 | |
const CHOSEN = 1 | |
const FALL = 2 | |
const GROUND = 3 | |
const CLEAR = 4 | |
// FALL sub-state | |
const FALL_GRAV = 0 | |
const FALL_DROP = 1 | |
// DAS sub-states | |
const DAS_CHARGE = 300 | |
const DAS_NONE = 0 | |
const DAS_LEFT = 1 | |
const DAS_RIGHT = 2 | |
// game speed (ms) | |
const TURN_LENGTH = 200 | |
const GROUND_LIMIT = 500 | |
// bloks | |
const bloks = [ | |
// I | |
[[0,0,0,0], | |
[1,1,1,1], | |
[0,0,0,0], | |
[0,0,0,0]], | |
// T | |
[[0,1,0], | |
[1,1,1], | |
[0,0,0]], | |
// L | |
[[0,0,1], | |
[1,1,1], | |
[0,0,0]], | |
// J | |
[[1,0,0], | |
[1,1,1], | |
[0,0,0]], | |
// S | |
[[0,1,1], | |
[1,1,0], | |
[0,0,0]], | |
// Z | |
[[1,1,0], | |
[0,1,1], | |
[0,0,0]], | |
// 0 | |
[[0,0,0,0], | |
[0,1,1,0], | |
[0,1,1,0], | |
[0,0,0,0]] | |
] | |
const initialBoard = () => { | |
const board = [] | |
range(BOARD_HEIGHT).forEach(i => { | |
const row = [] | |
range(BOARD_WIDTH).forEach(j => row.push(EMPTY)) | |
board.push(row) | |
}) | |
return board | |
} | |
const drawBoard = board => { | |
range(BOARD_WIDTH).forEach(x => { | |
range(BOARD_HEIGHT).forEach(y => { | |
const square = board[y][x] | |
if (square === EMPTY) { | |
rectFill( | |
BOARD_X + BLOK_SIZE * x, | |
BOARD_Y + BLOK_SIZE * y, | |
BLOK_SIZE, | |
BLOK_SIZE, | |
4 | |
) | |
} else { | |
rectFill( | |
BOARD_X + BLOK_SIZE * x, | |
BOARD_Y + BLOK_SIZE * y, | |
BLOK_SIZE, | |
BLOK_SIZE | |
) | |
} | |
}) | |
}) | |
} | |
const chooseBlok = () => { | |
const blokChoice = Math.floor(Math.random() * BLOK_TYPES) | |
return bloks[blokChoice] | |
} | |
const cloneMatrix = matrix => { | |
return matrix.map(row => [...row]) | |
} | |
const insertIntoMatrix = (base, piece, lx, ly) => { | |
const baseWidth = base[0].length | |
const baseHeight = base.length | |
const pieceWidth = piece[0].length | |
const pieceHeight = piece.length | |
const result = cloneMatrix(base) | |
range(lx, lx + pieceWidth).forEach(x => { | |
range(ly, ly + pieceHeight).forEach(y => { | |
if (x < 0 || x >= baseWidth || y < 0 || y >= baseHeight) { | |
return | |
} | |
const square = piece[y - ly][x - lx] | |
if (square === EMPTY) { | |
return | |
} | |
result[y][x] = piece[y - ly][x - lx] | |
}) | |
}) | |
return result | |
} | |
const invalidInsert = (base, piece, lx, ly) => { | |
const baseWidth = base[0].length | |
const baseHeight = base.length | |
const pieceWidth = piece[0].length | |
const pieceHeight = piece.length | |
let invalid = false | |
range(lx, lx + pieceWidth).forEach(x => { | |
if (invalid === true) { | |
return | |
} | |
range(ly, ly + pieceHeight).forEach(y => { | |
if (invalid === true) { | |
return | |
} | |
const psquare = piece[y - ly][x - lx] | |
if (x < 0 || x >= baseWidth || y < 0 || y >= baseHeight) { | |
// basically, we can actually extend beyond the board if it's an empty space on the inserted | |
// but if we want to insert a solid piece beyond the board, then it's bad | |
if (psquare !== EMPTY) { | |
invalid = true | |
} | |
return | |
} | |
const bsquare = base[y][x] | |
if (bsquare !== EMPTY && psquare !== EMPTY) { | |
invalid = true | |
} | |
}) | |
}) | |
return invalid | |
} | |
const rotateMatrix = (piece, clockwise) => { | |
const width = piece[0].length | |
const height = piece.length | |
const result = cloneMatrix(piece) | |
range(width).forEach(x => { | |
range(height).forEach(y => { | |
const square = piece[y][x]; | |
if (clockwise) { | |
result[x][height-y+1] = square; | |
} else { | |
result[width-x+1][y] = square; | |
} | |
}) | |
}) | |
return result | |
} | |
const handleHorizontals = ({ | |
input, | |
elapsed, | |
nextDasMode, | |
nextDasCharge, | |
nextBlokX | |
}) => { | |
// first handle inputs | |
// don't let new inputs override old ones | |
if (input.left && !(input.right && nextDasMode === DAS_RIGHT)) { | |
if (nextDasMode === DAS_LEFT) { | |
nextDasCharge += elapsed | |
if (nextDasCharge > DAS_CHARGE) { | |
nextBlokX -= 1 | |
} | |
} else { | |
nextBlokX -= 1 | |
nextDasMode = DAS_LEFT | |
nextDasCharge = 0 | |
} | |
} else if (input.right && !(input.left && nextDasMode === DAS_LEFT)) { | |
if (nextDasMode === DAS_RIGHT) { | |
nextDasCharge += elapsed | |
if (nextDasCharge > DAS_CHARGE) { | |
nextBlokX += 1 | |
} | |
} else { | |
nextBlokX += 1 | |
nextDasMode = DAS_RIGHT | |
nextDasCharge = 0 | |
} | |
} else if (!input.left && !input.right) { | |
nextDasMode = DAS_NONE | |
nextDasCharge = 0 | |
} | |
return { nextDasMode, nextDasCharge, nextBlokX } | |
} | |
init = state => { | |
state.board = initialBoard() | |
state.gameState = CHOOSE | |
state.fallState = FALL_GRAV | |
state.turnElapsed = 0 | |
state.currentBlok = undefined | |
state.blokX = 4 | |
state.blokY = 0 | |
state.dasCharge = 0 | |
state.dasMode = DAS_NONE | |
state.groundTime = 0 | |
} | |
update = (state, input, elapsed) => { | |
let nextGameState = state.gameState | |
let nextBlokX = state.blokX | |
let nextBlokY = state.blokY | |
let nextBoard = state.board | |
let nextBlok = state.currentBlok | |
let nextDasCharge = state.dasCharge | |
let nextDasMode = state.dasMode | |
let nextGroundTime = state.groundTime | |
state.turnElapsed += elapsed | |
let endOfTurn = false | |
if (state.turnElapsed >= TURN_LENGTH) { | |
state.turnElapsed = 0 | |
endOfTurn = true | |
} | |
if (state.gameState === CHOOSE) { | |
nextBlok = chooseBlok() | |
nextBlokX = 4 | |
nextBlokY = 0 | |
nextGameState = CHOSEN | |
} else if (state.gameState === CHOSEN) { | |
//if (endOfTurn) { | |
nextGameState = FALL | |
//} | |
} else if (state.gameState === FALL) { | |
const nextH = handleHorizontals({ | |
input, | |
elapsed, | |
nextDasMode, | |
nextDasCharge, | |
nextBlokX | |
}) | |
nextDasMode = nextH.nextDasMode | |
nextDasCharge = nextH.nextDasCharge | |
nextBlokX = nextH.nextBlokX | |
// don't let us slide off the board | |
if (invalidInsert(state.board, nextBlok, nextBlokX, nextBlokY)) { | |
nextBlokX = state.blokX | |
} | |
// spins are pretty hard | |
if (input.aPressed) { | |
console.log("yay") | |
nextBlok = rotateMatrix(nextBlok, false) | |
} | |
// then handle falling | |
if (state.fallState === FALL_GRAV && endOfTurn) { | |
nextBlokY += 1 | |
} | |
// check if we're gonna fall too far | |
if ( | |
invalidInsert(state.board, nextBlok, nextBlokX, nextBlokY + 1) | |
) { | |
// TODO go to ground mode for ground spins | |
nextGameState = GROUND | |
nextGroundTime = 0 | |
} | |
} else if (state.gameState === GROUND) { | |
if (nextGroundTime >= GROUND_LIMIT) { | |
nextGameState = CHOOSE | |
nextBoard = insertIntoMatrix( | |
nextBoard, | |
nextBlok, | |
nextBlokX, | |
nextBlokY | |
) | |
} else { | |
const nextH = handleHorizontals({ | |
input, | |
elapsed, | |
nextDasMode, | |
nextDasCharge, | |
nextBlokX | |
}) | |
nextDasMode = nextH.nextDasMode | |
nextDasCharge = nextH.nextDasCharge | |
nextBlokX = nextH.nextBlokX | |
// don't let us slide off the board | |
if (invalidInsert(state.board, nextBlok, nextBlokX, nextBlokY)) { | |
nextBlokX = state.blokX | |
} | |
if (nextBlokX === state.blokX) { | |
nextGroundTime += elapsed | |
} else { | |
nextGroundTime = 0 | |
} | |
// check if we can start falling again | |
if ( | |
!invalidInsert(state.board, nextBlok, nextBlokX, nextBlokY + 1) | |
) { | |
// TODO go to ground mode for ground spins | |
nextGameState = FALL | |
} | |
} | |
} | |
if (nextGameState !== state.gameState) { | |
state.turnElapsed = 0 | |
state.gameState = nextGameState | |
} | |
state.blokX = nextBlokX | |
state.blokY = nextBlokY | |
state.board = nextBoard | |
state.currentBlok = nextBlok | |
state.dasCharge = nextDasCharge | |
state.dasMode = nextDasMode | |
state.groundTime = nextGroundTime | |
} | |
draw = state => { | |
clear() | |
const { | |
board, | |
currentBlok, | |
blokX, | |
blokY | |
} = state | |
const currentBoard = insertIntoMatrix(board, currentBlok, blokX, blokY) | |
drawBoard(currentBoard) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"iframeVersion": "0.1.254", | |
"lines": [ | |
74, | |
41, | |
87, | |
0, | |
0, | |
0, | |
41, | |
154 | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"0": [ | |
" 0 ", | |
" ", | |
" 1 ", | |
" 1 0", | |
"0 1 ", | |
" 1 ", | |
" ", | |
" 0 " | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment