ref: 0428625c683eb42701271bafabb318a3728a503f
parent: acb956ad79b4e9458af3f1a1a8d029ba33a9dc40
author: qwx <qwx@sciops.net>
date: Sun Sep 12 04:56:56 EDT 2021
graphics improvements, mouse selection - building one-letter name (temporary until pixelart) - only print once char per tile (temporary until pixelart) - colors (temporary until pixelart) - usual background colors - center drawing canvas - draw "hud": selected tile name - limit drawing to visible tiles (for large maps)
--- a/city.c
+++ b/city.c
@@ -23,6 +23,18 @@
return p;
}
+int
+max(int a, int b)
+{
+ return a > b ? a : b;
+}
+
+int
+min(int a, int b)
+{
+ return a < b ? a : b;
+}
+
static void
timeproc(void *)
{
@@ -77,6 +89,8 @@
case Amouse:
if(eqpt(mo.xy, ZP))
mo = mc->Mouse;
+ if(mc->buttons & 1<<0)
+ mouseselect(mc->xy);
break;
case Akbd:
switch(r){
--- a/dat.h
+++ b/dat.h
@@ -58,6 +58,7 @@
};
struct Building{
char *name;
+ char *abbr;
int buildtime;
int buildcost[Gtot];
int prodtime;
@@ -80,6 +81,7 @@
};
struct Terrain{
char *name;
+ char *abbr;
int good;
int initialstock;
double yield;
--- a/defs.c
+++ b/defs.c
@@ -100,6 +100,7 @@
Building buildings[] = {
[Btownhall]{
.name "townhall",
+ .abbr "H",
.buildtime 1000,
.buildcost {0},
.terrain Tplain,
@@ -111,6 +112,7 @@
},
},[Bfishyard]{
.name "fishyard",
+ .abbr "F",
.buildtime 50,
.buildcost {
[Ggold] 5,
@@ -127,6 +129,7 @@
},
},[Bcarpentry]{
.name "carpentry",
+ .abbr "C",
.buildtime 50,
.buildcost {
[Ggold] 3,
@@ -143,6 +146,7 @@
},
},[Bsawmill]{
.name "sawmill",
+ .abbr "L",
.buildtime 50,
.buildcost {
[Ggold] 10,
@@ -161,6 +165,7 @@
},
},[Bmill]{
.name "mill",
+ .abbr "M",
.buildtime 50,
.buildcost {
[Ggold] 8,
@@ -177,6 +182,7 @@
},
},[Bfarm]{
.name "farm",
+ .abbr "B",
.buildtime 50,
.buildcost {
[Ggold] 8,
@@ -197,6 +203,7 @@
},
},[Bquarry]{
.name "quarry",
+ .abbr "Q",
.buildtime 50,
.buildcost {
[Ggold] 5,
@@ -214,6 +221,7 @@
},
},[Bsmeltery]{
.name "smeltery",
+ .abbr "S",
.buildtime 50,
.buildcost {
[Ggold] 12,
@@ -234,6 +242,7 @@
},
},[Bforge]{
.name "forge",
+ .abbr "F",
.buildtime 50,
.buildcost {
[Ggold] 10,
@@ -255,6 +264,7 @@
},
},[Blapidary]{
.name "lapidary",
+ .abbr "L",
.buildtime 50,
.buildcost {
[Ggold] 26,
@@ -277,6 +287,7 @@
},
},[Bmarket]{
.name "market",
+ .abbr "G",
.buildtime 50,
.buildcost {
[Ggold] 10,
@@ -295,36 +306,43 @@
Terrain terrains[] = {
[Tplain]{
.name "plain",
+ .abbr "p",
.good -1,
.initialstock 0,
.yield 0,
},[Twoods]{
.name "woods",
+ .abbr "w",
.good Gwood,
.initialstock 9001,
.yield 1,
},[Tpond]{
.name "pond",
+ .abbr "p",
.good Gfish,
.initialstock 9001,
.yield 1,
},[Tcrop]{
.name "crop",
+ .abbr "c",
.good Gwheat,
.initialstock 800,
.yield 0.8,
},[Tmountain]{
.name "mountain",
+ .abbr "m",
.good Gstone,
.initialstock 9001,
.yield 0.8,
},[Tironvein]{
.name "ironvein",
+ .abbr "i",
.good Giron,
.initialstock 9001,
.yield 0.5,
},[Tgoldvein]{
.name "goldvein",
+ .abbr "g",
.good Ggold,
.initialstock 9001,
.yield 0.3,
--- a/drw.c
+++ b/drw.c
@@ -8,8 +8,21 @@
static char *fontname = "/lib/font/bit/fixed/unicode.6x10.font";
-static Rectangle fbr;
+static Tile *selected;
+
+enum{
+ Cbg,
+ Cterrain,
+ Cbuild,
+ Ctext,
+ Cend,
+};
+static Image *cols[Cend];
+
+static Rectangle fbr, drwwin, hudr;
static Image *fb;
+static Point tlsize, tlofs, tlwindow;
+static int doupdate;
static Image *
eallocimage(Rectangle r, ulong chan, int repl, ulong col)
@@ -21,47 +34,98 @@
return i;
}
-void
+static Point
+scr2tilexy(Point p)
+{
+ p = subpt(p, drwwin.min);
+ p = Pt(p.x / (tlsize.x + 4), p.y / (tlsize.y + 4));
+ assert(p.x < tlwindow.x && p.x >= 0 && p.y < tlwindow.y && p.y >= 0);
+ return p;
+}
+
+static Tile *
+scr2tile(Point p)
+{
+ p = scr2tilexy(p);
+ return map + p.y * mapwidth + p.x;
+}
+
+static void
+drawhud(void)
+{
+ char *name;
+
+ if(selected == nil)
+ return;
+ name = selected->b != nil ? selected->b->name : selected->t->name;
+ draw(screen, hudr, cols[Cbg], nil, ZP);
+ string(screen, hudr.min, cols[Ctext], ZP, font, name);
+}
+
+static void
drawtile(Tile *m)
{
+ int hasbuild;
char *s;
Point p;
- p.x = (m - map) % mapwidth * 16 * font->width;
- p.y = (m - map) / mapwidth * 2 * font->height;
- s = m->b != nil ? m->b->name : m->t->name;
- string(fb, p, display->white, ZP, font, s);
+ p.x = ((m - map) % mapwidth) * (tlsize.x + 4);
+ p.y = ((m - map) / mapwidth) * (tlsize.y + 4);
+ hasbuild = m->b != nil;
+ s = hasbuild ? m->b->abbr : m->t->abbr;
+ string(fb, p, hasbuild ? cols[Cbuild] : cols[Cterrain], ZP, font, s);
}
void
updatedraw(void)
{
- int bail;
+ int x, y;
Tile *m;
- bail = 1;
qlock(&drwlock);
- for(m=map; m<map+mapwidth*mapheight; m++)
- if(m->stale){
- bail = 0;
- drawtile(m);
- m->stale = 0;
- }
+ for(y=0, m=map; y<tlwindow.y; y++){
+ for(x=0; x<tlwindow.x; x++, m++)
+ if(m->stale){
+ drawtile(m);
+ m->stale = 0;
+ doupdate = 1;
+ }
+ m += mapwidth - tlwindow.x;
+ }
qunlock(&drwlock);
- if(bail)
+ if(!doupdate)
return;
- draw(screen, screen->r, fb, nil, ZP);
+ draw(screen, screen->r, fb, nil, tlofs);
+ drawhud();
flushimage(display, 1);
+ doupdate = 0;
}
void
+mouseselect(Point p)
+{
+ doupdate = 1;
+ if(!ptinrect(p, drwwin)){
+ selected = nil;
+ return;
+ }
+ selected = scr2tile(p);
+ doupdate = 1;
+ updatedraw();
+}
+
+static void
redraw(void)
{
+ int x, y;
Tile *m;
draw(fb, fb->r, display->black, nil, ZP);
- for(m=map; m<map+mapwidth*mapheight; m++)
- m->stale = 1;
+ for(y=0, m=map; y<tlwindow.y; y++){
+ for(x=0; x<tlwindow.x; x++, m++)
+ m->stale = 1;
+ m += mapwidth - tlwindow.x;
+ }
updatedraw();
}
@@ -68,9 +132,27 @@
void
resetdraw(void)
{
+ int w, h;
+
+ w = Dx(screen->r);
+ h = Dy(screen->r);
+ fbr.min = ZP;
+ /* for fuck's sake */
+ fbr.max.x = min(w, tlsize.x * mapwidth + (mapwidth - 1) * 4);
+ fbr.max.y = min(h, tlsize.y * mapheight + (mapheight - 1) * 4 + abs(font->height - font->width));
+ tlofs.x = w > fbr.max.x ? (fbr.max.x - w) / 2 : 0;
+ tlofs.y = h > fbr.max.y ? (fbr.max.y - h) / 2 : 0;
+ tlwindow.x = w > fbr.max.x ? mapwidth : min(mapwidth, fbr.max.x / (tlsize.x + 4) + 1);
+ tlwindow.y = h > fbr.max.y ? mapheight : min(mapheight, fbr.max.y / (tlsize.y + 4) + 1);
+ drwwin.min = subpt(screen->r.min, tlofs);
+ drwwin.max = addpt(drwwin.min, fbr.max);
+ hudr.min = addpt(drwwin.max, Pt(-fbr.max.x - 16, 16));
+ hudr.max = Pt(screen->r.max.x - 16, hudr.min.y + font->height);
freeimage(fb);
- fbr = rectsubpt(screen->r, screen->r.min);
fb = eallocimage(fbr, screen->chan, 0, DNofill);
+ if(!eqpt(tlofs, ZP))
+ draw(screen, screen->r, cols[Cbg], nil, ZP);
+ doupdate = 1;
redraw();
}
@@ -79,5 +161,16 @@
{
if(initdraw(nil, fontname, "city") < 0)
sysfatal("initdraw: %r");
+ cols[Cbg] = eallocimage(Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
+ cols[Cterrain] = eallocimage(Rect(0,0,1,1), screen->chan, 1, 0x999999FF);
+ cols[Cbuild] = eallocimage(Rect(0,0,1,1), screen->chan, 1, 0x9B6917FF);
+ cols[Ctext] = display->black;
+ tlsize = stringsize(font, "0");
+ if(tlsize.x < tlsize.y)
+ tlsize.y = tlsize.x;
+ else
+ tlsize.x = tlsize.y;
+ fmtinstall('P', Pfmt);
+ fmtinstall('R', Rfmt);
resetdraw();
}
--- a/fns.h
+++ b/fns.h
@@ -5,5 +5,7 @@
void startsim(void);
void initdrw(void);
void resetdraw(void);
-void redraw(void);
void updatedraw(void);
+void mouseselect(Point);
+int min(int, int);
+int max(int, int);
--- a/sim.c
+++ b/sim.c
@@ -19,18 +19,6 @@
};
static int stock[Gtot], rstock[Rtot];
-int
-max(int a, int b)
-{
- return a > b ? a : b;
-}
-
-int
-min(int a, int b)
-{
- return a < b ? a : b;
-}
-
static void
spawn(Tile *m, int n)
{