shithub: gm4s

ref: 861520c581d13762bcd2f9d9a08e8b69a0af30a9
dir: /piece.c/

View raw version
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <pool.h>
#include <draw.h>
#include "dat.h"
#include "fns.h"
#include "/sys/src/games/eui.h"

/* FIXME: stabler rotations? */
int fours[NF][Nrot] = {
	[FI] {
		0b0000111100000000,
		0b0010001000100010,
		0b0000000011110000,
		0b0100010001000100,
	},
	[FJ] {
		0b1000111000000000,
		0b0110010001000000,
		0b0000111000100000,
		0b0100010011000000,
	},
	[FL] {
		0b0010111000000000,
		0b0100010001100000,
		0b0000111010000000,
		0b1100010001000000,
	},
	[FO] {
		0b0000011001100000,
		0b0000011001100000,
		0b0000011001100000,
		0b0000011001100000,
	},
	[FS] {
		0b1100011000000000,
		0b0010011001000000,
		0b0000110001100000,
		0b0100110010000000,
	},
	[FT] {
		0b0100111000000000,
		0b0100011001000000,
		0b0000111001000000,
		0b0100110001000000,
	},
	[FZ] {
		0b0110110000000000,
		0b0100011000100000,
		0b0000011011000000,
		0b1000110001000000,
	},
};

static u32int cols[NF] = {
	[FI] DCyan,
	[FJ] DBlue,
	[FL] DOrange,
	[FO] DYellow,
	[FS] DGreen,
	[FT] DPurple,
	[FZ] DRed,
};
static Image *piece[NF];

/* FIXME: draw level, line clears, score */
/* FIXME: freeze screen on game over + print message instead of immediate exit */

static void
drawplayfield(void)
{
	u32int c, *s, *p, *pe;
	char fc, *f, *fe;

	memset(pic, 0, Vwidth * Vheight * sizeof *p);	/* FIXME: sides */
	p = (u32int *)pic + Wside * Block;
	f = playfield + Wwidth * (Nrow - Wheight);
	for(s=p, fe=playfield+nelem(playfield); f<fe; f++){
		if((fc = *f) == 0)
			//c = cols[nrand(nelem(cols))];
			c = 0xff000000;
		else
			c = cols[fc - 1];
		for(pe=p+Block; p<pe; p++)
			*p = c;
		if(p - s == Wwidth * Block){
			p += Vwidth * (Block - 1) + 2 * Wside * Block;
			s = p;
		}
	}
}

static void
drawfour(int x, int y, int rot, int type)
{
	int f, m, n;
	u32int c, *l, *s, *p, *pe;

	s = (u32int *)pic;
	s += (y - Nstartrow + Nextrarows) * Vwidth * Block + x * Block;
	l = s;
	c = cols[type];
	f = fours[type][rot];
	for(n=0, m=1<<(Nside*Nside-1); m>0; m>>=1){
		if(s >= (u32int *)pic && f & m)
			for(p=s, pe=p+Block; p<pe; p++)
				*p = c;
		if(++n == Nside){
			l += Vwidth * Block;
			s = l;
			n = 0;
		}else
			s += Block;
	}
}

static void
drawui(void)
{
	int y, *h;

	if(held != -1)
		drawfour(-1, Nrow / 2, 1, held);
	for(y=1, h=hist+1; h<hist+nelem(hist); h++, y+=5)
		drawfour(Wside + Wwidth, Nstartrow - Nextrarows + y, 1, *h);
}

static void
drawpiece(void)
{
	if(cur == nil)
		return;
	drawfour(Wside + cur->x, cur->y, cur->rot, cur->type);
}

static void
vscalepic(void)
{
	int n;
	u32int *p, *s, *e;

	n = Vwidth;
	for(s=(u32int*)pic, e=s+n*Vheight; s<e; s=p)
		for(p=s+n; p<s+n*Block; p+=n)
			memcpy(p, s, n * sizeof *p);
}

void
redraw(void)
{
	drawplayfield();
	drawpiece();
	drawui();
	vscalepic();
	flushmouse(1);
	flushscreen();
}

void
initimg(void)
{
	u32int col, *c;
	Rectangle r;
	Image **i, **ie;

	r = Rect(0, 0, Block, Block);
	for(c=cols, i=piece, ie=i+nelem(piece); i<ie; i++, c++){
		col = *c;
		if((*i = allocimage(display, r, XRGB32, 0, col)) == nil)
			sysfatal("allocimage: %r");
		*c = col & 0xff << 24 | col >> 8 & 0xffffff;
	}
}