/*- * Copyright (C) 2025 Alessandro Iezzi * * This file is part of Tris Game. * * Tris Game is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Tris Game is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Tris Game. If not, see . */ #include #include #include #include #include "engine.h" #include "../util.h" #include "ui/ui.h" #include "../util/list.h" #include "types.h" #ifdef X11 #include #endif #define RANGE_GL 2.0f static float xstep; static float ystep; static int width; static int height; static list_t *lines = NULL; typedef struct Line { float x1, y1, x2, y2; } Line; typedef struct Engine { UI *ui; list_t *circles; void (*draw_frame)(); } Engine; static Engine *engine; /* FPS */ static time_t start; static int frames; static time_t end; void (*dispatch_ui_event)(int); void (*on_mouse_pressed)(); void engine_init(int w, int h) { engine = malloc(sizeof(Engine)); if (engine == NULL) { log_error("Error allocating memory for engine"); exit(EXIT_FAILURE); } engine->circles = list_create(); width = w; height = h; engine->ui = ui_init(w, h); lines = list_create(); } static Circle * engine_new_circle(float cx, float cy, float r, int num_segments, int outline) { Circle *circle = malloc(sizeof(Circle)); circle->cx = cx; circle->cy = cy; circle->r = r; circle->num_segments = num_segments; circle->outline = outline; return circle; } void engine_draw_circle(float cx, float cy, float r, int num_segments, int outline) { if (engine == NULL || engine->circles == NULL) return; list_add(engine->circles, engine_new_circle(cx, cy, r, num_segments, outline)); } static Line * engine_new_line(float x1, float y1, float x2, float y2) { Line *line = malloc(sizeof(Line)); line->x1 = x1; line->y1 = y1; line->x2 = x2; line->y2 = y2; return line; } void engine_draw_line(float x1, float y1, float x2, float y2) { if (lines != NULL) { Line *line = engine_new_line(x1, y1, x2, y2); list_add(lines, line); } } static void engine_calculate_fps() { frames ++; end = time(NULL); if (end - start >= 1.0) { printf("FPS: %d\n", frames); frames = 0; start = time(NULL); } } static void render_line(Line *line) { glVertex2f(line->x1, line->y1); glVertex2f(line->x2, line->y2); } static void draw_lines() { if (lines == NULL || lines->size <= 0) return; glLineWidth(5.0f); glBegin(GL_LINES); glColor3f(1.0f, 1.0f, 0.0f); /* Yellow */ list_node_t *current = lines->head; do { render_line(current->data); current = current->next; } while (current != NULL); glEnd(); } static void draw_frames() { glClearColor(0.0f, 0.0f, 0.2f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); draw_lines(); engine_calculate_fps(); } static void engine_on_ui_expose(UIEventResize *er) { /* Set the viewport to the window size */ glViewport(0, 0, er->width, er->height); /* Objects in the rendering area must maintain the proportions. So, let's enable Ortho */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); float aspect; if (er->width >= er->height) { aspect = (float)er->width / (float)er->height; glOrtho(-aspect, aspect, -1, 1, -1, 1); } else { aspect = (float)er->height / (float)er->width; glOrtho(-1, 1, -aspect, aspect, -1, 1); } /* Returns to the model view */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void engine_loop(void) { ui_set_resize_listener(engine_on_ui_expose); ui_set_loop_listener(draw_frames); /* FPS calculation */ start = time(NULL); frames = 0; ui_loop(); } void engine_on_mouse_pressed(void (*event)()) { on_mouse_pressed = event; } static void engine_dispatch_ui_events(int type) { int event_type = 0; switch (type) { #ifdef X11 case ButtonPress: event_type = ENGINE_MOUSE_PRESSED; if (on_mouse_pressed != NULL) { on_mouse_pressed(); } break; #endif default: event_type = 0; break; } dispatch_ui_event(event_type); } void engine_input(void (*f_input)(int engine_input)) { ui_set_generic_listener(engine_dispatch_ui_events); dispatch_ui_event = f_input; }