Duet/src/render.c

123 lines
3.2 KiB
C

#include "duet.h"
#include <stdlib.h>
/* Bresenham algorithm */
void dcircle(int cx, int cy, int r0, int color, bool fill)
{
int x=-r0, y=0, e=2-2*r0, r=r0;
do {
dpixel(cx-x, cy-y, color);
dpixel(cx+y, cy-x, color);
dpixel(cx+x, cy+y, color);
dpixel(cx-y, cy+x, color);
if(fill) {
dline(cx+x, cy-y, cx-x, cy-y, color);
dline(cx+x, cy+y, cx-x, cy+y, color);
}
r = e;
if(r <= y)
e += (++y * 2) + 1;
if(r > x || e > y)
e += (++x * 2) + 1;
}
while(x < 0);
}
/* From Windmill::render_triangle_black */
static int edge_start(int x1, int y1, int x2, int y2, int px, int py)
{
return (y2 - y1) * (px - x1) - (x2 - x1) * (py - y1);
}
static int min(int x, int y)
{
return (x < y) ? x : y;
}
static int max(int x, int y)
{
return (x > y) ? x : y;
}
void dtriangle(int x1, int y1, int x2, int y2, int x3, int y3, int color)
{
// calcul du rectangle circonscrit au triangle
int min_x = max(0, min(x1, min(x2, x3)));
int max_x = min(DWIDTH-1, max(x1, max(x2, x3)));
int min_y = max(0, min(y1, min(y2, y3)));
int max_y = min(DHEIGHT-1, max(y1, max(y2, y3)));
// calcul des produits vectoriels
int u0_start = edge_start(x2, y2, x3, y3, min_x, min_y);
int u0_step_x = y3 - y2;
int u0_step_y = x2 - x3;
int u1_start = edge_start(x3, y3, x1, y1, min_x, min_y);
int u1_step_x = y1 - y3;
int u1_step_y = x3 - x1;
int u2_start = edge_start(x1, y1, x2, y2, min_x, min_y);
int u2_step_x = y2 - y1;
int u2_step_y = x1 - x2;
int u0, u1, u2;
// parcours en ligne
for(int x=min_x; x<=max_x; x++)
{
u0 = u0_start; u1 = u1_start; u2 = u2_start;
// parcours en colonne
for(int y=min_y; y<=max_y; y++)
{
// si le pixel (x;y) est dans le triangle
if ((u0 | u1 | u2) > 0)
{
dpixel(x, y, color);
}
u0 += u0_step_y; u1 += u1_step_y; u2 += u2_step_y;
}
u0_start += u0_step_x; u1_start += u1_step_x; u2_start += u2_step_x;
}
}
void drectoid(rect_t const *r, int color)
{
if(r->x - max(r->w,r->h)/2 > DWIDTH || r->x + max(r->w,r->h)/2 < 0)
return;
float x0[4] = { r->w/2, -r->w/2, -r->w/2, r->w/2 };
float y0[4] = { -r->h/2, -r->h/2, r->h/2, r->h/2 };
if(r->r == 0) {
drect(r->x+x0[1], r->y+y0[1], r->x+x0[3], r->y+y0[3], color);
return;
}
float sin, cos;
sincosf(r->r, &sin, &cos);
int x[4], y[4];
for(int i = 0; i < 4; i++) {
x[i] = r->x + x0[i] * cos + y0[i] * sin;
y[i] = r->y - x0[i] * sin + y0[i] * cos;
}
dtriangle(x[0], y[0], x[1], y[1], x[2], y[2], color);
dtriangle(x[2], y[2], x[3], y[3], x[0], y[0], color);
}
void render_player(int x, int y, float angle)
{
dcircle(x, y, PLAYER_R, C_RGB(10, 10, 10), false);
float x1, y1, x2, y2;
player_position(angle, &x1, &y1, &x2, &y2);
x1 = x1 - PLAYER_X + x;
y1 = y1 - DHEIGHT/2 + y;
x2 = x2 - PLAYER_X + x;
y2 = y2 - DHEIGHT/2 + y;
dcircle(x1, y1, PLAYER_SIZE, C_RGB(0, 16, 26), true);
dcircle(x2, y2, PLAYER_SIZE, C_RGB(31, 6, 0), true);
}