shithub: etoys

Download patch

ref: 68941726957810d31765772e7d0ddb380d1a5f41
parent: 88a2aed0c2c5450437bd7935eb5847dfdfa50d59
author: rodri <rgl@antares-labs.eu>
date: Sun Jun 18 17:06:11 EDT 2023

isometric: fixed the RFrame transformations.

this simplified the code significantly as a result.
now everything falls into place!

--- a/isometric.c
+++ b/isometric.c
@@ -27,6 +27,9 @@
 	Image *img;
 };
 
+RFrame screenrf;
+RFrame worldrf;
+RFrame tilerf;
 Image *pal[NCOLOR];
 Tile tiles[] = {
 	{ .name = "empty", .id = 'e' },
@@ -35,31 +38,77 @@
 	{ .name = "focus", .id = 'F' }
 };
 Tile *tfocus;
-RFrame worldrf;
 char *map[] = {
 	"eeeee",
 	"eefee",
 	"efbfe",
 	"eefee",
-	"eefee"
+	"eefee",
 };
 Point mpos;
-Point2 spacegrid[10][10];
+Point spacegrid[10][10];
 int showgrid;
 
+Point2
+rfxform(Point2 p, RFrame rf)
+{
+	Matrix m = {
+		rf.bx.x, rf.by.x, 0,
+		rf.bx.y, rf.by.y, 0,
+		0, 0, 1
+	};
+	invm(m);
+	return xform(subpt2(p, rf.p), m);
+}
+
+Point2
+invrfxform(Point2 p, RFrame rf)
+{
+	Matrix m = {
+		rf.bx.x, rf.by.x, 0,
+		rf.bx.y, rf.by.y, 0,
+		0, 0, 1
+	};
+	return addpt2(xform(p, m), rf.p);
+}
+
+Point2
+fromscreen(Point p)
+{
+	return invrfxform(Pt2(p.x,p.y,1), screenrf);
+}
+
 Point
 toscreen(Point2 p)
 {
-	p = invrframexform(p, worldrf);
+	p = rfxform(p, screenrf);
 	return Pt(p.x,p.y);
 }
 
 Point2
-fromscreen(Point p)
+fromworld(Point2 p)
 {
-	return rframexform(Pt2(p.x,p.y,1), worldrf);
+	return invrfxform(p, worldrf);
 }
 
+Point2
+toworld(Point2 p)
+{
+	return rfxform(p, worldrf);
+}
+
+Point2
+fromtile(Point2 p)
+{
+	return invrfxform(p, tilerf);
+}
+
+Point2
+totile(Point2 p)
+{
+	return rfxform(p, tilerf);
+}
+
 void
 initpalette(void)
 {
@@ -93,7 +142,7 @@
 
 	for(i = 0; i < nelem(spacegrid); i++)
 		for(j = 0; j < nelem(spacegrid[i]); j++)
-			spacegrid[i][j] = Pt2(j*TW, i*TH, 1);
+			spacegrid[i][j] = toscreen(fromworld(Pt2(j, i, 1)));
 }
 
 void
@@ -102,15 +151,18 @@
 	Point2 mp, p;
 	char s[256];
 
-	mp = fromscreen(mpos);
+	mp = toworld(fromscreen(mpos));
 	snprint(s, sizeof s, "Global %v", mp);
 	stringbg(screen, addpt(screen->r.min, Pt(20,20)), pal[Cfg], ZP, font, s, pal[Ctxtbg], ZP);
-	p = Pt2(fmod(mp.x, TW),fmod(mp.y, TH),1);
+	p = Pt2(fmod(mp.x,1),fmod(mp.y,1),1);
 	snprint(s, sizeof s, "Local %v", p);
 	stringbg(screen, addpt(screen->r.min, Pt(20,20+font->height)), pal[Cfg], ZP, font, s, pal[Ctxtbg], ZP);
-	p = Pt2((int)mp.x/TW,(int)mp.y/TH,1);
+	p = Pt2((int)mp.x,(int)mp.y,1);
 	snprint(s, sizeof s, "Cell %v", p);
 	stringbg(screen, addpt(screen->r.min, Pt(20,20+font->height*2)), pal[Cfg], ZP, font, s, pal[Ctxtbg], ZP);
+	p = totile(fromscreen(mpos));
+	snprint(s, sizeof s, "Tile %v", p);
+	stringbg(screen, addpt(screen->r.min, Pt(20,20+font->height*3)), pal[Cfg], ZP, font, s, pal[Ctxtbg], ZP);
 }
 
 void
