Created
November 30, 2022 07:40
-
-
Save ubuntor/8abbec2162a6da31581756edd144111b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int frame = 0; | |
int depth_limit = 9; | |
int ti = -1; | |
String world = ""; | |
String world_ending = "..."; | |
int world_length = 3; | |
PVector main = new PVector(400, 400, 90); | |
PVector ba; | |
PVector bb; | |
PVector bc; | |
PVector p; | |
PImage stage1; | |
PImage stage2; | |
int movetime = 240; | |
float colorscale = 0.9; | |
// x,y,s vectors | |
PVector atargets[] = { | |
new PVector(400, 400, 30), | |
new PVector(400-30, 400, 30), | |
new PVector(400-90*1, 400, 90) | |
}; | |
PVector btargets[] = { | |
new PVector(400, 400+30, 30), | |
new PVector(400, 400+30, 30), | |
new PVector(400, 400+30, 30) | |
}; | |
PVector ctargets[] = { | |
new PVector(400-10, 400+30, 10), | |
new PVector(400-10, 400+30, 10), | |
new PVector(400-30, 400+30, 30) | |
}; | |
PVector ptargets[] = { | |
new PVector(400+30, 400, 30), | |
new PVector(400, 400, 30), | |
new PVector(400-30, 400, 30) | |
}; | |
void setup() { | |
rectMode(CENTER); | |
ellipseMode(CENTER); | |
size(800, 800); | |
stage1 = loadImage("stage_1.png"); | |
stage2 = loadImage("stage_2.png"); | |
frameRate(60); | |
} | |
boolean approx_equal(float x, float y) { | |
return abs(x-y) < 0.01; | |
} | |
void clipped_rect(float x, float y, float s) { | |
if (x + s/2 <= 0 || x - s/2 >= 800 || y + s/2 <= 0 || y - s/2 >= 800) { | |
return; | |
} | |
rect(x, y, s, s); | |
} | |
void draw_box(float x, float y, float s, float colorscale, String label, int depth, boolean cloned) { | |
boolean is_main = approx_equal(x, main.x) && approx_equal(y, main.y) && approx_equal(s, main.z); | |
if (is_main) { | |
stroke(255, 255, 255); | |
} else { | |
stroke(0, 0, 0); | |
} | |
if (s >= 2) { | |
fill(80*colorscale, 100*colorscale, 200*colorscale); | |
clipped_rect(x, y, s); | |
textAlign(CENTER, CENTER); | |
textSize(s); | |
fill(255, 255, 255, 128); | |
text(label, x, y - textAscent()*0.08); | |
fill(100*colorscale, 160*colorscale, 250*colorscale); | |
clipped_rect(x+s/3, y+s/3, s/3); | |
} | |
float ratio = s/main.z; | |
PVector ad = PVector.sub(ba, main); | |
PVector bd = PVector.sub(bb, main); | |
PVector cd = PVector.sub(bc, main); | |
PVector pd = PVector.sub(p, main); | |
draw_player(x + ratio*pd.x, y + ratio*pd.y, ratio*p.z, colorscale); | |
if (depth > 0) { | |
if (!cloned) { | |
draw_box(x + ratio*ad.x, y + ratio*ad.y, ratio*ba.z, colorscale + 0.1, "A", depth-1, cloned); | |
draw_box(x + ratio*bd.x, y + ratio*bd.y, ratio*bb.z, colorscale + 0.1, "B", depth-1, cloned); | |
} else { | |
if (label.equals("A")) { | |
draw_box(x + ratio*ad.x, y + ratio*ad.y, ratio*ba.z, colorscale + 0.1, "A", depth-1, cloned); | |
draw_box(x + ratio*bd.x, y + ratio*bd.y, ratio*bb.z, colorscale + 0.1, "B", depth-1, cloned); | |
draw_box(x + ratio*cd.x, y + ratio*cd.y, ratio*bc.z, colorscale + 0.1, "C", depth-1, cloned); | |
} else { | |
draw_box(x + ratio*bd.x, y + ratio*bd.y, ratio*bb.z, colorscale + 0.1, "B", depth-1, cloned); | |
draw_box(x + ratio*cd.x, y + ratio*cd.y, ratio*bc.z, colorscale + 0.1, "C", depth-1, cloned); | |
} | |
} | |
} | |
} | |
void draw_player(float x, float y, float s, float colorscale) { | |
stroke(0, 0, 0); | |
fill(242*colorscale, 134*colorscale, 228*colorscale); | |
clipped_rect(x, y, s); | |
fill(10*colorscale, 10*colorscale, 10*colorscale); | |
ellipse(x-2.8*s/10, y-0.8*s/10, s/5, s/5); | |
ellipse(x+2.8*s/10, y-0.8*s/10, s/5, s/5); | |
} | |
PVector interp(PVector a, PVector b, float t) { | |
return PVector.add(PVector.mult(a, 1-t), PVector.mult(b, t)); | |
} | |
void draw() { | |
boolean cloned = frame >= movetime*3; | |
if (frame % (movetime*2) == 0) { | |
ti += 1; | |
if (ti == atargets.length) { | |
println("done"); | |
noLoop(); | |
return; | |
} | |
} | |
if (frame % (movetime/2) == 0) { | |
String new_world = world; | |
while (new_world.equals(world)) { | |
new_world = ""; | |
if (cloned) { | |
world_ending = "..."; | |
for (int i = 0; i < world_length; i++) { | |
int r = (int)(random(8)); | |
if (r < 2) { | |
new_world += "A"; | |
world_ending = "∞"; | |
break; | |
} else if (r < 5) { | |
new_world += "B"; | |
} else if (r < 8) { | |
new_world += "C"; | |
} | |
} | |
} else { | |
for (int i = 0; i < world_length; i++) { | |
if ((int)(random(2)) == 0) { | |
new_world += "A"; | |
} else { | |
new_world += "B"; | |
} | |
} | |
} | |
} | |
println(Integer.toString(frame)+" "+new_world); | |
world = new_world; | |
} | |
if (frame % (movetime*2) >= movetime && ti < atargets.length-1) { | |
float t = ((float)(frame % (movetime*2) - movetime))/movetime; | |
ba = interp(atargets[ti], atargets[ti+1], t); | |
bb = interp(btargets[ti], btargets[ti+1], t); | |
bc = interp(ctargets[ti], ctargets[ti+1], t); | |
p = interp(ptargets[ti], ptargets[ti+1], t); | |
} else { | |
ba = atargets[ti]; | |
bb = btargets[ti]; | |
bc = ctargets[ti]; | |
p = ptargets[ti]; | |
} | |
background(0); | |
float outerx = main.x; | |
float outery = main.y; | |
float outers = main.z; | |
float cs = colorscale; | |
for (int i = 0; i < world.length(); i++) { | |
PVector parent; | |
switch (world.charAt(i)) { | |
case 'A': | |
default: | |
parent = ba; | |
break; | |
case 'B': | |
parent = bb; | |
break; | |
case 'C': | |
parent = bc; | |
break; | |
} | |
PVector d = PVector.sub(main, parent); | |
outerx += outers/parent.z * d.x; | |
outery += outers/parent.z * d.y; | |
outers *= main.z/parent.z; | |
} | |
if (world.charAt(world.length()-1) == 'A' && cloned) { | |
for (int i = 0; i < world_length - world.length() + 2; i++) { | |
PVector d = PVector.sub(main, ba); | |
outerx += outers/ba.z * d.x; | |
outery += outers/ba.z * d.y; | |
outers *= main.z/ba.z; | |
cs *= colorscale; | |
} | |
} | |
draw_box(outerx, outery, outers, cs, world.substring(world.length()-1), depth_limit, cloned); | |
textSize(36); | |
textAlign(LEFT); | |
fill(255, 255, 255, 255); | |
text("World: "+world+world_ending, 500, 750); | |
if (cloned) { | |
image(stage2, 50, 508); | |
} else { | |
image(stage1, 50, 525); | |
} | |
saveFrame("/tmp/parabox-######.tga"); | |
frame += 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
stage_1.png
:stage_2.png
: