Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ゼロからの、レトロゲームエンジンの作り方

tokujiros
January 18, 2025

 ゼロからの、レトロゲームエンジンの作り方

東京Ruby会議12 で発表した資料です。

tokujiros

January 18, 2025
Tweet

More Decks by tokujiros

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • ޷͖ͳݴޠ͸ Ruby ͱ C++ • ςΩετΤσΟλʔΛࣗ࡞ͨͯ͘͠ GUI πʔϧΩοτ͔

    Β࡞ͬͯͨΒ͍ͭͷؒʹ͔ήʔϜΤϯδϯΛ࡞ͬͯ·ͨ͠ • ࢓ࣄͰ͸લ͸ Android ͱ iOS ΞϓϦɺࠓ͸ Java Ͱ Spring Boot ॻ͍ͯ·͢  @tokujiros x.com/tokujiros github.com/xord
  2. ϨτϩήʔϜΤϯδϯͱ͸ ௿ղ૾౓άϥϑΟοΫͱϐίϐία΢ϯυ ϨτϩήʔϜಛԽͷπʔϧͱͯ͠ɺεϓϥΠτΤσΟλʔɺϚοϓΤ σΟλʔɺα΢ϯυΤσΟλʔɺϛϡʔδοΫΤσΟλʔͳͲΛ౥ࡌ ౷߹։ൃ؀ڥ ϓϩάϥϛϯάɺάϥϑΟοΫɺα΢ϯυͳͲΛҰͭͷ؀ڥͰ࡞੒Մೳ ϓϩάϥϛϯάͷ؆ུԽ Lua ΍ Python

    ͳͲͷεΫϦϓτݴޠͰήʔϜΛ࣮૷Մೳ ήʔϜ੍࡞ͷෑډ͕௿͍ ৭਺΍ղ૾౓ɺಉ࣌ൃԻ਺ͳͲ͕ҙਤతʹ੍ݶ͞Ε͍ͯΔͷͰήʔϜ σβΠϯͦͷ΋ͷʹूதͰ͖ɺήʔϜΛ࡞Γ࢝Ί΍͘͢׬੒ͤ͞΍͢ ͍ 
  3. ϨτϩήʔϜΤϯδϯ Reight ͷ঺հ Ruby Ͱ࣮૷ͨ͠ϨτϩήʔϜΤϯδϯ Ruby ͷ R ͱ PICO-8

    ͷ 8 Ͱ R8 ͔͠͠ R8 ͩͱݕࡧੑ͕ѱ͍ͷͰ Reight ʹ Ruby ΞιγΤʔγϣϯ։ൃॿ੒ۚʹ࠾୒͍͍ͨͩͯ։ൃத → https://www.ruby.or.jp/ja/news/20241030 
  4. ϨτϩήʔϜΤϯδϯ Reight ͷ঺հ ήʔϜͷίʔυΛ Ruby Ͱॻ͚Δ άϥϑΟοΫεͷ API ͸ Processing

    Λ࠾༻ ֤छΤσΟλʔΛ౥ࡌͨ͠౷߹։ൃ؀ڥ εϓϥΠτΤσΟλʔ ϚοϓΤσΟλʔ α΢ϯυΤσΟλʔʢ༧ఆʣ ϛϡʔδοΫΤσΟλʔʢ༧ఆʣ ςΩετΤσΟλʔ͸ࠓͷͱ͜Ζ֎෦ςΩετΤσΟλʔར༻Λ૝ఆ কདྷతʹ͸ςΩετΤσΟλʔ΋౥ࡌ͍ͨ͠ 
  5. Reight ͷ࢖͍ํ MacɺWindows Ͱ͸ “gem install reight” ͰΠϯετʔϧՄೳʢ˞ʣ $ gem

    install reight Fetching reflexion-0.3.2.gem Fetching xot-0.3.2.gem Fetching rays-0.3.2.gem Fetching rucy-0.3.2.gem Fetching beeps-0.3.2.gem Fetching rubysketch-0.7.2.gem Fetching processing-1.1.2.gem Building native extensions. This could take a while... Successfully installed xot-0.3.2 Building native extensions. This could take a while... Successfully installed rucy-0.3.2 Building native extensions. This could take a while... Successfully installed rays-0.3.2 Building native extensions. This could take a while... Successfully installed beeps-0.3.2 Building native extensions. This could take a while... Successfully installed reflexion-0.3.2 Successfully installed processing-1.1.2 Successfully installed rubysketch-0.7.2 Successfully installed reight-0.1 Parsing documentation for xot-0.3.2 Installing ri documentation for xot-0.3.2 Parsing documentation for rucy-0.3.2 Installing ri documentation for rucy-0.3.2 Parsing documentation for rays-0.3.2 Installing ri documentation for rays-0.3.2 Parsing documentation for beeps-0.3.2 Installing ri documentation for beeps-0.3.2 Parsing documentation for reflexion-0.3.2 Installing ri documentation for reflexion-0.3.2 Parsing documentation for processing-1.1.2 Installing ri documentation for processing-1.1.2 Parsing documentation for rubysketch-0.7.2 Installing ri documentation for rubysketch-0.7.2 Parsing documentation for reight-0.1 Done installing documentation for xot, rucy, rays, beeps, reflexion, processing, rubysketch, reight after 0 seconds 8 gems installed • Mac • Xcode ͷΠϯετʔϧ͕ඞཁ • Windows • ݱ࣌఺Ͱ͸ RubyInstaller+DevKit ͷΈαϙʔτ • ͞Βʹ pacman Ͱ glewɺopenal ͷΠϯετʔϧ͕ඞཁ ˞ 
  6. Reight ͷ࢖͍ํ “r8" ίϚϯυʹσΟϨΫτϦΛࢦఆͯ͠ىಈ ֎෦ΤσΟλʔͰ game.rb Λฤू  $ mkdir

    mygame $ cd mygame $ r8 . & $ emacs game.rb ... $ ls chips.json chips.png game.rb maps.json project.json
  7. ϨτϩήʔϜΤϯδϯͷٕज़ελοΫ 1.OpenGL ந৅ԽϨΠϠʔ → https://github.com/xord/rays 2.GUI πʔϧΩοτ → https://github.com/xord/re fl

    ex 3.Processing ޓ׵ API ϨΠϠʔ → https://github.com/xord/processing 4.ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ → https://github.com/xord/rubysketch 5.ΦʔσΟΦॲཧϥΠϒϥϦʔ → https://github.com/xord/beeps  https://discord.gg/C847WppZeT
  8. ϨτϩήʔϜΤϯδϯͷٕज़ελοΫ 1.OpenGL ந৅ԽϨΠϠʔ → https://github.com/xord/rays 2.GUI πʔϧΩοτ → https://github.com/xord/re fl

    ex 3.Processing ޓ׵ API ϨΠϠʔ → https://github.com/xord/processing 4.ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ → https://github.com/xord/rubysketch 5.ΦʔσΟΦॲཧϥΠϒϥϦʔ → https://github.com/xord/beeps  https://discord.gg/C847WppZeT
  9. 1. OpenGL ந৅ԽϨΠϠʔ OpenGL Λந৅Խͯ͠ Ruby Β͍͠ API ʹͯ͠ఏڙ ࠓޙ༨༟͕Ͱ͖ͨΒ

    VulkanɺMetal ͳͲʹ΋ରԠ͍ͨ͠ PainterɺImageɺFontɺPolygonɺPolylineɺShader ΫϥεͳͲ Ruby ͔Β Painter Ϋϥεܦ༝Ͱ OpenGL ͷඳը API Λݺͼग़͠ line()ɺrect()ɺellipse()ɺcurve()ɺimage()ɺtext()ɺ fi ll()ɺstroke()ɺ matrix() ͳͲ  https://discord.gg/C847WppZeT
  10. 1. OpenGL ந৅ԽϨΠϠʔ # ը૾ΦϒδΣΫτΛੜ੒ img = Rays::Image.new(256, 256) #

    ը૾ΦϒδΣΫτΛ Painter ΦϒδΣΫτͰඳը͢Δ img.paint do |painter| # എܠΛനͰΫϦΞ painter.background(1, 1, 1) # ੺ͰۣܗΛඳը painter.fill(1, 0, 0) painter.rect(10, 10, 100, 100) # ྘ͰؙΛඳը painter.fill(0, 1, 0) painter.ellipse(100, 100, 100, 100) end # ը૾ΛϑΝΠϧʹอଘ img.save(‘sample.png’)  TBNQMFQOH https://discord.gg/C847WppZeT
  11. ϨτϩήʔϜΤϯδϯͷٕज़ελοΫ 1.OpenGL ந৅ԽϨΠϠʔ → https://github.com/xord/rays 2.GUI πʔϧΩοτ → https://github.com/xord/re fl

    ex 3.Processing ޓ׵ API ϨΠϠʔ → https://github.com/xord/processing 4.ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ → https://github.com/xord/rubysketch 5.ΦʔσΟΦॲཧϥΠϒϥϦʔ → https://github.com/xord/beeps  https://discord.gg/C847WppZeT
  12. 2. GUI πʔϧΩοτ WindowɺView ΫϥεͳͲ View#on_draw Ͱ OpenGL ந৅ԽϨΠϠʔΛར༻ ֤

    OS ωΠςΟϒͷ API Ͱ࣮૷ ࠓͷͱ͜Ζ macOS(AppKit)ɺiOS(UIKit)ɺWindows(Win32) ʹରԠ ࠓޙ༨༟͕͋Ε͹ LinuxɺAndroid ʹ΋ରԠ͍ͨ͠ ෺ཧԋࢉϥΠϒϥϦʔͷ Box2D ΋૊ΈࠐΈ ॏྗΛઃఆͨ͠Γɺݸʑͷ View ΦϒδΣΫτʹ൓ൃ܎਺Λ෇͚ͨΓ  https://discord.gg/C847WppZeT
  13. 2. GUI πʔϧΩοτ w = Reflex::Window.new # ΢Οϯυ΢ΦϒδΣΫτΛੜ੒ w.width =

    256 # ΢Οϯυ΢ͷ෯Λઃఆ w.height = 256 # ΢Οϯυ΢ͷߴ͞Λઃఆ w.title = 'Hello, world!’ # ΢Οϯυ΢ͷλΠτϧΛઃఆ v = Reflex::View.new # ϏϡʔΦϒδΣΫτΛੜ੒ def v.on_draw(e) # ಺෦ͷඳըॲཧΛఆٛ # ΠϕϯτͰఏڙ͞ΕΔ Painter ΦϒδΣΫτͰඳը e.painter.background(1, 1, 1) e.painter.fill(1, 0, 0) e.painter.rect(10, 10, 100, 100) e.painter.fill(0, 1, 0) e.painter.ellipse(100, 100, 100, 100) end w.add(v) # ϏϡʔΦϒδΣΫτΛ΢Οϯυ΢ʹ௥Ճ w.show # ΢Οϯυ΢Λදࣔ  8JOEPXT NBD04
  14. ϨτϩήʔϜΤϯδϯͷٕज़ελοΫ 1.OpenGL ந৅ԽϨΠϠʔ → https://github.com/xord/rays 2.GUI πʔϧΩοτ → https://github.com/xord/re fl

    ex 3.Processing ޓ׵ API ϨΠϠʔ → https://github.com/xord/processing 4.ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ → https://github.com/xord/rubysketch 5.ΦʔσΟΦॲཧϥΠϒϥϦʔ → https://github.com/xord/beeps  https://discord.gg/C847WppZeT
  15. 3. Processing ޓ׵ API ϨΠϠʔ Creative Coding ϑϨʔϜϫʔΫͱͯ͠༗໊ͳ Processing ͱಉ͡ػೳΛఏڙ

    OpenGL ந৅ԽϨΠϠʔͷϥούʔϥΠϒϥϦʔ 2023೥౓ͷ Ruby ΞιγΤʔγϣϯ։ൃॿ੒ۚʹ࠾୒͞Ε։ൃ rubygems.org/gems/processing Ͱެ։த ϨτϩήʔϜΤϯδϯͱͯ͠ Processing API ͰήʔϜΛ࣮૷͢Δ͜ͱ͕Ͱ͖Δ Processing ͷྑ͍ͱ͜Ζ͸΢Σϒ্ͷ৘ใ͕྆ଟ͍ͱ͜Ζ  https://discord.gg/C847WppZeT
  16. 3. Processing ޓ׵ API ϨΠϠʔ setup do # ىಈ࣌ʹҰ౓͚ͩݺ͹ΕΔ size(256,

    256) # ΢Οϯυ΢ͷαΠζΛࢦఆ setTitle('Hello, world!’) # ΢Οϯυ΢ͷλΠτϧΛઃఆ ellipseMode(CORNER) # ପԁͷ࠲ඪ͸ࠨ্Λࢦఆ͢ΔϞʔυʹ end draw do # ຖඵ60ճݺ͹ΕΔ # എܠΛനͰΫϦΞ background(255) # ੺͍ۣܗΛඳը fill(255, 0, 0) rect(10, 10, 100, 100) # ྘ͷؙΛඳը fill(0, 255, 0) ellipse(100, 100, 100, 100) end  https://discord.gg/C847WppZeT
  17. ϨτϩήʔϜΤϯδϯͷٕज़ελοΫ 1.OpenGL ந৅ԽϨΠϠʔ → https://github.com/xord/rays 2.GUI πʔϧΩοτ → https://github.com/xord/re fl

    ex 3.Processing ޓ׵ API ϨΠϠʔ → https://github.com/xord/processing 4.ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ → https://github.com/xord/rubysketch 5.ΦʔσΟΦॲཧϥΠϒϥϦʔ → https://github.com/xord/beeps  https://discord.gg/C847WppZeT
  18. 4. ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ sprites = [] # ஍໘ΦϒδΣΫτΛੜ੒ ground = createSprite

    0, height - 10, width, 10 setup do gravity(0, 1000) # ॏྗΛઃఆ end draw do background 100 sprite(*sprites, ground) # ΫϦοΫͰੜ੒ͨ͠εϓϥΠτͱ஍໘Λඳը end # Ϛ΢ε͕ΫϦοΫ͞ΕͨΒݺ͹ΕΔ mousePressed do x, y = mouseX, mouseY # Ϛ΢εͷ࠲ඪΛऔಘ sp = createSprite(x, y, 50, 50) # εϓϥΠτΛੜ੒ sp.dynamic = true # ෺ཧԋࢉͷର৅ʹ͢Δ sprites << sp end  https://discord.gg/C847WppZeT
  19. ϨτϩήʔϜΤϯδϯͷٕज़ελοΫ 1.OpenGL ந৅ԽϨΠϠʔ → https://github.com/xord/rays 2.GUI πʔϧΩοτ → https://github.com/xord/re fl

    ex 3.Processing ޓ׵ API ϨΠϠʔ → https://github.com/xord/processing 4.ʢඇϨτϩʣ2DήʔϜϥΠϒϥϦʔ → https://github.com/xord/rubysketch 5.ΦʔσΟΦॲཧϥΠϒϥϦʔ → https://github.com/xord/beeps  https://discord.gg/C847WppZeT
  20. 5. ΦʔσΟΦॲཧϥΠϒϥϦʔ OpenAL Ͱα΢ϯυΛ࠶ੜ Synthesis Tool Kit Λ૊ΈࠐΈ OscillatorɺEnvelope ͳͲͷԻ੠৴߸ॲཧ

    Λ࣮૷ ͦͷଞ͍͔ͭ͘֎෦ϥΠϒϥϦΛར༻ͯ͠λΠϜετϨονɺϐονม ׵ɺαϯϓϦϯάϨʔτม׵ͳͲ΋ Sequencer ΫϥεΛར༻ͯ͠ɺα΢ϯυͱϛϡʔδοΫΤσΟλʔΛ࣮ ૷༧ఆ  https://discord.gg/C847WppZeT
  21. 5. ΦʔσΟΦॲཧϥΠϒϥϦʔ # γʔέϯαʔΦϒδΣΫτΛੜ੒ seq = Sequencer.new # ΦγϨʔλʔͰɺࢦఆͷप೾਺ͷαΠϯ೾Λੜ੒ seq.add

    Oscillator.new(freq: 261.626), 0.0, 0.1 # 0.0ඵޙʹ0.1ඵؒɺυͷԻΛ໐Β͢ seq.add Oscillator.new(freq: 293.665), 0.1, 0.1 # 0.1ඵޙʹ0.1ඵؒɺϨ seq.add Oscillator.new(freq: 329.628), 0.2, 0.1 # 0.2ඵޙʹ0.1ඵؒɺϛ seq.add Oscillator.new(freq: 349.228), 0.3, 0.1 # 0.3ඵޙʹ0.1ඵؒɺϑΝ seq.add Oscillator.new(freq: 391.995), 0.4, 0.1 # 0.4ඵޙʹ0.1ඵؒɺι seq.add Oscillator.new(freq: 440.000), 0.5, 0.1 # 0.5ඵޙʹ0.1ඵؒɺϥ seq.add Oscillator.new(freq: 493.883), 0.6, 0.1 # 0.6ඵޙʹ0.1ඵؒɺγ seq.add Oscillator.new(freq: 523.251), 0.7, 0.1 # 0.7ඵޙʹ0.1ඵؒɺυ # γʔέϯαʔΦϒδΣΫτ͕ੜ੒͢Δ೾ܗσʔλͰα΢ϯυΦϒδΣΫτΛੜ੒ snd = Sound.new(seq, 1) # α΢ϯυΛ࠶ੜ snd.play  https://discord.gg/C847WppZeT 0TDJMMBUPSΛͦͷ··໐Β͍ͯ͠ΔͷͰϊΠζʢΫϦοΫԻʣ ͕͋Γ·͢ͷͰɺ&OWFMPQFΛೖΕΔ͜ͱͰվળ͠·͢
  22. 5. ΦʔσΟΦॲཧϥΠϒϥϦʔ class MMLCompiler def compile(str) scanner = StringScanner.new str.gsub(/;.*\n/,

    '') seq = B::Sequencer.new bpm = 120 time = 0 tone = 0 octave = 4 length = 4 velocity = 127 scanner.skip /\s*/ until scanner.empty? case when scanner.scan(/T\s*(\d+)/i) bpm = scanner[1].to_i when scanner.scan(/O\s*(\d+)/i) octave = scanner[1].to_i when scanner.scan(/L\s*(\d+)/i) length = scanner[1].to_i when scanner.scan(/V\s*(\d+)/i) velocity = scanner[1].to_i when scanner.scan(/R\s*(\d+)?/i) time += seconds scanner[1]&.to_i || length, bpm when scanner.scan(/@\s*(\d+)/) tone = scanner[1].to_i when scanner.scan(/([<>])/) case scanner[1] when '<' then octave -= 1 when '>' then octave += 1 end when scanner.scan(/([CDEFGAB])\s*([#+-]+)?\s*(\d+)?\s*(\.+)?/i)&.chomp char, offset, len, dots = [1, 2, 3, 4].map {scanner[_1]} freq = frequency(char, offset, octave) or next sec = seconds len&.to_i || length, bpm sec *= 1 + dots.size.times.map {0.5 / (_1 + 1)}.sum if dots osc = B::Oscillator.new TONES[tone], freq: freq env = B::Envelope.new {note_on; note_off (sec - 0.01).clamp(0.01..)} gain = B::Gain.new gain: velocity.clamp(0, 127) / 127.0 * 0.5 seq.add osc >> env >> gain, time, sec time += sec else raise "Unknown input: #{scanner.rest[..10]}" end scanner.skip /\s*/ end seq end private TONES = [:sine, :triangle, :square, :sawtooth] DISTANCES = -> { notes = 'c_d_ef_g_a_b'.each_char.with_index.reject {|c,| c == '_'}.to_a octaves = (0..11).to_a octaves.product(notes) .map.with_object({}) {|(octave, (note, index)), hash| hash[[note, octave]] = octave * 12 + index - 57 } }.call def frequency(note, offset, octave) raise "Bad note: '#{note}'" unless note =~ /[cdefgab]/i distance = DISTANCES[[note.downcase, octave]] distance += (offset || '').each_char.reduce(0) {|value, char| case char when '+', '#' then value + 1 when '-' then value - 1 else value end } 440 * (2 ** (distance.to_f / 12)) end def seconds(length, bpm) 60.0 / bpm / length end end  ؆қ..-ίϯύΠϥʔ # Ϛ΢ε͕ΫϦοΫ͞ΕͨΒݺ͹ΕΔ mousePressed do # ΫϦοΫ͕Θ͔ΔΑ͏ʹؙΛඳը circle mouseX, mouseY, 50 # 2ͭͷ MML ΛίϯύΠϧͯ͠ Sequencer ΦϒδΣΫτΛ2ͭੜ੒ seq1 = MMLCompiler.new.compile '@1 ffffre-rgrf1' seq2 = MMLCompiler.new.compile '@1 c<bb-argrb-ra1' # 2ͭͷ Sequencer ΦϒδΣΫτΛಉ࣌ʹ໐Β͢ B::Sound.new(seq1, 3).play B::Sound.new(seq2, 3).play end https://discord.gg/C847WppZeT IUUQTHJTUHJUIVCDPNYPSEEDEBGFG
  23. ήʔϜશମ͸ Processing ϕʔεͰ࣮૷ ॏྗͷॲཧ΍িಥ൑ఆ͸ɺඇϨτϩͷ2DήʔϜϥΠ ϒϥϦʔͷεϓϥΠτͱ෺ཧԋࢉͰ؆୯ʹ࣮૷Մೳ ήʔϜ಺ͷα΢ϯυ΋ࣄલʹΦʔσΟΦσʔλԽ͠ ࠶ੜʢ༧ఆʣ GUI πʔϧΩοτͰ΢Οϯυ΢දࣔ ΢Οϯυ΢಺෦͸

    OpenGL ந৅ԽϨΠϠʔͰඳը ϨτϩήʔϜΤϯδϯͷ࡞Γํ  ground = createSprite 0, height - 10, width, 10 sprites = [] setup do gravity(0, 1000) end draw do background 100 sprite(*sprites, ground) end mousePressed do sp = createSprite(mouseX, mouseY, 50, 50) sp.dynamic = true sprites << sp end https://discord.gg/C847WppZeT
  24. macOS / iOS ΞϓϦԽ Reight ϨτϩήʔϜΤϯδϯࣗମΛΞϓϦԽ macOS ΍ iOS ͷ

    AppStore Ͱ഑෍͍ͨ͠ CRuby ΠϯλʔϓϦλʔ΋૊ΈࠐΉʢ˞ʣͷͰɺΞϓϦΛΠϯετʔϧ ͢Δ͚ͩͰϨτϩήʔϜ։ൃ؀ڥ͕੔͏ Ruby ͷॲཧܥΛ༻ҙͯ͠ gem install reight ͢ΔΑΓ΋खܰ  ˞ʣ$3VCZΠϯλʔϓϦλʔ૊ΈࠐΈͷ$PDPB1PE ˠIUUQTHJUIVCDPNYPSEDSVCZ https://discord.gg/C847WppZeT
  25. ϨτϩήʔϜΤϯδϯͰ࡞ͬͨήʔϜΛެ։ ήʔϜΛΞϓϦԽ֤ͯ͠ετΞʹެ։Ͱ͖ΔΑ͏ʹ͍ͨ͠ macOS ΞϓϦԽ iOS ΞϓϦԽ RubySolitaire ͱ͍͏ɺಉٕ͡ज़ελοΫͰ࡞ͬͨήʔϜΛ AppStore Ͱެ։த

    ༗ྉΞϓϦ΍޿ࠂɺ՝ۚʹ΋ରԠ͢ΔͷͰϚωλΠζ΋Մೳ Steam ͰͷϦϦʔε΋ ήʔϜΛ΢ΣϒͰެ։ WebAssembly (WASM) ʹରԠ͠ɺϒϥ΢βʔ্Ͱಈ͔͢ ϦϯΫΛڞ༗͢Δ͚ͩͰखܰʹଞਓʹ༡ΜͰ΋Β͑Δ  https://discord.gg/C847WppZeT
  26. ࢀߟϦϯΫ 2023 ೥౓ Ruby ΞιγΤʔγϣϯ։ൃॿ੒ۚ ࠷ऴใࠂʢ2024ʣ https://gist.github.com/xord/c464669d41f37f4858a193c658e9a705 Processing ϕʔεͷ2DήʔϜΤϯδϯ for

    CRuby ͷ঺հʢ2023ʣ https://zenn.dev/tokujiros/articles/7f0b44a6b7e2a6 ࣗલ Processing ࣮૷ͷޓ׵ੑݕূʹ p5.rb Λ࢖ͬͯΈͨ࿩ʢ2023ʣ https://zenn.dev/tokujiros/articles/973815bce7afdc 3ϲ݄ؒͷϑϧλΠϜݸਓ։ൃΛऴ͑ͯɻʢͦͯࣾ͠ձ෮ؼ΁ɾɾɾ ʢ2023ʣ https://note.com/tokujiros/n/ndb4bc589ef8f RubySketch ήʔϜΤϯδϯԽܭը ʙ ෺ཧԋࢉ෇͖εϓϥΠτΫϥεͷ ௥ՃͳͲʢ2022ʣ https://zenn.dev/tokujiros/articles/647d1f6df2b342 Ruby Ͱ Processing ͢Δ gemʢͱΞϓϦʣͷ঺հʢ2020ʣ https://zenn.dev/tokujiros/articles/96f63899760cb0 iPhone ͷʮΧϝϥೖྗʯͰ͓΋͠ΖϏσΦΧϝϥΛ࡞Ζ͏ʢ2020ʣ https://zenn.dev/tokujiros/articles/09988fc99b636c CRuby ͰήʔϜΛ࡞ͬͯ iPhone Ͱಈ͔ͦ͏ʢ2015ʣ https://qiita.com/tokujiros/items/0c4bd2dd995f0e6740b5 Ruby ༻ࣗ࡞ GUI πʔϧΩοτʹ Box2D Λ૊ΈࠐΜͩΒϒϩοΫ่͠ ήʔϜ͕؆୯ʹ࡞Εͨ࿩ʢ2014ʣ https://qiita.com/tokujiros/items/a9e8d16c2a4c1ccf2238 CRuby ΠϯλϓϦλͷ CocoaPod Λ࡞ͬͨͷͰ঺հ͠·͢ʢ2014ʣ https://qiita.com/tokujiros/items/30e9d0cf6236cd8e303d  https://discord.gg/C847WppZeT
  27. Textbringer ͷ૊ΈࠐΈ Ruby Ͱ࣮૷͞Εͨ Textbringer ͱ͍͏ςΩετΤσΟλʔ͕͋Δ Textbringer ͸ը໘දࣔͱΩʔೖྗʹ Curses ϥΠϒϥϦʔΛར༻͍ͯ͠Δ

    Textbringer ͷ Curses ར༻෦෼Λࠩ͠ସ͑Ε͹ GUI ΞϓϦԽͰ͖ΔͷͰ͸ʁ ͱ͍͏ࢥ͍͖ͭ Textbringer ͕ར༻͍ͯ͠Δ࠷௿ݶͷ Curses Λ GUI πʔϧΩοτͰ࠶ݱ͠ ͨΒಈ͍ͨ → https://x.com/tokujiros/status/1841538130148786677 ϨτϩήʔϜΤϯδϯͷςΩετΤσΟλʔͱͯ͠ Textbringer Λ૊ΈࠐΊΔ ͷͰ͸ʁ ೔ຊޠೖྗपΓ͕େมͦ͏Ͱ͸͋Δ͕ɾɾɾ  https://discord.gg/C847WppZeT