MarioPartyMaker/src/display.c

211 lines
10 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <ncurses.h>
#include <unistd.h>
#include <termios.h>
#include <limits.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "consts.h"
#include "base.h"
#include "display.h"
void updateRenderer(SDL_Renderer* renderer) {
//printf("E");
SDL_RenderPresent(renderer);
}
void resetRenderer(SDL_Renderer* renderer) {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
}
void drawRectToRenderer(SDL_Renderer* renderer, SDL_Rect* rect, int R, int G, int B, int A) {
SDL_SetRenderDrawColor(renderer, R, G, B, A);
SDL_RenderFillRect(renderer, rect);
}
void placeRectToRenderer(SDL_Renderer* renderer, int X, int Y, int W, int H, int R, int G, int B, int A) {
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_SetRenderDrawColor(renderer, R, G, B, A);
SDL_RenderFillRect(renderer, &rect);
}
void drawLineWithThicc(SDL_Renderer* renderer, int width, int x1, int x2, int y1, int y2, int R, int G, int B, int A) {
// draws line with width (native SDL cannot do that)
double theta = 0.0;
double seglen = distance_pt(x1, x2, y1, y2);
while(theta < 1.0) {
placeRectToRenderer(renderer, convex_seg(x1, x2, theta)-width/2, convex_seg(y1, y2, theta)-width/2, width, width, R, G, B, A);
theta += 1 / seglen;
}
}
void drawLineWithThiccGradient(SDL_Renderer* renderer, int start_width, int end_width, int x1, int x2, int y1, int y2, int R, int G, int B, int A) {
// draws line with width ;
// width goes from start_width to end_with in a linear way
double theta = 0.0;
double seglen = distance_pt(x1, x2, y1, y2);
while(theta < 1.0) {
int width = convex_seg(start_width, end_width, theta) ;
placeRectToRenderer(renderer, convex_seg(x1, x2, theta)-width/2, convex_seg(y1, y2, theta)-width/2, width, width, R, G, B, A);
theta += 1 / seglen;
}
}
void drawDigitToRenderer(SDL_Renderer* renderer, imgs data, int digit, int X, int Y, int W, int H) {
if (!(0 <= digit && digit <= 9))
{
fprintf(stderr, "Illegal digit : '%d'.\n", digit);
exit(1);
}
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_Texture* texture = data.arr[digit];
SDL_RenderCopy(renderer, texture, NULL, &rect);
}
void drawCharToRenderer(SDL_Renderer* renderer, imgs data, char c, int X, int Y, int W, int H) {
if ((int)c >= 97 && (int)c <= 122) {
SDL_Rect rect;
rect.x = X;
rect.y = Y;
rect.w = W;
rect.h = H;
SDL_Texture* texture = data.arr[(int)c - 97];
SDL_RenderCopy(renderer, texture, NULL, &rect);
}
}
void drawNumberToRenderer(SDL_Renderer* renderer, imgs data, int n, int X, int Y, int W, int H, int Woffset) {
if(n == 0) {
drawDigitToRenderer(renderer, data, 0, X + W, Y, W, H);
} else {
int toDraw = 0, remaining = n, nIter = ln_baseN(n, 10);
while(nIter != 0) {
toDraw = remaining%10;
remaining = remaining / 10;
drawDigitToRenderer(renderer, data, toDraw, X + (W-Woffset)*nIter, Y, W, H);
nIter--;
}
}
}
void drawStringToRenderer(SDL_Renderer* renderer, imgs data, char* s, int X, int Y, int W, int H) {
int k = 0 ;
while(s[k] != '\0') {
drawCharToRenderer(renderer, data, s[k], X + W*k, Y, W, H);
k += 1;
}
}
long cell_colors(cell* cl) {
switch (cl->type) {
case START:
return (long)(32) + (long)(256)*(long)(255) + (long)(256*256)*(long)(32);
case BLUE:
return (long)(32) + (long)(256)*(long)(32) + (long)(256*256)*(long)(255);
case RED:
return (long)(255) + (long)(256)*(long)(32) + (long)(256*256)*(long)(32);
case EVENT:
return (long)(32) + (long)(256)*(long)(128) + (long)(256*256)*(long)(32);
case VS:
return (long)(255) + (long)(256)*(long)(128) + (long)(256*256)*(long)(32);
case BOWSER:
return (long)(32) + (long)(256)*(long)(32) + (long)(256*256)*(long)(32);
case CHANCE_TIME:
return (long)(32) + (long)(256)*(long)(128) + (long)(256*256)*(long)(255);
case BOO:
return (long)(128) + (long)(256)*(long)(128) + (long)(256*256)*(long)(128);
case STAR:
return (long)(255) + (long)(256)*(long)(255) + (long)(256*256)*(long)(32);
case BANK:
return (long)(255) + (long)(256)*(long)(255) + (long)(256*256)*(long)(32);
case ITEM_SHOP:
return (long)(220) + (long)(256)*(long)(220) + (long)(256*256)*(long)(220);
}
}
void draw_cell(SDL_Renderer* renderer, int xmin, int xmax, int ymin, int ymax, cell* cl, int draw_id) {
if(cl != NULL && cl->id != draw_id && (cl->coord_x - tile_size > xmin || cl->coord_x - tile_size < xmax || cl->coord_y > ymin || cl->coord_y < ymax)) {
// draw lines
cl->id = draw_id;
int nxmin = to_int((to_double(cl->coord_x) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)) ;
int nymin = to_int((to_double(cl->coord_y) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)) ;
if(cl->next_1 != NULL) {
drawLineWithThiccGradient(renderer, tile_size*220/zoom_factor, 3, nxmin, to_int((to_double(cl->next_1->coord_x) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)), nymin, to_int((to_double(cl->next_1->coord_y) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)), 255, 255, 0, SDL_ALPHA_OPAQUE);
drawDigitToRenderer(renderer, digits, 1, to_int((to_double((cl->coord_x + cl->next_1->coord_x)/2) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)) - 75/6, to_int((to_double((cl->coord_y + cl->next_1->coord_y)/2) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)) - 105/6, 75/3, 105/3);
};
if(cl->next_2 != NULL) {
drawLineWithThiccGradient(renderer, tile_size*220/zoom_factor, 3, nxmin, to_int((to_double(cl->next_2->coord_x) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)), nymin, to_int((to_double(cl->next_2->coord_y) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)), 255, 255, 0, SDL_ALPHA_OPAQUE);
drawDigitToRenderer(renderer, digits, 2, to_int((to_double((cl->coord_x + cl->next_2->coord_x)/2) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)) - 75/6, to_int((to_double((cl->coord_y + cl->next_2->coord_y)/2) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)) - 105/6, 75/3, 105/3);
};
if(cl->next_3 != NULL) {
drawLineWithThiccGradient(renderer, tile_size*220/zoom_factor, 3, nxmin, to_int((to_double(cl->next_3->coord_x) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)), nymin, to_int((to_double(cl->next_3->coord_y) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)), 255, 255, 0, SDL_ALPHA_OPAQUE);
drawDigitToRenderer(renderer, digits, 3, to_int((to_double((cl->coord_x + cl->next_3->coord_x)/2) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)) - 75/6, to_int((to_double((cl->coord_y + cl->next_3->coord_y)/2) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)) - 105/6, 75/3, 105/3);
};
if(cl->next_4 != NULL) {
drawLineWithThiccGradient(renderer, tile_size*220/zoom_factor, 3, nxmin, to_int((to_double(cl->next_4->coord_x) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)), nymin, to_int((to_double(cl->next_4->coord_y) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)), 255, 255, 0, SDL_ALPHA_OPAQUE);
drawDigitToRenderer(renderer, digits, 4, to_int((to_double((cl->coord_x + cl->next_4->coord_x)/2) - to_double(xmin)) * to_double(__width__)) / (to_double(xmax) - to_double(xmin)) - 75/6, to_int((to_double((cl->coord_y + cl->next_4->coord_y)/2) - to_double(ymin)) * to_double(__height__)) / (to_double(ymax) - to_double(ymin)) - 105/6, 75/3, 105/3);
};
// recursive calls
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_1, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_2, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_3, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_4, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_1, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_2, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_3, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_4, draw_id);
// draw current cell
long packed_colors = cell_colors(cl);
if(cl == current) {
placeRectToRenderer(renderer, nxmin-tile_size*250/zoom_factor/2-10, nymin-tile_size*250/zoom_factor/2-10, tile_size*250/zoom_factor+20, tile_size*250/zoom_factor+20, 255, 255, 255, SDL_ALPHA_OPAQUE);
};
placeRectToRenderer(renderer, nxmin-tile_size*250/zoom_factor/2, nymin-tile_size*250/zoom_factor/2, tile_size*250/zoom_factor, tile_size*250/zoom_factor, (int)(packed_colors%256), (int)((packed_colors/256)%256), (int)((packed_colors/256/256)%256), SDL_ALPHA_OPAQUE);
} else if(cl != NULL && cl->id != draw_id) {
cl->id = draw_id;
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_1, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_2, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_3, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->prev_4, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_1, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_2, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_3, draw_id);
draw_cell(renderer, xmin, xmax, ymin, ymax, cl->next_4, draw_id);
}
}
void draw_board(SDL_Renderer* renderer, int xmin, int xmax, int ymin, int ymax, cell* one_cell) {
if(one_cell == NULL) {
fprintf(stderr, "ERROR : cannot draw NULL cell\n");
exit(1);
} else {
draw_cell(renderer, xmin, xmax, ymin, ymax, one_cell, (one_cell->id +1)%727);
}
}