#include #include #include #include #include #include #include #include "dat.h" #include "fns.h" Mousectl *mctl; ulong kdown; double Δt; Image *screenb; Memimage *fb; Memimage *bg, *fg; Sprite bob; Rune keys[Ke] = { [K↑] Kup, [K↓] Kdown, [K←] Kleft, [K→] Kright }; Memimage* eallocmemimage(Rectangle r, ulong chan) { Memimage *i; i = allocmemimage(r, chan); if(i == nil) sysfatal("allocmemimage: %r"); memfillcolor(i, DTransparent); return i; } Memimage* rgb(ulong c) { Memimage *i; i = eallocmemimage(Rect(0,0,1,1), screen->chan); i->flags |= Frepl; i->clipr = Rect(-1e6, -1e6, 1e6, 1e6); memfillcolor(i, c); return i; } Memimage* loadtexture(char *path) { Memimage *i; int fd; fd = open(path, OREAD); if(fd < 0) sysfatal("open: %r"); i = readmemimage(fd); if(i == nil) sysfatal("readmemimage: %r"); close(fd); return i; } void kbdproc(void*) { Rune r, *a; char buf[128], *s; int fd, n; threadsetname("kbdproc"); if((fd = open("/dev/kbd", OREAD)) < 0) sysfatal("kbdproc: %r"); memset(buf, 0, sizeof buf); for(;;){ if(buf[0] != 0){ n = strlen(buf)+1; memmove(buf, buf+n, sizeof(buf)-n); } if(buf[0] == 0){ if((n = read(fd, buf, sizeof(buf)-1)) <= 0) break; buf[n-1] = 0; buf[n] = 0; } if(buf[0] == 'c'){ if(utfrune(buf, Kdel)){ close(fd); threadexitsall(nil); } } if(buf[0] != 'k' && buf[0] != 'K') continue; s = buf+1; kdown = 0; while(*s){ s += chartorune(&r, s); for(a = keys; a < keys+Ke; a++) if(r == *a){ kdown |= 1 << a-keys; break; } } } } void drawproc(void *arg) { Channel *c; c = arg; for(;;){ send(c, nil); sleep(FPS2MS(60)); } } void resetfb(void) { freeimage(screenb); screenb = allocimage(display, Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan, 0, DNofill); freememimage(fb); fb = eallocmemimage(Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan); } void redraw(void) { Rectangle r; memimagedraw(fb, fb->r, bg, ZP, nil, ZP, SoverD); memimagedraw(fb, Rpt(subpt(bob.p, Pt(Dx(bob.spr->r),Dy(bob.spr->r))), addpt(bob.p, Pt(32,32))), bob.spr, ZP, nil, ZP, SoverD); for(r = fb->r; r.min.y < fb->r.max.y; r.min.y++){ r.max.y = r.min.y+1; loadimage(screenb, r, byteaddr(fb, r.min), bytesperline(r, fb->depth)); } lockdisplay(display); draw(screen, screen->r, screenb, nil, ZP); flushimage(display, 1); unlockdisplay(display); } void mouse(void) { } void resize(void) { if(getwindow(display, Refnone) < 0) fprint(2, "can't reattach to window\n"); resetfb(); redraw(); } void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } void threadmain(int argc, char *argv[]) { vlong t0, t; Channel *drawc; ARGBEGIN{ default: usage(); }ARGEND; if(argc) usage(); if(initdraw(nil, nil, nil) < 0) sysfatal("initdraw: %r"); if(memimageinit() < 0) sysfatal("memimageinit: %r"); if((mctl = initmouse(nil, screen)) == nil) sysfatal("initmouse: %r"); resetfb(); bg = rgb(DWhite); fg = rgb(DBlack); bob.spr = loadtexture("assets/bob.pic"); bob.p = divpt(fb->r.max, 2); drawc = chancreate(1, 0); display->locking = 1; unlockdisplay(display); proccreate(kbdproc, nil, mainstacksize); proccreate(drawproc, drawc, mainstacksize); t0 = nsec(); for(;;){ enum {MOUSE, RESIZE, DRAW}; Alt a[] = { {mctl->c, &mctl->Mouse, CHANRCV}, {mctl->resizec, nil, CHANRCV}, {drawc, nil, CHANRCV}, {nil, nil, CHANNOBLK} }; switch(alt(a)){ case MOUSE: mouse(); break; case RESIZE: resize(); break; case DRAW: redraw(); break; } t = nsec(); Δt = (t-t0)/1e9; t0 = t; if(kdown & 1<