Public
Edited
Feb 19, 2024
Insert cell
Insert cell
Insert cell
Insert cell
(() => {

//////////////////////////////////////////////////////////////////////////////////////////////////////////
// HELPERS //
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
// KEYS //
//////////////////////////////////////////////////////////////////////////////////////////////////////////

const RIGHT_KEY_CODE = 68
const LEFT_KEY_CODE = 65
const UP_KEY_CODE = 87
const DOWN_KEY_CODE = 83
const keysPressed = {}
keysPressed[RIGHT_KEY_CODE] = false
keysPressed[LEFT_KEY_CODE] = false
keysPressed[UP_KEY_CODE] = false
keysPressed[DOWN_KEY_CODE] = false

function keyDown(e) {
if (e.keyCode in keysPressed) keysPressed[e.keyCode] = true;
}

function keyUp(e) {
if (e.keyCode in keysPressed) keysPressed[e.keyCode] = false;
}

document.addEventListener('keydown', keyDown, false)
document.addEventListener('keyup', keyUp, false)

//////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMAGES //
//////////////////////////////////////////////////////////////////////////////////////////////////////////

const img1 = new Image()
const img2 = new Image()
img1.src = FileAttachment("Instituto-de-Artes.svg")._url

const imgs = [img1, img2]
const rotations = [0, 90, 180, 270]

//////////////////////////////////////////////////////////////////////////////////////////////////////////
// DIMENSIONS //
//////////////////////////////////////////////////////////////////////////////////////////////////////////

console.log(container.getBoundingClientRect())
let { width, height } = container.getBoundingClientRect()
const canvas = document.getElementById('canvas')
const dpr = window.devicePixelRatio
width = Math.ceil(width * dpr)
height = Math.ceil(height * dpr)

canvas.width = width
canvas.height = height
canvas.style.width = `${width / dpr}px`
canvas.style.height = `${height / dpr}px`

const context = canvas.getContext('2d')
context.scale(dpr, dpr)
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// TILES //
//////////////////////////////////////////////////////////////////////////////////////////////////////////

const tileSize = 48 * 2
const nTiles = 200
const worldSize = tileSize * nTiles
const tilesPerLine = Math.floor(worldSize / tileSize)
const tileHalfSize = tileSize / 2
let playerX = worldSize / 2
let playerY = worldSize / 2
const tileGrid = []
const angles = []
const viewTileWidth = Math.floor(width / tileSize)
const viewTileHeight = Math.floor(height / tileSize)

for (let i = 0; i < tilesPerLine; i++) {
const column = []
for (let j = 0; j < tilesPerLine; j++) {
column.push(
[
imgs[0],
rotations[getRandomIntInclusive(0, 3)]
]
)
}
tileGrid.push(column)
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
// DRAWING //
//////////////////////////////////////////////////////////////////////////////////////////////////////////
function rotateAndPaintImage(context, image, angle, positionX, positionY, axisX, axisY) {
const angleInRad = angle * (Math.PI / 180)
context.translate(positionX, positionY)
context.rotate(angleInRad)
context.drawImage(image, -axisX, -axisY)
context.rotate(-angleInRad);
context.translate(-positionX, -positionY)
}

const speed = 12

async function animate() {

if (keysPressed[RIGHT_KEY_CODE]) {
playerX += speed
}

if (keysPressed[LEFT_KEY_CODE]) {
playerX += -speed
}

if (keysPressed[UP_KEY_CODE]) {
playerY += -speed
}

if (keysPressed[DOWN_KEY_CODE]) {
playerY += speed
}

const left = playerX - width / 2
const top = playerY - height / 2

let leftTile = Math.floor(left / tileSize)
let topTile = Math.floor(top / tileSize)

const tileOffsetX = left % tileSize
const tileOffsetY = top % tileSize

context.clearRect(0, 0, width, height)
for (let x = 0; x < viewTileWidth; x++) {
for (let y = 0; y < viewTileHeight; y++) {

let row = (leftTile + x + tileGrid.length) % tileGrid.length;
let col = (topTile + y + tileGrid[0].length) % tileGrid[0].length;

const tile = tileGrid[row][col]

rotateAndPaintImage(
context,
tile[0],
tile[1],
x * tileSize - tileOffsetX,
y * tileSize - tileOffsetY,
tileHalfSize,
tileHalfSize
)
}
}
window.requestAnimationFrame(animate)
}
animate()

return 'Instituto de Artes da UNB'

})()
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more