@@ -119,9 +171,9 @@
 	int i, j;
 
 	for(i = 0; i < nelem(spacegrid); i++)
-		line(screen, toscreen(spacegrid[i][0]), toscreen(spacegrid[i][nelem(spacegrid[i])-1]), Endsquare, Endsquare, 0, pal[Cgrid0], ZP);
+		line(screen, spacegrid[i][0], spacegrid[i][nelem(spacegrid[i])-1], Endsquare, Endsquare, 0, pal[Cgrid0], ZP);
 	for(j = 0; j < nelem(spacegrid[0]); j++)
-		line(screen, toscreen(spacegrid[0][j]), toscreen(spacegrid[nelem(spacegrid)-1][j]), Endsquare, Endsquare, 0, pal[Cgrid1], ZP);
+		line(screen, spacegrid[0][j], spacegrid[nelem(spacegrid)-1][j], Endsquare, Endsquare, 0, pal[Cgrid1], ZP);
 }
 
 void
@@ -129,11 +181,8 @@
 {
 	Point p;
 
-	cell.x *= TW;
-	cell.y *= TH;
-	p = toscreen(cell);
-	p.x -= TW/2;
-	p.y -= Dy(t->img->r)-TH;
+	p = toscreen(fromtile(cell));
+	p.y -= Dy(t->img->r) - TH; /* XXX hack to draw overheight tile sprites */
 	draw(screen, Rpt(p,addpt(p, Pt(TW,Dy(t->img->r)))), t->img, nil, ZP);
 }
 
@@ -147,14 +196,14 @@
 	draw(screen, screen->r, pal[Cbg], nil, ZP);
 	for(i = 0; i < nelem(map); i++)
 		for(row = map[i]; *row; row++){
-			dp = Pt2(row-map[i],i,1);
+			dp = Pt2(row-map[i],nelem(map)-i-1,1);
 			for(j = 0; j < nelem(tiles); j++)
 				if(tiles[j].id == *row)
 					drawtile(&tiles[j], dp);
 		}
-	dp = fromscreen(mpos);
-	dp.x = (int)dp.x/TW;
-	dp.y = (int)dp.y/TH;
+	dp = toworld(fromscreen(mpos));
+	dp.x = (int)dp.x;
+	dp.y = (int)dp.y;
 	drawtile(tfocus, dp);
 	if(showgrid)
 		drawgrid();
@@ -169,16 +218,16 @@
 	Point cell;
 	char buf[2];
 
-	mp = fromscreen(mpos);
+	mp = toworld(fromscreen(mpos));
 	if(mp.x < 0 || mp.y < 0)
 		return;
-	cell.x = mp.x/TW;
-	cell.y = mp.y/TH;
+	cell.x = mp.x;
+	cell.y = mp.y;
 	if(cell.y >= nelem(map) || cell.x >= strlen(map[cell.y]))
 		return;
-	snprint(buf, sizeof buf, "%c", map[cell.y][cell.x]);
+	snprint(buf, sizeof buf, "%c", map[nelem(map)-cell.y-1][cell.x]);
 	if(eenter("tile id", buf, sizeof buf, m) > 0)
-		map[cell.y][cell.x] = buf[0];
+		map[nelem(map)-cell.y-1][cell.x] = buf[0];
 }
 
 void
@@ -235,10 +284,17 @@
 		sysfatal("initdraw: %r");
 	initpalette();
 	inittiles();
-	initgrid();
+	screenrf.p = Pt2(0,0,1);
+	screenrf.bx = Vec2(1,0);
+	screenrf.by = Vec2(0,1);
 	worldrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.min.y+Dy(screen->r)/3,1);
-	worldrf.bx = Vec2(1,2);
-	worldrf.by = Vec2(-0.5,1);
+	worldrf.bx = Vec2(TW/2,TH/2);
+	worldrf.by = Vec2(TW/2,-TH/2);
+	tilerf.p = subpt2(worldrf.p, Vec2(0,TH/2));
+	tilerf.bx = worldrf.bx;
+	tilerf.by = worldrf.by;
+
+	initgrid();
 	einit(Emouse|Ekeyboard);
 	redraw();
 	for(;;)
@@ -267,5 +323,6 @@
 	if(getwindow(display, Refnone) < 0)
 		sysfatal("resize failed");
 	worldrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.min.y+Dy(screen->r)/3,1);
+	tilerf.p = subpt2(worldrf.p, Vec2(0,TH/2));
 	redraw();
 }