Skip to content

Instantly share code, notes, and snippets.

@y2bd
Last active May 5, 2019 22:30
Show Gist options
  • Save y2bd/1fbe926bc902182d71b29477a692b59a to your computer and use it in GitHub Desktop.
Save y2bd/1fbe926bc902182d71b29477a692b59a to your computer and use it in GitHub Desktop.
SCRIPT-8
// 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
// 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
}
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
}
update = (state, input, elapsed) => {
let nextGameState = state.gameState
let nextBlokX = state.blokX
let nextBlokY = state.blokY
let nextBoard = state.board
let nextDasCharge = state.dasCharge
let nextDasMode = state.dasMode
state.turnElapsed += elapsed
let endOfTurn = false
if (state.turnElapsed >= TURN_LENGTH) {
state.turnElapsed = 0
endOfTurn = true
}
if (state.gameState === CHOOSE) {
state.currentBlok = chooseBlok()
nextBlokX = 4
nextBlokY = 0
nextGameState = CHOSEN
} else if (state.gameState === CHOSEN) {
if (endOfTurn) {
nextGameState = FALL
}
} else if (state.gameState === FALL) {
// 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
}
} else if (input.right && !(input.left && nextDasMode === DAS_LEFT)) {
if (nextDasMode === DAS_RIGHT) {
nextDasCharge += elapsed
if (nextDasCharge > DAS_CHARGE) {
nextBlokX -= 1
}
} else {
nextBlokX -= 1
}
}
// don't let us slide off the board
if (invalidInsert(state.board, state.currentBlok, nextBlokX, nextBlokY)) {
nextBlokX = state.blokX
}
// then handle falling
if (state.fallState === FALL_GRAV && endOfTurn) {
nextBlokY += 1
}
// check if we're gonna fall too far
if (invalidInsert(state.board, state.currentBlok, nextBlokX, nextBlokY + 1)) {
// TODO go to ground mode for ground spins
nextGameState = CHOOSE
nextBoard = insertIntoMatrix(nextBoard, state.currentBlok, nextBlokX, nextBlokY)
}
}
state.gameState = nextGameState
state.blokX = nextBlokX
state.blokY = nextBlokY
state.board = nextBoard
state.dasCharge = nextDasCharge
state.dasMode = nextDasMode
}
draw = state => {
clear()
const {
board,
currentBlok,
blokX,
blokY
} = state
const currentBoard = insertIntoMatrix(board, currentBlok, blokX, blokY)
drawBoard(currentBoard)
}
{
"iframeVersion": "0.1.254",
"lines": [
73,
41,
67,
0,
0,
0,
0,
107
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment