Egy képekre épülő board darabjai, mint a Teletype BBS TTG Klubház külseje: olvasható YAML-ben tartott rajzok, a modern arcon 256 színű ANSI-val, a Commodore 64-arcon nyers PETSCII-vel rajzolva; kurzoros menü a C64-es képen; widgetek, amelyek hotspotjai a board életét mutatják; és a napszak meg az évszak a kép rétegeinek kiválasztásához. A 0.30.0 óta érhető el; minden osztály benne van az API-referenciában.
| Darab | Mit csinál |
|---|---|
BBS::Petscii::Canvas |
A C64 képernyője 40×25 cellaként a nagybetűs/grafikus készletben, nyers PETSCII-ként ki: egy teljes kép, aztán foltok |
BBS::Art |
YAML-rajz: karakterek, színek, reverse, hátterek, hotspotok, rétegek; ki ANSI-ra, FrameBufferre vagy Canvasra |
BBS::Petscii::CanvasMenu |
A BBS::Selector billentyűi és elemei Canvasra rajzolva |
BBS::Widgets::Scene |
Egy Art widgetként a modern arcon, a hotspotjai adatból kitöltve |
BBS::Season |
Hajnal, nappal, alkony vagy éjjel a nap szerint; hó, tök, tűzijáték, zászlófüzér |
art-preview |
Ellenőrzi és megmutatja a rajzot: ANSI, PETSCII-bájtok, C64-képernyőkép |
A C64-nek két karakterkészlete van. A kisbetűsben, amelyet a session.petscii! és a BBS::Petscii::Screen beszél, mindkét betűméret megvan, de grafika nincs. A nagybetűsben vannak a kártyaszínek, golyók, lekerekített sarkok, átlók és negyedblokkok, ezért a kép ott készül. A BBS::Petscii::Canvas cellákként tartja a képernyőt és nyers PETSCII-t ír, amely a session.write_raw-val megy ki, a kisbetűs enkóder mellett:
C = BBS::Petscii::Canvas
canvas = C.new
canvas.text(0, 1, 'TTG CLUBHOUSE', :yellow)
canvas.text(2, 1, '╭──╮', :light_blue)
canvas.text(3, 1, '█▀▀█', :orange) # reversed glyphs work too
session.write_raw(canvas.frame) # the whole screen
before = canvas.dup
canvas.text(2, 2, '●', :red)
session.write_raw(canvas.update(before)) # a patch: only the cell that changed
Canvas::GLYPHS); a █ ▀ ▐ ◢ ◣ fordított kódok (GLYPHS_REVERSED). A Canvas.glyph?(ch) megmondja, meg tudja-e mutatni a készlet a karaktert.Canvas::YELLOW), nevek (:light_blue, 'dark grey'), vagy az 1.0.0 óta a paletta színei is: Canvas.color(YE) == Canvas::YELLOW, így ugyanazok a BBS::Petscii::Colors konstansok szolgálnak ki egy Screent és egy vásznat.╭╮╰╯) ebben a nagybetűs készletben a Petscii::ROUNDED_CORNERS, és a negyedblokkokat (▖▗▘▝▚) is megrajzolja; egy Screen kisbetűs készlete a sarkokat szögletesen mutatja.frame egyszer küldi el a képernyőt, minden sort az utolsó látható cellája után vágva; a span(row, col, width) egy sor egy szakaszát; a patch(positions) szétszórt cellákat, a kurzor a legközelebbihez lépve; az update(before) a folt és a teljes kép közül az olcsóbbat. Lassú vonalon cél: kb. 1,2 KB egy képernyő, 200 bájt alatt egy animációs lépés.feed(bytes) úgy játssza rá a PETSCII-t a vászonra, ahogy a C64 képernyőszerkesztője kiírja: tesztben az, amit a hívó lát a bájtjaid után (a canvas.changes(seen) üres, ha egyeznek).A vászon a TTG Gate BBS-ből jött; a bájtjai ugyanazok, mint a gate saját osztályáéi voltak.
A rajz szöveg, kódként írjuk és nézzük át. A chars a kép, a colors cellánként egy palettabetű (. = nincs szín), a reverse opcionális R-ek, a background opcionális (csak cp437: a félblokk második színe), a hotspots a cellák, amelyeket a board az adataiból tölt ki, a layers a ráhelyezhető további fájlok. Minden sor pontosan size[0] széles, a sorvégi szóközökkel együtt. A rácsokat |2-vel írd: behúzásjelző nélkül a YAML az első sorból veszi a behúzást, és a szóközzel kezdődő sor szétveri a blokkot.
PETSCII-rajz a C64-arcra:
# art/house.yml
size: [20, 6]
charset: petscii-upper # only glyphs the uppercase set shows
palette: # C64 colour names, 256-colour indexes or '#rrggbb'
y: yellow
r: red
b: brown
g: dark grey
w: white
chars: |2
◢████◣ ●
◢██████◣
│ ▒ ▒ │
│ ▒ █ │ TTG
▁▁▁▁│▁▁▁▁█▁│▁▁▁▁▁▁▁
colors: |2
.....rrrrrr....y....
....rrrrrrrr........
....b.y..y.b........
....b.y..b.b..www...
ggggbggggbgbggggggg.
....................
hotspots:
window_1: [6, 2] # [col, row], 0-based
window_2: [9, 2]
sign: [14, 3, 3, 1] # [col, row, width, height]
layers: [snow] # art/snow.yml
Egy réteg: a szóköz átlátszó, az at helyezi el, a palettája és a hotspotjai hozzáadódnak a rajzéhoz.
# art/snow.yml: a layer; spaces are transparent, 'at' places it
size: [10, 1]
at: [4, 0]
palette:
w: white
chars: |2
▄▄▄▄▄▄
colors: |2
.wwwwww...
cp437-rajz a modern arcra, hátterekkel:
size: [24, 4]
charset: cp437
palette: { y: yellow, o: 208, n: '#203060', w: white }
chars: |2
╔══════════════════════╗
║ ▄▀▀▄ TTG CLUBHOUSE ☼ ║
║ ▀▄▄▀ open tonight ║
╚══════════════════════╝
colors: |2
oooooooooooooooooooooooo
oyyyyywwwwwwwwwwwwwwwyyo
oyyyyyyyyyyyyyyyyyyyyyyo
oooooooooooooooooooooooo
background: |2
........................
.nnnnnnnnnnnnnnnnnnnnnn.
.nnnnnnnnnnnnnnnnnnnnnn.
........................
hotspots:
tonight: [8, 2, 13, 1]
Használat:
house = BBS::Art.load('art/house.yml').with(*BBS::Season.now.layers) # only the layers it lists
session.write(house.ansi) # modern: 256-colour ANSI lines
house.draw(frame, x: 1, y: 2) # … or into a BBS::FrameBuffer
session.write_raw(house.petscii) # C64: a whole frame
house.draw_canvas(canvas, row: 1, col: 10) # … or onto a canvas
house.hotspot(:window_1) # => Art::Hotspot col=6 row=2 …
A with csak a fájlban felsorolt rétegeket rakja rá, így a with(*season.layers) bármely rajznál biztonságos. A hiba BBS::Art::Error-t dob a fájl, a rács, a sor és az oszlop nevével: rossz szélességű sor, a palettában nem szereplő betű, a karakterkészletben nem megjeleníthető jel, a rajzon kívüli hotspot. A palettaszínek C64-nevek, 256-os indexek vagy #rrggbb; mindegyikhez a másik arc legközelebbi színe tartozik, így a PETSCII-rajz ANSI-ban is megnézhető, és fordítva.
A BBS::Petscii::CanvasMenu egy vászonra rajzoló BBS::Selector: ugyanazok az elemek, billentyűk és opciók (CRSR, RETURN, az elem betűje, RUN/STOP vagy ← vissza, számok, oszlopok, lapok, az about- és a hint-sor), a kiválasztott elem fordított sáv a saját színében. Minden lépés a megváltozott cellák foltjaként megy ki: egy 16 elemes, kétoszlopos menüben kb. 140 bájt.
S = BBS::Selector
items = [S.item('CORK BOARD', key: 'm', value: :boards, color: :light_blue, about: 'READ AND POST'),
S.item('GAMES ROOM', key: 'r', value: :doors, color: :orange),
S.item('LEAVE', key: 'q', value: :quit)]
menu = BBS::Petscii::CanvasMenu.new(session, items, canvas: canvas, row: 12, col: 1, width: 36,
columns: 2, hint: 'CRSR: CHOOSE RETURN: OPEN', idle: 0.5) do
smoke.step(canvas) # bytes for an animation step while the caller thinks
end
menu.paint
session.write_raw(canvas.frame) # the picture with the menu on it
choice = menu.run(drawn: true) # without drawn: it paints and sends its rows itself
Az idle: másodperccel és egy blokkal a blokk akkor fut, amíg a hívó gondolkodik, és egy animációs lépés bájtjait adja vissza; egy leütés azonnal véget vet a várakozásnak.
A menü színszerepei a Selectoréi, a BBS::Selector::COLORS (text key bar heading about hint), amelyeket a vásznon C64-kódokká alakít; a colors: ezek közül írhat felül néhányat. (A CanvasMenu::COLORS az 1.0.0-ban megszűnt.)
A BBS::Widgets::Scene egy rajz widgetként: a rajz, majd minden hotspot a blokkjával kitöltve minden renderkor. A blokk Stringet ad (ANSI-színekkel, magasabb hotspotnál sorokkal) vagy nil-t, ha marad a rajz; amit visszaad, a hotspotjára vágódik.
scene = BBS::Widgets::Scene.new(art: house, align: :center)
scene.fill(:window_1) { node_busy?(1) ? "\e[38;5;220m▓" : nil }
scene.fill(:sign) { |spot| "\e[1;37m#{inside_count}".ljust(spot.width) }
A rajznál kisebb terminálon a jelenet a határaira vágódik; crop: false-szal semmit sem rajzol, és a fits? megmondja egy dashboardnak, mutassa-e egyáltalán a képet.
A BBS::Season.now(tz: 'Europe/Budapest', at: Time.now, jam: nil) megadja a napszakot a nap állása szerint (a :dawn és a :dusk a napkelte és napnyugta körüli 45-45 perc, a latitude: és longitude: helyre számolva, alapból Budapest), az évszakot és az érvényes rétegeket:
| Réteg | Mikor |
|---|---|
:snow |
decembertől februárig |
:pumpkin |
október 24–31. |
:fireworks |
december 31., és újév napján 6:00-ig |
:bunting |
a jam: napjain (Date-ek Range-e) |
s = BBS::Season.now(jam: Date.new(2027, 1, 8)..Date.new(2027, 1, 10))
s.time_of_day # => :night
s.layers # => [:snow]
art = BBS::Art.load("art/house_#{s.night? ? 'night' : 'day'}.yml").with(*s.layers)
Tiszta függvény: a teszt átadja az at:-et. Az EU-s időzónák és a fix eltolások ('+01:00') más gem nélkül működnek; más IANA-névhez a tzinfo kell.
A gem futtatható programja (bundle exec art-preview, vagy rubbs-checkoutban bin/art-preview) a rajz ellenőrzésére rajzolás közben:
art-preview art/house.yml # ANSI here, then size, palette, hotspots, PETSCII bytes
art-preview art/house.yml -l snow -s # a layer stacked, the hotspots marked
art-preview art/house.yml --hex # the PETSCII frame as a hex dump
art-preview art/house.yml --petscii h.seq # the raw frame, e.g. for a C64 terminal program
art-preview art/house.yml --png h.png # a C64 screenshot of the frame (VICE's character ROM)
A --png a PETSCII-képet egy vászonra játssza, és a VICE által telepített C64-karakter-ROM-mal rajzolja ki (más ROM: --chargen FILE vagy $C64_CHARGEN); a ROM nem része a gemnek. Az emulátoron belüli ellenőrzéshez töltsd be a --petscii fájlt egy C64-es terminálprogramba, vagy nézd a boardot VICE-ban.