├── .gitignore ├── 2023-ncl-creative-code-club └── invite-202307-ncl-creative-code.tic ├── 2024-ncl-creative-code-club └── invite-20240619-ncl-creative-code.tic ├── 2024-peckham-digital ├── invite-20240720-peckham-digital.tic └── peckhamdigital-logo.lua ├── bounces.lua ├── emfcamp-invite.tic ├── hosting └── readme.md ├── house.lua ├── outline.md ├── plasma.gif ├── plasma.lua ├── primitive-house.gif ├── readme.md ├── running └── readme.md ├── sincos.lua ├── swirly.lua ├── swirly.mp4 ├── video1.gif ├── video2.gif ├── video3.gif └── workshop.md /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/.gitignore -------------------------------------------------------------------------------- /2023-ncl-creative-code-club/invite-202307-ncl-creative-code.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/2023-ncl-creative-code-club/invite-202307-ncl-creative-code.tic -------------------------------------------------------------------------------- /2024-ncl-creative-code-club/invite-20240619-ncl-creative-code.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/2024-ncl-creative-code-club/invite-20240619-ncl-creative-code.tic -------------------------------------------------------------------------------- /2024-peckham-digital/invite-20240720-peckham-digital.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/2024-peckham-digital/invite-20240720-peckham-digital.tic -------------------------------------------------------------------------------- /2024-peckham-digital/peckhamdigital-logo.lua: -------------------------------------------------------------------------------- 1 | local T=0 2 | local SIN=math.sin 3 | local COS=math.cos 4 | local ATAN2=math.atan2 5 | local POLAR={} 6 | 7 | function R(a,b,r) 8 | return COS(r)*a-SIN(r)*b, 9 | SIN(r)*a+COS(r)*b 10 | end 11 | 12 | function BOOT() 13 | cls() 14 | drawLogo(120,68,30) 15 | POLAR=toPolar() 16 | end 17 | 18 | function BDR(y) 19 | vbank(0) 20 | for i=1,15 do 21 | local r=i/15*255 22 | local g=127+SIN(y*.03-T*.03)*127 23 | local b=255-(i/15*255) 24 | rgb(i,r,g,b) 25 | end 26 | end 27 | 28 | function TIC() 29 | poke(0x3ffb,0) 30 | vbank(0) 31 | local zoom=1.1+SIN(T*.01)*.8 32 | local spin=COS(T*.04)*2+COS(T*.03)*2 33 | plotPolar(POLAR,spin,zoom) 34 | 35 | vbank(1) 36 | local txt="Peckham Digital" 37 | local x,y=40,115 38 | print(txt,x-1,y-1,14,false,2) 39 | print(txt,x+1,y+1,13,false,2) 40 | print(txt,x,y,12,false,2) 41 | T=T+1 42 | end 43 | 44 | function drawLogo(xc,yc,sc) 45 | local coR=sc 46 | local ciR=sc*.5 47 | circ(xc,yc,coR,12) 48 | circ(xc,yc,ciR,0) 49 | local barW=sc*.6 50 | local barH=sc*2.75 51 | rect(xc-coR-barW,yc-sc,barW,barH,12) 52 | rect(xc+coR,yc-barH+sc,barW,barH,12) 53 | end 54 | 55 | function toPolar() 56 | local o={} 57 | for dx=-120,119 do 58 | for dy=-68,67 do 59 | o[#o+1]={ 60 | a=ATAN2(dy,dx), 61 | d=(dx^2+dy^2)^.5, 62 | c=pix(120+dx,68+dy) 63 | } 64 | end 65 | end 66 | return o 67 | end 68 | 69 | function plotPolar(o,spin,zoom) 70 | for i=1,#o do 71 | local p=o[i] 72 | local d=p.d*zoom 73 | local x=COS(p.a)*d 74 | local y=SIN(p.a)*d 75 | local spinP=spin+p.d*SIN(T*.01)*.1 76 | x,y=R(x,y,spinP) 77 | local c=(p.c>0) and p.d/5 or 0 78 | pix(120+x,68+y,c) 79 | end 80 | end 81 | 82 | function rgb(i,r,g,b) 83 | local a=16320+i*3 84 | poke(a,r) 85 | poke(a+1,g) 86 | poke(a+2,b) 87 | end 88 | -- 89 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 90 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 91 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 92 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 93 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 94 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 95 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 96 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 97 | -- 98 | 99 | -- 100 | -- 000:00000000ffffffff00000000ffffffff 101 | -- 001:0123456789abcdeffedcba9876543210 102 | -- 002:0123456789abcdef0123456789abcdef 103 | -- 104 | 105 | -- 106 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 107 | -- 108 | 109 | -- 110 | -- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 111 | -- 112 | 113 | -- 114 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 115 | -- 116 | 117 | -------------------------------------------------------------------------------- /bounces.lua: -------------------------------------------------------------------------------- 1 | local SIN=math.sin 2 | local COS=math.cos 3 | local ABS=math.abs 4 | 5 | T=0 6 | function TIC() 7 | cls() 8 | for i=1,10 do 9 | local t=T*.1+i*.2 10 | drawSin(10,10,50,50,t,i) 11 | drawCos(70,10,50,50,t,i) 12 | drawSinCos(130,10,50,50,t,i) 13 | drawSinAbs(190,10,50,50,t,i) 14 | drawSin2Cos(10,80,50,50,t,i) 15 | drawSinYCosY(70,80,50,50,t,i) 16 | end 17 | 18 | T=T+1 19 | end 20 | 21 | function drawSin(x,y,w,h,t,c) 22 | local px=x+w/2 23 | local py=y+h/2+SIN(t)*h/2 24 | circ(px,py,3,c) 25 | end 26 | 27 | function drawCos(x,y,w,h,t,c) 28 | local px=x+w/2 29 | local py=y+h/2+COS(t)*h/2 30 | circ(px,py,3,c) 31 | end 32 | 33 | function drawSinCos(x,y,w,h,t,c) 34 | local px=x+w/2+SIN(t)*w/2 35 | local py=y+h/2+COS(t)*h/2 36 | circ(px,py,3,c) 37 | end 38 | 39 | function drawSinAbs(x,y,w,h,t,c) 40 | local px=x+w/2 41 | local py=y+h-ABS(COS(t)*h) 42 | circ(px,py,3,c) 43 | end 44 | 45 | function drawSin2Cos(x,y,w,h,t,c) 46 | local px=x+w/2+SIN(t)*h/2 47 | local py=y+h/2-COS(t*2)*h/2 48 | circ(px,py,3,c) 49 | end 50 | 51 | function drawSinYCosY(x,y,w,h,t,c) 52 | local px=x+w/2 53 | local py=y+h/2+SIN(t)*w/4+SIN(t*2)*w/4 54 | circ(px,py,3,c) 55 | end 56 | 57 | -- 58 | -- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc 59 | -- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c 60 | -- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc 61 | -- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c 62 | -- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 63 | -- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 64 | -- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec 65 | -- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee 66 | -- 67 | 68 | -- 69 | -- 000:00000000ffffffff00000000ffffffff 70 | -- 001:0123456789abcdeffedcba9876543210 71 | -- 002:0123456789abcdef0123456789abcdef 72 | -- 73 | 74 | -- 75 | -- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000 76 | -- 77 | 78 | -- 79 | -- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 80 | -- 81 | 82 | -- 83 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 84 | -- 85 | 86 | -------------------------------------------------------------------------------- /emfcamp-invite.tic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/emfcamp-invite.tic -------------------------------------------------------------------------------- /hosting/readme.md: -------------------------------------------------------------------------------- 1 | # Hosting 2 | 3 | I'd love to run this workshop for you! 4 | 5 | Demo making is a great way for people to express their creativity, and TIC-80 is a safe and fun environment to play with. 6 | 7 | The workshop has proven suitable for anyone who has done a little bit of programming before, and also for those who are experienced but would like to get started in creative coding, or learn a new platform for doing so. 8 | 9 | Please get in touch: 10 | 11 | - [Mastodon](https://mastodon.social/@jtruk) 12 | -------------------------------------------------------------------------------- /house.lua: -------------------------------------------------------------------------------- 1 | function TIC() 2 | cls(11) 3 | 4 | grassY=90 5 | 6 | t=time()/600 7 | x=120+math.sin(-t)*100 8 | y=grassY+20+math.cos(t)*80 9 | 10 | drawSun(x,y) 11 | 12 | rect(0,grassY,240,136-grassY,6) 13 | rect(80,40,80,60,3) 14 | tri(70,40,170,40,120,10,1) 15 | 16 | for x=0,240,6 do 17 | if x<140 or x>160 then 18 | line(x,80,x,110,1) 19 | end 20 | end 21 | line(140,80,160,110,2) 22 | 23 | text="jtruk made this" 24 | x=80+math.sin(t)*60 25 | y=125 26 | print(text,x+1,y+1,0) 27 | print(text,x,y,12) 28 | end 29 | 30 | function drawSun(x,y) 31 | circ(x,y,22,4) 32 | circ(x,y,20,12) 33 | end 34 | 35 | -- 36 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 37 | -- 38 | 39 | -------------------------------------------------------------------------------- /outline.md: -------------------------------------------------------------------------------- 1 | In 2 hours and I'm hoping to hit: 2 | 3 | - Check folks have downloaded TIC-80 4 | - Preamble (outline, expectations, check for photosensitivity requirements) 5 | - What TIC-80 does and why people like it 6 | - Origin and overview of the demoscene 7 | - TIC-80 Setup (i.e. dev menu option) and orientation (including F1-F5) 8 | - TIC-80 capabilities (including Pro and web) 9 | - Hands on: A Primitive House 10 | - Housekeeping: new cart, save, load, run 11 | - Intro to drawing primitives + print 12 | - vars, for, if, selected operators, function, comments 13 | - The secret sauce of Sin and Cos 14 | - (if time) Hands on: Plasma 15 | - Full screen pixels 16 | - time() 17 | - Sizecoding 18 | - Livecoding 19 | - Hands on: Swirly 20 | - atan2 21 | - (x^2+y^2)^.5 22 | - palette wash 23 | - Other stuff (if time) 24 | - reading pix() 25 | - math.random 26 | - vbank 27 | - For more: 28 | - tic80.com 29 | - SURF command 30 | - Monday night ByteJam 31 | - Field-FX Discord 32 | - tcc.lovebyte.party 33 | - Longer form -------------------------------------------------------------------------------- /plasma.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/plasma.gif -------------------------------------------------------------------------------- /plasma.lua: -------------------------------------------------------------------------------- 1 | T=0 2 | 3 | function TIC() 4 | for y=0,135 do 5 | for x=0,239 do 6 | local c=math.sin(y/19+x/15)+math.sin(x/40+T/12) 7 | c=c+math.cos(x/12+y/21)+math.sin(y/10+T/10) 8 | c=c+math.sin(T/100)^2 9 | c=1+(14*c) 10 | pix(x,y,c) 11 | end 12 | end 13 | 14 | T=T+1 15 | end 16 | 17 | -- 18 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 19 | -- 20 | 21 | -------------------------------------------------------------------------------- /primitive-house.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/primitive-house.gif -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # TIC-80 Workshop 2 | 3 | Hi. Here are some resources for folks who attended my demoscene workshop. 4 | 5 | Please get in touch if you'd like to [host me to run this workshop](./hosting/). 6 | 7 | There are also resources for [running this workshop](./running/) yourself. 8 | 9 | ## Download TIC-80 10 | 11 | [Download Page](https://tic80.com/create) - Skip past 'In the Browser' to the 'Download' heading. 12 | 13 | ## Links 14 | 15 | ### Documentation 16 | 17 | The TIC-80 website has a [Learn page](https://tic80.com/learn) featuring an outline of all commands. For further detail, see the [wiki](https://github-wiki-see.page/m/nesbox/TIC-80/wiki), which is regularly updated. 18 | 19 | ### Sizecoding 20 | 21 | If you're interested in making big effects in the smallest space: 22 | 23 | [Nanogems](https://nanogems.demozoo.org/) showcases some of their favourites across a range of platforms, including TIC-80. 24 | 25 | For variety/technical inspiration, I'd select: 26 | 27 | - [Thrive](https://www.youtube.com/watch?v=qU5EGLvFXd8) - So much going on, and a wonderful use of colour palette [256 bytes] 28 | - [cthulhu128](https://www.youtube.com/watch?v=G-7qy--BEEQ) - A captivating dynamic effect. Just [128 bytes]! 29 | - [Terrain Spotting](https://www.youtube.com/watch?v=brCWRuUw8zw) - Nicely balanced perspective and colour use [256 bytes] 30 | - [House of Mojo](https://www.youtube.com/watch?v=c5U-Sz1zN1s) - Well considered progression across a few effects combined [256 bytes] 31 | - [Martian Madrigal](https://tic80.com/play?cart=3296) - One of mine. They just make me smile. Includes sound [256 bytes] 32 | - [Sunset Cove Moods](https://www.youtube.com/watch?v=VNDYInToM7s) - Another of mine, with a gentle colour palette change [256 bytes] 33 | 34 | Also see [Tiny Code Christmas](https://tcc.lovebyte.party/) for a brilliant set of short tutorials in TIC-80 and another fantasy console, [PICO-8](https://www.lexaloffle.com/pico-8.php). 35 | 36 | [The Sizecoding wiki](http://www.sizecoding.org/wiki/TIC-80) collects together some techniques. 37 | 38 | ### Livecoding 39 | 40 | Some selected examples in [Demozoo's Livecoding section](https://livecode.demozoo.org/) 41 | 42 | Look out for regular Byte Jams (see Field-FX in the community links below) and the competition version (timed/restricted length) Byte Battles in demo parties. 43 | 44 | ### Other 45 | 46 | PSEnough made a [general demoscene getting started doc](https://github.com/psenough/teach_yourself_demoscene_in_14_days). When you're a bit more embedded, they produce [monthly reports](https://www.youtube.com/@psenough) on the demoscene, featuring releases and demoparties. 47 | 48 | ### Sound 49 | 50 | The workshop covered some starting points for visual effects. For sound, see the `music` and `sfx` calls [Under 'sound' in the API](https://github.com/nesbox/TIC-80/wiki/API#sound). There is documenation for the [SFX Editor](https://github.com/nesbox/TIC-80/wiki/SFX-Editor). The Music Editor (Tracker) generally doesn't have a great reputation, but some do get some brilliant things out of it. [PSEnough's Music editor intro tutorial](https://www.youtube.com/watch?v=V9oAccwjeDA) is recommended, and there's an explanation and good guide to the effects modifiers in the [Music Editor documentation](https://github.com/nesbox/TIC-80/wiki/Music-Editor). 51 | 52 | If you'd like to go low-level, and poke/peek stuff, check out the [Sound register documentation](https://github.com/nesbox/TIC-80/wiki/RAM#sound-registers). [The code in this cart](https://tic80.com/play?cart=807) may help you pick it apart. This [music visualiser](https://tic80.com/play?cart=115) may also illuminate. 53 | 54 | ### Communities 55 | 56 | There are many demoscene communities. I've found myself following a number of Discords, which have their own specialisms, but include overlapping groups of people. 57 | 58 | - Field-FX 59 | A community that grew from a demo event at EMF Camp. Very friendly and welcoming, and a good starting point for newcomers. 60 | I recommend the [Discord](https://discord.com/invite/RuSxTNzhZS), and following on [Twitter](https://twitter.com/fx_field) and/or [Mastodon](https://mastodon.online/@FieldFX). 61 | They also run Byte Jams (hour long streams on [Twitch](https://www.twitch.tv/fieldfxdemo) on most Monday evenings) and they have a [YouTube](https://www.youtube.com/@field-fx5751) channel featuring previous streams. 62 | - [Lovebyte](https://lovebyte.party/) 63 | An annual online event for sizecoding, featuring many computer systems, from TIC-80 to obscure hardware from the 1980s 64 | I highly, highly recommend their [Tiny Code Christmas](https://tcc.lovebyte.party/) a series of gentle, but nicely progressive series of tutorials. These are oriented towards sizecoding, but also helpful for general demo tips. This was my entrypoint, and I've loved where it's gone. They also have a [Discord](https://discord.gg/pUS5kCJTzp) - also a very supportive community. 65 | - [NOVA Demoparty](https://novaparty.org/) 66 | The UK's biggest in-person demoparty, down on the Devon coast, annually in June. Also very welcoming! 67 | They don't use their Twitter/Mastodon accounts currently, but do have a [Discord](https://discord.gg/rBJTXJBeq2). 68 | 69 | ### Longer Demos 70 | 71 | - [You Better Walk](https://www.youtube.com/watch?v=HxrIOyLwYXk) 72 | - [GRMA](https://www.youtube.com/watch?v=g136jyMHSUU) 73 | - [AssemblyTV Megademo](https://www.youtube.com/watch?v=KFpohQa8jgk) 74 | - [Life's a Beach](https://www.youtube.com/watch?v=8Kz3_fqToNI) 75 | - [Nullius in Verba](https://www.youtube.com/watch?v=fhqKE_sTXeg) 76 | - [The Welsh Demo](https://www.youtube.com/watch?v=DOI5iUfohY0) 77 | - [Fallspire](https://www.youtube.com/watch?v=tWEU-bOT90w) 78 | - [Cracklebass](https://www.youtube.com/watch?v=KcmTcYuxp9w) 79 | - [You am the robot Zombie](https://www.youtube.com/watch?v=TkpLYwMQHrw) 80 | - [In Search of Love](https://www.youtube.com/watch?v=4m8IF7nwCa0) 81 | 82 | ### Archives 83 | 84 | - [Demozoo](https://demozoo.org/) is a database of productions across the demoscene. They also have [Nanogems](https://nanogems.demozoo.org/) and [Livecode](https://livecode.demozoo.org/) archives. 85 | - [Pouët](https://www.pouet.net/) is a huge archive of productions and associated stuff. It can be a bit aggresive in places, but it's a great resource. 86 | 87 | # Examples of Demoscene Productions 88 | 89 | ## Watchparty 90 | 91 | - [Intrinsic Gravity / ^Still](https://demozoo.org/productions/130155/) 92 | Geometric, colour play. 93 | - [State of the Art / ^Spaceballs](https://demozoo.org/productions/2/) 94 | - 1992 Amiga. Photosensitivity warning. 95 | - [Eon / ^The Black Lotus](https://demozoo.org/productions/202831/) 96 | - [VX2 / ^Spectrals](https://demozoo.org/productions/277304/) 97 | - [ix / ^Moppi](https://demozoo.org/productions/67521/) 98 | - [Remnants / ^Alcatraz](https://demozoo.org/productions/342211/) 99 | - 256b 100 | - [GhostNOP / ^Futurs' and ^Pulpo Corrosivo](https://demozoo.org/productions/342223/) 101 | - Amstrad CPC 102 | - [Empires / ^Conspiracy](https://demozoo.org/productions/342435/) 103 | - Bokeh / fluid / FOV. 104 | - [Legend of Sisyphus / ^ASD](https://demozoo.org/productions/327586/) 105 | - Mocap. Nudity. 106 | - [Batman Rises / ^Batman Group](https://demozoo.org/productions/316180/) 107 | - Amiga OCS 108 | - [Mechasm / ^Fairlight](https://demozoo.org/productions/322662/) 109 | - [In Color / ^Darklite and ^Offence](https://demozoo.org/productions/322396/) 110 | - Spectrum 128k 111 | - [Replay / ^SMFX](https://demozoo.org/productions/325859/) 112 | - Atari ST 113 | - [The Interloper / ^MFX](https://demozoo.org/productions/322661/) 114 | - [Masagin / ^Farbrausch and ^Neuro](https://demozoo.org/productions/4910/) 115 | - [Come Together / ^Melon Dezign](https://demozoo.org/productions/313312/) 116 | 117 | ### Further questions / My resources 118 | 119 | Feel welcome to contact me with any questions, or to share your progress :) 120 | 121 | - [Mastodon](https://mastodon.social/@jtruk) 122 | - [Twitter](https://twitter.com/jtruk) 123 | - [My TIC-80 sketches](https://github.com/creativenucleus/tic-80-sketches) 124 | - [Code on the TIC-80 website](https://tic80.com/dev?id=8568) 125 | -------------------------------------------------------------------------------- /running/readme.md: -------------------------------------------------------------------------------- 1 | # Running 2 | 3 | You're very welcome to run this workshop yourself. If you use significant parts of it, do mention this in event descriptions on websites, e.g. "...based on jtruk's demoscene workshop". This is welcome, but not necessary for social media promotion. 4 | 5 | Please drop me a line if you do so (see the bottom of this page). I'd be keen to promote your event, and also to gather any improvements. 6 | 7 | # Intro 8 | 9 | - Make sure everyone has a running version of TIC-80 (part way down [tic-80 Create page](https://tic80.com/create)) 10 | - Anyone susceptible to photosensitity 11 | - Outline of workshop 12 | - Become familiar with TIC-80 13 | - Drawing primitives 14 | - sin/cos 15 | - poke palette 16 | - full screen effect 17 | - History of the demoscene 18 | - Showcasing some demoscene things 19 | - Jumping off points 20 | - Level of programming experience (above 7 / below 3) 21 | - Anyone know about the demoscene? 22 | 23 | ## Primitives and structures 24 | 25 | `cls, rect, tri, circ, line, elli, pix, print` 26 | (rectb, trib, circb, ellib) 27 | 28 | `function, for, var, if` 29 | 30 | ```lua 31 | function TIC() 32 | T=time()/500 33 | 34 | cls(8) 35 | 36 | for i=0,30 do 37 | x=(i^7)%240 38 | y=(i^5)%68 39 | pix(x,y,12) 40 | end 41 | 42 | circ( 43 | 120+math.sin(T)*100, 44 | 90-math.cos(T)*80, 45 | 20, 46 | 4) 47 | 48 | rect(0,68,240,68,6) 49 | 50 | rect(50,40,80,60,2) 51 | tri(40,40, 90,10, 140,40, 1) 52 | 53 | for x=10,230,10 do 54 | if x<150 or x>=180 then 55 | drawPicket(x) 56 | end 57 | end 58 | end 59 | 60 | function drawPicket(x) 61 | line(x,90, x,110, 12) 62 | end 63 | ``` 64 | 65 | ## Sin/Cos 66 | 67 | ```lua 68 | local ATAN2=math.atan2 69 | local PI=math.pi 70 | local TAU=PI*2 71 | local SIN=math.sin 72 | 73 | function TIC() 74 | T=time() 75 | 76 | for y=0,135 do 77 | for x=0,239 do 78 | local p=y*240+x 79 | local dx=120-x 80 | local dy=68-y 81 | local d=(dx^2+dy^2)^.5 82 | local a=(ATAN2(dy,dx)+PI)/TAU 83 | poke4(p,a*16+T*.001) 84 | end 85 | end 86 | end 87 | ``` 88 | 89 | ## Contact Me 90 | 91 | Please get in touch: 92 | 93 | - [Mastodon](https://mastodon.social/@jtruk) 94 | -------------------------------------------------------------------------------- /sincos.lua: -------------------------------------------------------------------------------- 1 | local SIN,COS,PI=math.sin,math.cos,math.pi 2 | local ATAN2=math.atan2 3 | local TAU=PI*2 4 | local MIN,MAX=math.min,math.max 5 | 6 | local ANIM_MUL=0.01 7 | local I_ANIM_MUL_MIN=1 8 | local I_ANIM_MUL_MAX=8 9 | local I_ANIM_MUL=2 10 | local ANIM_T=0 11 | local ANIM_D=50 12 | local ANIM_X=70 13 | local ANIM_Y=ANIM_D+10 14 | 15 | local STAGES={ 16 | { 17 | title="TARGET", 18 | func=function() 19 | drawTarget(true, false) 20 | drawHTick(ANIM_X, getAnimYPos(0)) 21 | 22 | printValues(true, false, false) 23 | end, 24 | incT=false, 25 | }, 26 | { 27 | title="SIN(y)", 28 | func=function() 29 | drawTarget(true, false) 30 | drawHTick(ANIM_X, getAnimYPos(ANIM_T)) 31 | 32 | printValues(true, false, false) 33 | end, 34 | incT=true, 35 | }, 36 | { 37 | title="SIN(y) with trail", 38 | func=function() 39 | drawTarget(true, false) 40 | drawHTrail(ANIM_T, MIN(ANIM_T,ANIM_X)) 41 | drawHTick(ANIM_X, getAnimYPos(ANIM_T)) 42 | 43 | printValues(true, false, false) 44 | end, 45 | incT=true, 46 | }, 47 | { 48 | title="TARGET 2", 49 | func=function() 50 | drawTarget(true, true) 51 | local x = getAnimXPos(0) 52 | local y = getAnimYPos(0) 53 | drawVTick(x,y) 54 | 55 | printValues(false, true, false) 56 | end, 57 | incT=false, 58 | }, 59 | { 60 | title="COS(x)", 61 | func=function() 62 | drawTarget(true, true) 63 | drawVTick(getAnimXPos(ANIM_T),ANIM_Y) 64 | 65 | printValues(false, true, false) 66 | end, 67 | incT=true, 68 | }, 69 | { 70 | title="CIRCLE", 71 | func=function() 72 | drawTarget(true, true) 73 | drawHTick(ANIM_X,getAnimYPos(ANIM_T)) 74 | drawVTick(getAnimXPos(ANIM_T),ANIM_Y) 75 | circb(getAnimXPos(ANIM_T),getAnimYPos(ANIM_T),8,12) 76 | 77 | printValues(true, true, false) 78 | end, 79 | incT=true, 80 | }, 81 | { 82 | title="CIRCLE with trail", 83 | func=function() 84 | drawTarget(true, true) 85 | drawCircTrail(ANIM_T, MIN(ANIM_T,200)) 86 | drawHTick(ANIM_X,getAnimYPos(ANIM_T)) 87 | drawVTick(getAnimXPos(ANIM_T),ANIM_Y) 88 | circb(getAnimXPos(ANIM_T),getAnimYPos(ANIM_T),8,12) 89 | 90 | printValues(true, true, false) 91 | end, 92 | incT=true, 93 | }, 94 | { 95 | title="ATAN2", 96 | func=function() 97 | drawTarget(true, true) 98 | drawHTick(ANIM_X,getAnimYPos(ANIM_T)) 99 | drawVTick(getAnimXPos(ANIM_T),ANIM_Y) 100 | circb(getAnimXPos(ANIM_T),getAnimYPos(ANIM_T),8,12) 101 | 102 | printValues(true, true, true) 103 | end, 104 | incT=true, 105 | }, 106 | } 107 | 108 | local ISTAGE=1 109 | 110 | function TIC() 111 | cls() 112 | poke(0x3FFB,0) -- cursor begone 113 | 114 | if btnp(0) then -- up 115 | I_ANIM_MUL=MIN(I_ANIM_MUL+1,I_ANIM_MUL_MAX) 116 | elseif btnp(1) then -- down 117 | I_ANIM_MUL=MAX(I_ANIM_MUL-1,I_ANIM_MUL_MIN) 118 | end 119 | 120 | if btnp(3) then -- right 121 | ISTAGE=MIN(ISTAGE+1,#STAGES) 122 | ANIM_T=0 123 | elseif btnp(2) then -- left 124 | ISTAGE=MAX(ISTAGE-1,1) 125 | ANIM_T=0 126 | end 127 | 128 | local stage=STAGES[ISTAGE] 129 | stage.func() 130 | 131 | local text="<= " .. stage.title .. " =>" 132 | local w=print(text,0,150) 133 | print(text,120-w/2,128,14) 134 | 135 | print(I_ANIM_MUL .. "x", 210,128,14) 136 | 137 | if stage.incT then 138 | ANIM_T=ANIM_T+1 139 | end 140 | end 141 | 142 | function drawTarget(doHoriz, doVert) 143 | local hairD=5 144 | if doHoriz then 145 | local y0=ANIM_Y-ANIM_D 146 | local y1=ANIM_Y+ANIM_D 147 | line(ANIM_X-hairD,y0, ANIM_X+hairD,y0,2) 148 | line(ANIM_X-hairD,y1, ANIM_X+hairD,y1,2) 149 | line(ANIM_X,y0, ANIM_X,y1,2) 150 | 151 | print("-1", ANIM_X+10,y0-2,2) 152 | print("1", ANIM_X+10,y1-2,2) 153 | end 154 | 155 | if doVert then 156 | local x0=ANIM_X-ANIM_D 157 | local x1=ANIM_X+ANIM_D 158 | line(x0,ANIM_Y-hairD, x0,ANIM_Y+hairD,6) 159 | line(x1,ANIM_Y-hairD, x1,ANIM_Y+hairD,6) 160 | line(x0,ANIM_Y, x1,ANIM_Y,6) 161 | 162 | print("-1", x0-4, ANIM_Y+8, 6) 163 | print("1", x1-2, ANIM_Y+8, 6) 164 | end 165 | 166 | circ(ANIM_X,ANIM_Y,3,9) 167 | print("0",ANIM_X+10,ANIM_Y-2,9) 168 | end 169 | 170 | function drawHTrail(pos,d) 171 | for i=1,d do 172 | local x=ANIM_X-i 173 | local y=getAnimYPos(pos-i) 174 | circb(x,y,2,15) 175 | end 176 | end 177 | 178 | function drawCircTrail(pos,d) 179 | for i=1,d do 180 | local x=getAnimXPos(pos-i) 181 | local y=getAnimYPos(pos-i) 182 | circb(x,y,2,15) 183 | end 184 | end 185 | 186 | function getAnimMul() 187 | return ANIM_MUL*I_ANIM_MUL 188 | end 189 | 190 | function getAnimXPos(pos) 191 | return ANIM_X+COS(pos*getAnimMul())*ANIM_D 192 | end 193 | 194 | function getAnimYPos(pos) 195 | return ANIM_Y+SIN(pos*getAnimMul())*ANIM_D 196 | end 197 | 198 | function drawHTick(x,y) 199 | tri(x-5,y, x-8,y-3, x-8,y+3, 4) 200 | tri(x+5,y, x+8,y-3, x+8,y+3, 4) 201 | end 202 | 203 | function drawVTick(x,y) 204 | tri(x,y-5, x-3,y-8, x+3,y-8, 5) 205 | tri(x,y+5, x-3,y+8, x+3,y+8, 5) 206 | end 207 | 208 | function printValues(doPrintSin, doPrintCos, doPrintAtan2) 209 | local a=math.fmod(ANIM_T*getAnimMul(), TAU) 210 | local aUnit=a/TAU 211 | 212 | local px=140 213 | 214 | local str=string.format("angle: %.2f",a) 215 | print(str,px,10,12) 216 | 217 | if doPrintSin then 218 | local str=string.format("SIN(angle) = %.2f", SIN(a)) 219 | print(str,px,30,12) 220 | end 221 | 222 | if doPrintCos then 223 | local str=string.format("COS(angle) = %.2f", COS(a)) 224 | print(str,px,50,12) 225 | end 226 | 227 | if doPrintAtan2 then 228 | local str=string.format("ATAN2(sa,ca) = %.2f", ATAN2(SIN(a), COS(a))) 229 | print(str,px,70,12) 230 | end 231 | end 232 | 233 | -- 234 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 235 | -- 236 | -------------------------------------------------------------------------------- /swirly.lua: -------------------------------------------------------------------------------- 1 | local SIN=math.sin 2 | local ATAN2=math.atan2 3 | local PI=math.pi 4 | local TAU=PI*2 5 | T=0 6 | 7 | function TIC() 8 | for y=0,135 do 9 | for x=0,239 do 10 | local dx=x-120 11 | local dy=y-68 12 | local a=ATAN2(dy,dx) 13 | local d=(dx^2+dy^2)^.5 14 | local c=8+SIN(a-T*.1+d)*7 15 | pix(x,y,c) 16 | end 17 | end 18 | 19 | local text="jtruk" 20 | local x=200 21 | local y=124 22 | print(text,x+1,y+1,2) 23 | print(text,x,y,12) 24 | 25 | T=T+1 26 | end 27 | 28 | function BDR(y) 29 | local t=T 30 | for i=1,15 do 31 | local a=0x3fc0+i*3 32 | local r=128+math.sin(y/100+i*.1+t/30)*127 33 | local g=128+math.sin(1+y/113+i*.12+t/31)*127 34 | local b=128+math.sin(2+y/126+i*.13+t/32)*127 35 | poke(a,r) 36 | poke(a+1,g) 37 | poke(a+2,b) 38 | end 39 | end 40 | 41 | -- 42 | -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57 43 | -- 44 | 45 | -------------------------------------------------------------------------------- /swirly.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/swirly.mp4 -------------------------------------------------------------------------------- /video1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/video1.gif -------------------------------------------------------------------------------- /video2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/video2.gif -------------------------------------------------------------------------------- /video3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativenucleus/tic-80-demo-workshop/e75576d6dd6c2a409f77c1039316bf5556dc45ae/video3.gif -------------------------------------------------------------------------------- /workshop.md: -------------------------------------------------------------------------------- 1 | # Workshop Schedule 2 | 3 | ## Intro 4 | 5 | - Make sure everyone has a running version of TIC-80 (part way down [tic-80 Create page](https://tic80.com/create)) 6 | - Anyone susceptible to photosensitity 7 | - Outline of workshop 8 | - Become familiar with TIC-80 9 | - Drawing primitives 10 | - sin/cos 11 | - poke palette 12 | - full screen effect 13 | - History of the demoscene 14 | - Showcasing some demoscene things 15 | - Jumping off points 16 | - Level of programming experience (above 7 / below 3) 17 | - Anyone know about the demoscene? 18 | 19 | ## Switch Dev mode on 20 | 21 | If Dev mode is off (the default), when you hit ESC, you're taken to a menu. When dev mode is off, it takes you back into the command line, or editor. 22 | 23 | - Run a program (Ctrl-R) 24 | - Hit ESC to break program 25 | - Select (options) in menu 26 | - Move up to 'Dev Mode' and switch it on. 27 | - Select Back 28 | - Press Esc 29 | 30 | ## Learning Stuff 31 | 32 | ### Primitives and structures 33 | 34 | `cls, rect, tri, circ, line, elli, pix, print` 35 | (rectb, trib, circb, ellib) 36 | 37 | `function, for, var, if` 38 | 39 | ```lua 40 | function TIC() 41 | T=time()/500 42 | 43 | cls(8) 44 | 45 | for i=0,30 do 46 | x=(i^7)%240 47 | y=(i^5)%68 48 | pix(x,y,12) 49 | end 50 | 51 | circ( 52 | 120+math.sin(T)*100, 53 | 90-math.cos(T)*80, 54 | 20, 55 | 4) 56 | 57 | rect(0,68,240,68,6) 58 | 59 | rect(50,40,80,60,2) 60 | tri(40,40, 90,10, 140,40, 1) 61 | 62 | for x=10,230,10 do 63 | if x<150 or x>=180 then 64 | drawPicket(x) 65 | end 66 | end 67 | end 68 | 69 | function drawPicket(x) 70 | line(x,90, x,110, 12) 71 | end 72 | ``` 73 | 74 | ### Sin/Cos 75 | 76 | ```lua 77 | local ATAN2=math.atan2 78 | local PI=math.pi 79 | local TAU=PI*2 80 | local SIN=math.sin 81 | 82 | function TIC() 83 | T=time() 84 | 85 | for y=0,135 do 86 | for x=0,239 do 87 | local p=y*240+x 88 | local dx=120-x 89 | local dy=68-y 90 | local d=(dx^2+dy^2)^.5 91 | local a=(ATAN2(dy,dx)+PI)/TAU 92 | poke4(p,a*16+T*.001) 93 | end 94 | end 95 | end 96 | ``` 97 | 98 | --------------------------------------------------------------------------------