The 512 bytes code challenge

BlitzMax Forums/BlitzMax Programming/The 512 bytes code challenge

remz(Posted 2007) [#1]
Hi Blitzmax coders and welcome to a fun, educational code challenge! Similar to the previous 255 bytes challenge, this one only pushes the limit a bit farther, allowing plenty of creative code and amazing effects!

Here's my entry, the Red 3D Cloud (512 bytes)
p=512 h=256 Graphics p,p m=1000 a#=0.004 v=w=0 Local f#[p*p]
For j=0To p*p-1 f[j]=Rand(9,h)Next
b:TPixmap=CreatePixmap(p,p,6)
Repeat z#=1.3 s=1 e=p-240 For j=s To e-1 For i=0 To p-1
c=f[i+j*p] x#=(i-h)/z y#=(j-c)/z+h+Rand(-3,3)
v=x w=y If x>=0 And x<p And y>=0 And y<p b.pixels[v*4+w*b.pitch]=c
Next z=z/1.0081Next
For j=e-1 To s Step -1 For i=0 Until p f[i+j*p]=f[i+(j-1)*p]*0.999Next Next
f[j*p]=Rand(80,220) For i=1 Until p f[i+j*p]=f[i-1+j*p]+Rand(-m,m)*a Next
DrawPixmap b,0,0 Flip;Until KeyHit(27)



Sledge(Posted 2007) [#2]
Yeah it's an oldie but it's one of my faves... UNLIMITED BOBS!

(512 Bytes -- I'm still on 1.26 so let me know if it flakes out on 1.28!)

Liked the Red 3D Cloud by the way, remz -- kinda therapeutic :D


xlsior(Posted 2007) [#3]
(512 Bytes -- I'm still on 1.26 so let me know if it flakes out on 1.28!)


works OK on 1.28


ImaginaryHuman(Posted 2007) [#4]
Okay, so I couldn't do decent blobby objects in 256 bytes, but here's a nice realtime blobby-object plasma in 511 bytes (not including carriage returns, line feeds, indentation or comments.) The numbers commented on the end of each line is a character count for the line.
Const O=60,B=1024,M=768,Z=512,S=256,W=511,N#=0.2'48
Graphics B,M,32'15
For R#=1To W Step N'19
	A#=R*R/B'8
	SetColor A,A,A'14
	DrawOval R/2,R/2,Z-R,Z-R'24
Next'4
H:TImage=CreateImage(Z,Z)'25
GrabImage(H,0,0)'16
Local C[O],D[O],E[O],F[O],K#[O]'31
For G=0To O-1'13
	C[G]=Rand(0,B)'14
	D[G]=Rand(0,M)'14
	E[G]=Rand(0,4)-2'16
	F[G]=Rand(0,4)-2'16
	K[G]=C[G]'9
Next'4
SetBlend 4'10
Repeat'6
	Cls'3
	For G=0To O-1'13
		C[G]:+E[G]'10
		D[G]:+F[G]'10
		If C[G]<0 Or C[G]>B Then E[G]=-E[G]'35
		If D[G]<0 Or D[G]>M Then F[G]=-F[G]'35
		K[G]:+N'7
		SetColor B-K[G],Z-C[G],Z-D[G]'29	'multi
		SetRotation K[G]'16
		DrawImage H,C[G],D[G]'21
	Next'4
	Flip 1'6
Until KeyHit(27)'16

'Alternative palettes
'SetColor K[G]/2,S-C[G]/3,D[G]/2'31	'hotpink
'SetColor K[G]/2,C[G]/3,S-D[G]/2'32	'yellow
'SetColor K[G],S-C[G]/3,S-D[G]'30	'redyellow
'SetColor B-K[G],Z-C[G],S-D[G]'29	'redyellowmulti
'SetColor B-C[G],Z-D[G],S-K[G]/2'31	'redyellowpinkgreen
'SetColor S-K[G],Z-C[G],B-D[G]'29	'blues
'SetColor K[G],S-C[G]/3,S-D[G]/3'32	'hotpink red
'SetColor S-C[G]/2,D[G]/3,K[G]/2'32	'bluegreen
'SetColor C[G]-D[G],S-K[G],C[G]'31	'blue and pink
'SetColor K[G]-C[G],C[G]-D[G],D[G]'34	'multi
'SetColor K[G]-C[G]-D[G],C[G]-D[G],K[G]'40	'blues

At the end there you can see some alternative ways to generate colors. I liked the multicolored one currently produced, and at 1024x768 anything from 40 to 100 objects looks good.

At the start of the code, the first constant O is the number of blobby objects (currently 60 to give a fairly even density), the constant B is the screen width and M is the screen height. If you change the resolution you may want to change the number of objects to compensate for the change in distribution density.

Changing the DrawOval to a DrawRect will give you inverted blob fields which looks quite different. Also it could do with a SeedRnd(Millisecs()) near the start otherwise I think you get the same behavior and colors each time - but there's no bytes free. Also the colors seem to drift toward a blue/green palette after a while for some reason, but hey.

Each object covers a 512x512 area, which is 262,144 pixels per object in 32-bit color, or about 1.05 megabytes per object. For 60 objects there are about 15.7 million rendered pixels per frame, and approximately 63 megabytes graphics rendered per frame (although a fair amount is clipped). Every pixel is also doing blending operations and since blending is done on a per-color-component basis, there are actually up to 63 million color-blend calculations per frame. The maximum total rendered per second is about 3.7 billion pixels.

Fortunately since not every object is fully on-screen at the same time, it runs smoothly on my ATI X1600 card - which has texture rendering throughput of about 2 billion texels per second. I am not sure if it's going at 60fps or 30. So it'll depend on your graphics card as to whether it runs fast enough.

And finally, press Escape to exit ;-)


plash(Posted 2007) [#5]
^ awesome.


DavidDC(Posted 2007) [#6]
Loved that plasma! Can you slow it down?

Maybe: ?

E[G]=Rand(1,2)-2
F[G]=Rand(1,2)-2


ImaginaryHuman(Posted 2007) [#7]
If you don't mind going beyond the 512 byte limit, you can convert the arrays to all Floats and then specify something like E[G]=(FloatRnd()-0.5)*Speed and the same for F[G]. The C and D arrays (x and y positions) must be float also. Then you can make it really slow if you want to.

Another aspect of how it moves is the rotation around the corner of each object. Currently a constant N is shared between two parts of the program. For the loop with the drawing of ovals the Step should really be 0.5 but it doesn't hurt when it's down at 0.2, since that value is also the rotation speed. You can change K[G]:+N to something like K[G]:+0.1 to slow down the rotation, since K is the rotation angle array.


DavidDC(Posted 2007) [#8]
Thanks! Do you have a website?


ImaginaryHuman(Posted 2007) [#9]
Hi, no I don't have a website yet. I want to make one, actually a few, but I know it will take quite a lot of time and effort and I need some decent content to make it about, so I'm focussing on programming at the moment. Then when I am ready with a game or at least a demo I will put up a website.

I am waiting also for someone else to write another 512-byte effect. Come on guys and gals! ;-)


Sledge(Posted 2007) [#10]
Well I just added the Framework command to my entry (still under 512 bytes source!) in order to get the exe size down too... BRL.GLMax2D produces a smaller exe than BRL.D3D7Max2D but there's a weird stippling effect with the former.

Here's a zip containing both versions -- if you've got time then let me know if you see the difference too as I'm wondering whether to post a bug report.

[Piccies no longer needed]


remz(Posted 2007) [#11]
if you've got time then let me know if you see the difference too as I'm wondering whether to post a bug report.

Tested them both on my Win XP machine, they both look exactly the same.
What's that decompressing thing with your exe? An EXE packer?


plash(Posted 2007) [#12]
hmm.. OpenGL shows a transparent triangle covering half the screen, and dx7 only shows one cirlce (bob?); yet continues to count up.


Sledge(Posted 2007) [#13]
What's that decompressing thing with your exe? An EXE packer?

Yup -- ANDpakk2. Seems to pack smaller than UPX at the expense of some decompression time.

Tested them both on my Win XP machine, they both look exactly the same.

Ah. Must be a driver issue here then (integrated GFX FTW!) -- makes sense as it's fine fullscreen.

hmm.. OpenGL shows a transparent triangle covering half the screen, and dx7 only shows one cirlce (bob?); yet continues to count up.

Now that's not good! (I added some screenshots to my previous post -- the second is what it's supposed to look like.) Do you mind me asking what OS and GFX card you're using? You can see from the source above (have you tried compiling it, incidentally?) that I am not doing anything particularly esoteric.

Thanks for the feedback, chaps.


remz(Posted 2007) [#14]
Ok I got another one, even with on-screen instruction ;)

The Random Tree. 512 bytes. Click the mouse to generate a random tree!
w=512 Graphics w,w Global b#=0.75,p#=33,z#=150,v#=0.0073,d=0,e=1,t=0
n#=0 g=200 Repeat
SeedRnd(e) t:+1 p:+Sin(t)*0.08 Cls
r(256,w,z,-90) DrawText"Click",0,0 Flip() GCCollect() If MouseHit(1) t=-50 e:+1	
Until KeyHit(27)
Function r(x#,y#,l#,a#)
If d>14 Return
d:+1 c#=Cos(a)*l s#=Sin(a)*l x2#=x+c y2#=y+s
If d<5 SetColor 150,99,40 Else h#=Rnd(0.4,1) SetColor 0,255*h,0
DrawLine x,y,x2,y2 w#=Rnd(0.3,1) r(x+c*w,y+s*w,l*b,a-Rnd(p-20,p+20)) w=Rnd(0.3,1) r(x+c*w,y+s*w,l*b,a+Rnd(p-20,p+20)) d:-1
EndFunction



Sledge(Posted 2007) [#15]
WOOT!


ImaginaryHuman(Posted 2007) [#16]
Sledge, it looks as though your window on the left there looks like it has dithering switched on, which suggests it may be a 16-bit display.

Remz - that is very cool indeed, great to see a realtime fractal in motion!


Brucey(Posted 2007) [#17]
Nothing as groovy as fractals and blobs...
511 bytes.
Left/Right and Space to play.
x=995p=360Type t Field a=Rand(0,360),d#=300EndType
w=512 Graphics w,w HideMouse()c=256s=0q=0h=0e:TList=New TList
Repeat
If Rand(1000)>x z=New t e.addlast(z)
If KeyDown(37)a:-2
If KeyDown(39)a:+2
a=(p+a)Mod p
If KeyDown(32) And Not h h=11
If h h:-1
f#=Cos(a)g#=Sin(a)
Cls
DrawText s,9,9
l=20If h=10 l=w
DrawLine c,c,c+f*l,c+g*l
For i:t=EachIn e
m=i.a
k#=i.d
If h=10 And Abs(a-m)<400/k s:+5x:-1e.remove i
DrawOval c+k*Cos(m),c+k*Sin(m),10,10
i.d:-0.5If i.d<5 q=1
Next
Flip
Until KeyHit(27)Or q;Notify s



Brucey(Posted 2007) [#18]
Oh... my best so far is 300 :-p


plash(Posted 2007) [#19]
Do you mind me asking what OS and GFX card you're using


Windows XPSP2 ATI Radeon 7500

@remz:Thats amazing!

EDIT: Left is OpenGL, right is DirectX.
You might have to look closely to see the triangle (it starts at the top left corner)



plash(Posted 2007) [#20]
I just thought of something for the plasma thingy; you should play around with different shapes (maybe create an anim image?)

I would try that, but I'm about to fall asleep on my keyboard, so night!


ImaginaryHuman(Posted 2007) [#21]
Been there done that. ;-)


Sledge(Posted 2007) [#22]
Sledge, it looks as though your window on the left there looks like it has dithering switched on, which suggests it may be a 16-bit display.

You know, that's the very first thing I thought so I had a look at my display properties and -- yup -- 32-bit. But I took another look just now and it was set to bloody 16-bit! I've been running a few fullscreen apps on and off recently so I guess one of 'em stiffed me I FEEL SUCH A FOOL!

@Plash: Thanks for that. Between ATI and Vista (imagine having both!) a bright and glorious future for the PC is assured. 'Grab and paste a portion of the screen mate? Grab and paste a portion of the screen mate? Nah mate. You're mad mate. You're asking for the uuuuuurf!'


plash(Posted 2007) [#23]
'Grab and paste a portion of the screen mate? Grab and paste a portion of the screen mate? Nah mate. You're mad mate. You're asking for the uuuuuurf!'


/me is lost.


Sledge(Posted 2007) [#24]
I'm saying that if ATI hate writing GFX drivers so much then they're probably in the wrong business. What Windows scheme is that in your screenies, by the way?


ImaginaryHuman(Posted 2007) [#25]
Cute game, Brucey, I got 130. ;-\


plash(Posted 2007) [#26]
What Windows scheme is that in your screenies, by the way?


http://lassekongo83.deviantart.com/art/Lakrits-Visual-Style-59440359


Brucey(Posted 2007) [#27]
This one's not very amazing....

511 chars..

Right to turn (right), and Up for forward..

The idea is to navigate to the bottom right corner (which would have been the "exit" had I had more space to work with...

Thanks to DavidDC for the "mod 4" tweak :-)

Anyhoo... have fun :-)


Warpy(Posted 2007) [#28]



Damien Sturdy(Posted 2007) [#29]
@WARPY.

Press Play on tape.
_


Difference(Posted 2007) [#30]
Here's one, Type based, 505'ish


[EDIT] made a small change to let the C() method of the world object take a parameter, because otherwise I could have just used new()


DavidDC(Posted 2007) [#31]
Excellent Peter!


ImaginaryHuman(Posted 2007) [#32]
Nice bubbly particle effect, Peter.


Boiled Sweets(Posted 2007) [#33]
@ImaginaryHuman

Awesome! But how to stop it from going to the blue palette?


ImaginaryHuman(Posted 2007) [#34]
Trying to squeeze that effect into 512 bytes wasn't very easy. I had to make multiple use of some of the variables for things which shouldn't really be tied together. The palette values are being calculated based on the coordinates of the objects and the angle of rotation. It might be preferable to have an entirely separate array for color values per object and to then animate those values as you wish.

Since the objects basically are bouncing off the edges of the screen (even though they appear to move beyond the screen due to rotation), their coordinates should generally increase up to a point and then decrease again so it shouldn't drift towards green/blue and then stay there.

I think possibly it is due to the red component being based on the rotation angle, and there not being any cap on the maximum angle value. It just keeps adding more to the angle so once it goes over 360 it just keeps on going. If you simply change the red color calculation to `(B-K[G]) Mod 256` or something like that you should see the red component being retained, although it's going to jump when it wraps around from 255 to 0. It might be preferable to implement some kind of sine-wave type of color animation, e.g. component=128*Sin(Angle). You'll notice that in the demo it's `B-` the angle which subtracts the angle from 1024, so you might need to play around with it to get the values into a range that appeals to you.

And yes feel free to make it your next screensaver because I don't plan to make screensavers - just had too many difficulties trying to get it to work on a Mac since Apple requires the use of their Objective C framework. I am going to make a blobby-object game at some point, though.


Brucey(Posted 2007) [#35]
just had too many difficulties trying to get it to work on a Mac since Apple requires the use of their Objective C framework

Had a long look into this recently, but we need a way to compile in such a way as to have the end-product a special object file (rather than an executable). Requires a custom appstub, more work on BMK, and a bit more time understanding the compiler flags.
I got as far as having everything (stub+mod) except the bmk changes working. But it seems a lot of effort for something so niche.


ImaginaryHuman(Posted 2007) [#36]
Yes, I looked into it a bit but not quite at that depth, since I didn't quite understand what was needed. My impression was you have to write it in Objective C and use Apple's libraries to open the screen and do timing and stuff so I just gave up on it. If it can't be almost entirely written in BlitzMax I'm not interested. It seemed like a lot of difficult effort just to make a screensaver.

A screensaver can be really cool and fun and get fast results, but not when it's hard to implement. I did sort of get one working on Windows and I noticed many other people have released them for Windows, since Windows makes it relatively easy to do, but even there I had problems getting the preview window to be consistent. So I gave up.

These days screensavers aren't even really screen savers and the whole point is that they show up when you're NOT at your computer, so I don't see the point, but I think they're really cool to actually play around with (options etc) when used for that purpose.


Brucey(Posted 2007) [#37]

left/right, esc to quit


ImaginaryHuman(Posted 2007) [#38]
Cool brucey, I got 2824 on my first attempt. I seem to remember seeing a simple game like this somewhere before. Good job.


Damien Sturdy(Posted 2008) [#39]
some pretty cool stuff.

here's mine. simple, no chance of "winning" hehe.

SuperStrict
Global scx:Int=256
Global scy:Int=256
Graphics scx,scy
Global x:Int,y:Int,c:Int
Global colr:Int,colg:Int,colb:Int,frame:Int
While Not AppTerminate()
	For x=0 To scx-1
		For y=0 To scy-1
			colr=(Sin((((Sin(x)*Cos(y)))*360)+frame)/2)+1
			colg=(Sin((((Cos(x)*Sin(y)))*360)+frame)/2)+1
			colb=(Sin((((Sin((x+y)/1)*Cos((x+y)/2)))*360)+frame)/2)+1
			SetColor colr*255,colg*255,colb*255
			Plot x,y
		Next
	Next
	Flip
	frame=frame+10
Wend


[edit]

Entry 2.

Both of these done at work. this one is inspired by something Chris C did a few days back, decided to code my own version. Pretty easy to put walls in :-)

Global a=256,b=256,e#,cb,ob=1,c#,w#[2,a,b]
Graphics a,b
i=CreateImage(a,b,1,10)
SetBlend 2
While AppTerminate()=0
p:TPixmap=LockImage(i)
w[ob,MouseX(),MouseY()]=Sin(MilliSecs())*2
For x=1 To a-2;For y=1 To b-2;c=((w[ob,x+1,y]+w[ob,x-1,y]+w[ob,x,y+1]+w[ob,x,y-1])/2-w[cb,x,y])*0.999;w[cb,x,y]=c;Next;Next
For x=1 To a-2;For y=1 To b-2;e=(((w[cb,x+1,y]-w[cb,x,y+1])*0.9)+1)*200;WritePixel p,x,y,e+(Int(e) Shl 16);Next;Next
UnlockImage i
DrawImage i,0,0
ob=cb;cb=(cb+1) Mod 2
Flip 0
Wend


I *hope* this one works for you all, i have problems with pixmaps so I get a black screen (including the fix slows it down and isn't required if the problem is with my machine.)


sswift(Posted 2008) [#40]
Imaginary:
How does that blob code of yours work? I could spend a half an hour trying to figure it out, but I'm sure you can describe exactly what it's doing in a couple seconds.

I can see you're drawing something with ovals, copying it and then blitting it about with lightblend, but are they blurry ovals with an exponential falloff or what?


tonyg(Posted 2008) [#41]
Is it this and/or this ?


sswift(Posted 2008) [#42]
Tony:
Well that exponential falloff thing is what I thought he might be doing, but it's not obvious from his code that it is in face what he's doing. I'm not sure how drawing a bunch of ellipses arrives at that, unless maybe he's drawing over the same pixels a ton of times in a wasteful manner to generate the graphic.

(I say wasteful, but I realise it might have been the way that required the least amount of code, and since it's only done once speed may not be an issue.)

I was thinking about exploring this effect for use in my Space Beetles game, cause a bunch of blue blobs merging and seperating would look a lot like some nebula I was planning on having in the background but might be more interesting to look at than a repeating scroll. (On the other hand, it might be too distracting, but maybe if I made it move slowly enough...)


ImaginaryHuman(Posted 2008) [#43]
Yes, read the tutorial as linked to by TonyG, it will explain how the curvature of the gradient is different to a linear curve and how that is what is required in order to produce a curved boundary.

You will notice that if you just draw ovals at decreasing radius' and for each oval you also increase the color value by 1, you're going to get a linear gradient and when you do a lightblend (ADD) of two such images together you do NOT get a blobby-object behavior. You get very angular linear areas of merging like straight tunnels or like the parting of an ocean, but nothing at all curved.

To produce the curvature of the blobby contour you have to modify the gradient to be based on *some* kind of a curved increase rather than linear. It doesn't have to be squared but in my case that seemed to produce a good enough result - different subgenre's of blobby objects seem to have different formula to calculate the falloff amount at a given radius, but squaring is ok.

The way that the blobby objects behave is produced *entirely* from the fact that the gradient is curved.

I draw a bunch of ovals with linearly decreasing size to make sure there are as many levels as possible to create a smooth progression, but as the size decreases linearly the amount of change in the color changes following a squared curve. At the middle of the blob image the colors are being added by about 1 per radius but it levels out to create a curve the further you get. ie the further you get from the center, the quicker the color diminishes.

When you then add two such images together, the result of all the additions, given that the gradient is curved not linear, results in a curved result rather than a linear one, and basically is what you'd consider a blobby object behavior - ie the closer one object gets to the center of another, the more intensity there is and thus the curve appears spacially instead of just in terms of intensity.

Basically, blobby objects are simply `particles` of energy with an energy field around them, and similar to gravity the energy falls off increasingly quickly the further you get from the center, rather than linearly. When you put two particles near to each other, the `value` at any position in the field is simply the sum (addition) of the energy fields of both objects at that coordinate. The addition is done by the lightblend drawing and the squared fall-off energy field values are precalculated per-pixel into images (pixel arrays), making it possible for graphics hardware to render an entire blob field as a single quad, which it is very good at.

This isn't really my invention as such, as blobby objects are done quite a bit already, but doing blobby objects in 2D by precalculating the fields into images and using the hardware to render it fast is (i think) my invention.

And yes there is lots of overdraw from the ellipses - I've since made a function which goes through each pixel once in x-y loops and just figures out the amount of energy at each pixel. I'm not sure it's really any faster.


Does that explain it? It's not that advanced really, it's just clever.


sswift(Posted 2008) [#44]
That's what I thought you were doing. The only thing that's confusing me though is why there's such big flat colored areas. I can see the glowing dots moving about the the falloff around them, but when they approach another dot suddenly there's a big clipped region.

I guess maybe that's to do with color 128 being decently far out from the center of the dot cause it looks like your gradient is spherelike inverse exponential instead of like a regular exponential curve where the center dot would be far higher than the pixels neighboring it.

Also it seems like you're color shifting the dots as they move about as well and fading them out at some points.


ImaginaryHuman(Posted 2008) [#45]
That demo does fade and change the colors which causes the energy field values to be scaled, and since the additions are done on a per-component basis you see different changes in the Red, Blue and Green channels separately.

I think you're referring to what happens when the result of the additions produces a value >255. The value will be clipped. There isn't enough dynamic range, is all. Ideally for the blobs to be accurate and perfect you'd need a floating point buffer and would make sure that values can be added several times higher than the maximum energy in a given object. The flat areas are just the areas where the values have been clipped due to too much brightness, which in part is due to too many objects. Reduce the object count and you'll see less of it, but wherever a blob's edge overlaps another blobs center you'll start to see clipping.


sswift(Posted 2008) [#46]
I thought you might be blitting the scene over itself or using a special blob shape to get that effect. Didn't seem like a the few blobs there seemed to be could make such large flat areas by themselves. But maybe there's more there than it looks like and the only points I see moving around are ones that happen to not have any others nearby.


.rIKmAN.(Posted 2008) [#47]
You guys are mental - some crazy shit in this thread! :)


sswift(Posted 2008) [#48]
I'm glad I ran Brucey's sample, I was thinking about doing that, after seeing a youtube video today of some people in a theatre simulating that game.


fredborg(Posted 2008) [#49]
Can I kick it?

- 512 bytes
- click the ball to keep it in the air
- with motion blur :)
- including hiscore!


ImaginaryHuman(Posted 2008) [#50]
Sswift, yeah, it's just based on the number of objects. 80 is actually a lot and you see the general effect better with like 20 objects.