Гладкая точка на дисплее 5х5, как избежать эффекта лестничной клетки?

Я недавно получил BBC-Micro: бит, и у него есть небольшой светодиодный дисплей 5x5.

Я хочу сделать код, который рисует плавные движущиеся точки без эффекта лестницы, но я изо всех сил стараюсь сделать его вертикально и горизонтально сглаженным при движении.

Это то, что у меня есть, оно только сглаживает точку по вертикали:

while (true) {
    basic.clearScreen()
    plotAA(input.acceleration(Dimension.X), input.acceleration(Dimension.Y),
        255, 255)
    basic.pause(15)
}

function plotAA(_x: number, _y: number, _brightness: number, _scale: number) {

    /* 
    * Draw a dot without "staircase effect"/aliasing.
    * _x           : from 0 to 4 but in _scale scale
    * _y           : from 0 to 4 but in _scale scale
    * _brightness  : led brightness
    * 
    * Half of _scale is a number of [0,0] pixel center
    */

    // Keep in mind that numbers are 32 bit signed integers!

    let px = (_x + _scale) % _scale * 2 // subpixel x position
    let py = (_y + _scale) % _scale * 2 // subpixel y position

    // It should be _x / _scale, but to fix a bug I use this...
    let rx = (_x + _scale) / _scale - 1 // real x position (ceil)
    let ry = (_y + _scale) / _scale - 1 // real y position (ceil)

    led.plotBrightness(rx, ry, ((_scale - py) + /* Add something here? */0) * _brightness / _scale)
    led.plotBrightness(rx + 1, ry, ((_scale - py)) * _brightness / _scale)
    led.plotBrightness(rx, ry + 1, (py) * _brightness / _scale)
    led.plotBrightness(rx + 1, ry + 1, (py) * _brightness / _scale)
}

Чтобы проверить этот код, используйте https://makecode.microbit.org/ (выберите JavaScript вверху).

Как заставить его двигаться плавно по вертикали и по горизонтали одновременно?

1 ответ

Решение

Я думаю, что могу рассчитать расстояние между 4 светодиодами и выбранной точкой. В зависимости от их расстояния я могу установить яркость светодиодов. Это самый точный способ сделать это, насколько я знаю.

РЕДАКТИРОВАТЬ: Решено.

// numbers are 32bit signed integers!

while (true) {
    basic.pause(30)
    basic.clearScreen()
    plotAA(input.acceleration(Dimension.X) + 255 * 2, input.acceleration(Dimension.Y) + 255 * 2, 255, 255)
    //plotAAY(255 * 2, input.acceleration(Dimension.Y) + 255 * 2, 255, 255)
    //plotAAX(input.acceleration(Dimension.X) + 255 * 2, 255 * 2, 255, 255)
}

function plotAAX(_x: number, _y: number, _brightness: number, _scale: number) {
    let vertical = false;

    /* 
    * Draw a dot without "staircase effect"/aliasing.
    * _x           : from 0 to 4 but in _scale scale
    * _y           : from 0 to 4 but in _scale scale
    * _brightness  : led brightness
    * 
    * Half of _scale is a number of pixel center
    */

    let px = (_x + _scale) % _scale * 2 // subpixel x position

    let rx = (_x + _scale) / _scale - 1 // real x position (ceil)
    let ry = (_y + _scale) / _scale - 1 // real y position (ceil)

    led.plotBrightness(rx, ry, (_scale - px) * _brightness / _scale)
    led.plotBrightness(rx + 1, ry, px * _brightness / _scale)
}

function plotAAY(_x: number, _y: number, _brightness: number, _scale: number) {
    /* 
    * Draw a dot without "staircase effect"/aliasing.
    * _x           : from 0 to 4 but in _scale scale
    * _y           : from 0 to 4 but in _scale scale
    * _brightness  : led brightness
    * 
    * Half of _scale is a number of pixel center
    */

    let py = (_y + _scale) % _scale * 2 // subpixel y position

    let rx = (_x + _scale) / _scale - 1 // real x position (ceil)
    let ry = (_y + _scale) / _scale - 1 // real y position (ceil)

    led.plotBrightness(rx, ry, (_scale - py) * _brightness / _scale)
    led.plotBrightness(rx, ry + 1, py * _brightness / _scale)
}

function plotAA(_x: number, _y: number, _brightness: number, _scale: number) {

    /* 
    * Draw a dot without "staircase effect"/aliasing.
    * _x           : from 0 to 4 but in _scale scale
    * _y           : from 0 to 4 but in _scale scale
    * _brightness  : led brightness
    * 
    * Half of _scale is a number of pixel center
    */

    let px = (_x + _scale) % _scale // subpixel x position
    let py = (_y + _scale) % _scale // subpixel y position
    // -(half of scale) to (half of scale)

    let rx = (_x + _scale) / _scale - 1 // real x position (ceil)
    let ry = (_y + _scale) / _scale - 1 // real y position (ceil)

    led.plotBrightness(rx, ry, Math.max(_scale - distance(0, 0, px, py), 0) * _brightness / _scale)
    led.plotBrightness(rx, ry + 1, Math.max(_scale - distance(0, _scale, px, py), 0) * _brightness / _scale)
    led.plotBrightness(rx + 1, ry, Math.max(_scale - distance(_scale, 0, px, py), 0) * _brightness / _scale)
    led.plotBrightness(rx + 1, ry + 1, Math.max(_scale - distance(_scale, _scale, px, py), 0) * _brightness / _scale)
}

function distance(_1x: number, _1y: number, _2x: number, _2y: number) {
    _1x -= _2x
    _1y -= _2y
    return Math.sqrt(_1x * _1x + _1y * _1y)
}

Я подправлю это чуть позже.

Другие вопросы по тегам