mirror of https://github.com/fairyglade/ly.git
				
				
				
			Matrix scrolling text animation (#283)
This commit is contained in:
		
							parent
							
								
									40af8ab4c7
								
							
						
					
					
						commit
						332d7aeefc
					
				|  | @ -2,7 +2,9 @@ | |||
| #animate = false | ||||
| #animate = true | ||||
| 
 | ||||
| # the active animation (only animation '0' available for now) | ||||
| # the active animation | ||||
| # 0 -> PSX DOOM fire (default) | ||||
| # 1 -> CMatrix  | ||||
| #animation = 0 | ||||
| 
 | ||||
| # the char used to mask the password | ||||
|  |  | |||
							
								
								
									
										267
									
								
								src/draw.c
								
								
								
								
							
							
						
						
									
										267
									
								
								src/draw.c
								
								
								
								
							|  | @ -69,11 +69,22 @@ void draw_init(struct term_buf* buf) | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| static void doom_free(struct term_buf* buf); | ||||
| static void matrix_free(struct term_buf* buf); | ||||
| 
 | ||||
| void draw_free(struct term_buf* buf) | ||||
| { | ||||
| 	if (config.animate) | ||||
| 	{ | ||||
| 		free(buf->tmp_buf); | ||||
| 		switch (config.animation) | ||||
| 		{ | ||||
| 			case 0: | ||||
| 				doom_free(buf); | ||||
| 				break; | ||||
| 			case 1: | ||||
| 				matrix_free(buf); | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -481,18 +492,118 @@ static void doom_init(struct term_buf* buf) | |||
| { | ||||
| 	buf->init_width = buf->width; | ||||
| 	buf->init_height = buf->height; | ||||
| 	buf->astate.doom = malloc(sizeof(struct doom_state)); | ||||
| 
 | ||||
| 	uint16_t tmp_len = buf->width * buf->height; | ||||
| 	buf->tmp_buf = malloc(tmp_len); | ||||
| 	tmp_len -= buf->width; | ||||
| 
 | ||||
| 	if (buf->tmp_buf == NULL) | ||||
| 	if (buf->astate.doom == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	memset(buf->tmp_buf, 0, tmp_len); | ||||
| 	memset(buf->tmp_buf + tmp_len, DOOM_STEPS - 1, buf->width); | ||||
| 	uint16_t tmp_len = buf->width * buf->height; | ||||
| 	buf->astate.doom->buf = malloc(tmp_len); | ||||
| 	tmp_len -= buf->width; | ||||
| 
 | ||||
| 	if (buf->astate.doom->buf == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	memset(buf->astate.doom->buf, 0, tmp_len); | ||||
| 	memset(buf->astate.doom->buf + tmp_len, DOOM_STEPS - 1, buf->width); | ||||
| } | ||||
| 
 | ||||
| static void doom_free(struct term_buf* buf) | ||||
| { | ||||
| 	free(buf->astate.doom->buf); | ||||
| 	free(buf->astate.doom); | ||||
| } | ||||
| 
 | ||||
| // Adapted from cmatrix
 | ||||
| static void matrix_init(struct term_buf* buf) | ||||
| { | ||||
| 	buf->init_width = buf->width; | ||||
| 	buf->init_height = buf->height; | ||||
| 	buf->astate.matrix = malloc(sizeof(struct matrix_state)); | ||||
| 	struct matrix_state* s = buf->astate.matrix; | ||||
| 
 | ||||
| 	if (s == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	uint16_t len = buf->height + 1; | ||||
| 	s->grid = malloc(sizeof(struct matrix_dot*) * len); | ||||
| 
 | ||||
| 	if (s->grid == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	len = (buf->height + 1) * buf->width; | ||||
| 	(s->grid)[0] = malloc(sizeof(struct matrix_dot) * len); | ||||
| 
 | ||||
| 	if ((s->grid)[0] == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	for (int i = 1; i <= buf->height; ++i) | ||||
| 	{ | ||||
| 		s->grid[i] = s->grid[i - 1] + buf->width; | ||||
| 
 | ||||
| 		if (s->grid[i] == NULL) | ||||
| 		{ | ||||
| 			dgn_throw(DGN_ALLOC); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	s->length = malloc(buf->width * sizeof(int)); | ||||
| 
 | ||||
| 	if (s->length == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	s->spaces = malloc(buf->width * sizeof(int)); | ||||
| 
 | ||||
| 	if (s->spaces == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	s->updates = malloc(buf->width * sizeof(int)); | ||||
| 
 | ||||
| 	if (s->updates == NULL) | ||||
| 	{ | ||||
| 		dgn_throw(DGN_ALLOC); | ||||
| 	} | ||||
| 
 | ||||
| 	// Initialize grid
 | ||||
| 	for (int i = 0; i <= buf->height; ++i) | ||||
| 	{ | ||||
| 		for (int j = 0; j <= buf->width - 1; j += 2) | ||||
| 		{ | ||||
| 			s->grid[i][j].val = -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (int j = 0; j < buf->width; j += 2) | ||||
| 	{ | ||||
| 		s->spaces[j] = (int) rand() % buf->height + 1; | ||||
| 		s->length[j] = (int) rand() % (buf->height - 3) + 3; | ||||
| 		s->grid[1][j].val = ' '; | ||||
| 		s->updates[j] = (int) rand() % 3 + 1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void matrix_free(struct term_buf* buf) | ||||
| { | ||||
| 	free(buf->astate.matrix->grid[0]); | ||||
| 	free(buf->astate.matrix->grid); | ||||
| 	free(buf->astate.matrix->length); | ||||
| 	free(buf->astate.matrix->spaces); | ||||
| 	free(buf->astate.matrix->updates); | ||||
| 	free(buf->astate.matrix); | ||||
| } | ||||
| 
 | ||||
| void animate_init(struct term_buf* buf) | ||||
|  | @ -501,11 +612,16 @@ void animate_init(struct term_buf* buf) | |||
| 	{ | ||||
| 		switch(config.animation) | ||||
| 		{ | ||||
| 			default: | ||||
| 			case 0: | ||||
| 			{ | ||||
| 				doom_init(buf); | ||||
| 				break; | ||||
| 			} | ||||
| 			case 1: | ||||
| 			{ | ||||
| 				matrix_init(buf); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -534,7 +650,7 @@ static void doom(struct term_buf* term_buf) | |||
| 	uint16_t dst; | ||||
| 
 | ||||
| 	uint16_t w = term_buf->init_width; | ||||
| 	uint8_t* tmp = term_buf->tmp_buf; | ||||
| 	uint8_t* tmp = term_buf->astate.doom->buf; | ||||
| 
 | ||||
| 	if ((term_buf->width != term_buf->init_width) || (term_buf->height != term_buf->init_height)) | ||||
| 	{ | ||||
|  | @ -573,6 +689,130 @@ static void doom(struct term_buf* term_buf) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Adapted from cmatrix
 | ||||
| static void matrix(struct term_buf* buf) | ||||
| { | ||||
| 	static int frame = 3; | ||||
| 	const int frame_delay = 8; | ||||
| 	static int count = 0; | ||||
| 	bool first_col; | ||||
| 	struct matrix_state* s = buf->astate.matrix; | ||||
| 
 | ||||
| 	// Allowed codepoints
 | ||||
| 	const int randmin = 33; | ||||
| 	const int randnum = 123 - randmin; | ||||
| 	// Chars change mid-scroll
 | ||||
| 	const bool changes = true; | ||||
| 
 | ||||
| 	if ((buf->width != buf->init_width) || (buf->height != buf->init_height)) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	count += 1; | ||||
| 	if (count > frame_delay) { | ||||
| 		frame += 1; | ||||
| 		if (frame > 4) frame = 1; | ||||
| 		count = 0; | ||||
| 
 | ||||
| 		for (int j = 0; j < buf->width; j += 2) | ||||
| 		{ | ||||
| 			int tail; | ||||
| 			if (frame > s->updates[j]) | ||||
| 			{ | ||||
| 				if (s->grid[0][j].val == -1 && s->grid[1][j].val == ' ') | ||||
| 				{ | ||||
| 					if (s->spaces[j] > 0) | ||||
| 					{ | ||||
| 						s->spaces[j]--; | ||||
| 					} else { | ||||
| 						s->length[j] = (int) rand() % (buf->height - 3) + 3; | ||||
| 						s->grid[0][j].val = (int) rand() % randnum + randmin; | ||||
| 						s->spaces[j] = (int) rand() % buf->height + 1; | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				int i = 0, seg_len = 0; | ||||
| 				first_col = 1; | ||||
| 				while (i <= buf->height) | ||||
| 				{ | ||||
| 					// Skip over spaces
 | ||||
| 					while (i <= buf->height | ||||
| 							&& (s->grid[i][j].val == ' ' || s->grid[i][j].val == -1)) | ||||
| 					{ | ||||
| 						i++; | ||||
| 					} | ||||
| 
 | ||||
| 					if (i > buf->height) break; | ||||
| 
 | ||||
| 					// Find the head of this col
 | ||||
| 					tail = i; | ||||
| 					seg_len = 0; | ||||
| 					while (i <= buf->height | ||||
| 							&& (s->grid[i][j].val != ' ' && s->grid[i][j].val != -1)) | ||||
| 					{ | ||||
| 						s->grid[i][j].is_head = false; | ||||
| 						if (changes) | ||||
| 						{ | ||||
| 							if (rand() % 8 == 0) | ||||
| 								s->grid[i][j].val = (int) rand() % randnum + randmin; | ||||
| 						} | ||||
| 						i++; | ||||
| 						seg_len++; | ||||
| 					} | ||||
| 
 | ||||
| 					// Head's down offscreen
 | ||||
| 					if (i > buf->height) | ||||
| 					{ | ||||
| 						s->grid[tail][j].val = ' '; | ||||
| 						continue; | ||||
| 					} | ||||
| 
 | ||||
| 					s->grid[i][j].val = (int) rand() % randnum + randmin; | ||||
| 					s->grid[i][j].is_head = true; | ||||
| 
 | ||||
| 					if (seg_len > s->length[j] || !first_col) { | ||||
| 						s->grid[tail][j].val = ' '; | ||||
| 						s->grid[0][j].val = -1; | ||||
| 					} | ||||
| 					first_col = 0; | ||||
| 					i++; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	uint32_t blank; | ||||
| 	utf8_char_to_unicode(&blank, " "); | ||||
| 
 | ||||
| 	for (int j = 0; j < buf->width; j += 2) { | ||||
| 		for (int i = 1; i <= buf->height; ++i) | ||||
| 		{ | ||||
| 			uint32_t c; | ||||
| 			int fg = TB_GREEN; | ||||
| 			int bg = TB_DEFAULT; | ||||
| 
 | ||||
| 			if (s->grid[i][j].val == -1 || s->grid[i][j].val == ' ') | ||||
| 			{ | ||||
| 				tb_change_cell(j, i - 1, blank, fg, bg); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			char tmp[2]; | ||||
| 			tmp[0] = s->grid[i][j].val; | ||||
| 			tmp[1] = '\0'; | ||||
| 			if(utf8_char_to_unicode(&c, tmp)) | ||||
| 			{ | ||||
| 				if (s->grid[i][j].is_head) | ||||
| 				{ | ||||
| 					fg = TB_WHITE | TB_BOLD; | ||||
| 				} | ||||
| 				tb_change_cell(j, i - 1, c, fg, bg); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void animate(struct term_buf* buf) | ||||
| { | ||||
| 	buf->width = tb_width(); | ||||
|  | @ -582,11 +822,16 @@ void animate(struct term_buf* buf) | |||
| 	{ | ||||
| 		switch(config.animation) | ||||
| 		{ | ||||
| 			default: | ||||
| 			case 0: | ||||
| 			{ | ||||
| 				doom(buf); | ||||
| 				break; | ||||
| 			} | ||||
| 			case 1: | ||||
| 			{ | ||||
| 				matrix(buf); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										27
									
								
								src/draw.h
								
								
								
								
							
							
						
						
									
										27
									
								
								src/draw.h
								
								
								
								
							|  | @ -19,6 +19,31 @@ struct box | |||
| 	uint32_t right; | ||||
| }; | ||||
| 
 | ||||
| struct matrix_dot | ||||
| { | ||||
| 	int val; | ||||
| 	bool is_head; | ||||
| }; | ||||
| 
 | ||||
| struct matrix_state | ||||
| { | ||||
| 	struct matrix_dot** grid; | ||||
| 	int* length; | ||||
| 	int* spaces; | ||||
| 	int* updates; | ||||
| }; | ||||
| 
 | ||||
| struct doom_state | ||||
| { | ||||
| 	uint8_t* buf; | ||||
| }; | ||||
| 
 | ||||
| union anim_state | ||||
| { | ||||
| 	struct doom_state* doom; | ||||
| 	struct matrix_state* matrix; | ||||
| }; | ||||
| 
 | ||||
| struct term_buf | ||||
| { | ||||
| 	uint16_t width; | ||||
|  | @ -34,7 +59,7 @@ struct term_buf | |||
| 	uint16_t box_width; | ||||
| 	uint16_t box_height; | ||||
| 
 | ||||
| 	uint8_t* tmp_buf; | ||||
| 	union anim_state astate; | ||||
| }; | ||||
| 
 | ||||
| void draw_init(struct term_buf* buf); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue