THIS PAGE WON'T BE UPDATED. Future updates will be in the sizecoding.org wiki: [http://www.sizecoding.org/wiki/Bytebattles]
This is an evolving list of various useful tricks for delivering the most awesome fatalities in byte battles. Possibly also interesting for TIC-80 sizecoding in general.
Symbol | Definition |
---|---|
x |
x-coordinate of a pixel |
y |
y-coordinate of a pixel |
i |
index of a pixel |
s |
alias for math.sin |
-
Functions, that are called 3 or more times should be aliased. For example,
e=elli
withe()e()e()
is 3 bytes shorter thanelli()elli()elli()
. Functions with 5 characters may already benefit from aliasing with 2 calls:r=rectb
withr()r()
is 1 byte shorter thanrectb()rectb()
. -
t=0
witht=t+.1
is 3 bytes shorter thant=time()/399
. -
for i=0,32639 do x=i%240y=i/240 end
is 2-3 bytes shorter thanfor y=0,135 do for x=0,239 do end end
. -
(x*x+y*y)^.5
is 6 bytes shorter thanmath.sqrt(x*x+y*y)
. -
s(w-11)
ands(w+8)
both approximatemath.cos(w)
, so onlymath.sin
needs to be aliased.s(w-11)
is slightly more accurate, with the cost of 1 byte.
Most whitespace can be removed from LUA code. For example: x=0y=0
is
valid. All new lines can be removed or replaced with space, making the
whole code a single line:
function TIC()cls()for i=0,32639 do poke4(i,i)end end
⚠️ Lettersa-f
andA-F
after a number cause problems.a=0b=0
is not valid code. It is advisable to only used one letter variables in the rangesg-z
andG-Z
from the start; this will make eventual one-lining easier.
Function load
takes a string of code and returns a function with no
named arguments, with the code as its body. It's particularly useful for
shortening the TIC function after it's onelined:
TIC=load'cls()for i=0,32639 do poke4(i,i)end'
As a rule of thumb, one-lining and using the load trick can bring a ~ 275 character code down to 256.
load
can be even used to minimize a function with parameters: ...
returns the parameters. For example, the following saves 3 bytes:
SCN=load'r=...poke(16320,r)'
⚠️ The backlash causes problems when using the load trick. In particular, if you have a string with escaped characters in the original code i.e.print("foo\nbar")
, then this needs to be double-escaped:load'print("foo\\nbar")'
.
If you have a floating point color value, TIC-80 pix and poke functions
round it (toward zero). To add dithering, add a small value, between 0
and 1, to the color. The best technique depends whether you have x
and
y
available or only i
and how many bytes you can spare:
A quick example demonstrating the 2x2 block dithering:
function TIC()
cls()
for i=0,2399 do
x=i%240
y=i//240
poke4(i,x/30+(x*2-y%2)%4/4)
end
end
The following palettes assume that j
goes from 0 to 47. Usually
there's no need to make a new loop for this: just reuse another loop
with j=i%48
.
Code for testing palettes:
function TIC()
cls()
for j=0,47 do poke(16320+j,s(j/15)*255)end
for c=0,15 do rect(c*5,0,5,5,c)end
end
s=math.sin
In TIC-80 API, the pix
and poke4
functions round numbers towards
zero. This can be abused for a motion blur: poke4(i,peek4(i)-.9)
maps
colors 1 to 15 into one lower value, but value 0 stays at it is. Like
so:
function TIC()
t=time()/9
circ(t%240,t%136,9,15)
for i=0,32639 do poke4(i,peek4(i)-.9)end
end
The basic structure for a raymarcher that has not been crunched to keep it readable. The map is bunch of repeated spheres here:
function TIC()
for i=0,32639 do
-- ray (u,v,w), not normalized!
u=i%240/120-1
v=i/32639-.5
w=1
-- camera origo (x,y,z)
x=3
y=0
z=time()/999 -- camera moves with time
j=0
repeat
X=x%6-3 -- domain repetition
Y=y%6-3
Z=z%6-3
-- ray not normalized=>reduce scale
m=(X*X+Y*Y+Z*Z)^.5/2-1
x=x+m*u
y=y+m*v
z=z+m*w
j=j+1
until j>15 or m<.1
poke4(i,j)
end
end