Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#include "GL/glew.h"
- #include "SDL/SDL.h"
- #include "SDL/SDL_ttf.h"
- #include "SDL/SDL_opengl.h"
- #include <math.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <time.h>
- // astyle -SUET81
- // LINUX.Makefile: "gcc main.c -Wall -g -o hex -lGL -lGLU -lSDL"
- /* WIN.bat
- PATH = ..\..\b\MinGW\bin
- gcc.exe main.c -pg -o hex.exe -lmingw32 -lglew32 -lSDLmain \
- -lSDL -lSDL_image -lSDL_ttf -lopengl32 -lglu32
- hex.exe
- */
- //TODO LIST
- /*
- -реализовать диалоги.
- -подсвечивать путь, по которому пойдет юнит при наведении на клетку.
- -массив персонажей -> динамический список. а то сложно удалять. хз !!!
- -скелетная анимация
- -загрузка статических мешей(и покадровой анимации) в vertex arrays
- -освещение
- -нормальные тени
- -базовый гуй.
- -ландшафт. маска высоты.
- -УПОРЯДОЧИТЬ ЭТОТ БРЕД
- -искуственный интеллект. хоть какойнибудь.
- -возможность привязывать кнопки\лейблы к разным краям экрана
- */
- #define ushort unsigned short int
- #define uint unsigned int
- #define AFTERSCAN_PRINT 0
- #define RESIZE 1 //remove later
- #define resize_coefficient (0.10) //remove later
- #define V_COUNT 500
- #define VT_COUNT 500
- #define VN_COUNT 500
- #define F_COUNT 500
- #define attack_cost 2 //TODO. надо что б считалась была вбита в юнит.
- //возможно вытаскивалась из типа атаки, если у юнита несколько атак.
- // STRUCTURES
- typedef struct Q {
- long int tail;
- long int head;
- ushort *qx;
- ushort *qy;
- long int qu_size;
- } Q;
- typedef struct vector {
- float x, y, z;
- } vector;
- typedef struct texture_coords {
- float u, v;
- } texture_coords;
- typedef struct indexes {
- int v1, v2, v3;
- int vt1, vt2, vt3;
- int vn1, vn2, vn3;
- } indexes;
- //TODO ПЕРЕДЕЛАТЬ НАХЕР К ОДНОМУ МАССИВУ!!!
- typedef struct model {
- vector vertexes[V_COUNT];
- vector normals[VN_COUNT];
- texture_coords text_coords[VT_COUNT];
- indexes faces[F_COUNT];
- int f_count; //количество фэйсов
- } model;
- //хранит свойства юнитов. потом сделать.
- typedef struct u_prop { //unit properties
- char *name;
- int value;
- } u_prop;
- typedef struct unit unit;
- struct unit {
- u_prop properties[10]; // свойства персонажа. TODO
- int mx, my; // grid position
- float x, y; // real position
- int health; //TODO
- int cost_attack;
- int attack_distance;
- int player;
- float rot;
- int frame;
- //bool can_atack;
- //bool can_move;
- ushort ap; //acton points
- float movement_speed; // скорость перемещения
- float rotation_speed; // скорость поворота
- unit* next;
- };
- typedef struct cell {
- uint init_cost;
- uint move_cost;
- ushort parent_x, parent_y; //используется в путенахождении
- //TODO тут еще можно зафигначить всякие дополнительные параметры, типа
- //"есть ли у юнита на этйо клетке поддержка"
- // или туман войны
- //мысль. можно ввести уровни тумана войны. вполне можно =)
- //character *ch;
- unit* unit;
- } cell;
- typedef struct gui_button {
- char *name; //логическое имя кнопки(напр. "идентификатор игрока")
- int x, y; //position
- int sx, sy; //size
- int textSX, textSY; //ширина и высота текстуры. пиксили.
- unsigned textureID; //индекс текстуры кнопки
- char *text; //отображаемый текст кнопки
- //colorFG
- //colorBG
- } gui_button;
- //~STRUCTURES
- /* GLOBAL VARIABLES */
- GLUquadricObj *GQO; //тестовый объект
- #define MODE_SELECT 1
- #define MODE_MOVE 2
- #define MODE_FIGHT 3
- #define MODE_PAUSE 5
- int MODE = MODE_SELECT;
- int PREVIOUS_MODE;
- typedef struct fight fight;
- struct fight{
- unit* u1;
- unit* u2;
- };
- fight FIGHT = {NULL, NULL};
- int PLAYER = 1; //TODO игроков то может быть и больше двух. подумать. потом.
- int cursorX, cursorY; //координаты курсора
- int aX = 99, aY = 99; //active cell
- unit* SELECTED_UNIT = NULL;
- typedef struct camera {
- float x, y;
- float horiz_angle;
- float vert_angle;
- float distanse;
- bool is_rotating;
- } camera;
- camera CAMERA = {0, 0, 0, 60, 6, false};
- //инфа о сторонах шестигранника. TODO посчитать и захардкодить. )
- float HEX_EX;
- float HEX_IN;
- float HEX[6*3]; //хранит координаты вершин шестригранника
- //размеры поля TODO ошибка если не квадратное.
- //проверить на неквадратном и исправить ошибки
- #define MAP_SIZE_X (10)
- #define MAP_SIZE_Y (10)
- int PICKED_SMTH;
- bool isProgramLooping = true;
- SDL_Surface *surface;
- int video_flags; /* Flags to pass to SDL_SetVideoMode */
- int SCR_WIDTH = 800;
- int SCR_HEIGHT = 600;
- int SCR_BPP = 32;
- TTF_Font* font;
- cell MAP[MAP_SIZE_X][MAP_SIZE_Y]; //собсственно это и есть карта =)
- model mdl[130]; //массив анимаций. пока что только одна модель.
- GLuint texture; //ID текстуры персонажа
- GLuint sky_texture[6]; //ID текстур неба.
- //нужен для нахождения пути. завернуто в структуру
- typedef struct move {
- int mx1, my1, mx2, my2;
- float rx1, ry1, rx2, ry2;
- float speed;
- float step_x; //за кадр по оси Х
- float step_y; //за кадр по оси Y
- int step_count; //сколко кадров осталось до конца движения
- unit* unit;
- } move;
- move MOVE;
- unit* UNITS; // список с юнитами
- int BUTTONS_COUNT = 0; //число задействованных кнопок
- int SELECTED_BUTTON; //индекс выбранной кнопки
- gui_button BUTTONS[100]; //массив кнопок
- Q q; // очередь. нужна для нахождения пути
- ushort back_path_x[100];
- ushort back_path_y[100];
- ushort back_path_current = 0;
- //======================================================
- /*
- void list_remove(node **p) // remove head
- {
- if (p != NULL && *p != NULL)
- {
- node *n = *p;
- *p = (*p)->next;
- free(n);
- }
- }
- */ //TODO при смерти юнита
- int
- get_distance(int x1, int y1, int x2, int y2)
- {
- x1 += y1/2;
- x2 += y2/2;
- int dx = x2 - x1;
- int dy = y2 - y1;
- return((abs(dx) + abs(dy) + abs(dx-dy)) / 2);
- }
- bool
- get_close_hex_pos(int x, int y, int id, int *dest_x, int *dest_y)
- {
- int dx, dy;
- switch (id) {
- case 0:
- dx = x+1;
- dy = y;
- break;
- case 1:
- dx = x-1;
- dy = y;
- break;
- case 2:
- dx = x+1;
- dy = y;
- break;
- case 3:
- dx = x;
- dy = y+1;
- break;
- case 4:
- if (y%2==0) {
- dx = x+1;
- dy = y-1;
- } else {
- dx = x-1;
- dy = y-1;
- }
- break;
- case 5:
- if (y%2==0) {
- dx = x+1;
- dy = y+1;
- } else {
- dx = x-1;
- dy = y+1;
- }
- break;
- }
- if ((dx < MAP_SIZE_X) && (dy < MAP_SIZE_Y) && (dx >= 0 && dy >= 0)) {
- *dest_x = dx;
- *dest_y = dy;
- return(true);
- }
- return(false);
- }
- // преобразовывает координаты сетки в реальные
- void
- map_to_real(int mx, int my, float *rx, float *ry)
- {
- *rx = (2 * HEX_IN * mx);
- if (my%2 != 0)
- *rx -= HEX_IN;
- *ry = 1.5 * HEX_EX * (float)my;
- }
- void
- generate_hex()
- {
- HEX_EX = 0.42;
- //HEX_EX = 1;
- HEX_IN = sqrt(HEX_EX*HEX_EX - (HEX_EX/2)*(HEX_EX/2));
- int i;
- //for(i = 5; i >= 0; i--)
- for (i=0; i<6; i++) {
- HEX[i*3] = HEX_EX * cos((M_PI_2) + 2*M_PI * i/6); //x
- HEX[i*3+1] = HEX_EX * sin((M_PI_2) + 2*M_PI * i/6); //y
- HEX[i*3+2] = 0; //пропустить Z элемент
- }
- }
- bool
- is_lines_cross(float x1, float y1, float x2, float y2,
- float x3, float y3, float x4, float y4)
- {
- float ua = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3))
- /((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
- float ub = ((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3))
- /((y4-y3)*(x2-x1)-(x4-x3)*(y2-y1));
- // printf("ua:%f, ub:%f\n", ua, ub);
- //TODO как то странно он иногда подсвечивает граничные хексы
- // if(0<ua && ua<1 && 0<ub && ub <1){ //НЕ учитывать общие вершины
- if (0<=ua && ua<=1 && 0<=ub && ub <=1) { // учитывать общие вершины
- //printf("point is (%.2f, %.2f)\n", x1+ua*(x2-x1), y1+ua*(y2-y1));
- return(true);
- } else {
- //puts("no point");
- return(false);
- }
- }
- bool
- check_line_hex_intersects(
- int bx, int by, // begin
- int ex, int ey, // end
- int cx, int cy // check it
- )
- {
- float rbx, rby; // begin
- float rex, rey; // end
- float rcx, rcy; // check it
- bool intersects = false;
- int i;
- for (i = 0; i < 3; i++) {
- map_to_real(cx, cy, &rcx, &rcy);
- float x1 = rcx + HEX_EX * cos((M_PI_2) + 2*M_PI * i/6);
- float y1 = rcy + HEX_EX * sin((M_PI_2) + 2*M_PI * i/6);
- float x2 = rcx + HEX_EX * cos((M_PI_2) + 2*M_PI * (i+3)/6);
- float y2 = rcy + HEX_EX * sin((M_PI_2) + 2*M_PI * (i+3)/6);
- map_to_real(bx, by, &rbx, &rby);
- map_to_real(ex, ey, &rex, &rey);
- if (is_lines_cross(x1,y1,x2,y2, rbx,rby,rex,rey)) {
- intersects = true;
- }
- }
- return(intersects);
- }
- void
- translate(ushort y, ushort x)
- {
- float ry, rx;
- map_to_real(x, y, &rx, &ry);
- glTranslatef(rx, ry, 0);
- }
- float
- get_rot_angle(int x1, int y1, int x2, int y2)
- {
- float rx1, ry1, rx2, ry2;
- map_to_real(x1, y1, &rx1, &ry1);
- map_to_real(x2, y2, &rx2, &ry2);
- float distance = sqrt(pow(ry2-ry1, 2) + pow(rx2-rx1, 2));
- float angle = (asin((rx2-rx1)/distance))/ M_PI * 180.0;
- if (ry2-ry1 > 0)
- angle = -(180+angle);
- return(angle);
- }
- //TODO встроить в movelogic
- void
- start_move(int x1, int y1, int x2, int y2)
- {
- map_to_real(x1, y1, &MOVE.rx1, &MOVE.ry1);
- map_to_real(x2, y2, &MOVE.rx2, &MOVE.ry2);
- float speed = SELECTED_UNIT->movement_speed;
- float distance = sqrt(pow(MOVE.ry2-MOVE.ry1, 2) + pow(MOVE.rx2-MOVE.rx1, 2));
- MOVE.step_x = speed * ((MOVE.rx2-MOVE.rx1)/distance);
- MOVE.step_y = speed * ((MOVE.ry2-MOVE.ry1)/distance);
- MOVE.step_count = (int)(distance/speed);
- //MOVE.angle = (asin((MOVE.rx2-MOVE.rx1)/distance))/M_PI*180.0;
- //if (MOVE.step_y > 0)
- // MOVE.angle = -(180+MOVE.angle);
- }
- void
- push(Q *q, ushort x, ushort y, ushort px, ushort py, uint NEW)
- {
- MAP[x][y].move_cost = NEW;
- MAP[x][y].parent_x = px;
- MAP[x][y].parent_y = py;
- if (q->tail == q->qu_size) {
- q->tail = 0;
- }
- q->qx[q->tail] = x;
- q->qy[q->tail] = y;
- (q->tail)++;
- }
- void
- try_push(Q *q, ushort x, ushort y, ushort px, ushort py)
- {
- if ((x < MAP_SIZE_X) && (y < MAP_SIZE_Y)) { //(x >= 0 && y >= 0) but ushort
- if (!MAP[x][y].unit) { //что бы не проходить через другх
- uint NEW = MAP[px][py].move_cost + MAP[x][y].init_cost;
- if ((MAP[x][y].move_cost > NEW)) //if(OLD > NEW)
- push(q, x, y, px, py, NEW);
- }
- }
- }
- bool
- pop(Q *q, ushort *x, ushort *y)
- {
- if (q->head == q->tail) {
- return(false); // Q is empty
- }
- *x = q->qx[q->head];
- *y = q->qy[q->head];
- (q->head)++;
- if (q->head == q->qu_size)
- q->head = 0;
- return(true);
- }
- bool
- init_q(Q *q, long int size)
- {
- q->qx = (malloc(size * sizeof(ushort)));
- q->qy = (malloc(size * sizeof(ushort)));
- if (q->qx == NULL || q->qy == NULL)
- return(false);
- q->tail = 0;
- q->head = 0;
- q->qu_size = size;
- return(true);
- }
- GLuint
- load_texture(/*int texnum, */char *name)
- {
- SDL_Surface *tmp_surface;
- // GLenum textureFormat;
- GLuint textureID;
- //tmp_surface = IMG_Load(name);
- tmp_surface = SDL_LoadBMP(name);
- #if(0) //TODO: repair SDL_image loading
- if (tmp_surface->format->BytesPerPixel == 4) {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
- textureFormat = GL_BGRA;
- else
- textureFormat = GL_RGBA;
- } else {
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
- textureFormat = GL_BGR;
- else
- textureFormat = GL_RGB;
- }
- #endif
- /* Genarate texture */
- glGenTextures(1, &textureID);
- glBindTexture(GL_TEXTURE_2D, textureID);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, tmp_surface->format->BytesPerPixel,
- //tmp_surface->w, tmp_surface->h, 0, textureFormat, //TODO
- tmp_surface->w, tmp_surface->h, 0, GL_BGR, // => SDL_LoadBMP
- GL_UNSIGNED_BYTE, tmp_surface->pixels);
- SDL_FreeSurface(tmp_surface);
- return(textureID);
- }
- model
- read_obj_file(char* filename)
- {
- model mdl;
- char buffer[100];
- FILE *obj_file = NULL;
- int v_count = 0;
- int vn_count = 0;
- int vt_count = 0;
- int f_count = 0;
- obj_file = fopen(filename, "r");
- if (obj_file == NULL)
- printf("can't find file: %s", filename);
- while (fgets(buffer, 100, obj_file)) {
- /* puts(buffer); */
- /* vertex coords */
- if (buffer[0] == 'v' && buffer [1] == ' ') {
- v_count++;
- sscanf(buffer, "v %f %f %f",
- &mdl.vertexes[v_count].x,
- &mdl.vertexes[v_count].y,
- &mdl.vertexes[v_count].z);
- #if(RESIZE)
- mdl.vertexes[v_count].x *= resize_coefficient;
- mdl.vertexes[v_count].y *= resize_coefficient;
- mdl.vertexes[v_count].z *= resize_coefficient;
- #endif
- }
- /* vertex normals */
- else if (buffer[0] == 'v' && buffer[1] == 'n') {
- vn_count++;
- sscanf(buffer, "vn %f %f %f",
- &mdl.normals[v_count].x,
- &mdl.normals[v_count].y,
- &mdl.normals[v_count].z);
- }
- /* texture coords */
- else if (buffer[0] == 'v' && buffer[1] == 't') {
- vt_count++;
- sscanf(buffer, "vt %f %f",
- &mdl.text_coords[vt_count].v,
- &mdl.text_coords[vt_count].u);
- }
- /* faces */
- else if (buffer[0] == 'f' && buffer [1] == ' ') {
- int slash_count = 0;
- f_count++;
- int i;
- for (i = 2; buffer[i] != ' '; i++)
- if (buffer[i] == '/')
- slash_count++;
- /* printf("%i\n", slash_count); */
- if (slash_count == 1)
- sscanf(buffer, "f %i/%i %i/%i %i/%i",
- &mdl.faces[f_count].v1, &mdl.faces[f_count].vt1,
- &mdl.faces[f_count].v2, &mdl.faces[f_count].vt2,
- &mdl.faces[f_count].v3, &mdl.faces[f_count].vt3
- );
- else if (slash_count == 2)
- sscanf(buffer, "f %i/%i/%i %i/%i/%i %i/%i/%i",
- &mdl.faces[f_count].v1, &mdl.faces[f_count].vt1, &mdl.faces[f_count].vn1,
- &mdl.faces[f_count].v2, &mdl.faces[f_count].vt2, &mdl.faces[f_count].vn2,
- &mdl.faces[f_count].v3, &mdl.faces[f_count].vt3, &mdl.faces[f_count].vn3);
- else {
- puts("ERRRRORRRR!!!");
- exit(0);
- }
- }
- }
- fclose(obj_file);
- #if(0) // AFTERSCAN_PRINT
- printf("vertex count: %i\n", v_count);
- printf("texture coords count: %i\n", vt_count);
- printf("faces count: %i\n", f_count);
- #endif
- mdl.f_count = f_count; //remember for each model. later we'll use it for rendering
- return(mdl);
- }
- void
- draw_model(/*int texnum, */model mdl)
- {
- int ii = 0;
- //glBindTexture(GL_TEXTURE_2D, texture[texnum]); /* Select Texture */
- glBindTexture(GL_TEXTURE_2D, texture);
- //glBindTexture(GL_TEXTURE_2D, sky_texture[3]);
- glBegin(GL_TRIANGLES);
- {
- for (ii = 0; ii <= mdl.f_count; ii++) {
- /* TODO: remake whole structure. использовать вертексные массивы? */
- glTexCoord2f(mdl.text_coords[ mdl.faces[ii].vt1 ].u,
- mdl.text_coords[ mdl.faces[ii].vt1 ].v);
- glVertex3f(mdl.vertexes [ mdl.faces[ii].v1 ].x,
- mdl.vertexes [ mdl.faces[ii].v1 ].y,
- mdl.vertexes [ mdl.faces[ii].v1 ].z);
- //glNormal3f(mdl.normals [ mdl.faces[ii].v1 ].x,
- // mdl.normals [ mdl.faces[ii].v1 ].y,
- // mdl.normals [ mdl.faces[ii].v1 ].z);
- glTexCoord2f(mdl.text_coords[ mdl.faces[ii].vt2 ].u,
- mdl.text_coords[ mdl.faces[ii].vt2 ].v);
- glVertex3f(mdl.vertexes [ mdl.faces[ii].v2 ].x,
- mdl.vertexes [ mdl.faces[ii].v2 ].y,
- mdl.vertexes [ mdl.faces[ii].v2 ].z);
- //glNormal3f(mdl.normals [ mdl.faces[ii].v1 ].x,
- // mdl.normals [ mdl.faces[ii].v1 ].y,
- // mdl.normals [ mdl.faces[ii].v1 ].z);
- glTexCoord2f(mdl.text_coords[ mdl.faces[ii].vt3 ].u,
- mdl.text_coords[ mdl.faces[ii].vt3 ].v);
- glVertex3f(mdl.vertexes [ mdl.faces[ii].v3 ].x,
- mdl.vertexes [ mdl.faces[ii].v3 ].y,
- mdl.vertexes [ mdl.faces[ii].v3 ].z);
- //glNormal3f(mdl.normals [ mdl.faces[ii].v1 ].x,
- // mdl.normals [ mdl.faces[ii].v1 ].y,
- // mdl.normals [ mdl.faces[ii].v1 ].z);
- }
- }
- glEnd();
- }
- void
- reshape(int w, int h)
- {
- glViewport(0, 0, w, h); // Reset The Current Viewport
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- //gluPerspective(45, (GLfloat)w/(GLfloat)h, 1, 100);
- gluPerspective(45, (GLfloat)w/(GLfloat)h, 0.01, 100);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- SCR_WIDTH = w;
- SCR_HEIGHT = h;
- }
- void
- draw_filled_hex()
- {
- #if(0)
- int i;
- for (i=0; i<6; i++) {
- glBegin(GL_TRIANGLES);
- {
- glVertex2f(0, 0);
- glVertex2f(0, HEX_EX);
- glVertex2f(HEX_IN, HEX_EX/2);
- }
- glEnd();
- glRotatef(60, 0, 0, 1);
- }
- #else
- glVertexPointer(3, GL_FLOAT, 0, HEX);
- glDrawArrays(GL_POLYGON, 0, 6);
- GLuint indexes[] = {0, 1, 2, 3, 4, 5};
- glDrawElements(GL_LINE_LOOP, 6, GL_UNSIGNED_INT, indexes);
- #endif
- }
- void
- draw_wire_hex()
- {
- // glLineStipple(1,0x00FF);
- // glEnable(GL_LINE_STIPPLE);
- #if(0)
- glBegin(GL_LINE_STRIP);
- {
- glVertex3f(0, HEX_EX, 0.01);
- glVertex3f(-HEX_IN, +HEX_IN/2, 0.01);
- glVertex3f(-HEX_IN, -HEX_IN/2, 0.01);
- glVertex3f(0, -HEX_EX, 0.01);
- glVertex3f(HEX_IN, -HEX_IN/2, 0.01);
- glVertex3f(HEX_IN, HEX_IN/2, 0.01);
- glVertex3f(0, HEX_EX, 0.01);
- }
- glEnd();
- // glDisable(GL_LINE_STIPPLE);
- #else
- glVertexPointer(3, GL_FLOAT, 0, HEX);
- glDrawArrays(GL_LINE_LOOP, 0, 6);
- //GLuint indexes[] = {0, 1, 2, 3, 4, 5};
- //glDrawElements(GL_LINE_LOOP, 6, GL_UNSIGNED_INT, indexes);
- #endif
- }
- void
- draw_character(unit u)
- {
- glPushMatrix();
- glTranslatef(u.x, u.y, 0.01); //slightly above the floor
- //draw players identifier
- if (u.player == 1) glColor3f(1.0, 0.5, 0.5);
- if (u.player == 2) glColor3f(0.5, 0.5, 1.0);
- gluDisk(GQO, HEX_IN*0.7, HEX_IN*0.9, 12, 2);
- //action points
- glColor3f(0.3, 1, 0.3);
- gluPartialDisk(GQO, HEX_IN*0.5, HEX_IN*0.7, u.ap, 2, 0, u.ap*60.0);
- //TODO где то тут должна рисоваться повернутая к камере фигнюшка с инфой над перцем
- // + стоит находить для нее поправочный угол тут какнибудь =)
- glPushMatrix();
- {
- glEnable(GL_BLEND);
- glColor4f(0, 0, 1, 0.5);
- glTranslatef(0, 0, 0.8);
- glRotatef(CAMERA.horiz_angle+90, 0, 0, -1);
- glRotatef(90, 0, 1, 0);
- if(u.player == PLAYER)
- gluPartialDisk(GQO, HEX_IN*0.1, HEX_IN*0.3, u.ap, 2, 0, u.ap*60.0);
- glColor4f(0, 1, 0, 0.5);
- gluPartialDisk(GQO, HEX_IN*0.3, HEX_IN*0.4, u.health, 2, 0, u.health*30);
- glColor4f(1, 0, 0, 0.5);
- gluPartialDisk(GQO, HEX_IN*0.3, HEX_IN*0.4, 12-u.health, 2, u.health*30, 360-u.health*30);
- glDisable(GL_BLEND);
- }
- glPopMatrix();
- //glColor3f(1, 1, 1);
- if (u.player == 1)
- glColor3f(1.0, 0.8, 0.8);
- else
- glColor3f(0.8, 0.8, 1.0);
- #if(0) //draw some test sphere
- glTranslatef(0, 0, 0.2); //slightly above the floor
- gluSphere(GQO, HEX_IN*0.3, 6, 6);
- #else //draw model
- glRotatef(90, 1, 0, 0); // because of blender exporter
- glRotatef(u.rot, 0, 1, 0); //individual character rotation
- glEnable(GL_TEXTURE_2D);
- draw_model(mdl[u.frame]);
- glDisable(GL_TEXTURE_2D);
- #if(1) //model's shadow
- glScalef(1, 0.01, 1); //расплющить перца, что б был похож на тень
- glColor4f(0, 0, 0, 0.5);
- draw_model(mdl[u.frame]);
- #endif
- #endif
- glPopMatrix();
- }
- void
- set_camera()
- {
- glLoadIdentity();
- glTranslatef(0, 0, -CAMERA.distanse); //отдаление
- glRotatef(-CAMERA.vert_angle, 1, 0, 0);
- glRotatef(CAMERA.horiz_angle, 0, 0, 1);
- glTranslatef(CAMERA.x, CAMERA.y, 0);
- }
- #define PICK_BG 0 // code for backround
- #define PICK_HEX 1 //code for terrain hex
- void
- draw_for_picking()
- {
- glClearColor(0, 0, PICK_BG, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- set_camera();
- glPushMatrix();
- glEnableClientState(GL_VERTEX_ARRAY);
- int x, y;
- for (y=0; y<MAP_SIZE_Y; y++) {
- for (x=0; x<MAP_SIZE_X; x++) {
- glColor3ub(x, y, PICK_HEX);
- draw_filled_hex();
- glTranslatef(2*HEX_IN, 0, 0);
- }
- if (y%2 == 0)
- glTranslatef(-HEX_IN, 1.5*HEX_EX, 0);
- else
- glTranslatef(+HEX_IN, 1.5*HEX_EX, 0);
- glTranslatef(-(2*HEX_IN *MAP_SIZE_X), 0, 0);
- }
- glDisableClientState(GL_VERTEX_ARRAY);
- glPopMatrix();
- }
- #if(0)
- #define MAX_CHCOUNT 20
- typedef struct Bone {
- float a, l;
- float rel[16];
- int childCount;
- struct Bone *child[MAX_CHCOUNT],
- *parent;
- } Bone;
- typedef struct vertex {
- float pos[3];
- Bone *bone;
- } vertex;
- Bone*
- boneAddChild(Bone *root, float a, float l)
- {
- Bone *tmp_bone;
- int i;
- if (!root) { /* If there is no root, create one */
- if (!(root = (Bone *)malloc(sizeof(Bone))))
- return(NULL);
- root->parent = NULL;
- } else if (root->childCount < MAX_CHCOUNT) { /* If there is space for another child */
- /* Allocate the child */
- if (!(tmp_bone = (Bone *)malloc(sizeof(Bone))))
- return(NULL);
- tmp_bone->parent = root; /* Set it's parent */
- /* Increment the childCounter and set the pointer */
- root->child[root->childCount++] = tmp_bone;
- root = tmp_bone; /* Change the root */
- } else /* Can't add a child */
- return(NULL);
- /* Set data */
- root->a = a;
- root->l = l;
- root->childCount = 0;
- for (i = 0; i < MAX_CHCOUNT; i++)
- root->child[i] = NULL;
- return(root); //return bone, that we just have added!
- }
- void
- boneDraw(Bone *root)
- {
- glPushMatrix();
- glRotatef(root->a, 0, 0, 1);
- glGetFloatv(GL_MODELVIEW_MATRIX, root->rel);
- glBegin(GL_TRIANGLES);
- //glBegin(GL_LINES);
- {
- glColor3f(1.0, 0.0, 0.0);
- glVertex2f(0, -5);
- glVertex2f(0, +5);
- //glVertex2f(0, 0);
- glColor3f(1.0, 1.0, 1.0);
- glVertex2f(root->l, 0);
- }
- glEnd();
- /* Translate to reach the new starting position */
- glTranslatef(root->l, 0.0, 0.0);
- int i;
- /* Call function on bones children */
- for (i = 0; i < root->childCount; i++)
- boneDraw(root->child[i]);
- glPopMatrix();
- }
- void
- rotate_vertex(float *m, float *pos)
- {
- float v[3] = {pos[0], pos[1], pos[2]};
- pos[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8];
- pos[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9];
- pos[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10];
- }
- #endif //не надо мне пока костей. не до этого((
- //TODO. просто хер знает что, честно((
- void
- draw_sky()
- {
- glPushMatrix();
- glScalef(50, 50, 50);
- glColor3f(1, 1, 1);
- glEnable(GL_TEXTURE_2D);
- // сторона 1
- glBindTexture(GL_TEXTURE_2D, sky_texture[1]);
- glBegin(GL_QUADS);
- //glColor3f(1, 0, 0);
- //glNormal3f(0.0f, -1.0f, 0.0f);
- glTexCoord2f(1, 1);
- glVertex3f(-1, -1, -1);
- glTexCoord2f(0, 1);
- glVertex3f(1, -1, -1);
- glTexCoord2f(0, 0);
- glVertex3f(1, -1, 1);
- glTexCoord2f(1, 0);
- glVertex3f(-1, -1, 1);
- glEnd();
- // сторона 2
- glBindTexture(GL_TEXTURE_2D, sky_texture[2]);
- glBegin(GL_QUADS);
- //glColor3f(0, 1, 0);
- //glNormal3f(0.0f, 1.0f, 0.0f);
- glTexCoord2f(0, 1);
- glVertex3f(-1, 1, -1);
- glTexCoord2f(0, 0);
- glVertex3f(-1, 1, 1);
- glTexCoord2f(1, 0);
- glVertex3f(1, 1, 1);
- glTexCoord2f(1, 1);
- glVertex3f(1, 1, -1);
- glEnd();
- // НИЖНЯЯ. ее вообще можно бы и удалить.
- //glBindTexture(GL_TEXTURE_2D, sky_texture[1]);
- //glBegin(GL_QUADS);
- //glColor3f(0, 0, 1);
- //glNormal3f(0.0f, 0.0f,-1.0f);
- glTexCoord2f(1, 0);
- glVertex3f(-1, -1, -1);
- glTexCoord2f(1, 1);
- glVertex3f(-1, 1, -1);
- glTexCoord2f(0, 1);
- glVertex3f(1, 1, -1);
- glTexCoord2f(0, 0);
- glVertex3f(1, -1, -1);
- glEnd();
- // сторона 3
- glBindTexture(GL_TEXTURE_2D, sky_texture[3]);
- glBegin(GL_QUADS);
- //glColor3f(1, 0, 1);
- //glNormal3f(1.0f, 0.0f, 0.0f);
- glTexCoord2f(0, 0);
- glVertex3f(1, -1, -1);
- glTexCoord2f(1, 0);
- glVertex3f(1, 1, -1);
- glTexCoord2f(1, 1);
- glVertex3f(1, 1, 1);
- glTexCoord2f(0, 1);
- glVertex3f(1, -1, 1);
- glEnd();
- // ВЕРХ
- //glBindTexture(GL_TEXTURE_2D, sky_texture[3]);
- //glBegin(GL_QUADS);
- //glColor3f(1, 1, 1);
- //glNormal3f(0.0f, 0.0f, 1.0f);
- glTexCoord2f(0, 0);
- glVertex3f(-1, -1, 1);
- glTexCoord2f(1, 0);
- glVertex3f(1, -1, 1);
- glTexCoord2f(1, 1);
- glVertex3f(1, 1, 1);
- glTexCoord2f(0, 1);
- glVertex3f(-1, 1, 1);
- glEnd();
- // сторона 4
- glBindTexture(GL_TEXTURE_2D, sky_texture[4]);
- glBegin(GL_QUADS);
- //glColor3f(1, 1, 0);
- //glNormal3f(-1.0f, 0.0f, 0.0f);
- glTexCoord2f(0, 1);
- glVertex3f(-1, -1, -1);
- glTexCoord2f(0, 0);
- glVertex3f(-1, -1, 1);
- glTexCoord2f(1, 0);
- glVertex3f(-1, 1, 1);
- glTexCoord2f(1, 1);
- glVertex3f(-1, 1, -1);
- glEnd();
- glPopMatrix();
- glDisable(GL_TEXTURE_2D);
- }
- void
- draw_terrain()
- {
- glPushMatrix();
- int x, y;
- for (y=0; y< MAP_SIZE_Y; y++) {
- for (x=0; x<MAP_SIZE_X; x++) {
- glPushMatrix();
- glTranslatef(0, 0, 0.01);
- if (SELECTED_UNIT) {
- //это можно бы вынести отсюда и рисовать простым переносом.
- if (SELECTED_UNIT->mx == x && SELECTED_UNIT->mx == y) {
- glColor3f(0.8, 0.3, 0.3);
- gluDisk(GQO, HEX_IN*0.9, HEX_IN*0.95, 12, 2);
- }
- //рисует кружок над клетой, если мы можем дойти туда
- if (MAP[x][y].move_cost <= SELECTED_UNIT->ap) {
- glColor3f(0.5, 0.5, 1.0);
- gluDisk(GQO, HEX_IN*0.2, HEX_IN*0.4, 12, 2);
- }
- }
- if (PICKED_SMTH && aX == x && aY == y) {
- glColor3f(0.3, 0.8, 0.3);
- gluDisk(GQO, HEX_IN*0.95, HEX_IN*1.1, 12, 2);
- }
- glPopMatrix();
- float coff = 1.0 - (float)(MAP[x][y].init_cost*20)/256;
- glColor3f(coff, coff, coff);
- if (SELECTED_UNIT && MODE == MODE_SELECT
- && MAP[x][y].unit
- && MAP[x][y].unit->player != PLAYER
- //&& (get_distance(sX, sY, x, y) == 1 || get_distance(aX, aY, x, y) == 1))
- //&& (get_distance(sX, sY, x, y) <= D || get_distance(aX, aY, x, y) <= D))
- && (get_distance(SELECTED_UNIT->mx, SELECTED_UNIT->my, x, y) <= SELECTED_UNIT->attack_distance)) {
- glColor3f(coff, 0, 0);
- }
- //гексы на пути будут подсвечены
- //можно делать проверку на то, что точка вообще в нужном районе для оптимизации
- if (SELECTED_UNIT && check_line_hex_intersects(SELECTED_UNIT->mx, SELECTED_UNIT->my, aX,aY, x,y))
- glColor3f(0, coff, 0);
- glEnableClientState(GL_VERTEX_ARRAY);
- draw_filled_hex();
- #if(1) //draw wire
- //glColor3f(0.5, 0.5, 0.5);
- if(PLAYER == 1)
- glColor3f(1, 0, 0);
- else
- glColor3f(0, 0, 1);
- draw_wire_hex();
- #endif //draw wire
- glDisableClientState(GL_VERTEX_ARRAY);
- glTranslatef(2*HEX_IN, 0, 0);
- }
- if (y%2 == 0)
- glTranslatef(-HEX_IN, 1.5*HEX_EX, 0);
- else
- glTranslatef(+HEX_IN, 1.5*HEX_EX, 0);
- glTranslatef(-(2*HEX_IN *MAP_SIZE_X), 0, 0);
- }
- glPopMatrix();
- }
- void
- draw_characters()
- {
- unit* tmp = UNITS;
- while(tmp != NULL)
- {
- draw_character(*tmp);
- tmp = tmp->next;
- }
- }
- void
- draw()
- {
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- set_camera();
- draw_terrain();
- draw_characters();
- draw_sky();
- #if(1)
- if (SELECTED_UNIT) {
- //рисует белую линию от выбранной ячейки до активной(куда тыкает мышка)
- glColor3f(1, 1, 1);
- glBegin(GL_LINES);
- {
- float rx, ry;
- map_to_real(aX, aY, &rx, &ry);
- glVertex3f(rx, ry, 0);
- map_to_real(SELECTED_UNIT->mx, SELECTED_UNIT->my, &rx, &ry);
- glVertex3f(rx, ry, 0);
- }
- glEnd();
- }
- #endif
- #if(0) //направление движения
- if (MODE == MODE_MOVE) {
- glColor3f(0, 1, 0);
- glBegin(GL_LINES);
- {
- float rx, ry;
- map_to_real(back_path_x[back_path_current], back_path_y[back_path_current], &rx, &ry);
- glVertex3f(rx, ry, 0);
- map_to_real(back_path_x[back_path_current-1], back_path_y[back_path_current-1], &rx, &ry);
- glVertex3f(rx, ry, 0);
- }
- glEnd();
- }
- #endif
- #if(1) // типа земля или чего то такое.
- glPushMatrix();
- glTranslatef(0, 0, -0.2);
- glScalef(100, 100, 100);
- glColor3f(1, 1, 1);
- glBegin(GL_QUADS);
- {
- glVertex2f(-1, -1);
- glVertex2f(+1, -1);
- glVertex2f(+1, +1);
- glVertex2f(-1, +1);
- }
- glEnd();
- glPopMatrix();
- #endif
- }
- void
- do_picking()
- {
- GLint viewport[4];
- GLubyte pixel[3];
- glGetIntegerv(GL_VIEWPORT, viewport);
- glReadPixels(cursorX, viewport[3]-cursorY, 1, 1, GL_RGB,
- GL_UNSIGNED_BYTE, (void*)pixel);
- //update active cell
- aX = pixel[0]; //TODO вот изза этого то и выбирается первая ячейка, вроде.
- aY = pixel[1];
- //printf("ax:%i, ay%i\n", aX, aY);
- // поворачивать выделенный юнит к активной ячейке
- //if (IS_SOMEONE_SELECTED) {
- // UNITS[MAP[sX][sY].unit_id].rot = get_rot_angle(sX, sY, aX, aY);
- // printf("angle = %f\n", get_rot_angle(sX, sY, aX, aY));
- // }
- PICKED_SMTH = (bool)pixel[2];
- //printf("%u\n", pixel[2]);
- if (pixel[2] > 1) { //если 3й элемент больше еденицы - мы тыркнулись в интерфейс
- //printf("some button\n");
- SELECTED_BUTTON = pixel[2]-2;
- printf("%s\n", BUTTONS[ pixel[2]-2 ].name);
- } else {
- SELECTED_BUTTON = -1;
- }
- }
- void
- fill_map(Q *q, ushort by, ushort bx)
- {
- ushort x, y;
- for (y=0; y<MAP_SIZE_Y; y++) {
- for (x=0; x<MAP_SIZE_X; x++) {
- // TODO: put there some information about other units
- MAP[x][y].move_cost = 30000;
- }
- }
- push(q, bx, by, bx, by, 0); //push start point
- while (pop(q, &x, &y)) { //TODO переписать исползуя новую функцию получения соседей.
- try_push(q, x+1, y , x, y);
- try_push(q, x-1, y , x, y);
- try_push(q, x , y+1, x, y);
- try_push(q, x , y-1, x, y);
- if (y%2==0) {
- try_push(q, x+1, y-1, x, y);
- try_push(q, x+1, y+1, x, y);
- } else {
- try_push(q, x-1, y-1, x, y);
- try_push(q, x-1, y+1, x, y);
- }
- }
- }
- //TODO: blablabla
- void
- get_path(ushort bx, ushort by, ushort ex, ushort ey)
- {
- back_path_current = 0;
- ushort x = ex, y = ey, tmpx, tmpy;
- while ((x != bx) || (y != by)) {
- back_path_x[back_path_current] = x;
- back_path_y[back_path_current] = y;
- back_path_current++;
- tmpx = MAP[x][y].parent_x;
- tmpy = MAP[x][y].parent_y;
- x = tmpx;
- y = tmpy;
- }
- back_path_x[back_path_current] = x;
- back_path_y[back_path_current] = y;
- back_path_current++; //TODO я не уверен, что это должно быть в конце.
- }
- unsigned
- generate_texture_from_str(char* Text, int *w, int *h)
- {
- SDL_Color Color = {255, 255, 255, 0};
- SDL_Surface *txt = TTF_RenderUTF8_Blended(font, Text, Color);
- unsigned id = 0; // айди текстуры
- glGenTextures(1, &id); /*Generate an OpenGL 2D texture from the SDL_Surface*.*/
- glBindTexture(GL_TEXTURE_2D, id); //вот зза отстутсвтвия этой строки я столько мудохался
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, txt->w, txt->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, txt->pixels);
- *w = txt->w;
- *h = txt->h;
- SDL_FreeSurface(txt);
- return(id);
- }
- void
- change_button_text (gui_button* b, char* text)
- {
- glDeleteTextures(1, &(b->textureID));
- b->textureID = generate_texture_from_str(text, &(b->textSX), &(b->textSY));
- }
- void
- end_player_turn()
- {
- SELECTED_UNIT = false;
- if (PLAYER == 1) {
- PLAYER = 2;
- int i;
- for(i=0; i< BUTTONS_COUNT; i++){
- if(!strcmp(BUTTONS[i].name, "player identifier")){
- change_button_text(&(BUTTONS[i]), "синий");
- break;
- }
- }
- } else {
- PLAYER = 1;
- int i;
- for(i=0; i< BUTTONS_COUNT; i++){
- if(!strcmp(BUTTONS[i].name, "player identifier")){
- change_button_text(&(BUTTONS[i]), "красный");
- break;
- }
- }
- }
- unit* tmp = UNITS;
- while(tmp != NULL){
- if (tmp->player == PLAYER) {
- tmp->ap = 6;
- }
- tmp = tmp->next;
- }
- //CHECK WIN
- int p1=0, p2=0;
- unit* t = UNITS;
- while(t != NULL){
- if (t->player == 1) p1++;
- if (t->player == 2) p2++;
- t = t->next;
- }
- if(p1 == 0)
- {
- puts("PLAYER 2 WIN");
- exit(0);
- }
- if(p2 == 0)
- {
- puts("PLAYER 1 WIN");
- exit(0);
- }
- }
- void
- handle_mouse_events(SDL_Event E)
- {
- if (SELECTED_BUTTON != -1 && E.type == SDL_MOUSEBUTTONUP)
- {
- printf("%s\n", BUTTONS[ SELECTED_BUTTON ].name);
- return;
- }
- if (PICKED_SMTH && MODE == MODE_SELECT) {
- if (MAP[aX][aY].unit) { //если тут хто то есть
- //если это наш перец
- if (MAP[aX][aY].unit->player == PLAYER) {
- //если опять кликнуть на уже выделенном юните
- // - камера отцентрируется на нем
- if (SELECTED_UNIT && MAP[aX][aY].unit == SELECTED_UNIT) {
- map_to_real(aX, aY, &(CAMERA.x), &(CAMERA.y));
- CAMERA.y = -CAMERA.y;
- CAMERA.x = -CAMERA.x;
- }else{
- //select character
- SELECTED_UNIT = MAP[aX][aY].unit;
- fill_map(&q, aY, aX);
- }
- } else if (SELECTED_UNIT
- && SELECTED_UNIT->ap >= attack_cost
- //&& get_distance(aX, aY, sX, sY) == 1) //ближний бой
- //&& get_distance(aX, aY, sX, sY) <= 2) //дальний бой
- && get_distance(aX, aY, SELECTED_UNIT->mx, SELECTED_UNIT->my)
- <= SELECTED_UNIT->attack_distance)
- {
- // try to kill KILL enemy unit!
- //TODO ввести доп переменные в стрктуру ФАЙТ:
- // смерть один, ответ, отступление, т.д.
- //if (rand()%2) {
- // free(MAP[aX][aY].ch);
- // MAP[aX][aY].ch = NULL; //TODO подумать...
- // UNITS[MAP[aX][aY].unit_id].dead = true; //TODO подумать...
- // UNITS[MAP[aX][aY].unit_id].health -= 4;
- //}
- SELECTED_UNIT->ap -= attack_cost;
- FIGHT.u1 = SELECTED_UNIT;
- FIGHT.u2 = MAP[aX][aY].unit;
- MODE = MODE_FIGHT;
- }
- } else { //если тут никого нет
- //но если все таки кто то выбран
- if (SELECTED_UNIT) {
- // try move selected character
- fill_map(&q, SELECTED_UNIT->my, SELECTED_UNIT->mx);
- if (MAP[aX][aY].move_cost <= SELECTED_UNIT->ap) {
- //if character has requested action points
- SELECTED_UNIT->ap -= MAP[aX][aY].move_cost; //TODO убирать поэтапно
- get_path(SELECTED_UNIT->mx, SELECTED_UNIT->my, aX, aY); //TODO изменить порядок
- MODE = MODE_MOVE;
- MOVE.step_count = 0;
- MOVE.unit = SELECTED_UNIT;
- MAP[SELECTED_UNIT->mx][SELECTED_UNIT->my].unit = NULL;
- }
- }
- }
- }
- }
- void
- hanlde_events(SDL_Event E)
- {
- switch (E.type) {
- default:
- //puts("unknown event!");
- break;
- case SDL_QUIT:
- isProgramLooping = false;
- break;
- case SDL_VIDEORESIZE:
- reshape(E.resize.w, E.resize.h);
- break;
- case SDL_MOUSEMOTION:
- cursorX = E.motion.x;
- cursorY = E.motion.y;
- if (CAMERA.is_rotating) {
- CAMERA.horiz_angle += E.motion.xrel;
- CAMERA.vert_angle += E.motion.yrel;
- #if(1) //ограничивает вращение камеры
- if (CAMERA.vert_angle < 30 || CAMERA.vert_angle > 85)
- CAMERA.vert_angle -= E.motion.yrel;
- if (CAMERA.horiz_angle > 360 || CAMERA.horiz_angle < -360)
- CAMERA.horiz_angle = 0;
- #endif
- }
- break;
- case SDL_MOUSEBUTTONDOWN:
- if (E.button.button == SDL_BUTTON_RIGHT) {
- CAMERA.is_rotating = true;
- }
- if (E.button.button == SDL_BUTTON_LEFT)
- handle_mouse_events(E);
- break;
- case SDL_MOUSEBUTTONUP:
- if (E.button.button == SDL_BUTTON_RIGHT) {
- CAMERA.is_rotating = false;
- } else {
- if (E.button.button == SDL_BUTTON_WHEELUP && CAMERA.distanse < 15)
- CAMERA.distanse++;
- if (E.button.button == SDL_BUTTON_WHEELDOWN && CAMERA.distanse > 4)
- CAMERA.distanse--;
- }
- // если это не закоментить - то обработка вызыывается дважды за клик.
- //if (E.button.button == SDL_BUTTON_LEFT)
- // handle_mouse_events(E);
- break;
- case SDL_KEYDOWN:
- switch (E.key.keysym.sym) {
- default:
- break;
- case SDLK_q:
- case SDLK_ESCAPE:
- isProgramLooping = false;
- break;
- case SDLK_SPACE:
- end_player_turn();
- break;
- case SDLK_UP:
- CAMERA.y--;
- break;
- case SDLK_DOWN:
- CAMERA.y++;
- break;
- case SDLK_LEFT:
- if (E.key.keysym.mod & KMOD_LCTRL)
- CAMERA.distanse++;
- else
- CAMERA.x++;
- break;
- case SDLK_RIGHT:
- if (E.key.keysym.mod & KMOD_LCTRL)
- CAMERA.distanse--;
- else
- CAMERA.x--;
- break;
- case SDLK_p:
- if (MODE != MODE_PAUSE) {
- PREVIOUS_MODE = MODE;
- MODE = MODE_PAUSE;
- } else {
- MODE = PREVIOUS_MODE;
- }
- break;
- }
- }
- }
- void
- init_sdl()
- {
- SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
- atexit(SDL_Quit);
- /* the flags to pass to SDL_SetVideoMode */
- video_flags = SDL_OPENGL;
- video_flags |= SDL_GL_DOUBLEBUFFER;
- video_flags |= SDL_RESIZABLE;
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- /* get a SDL surface */
- surface = SDL_SetVideoMode(SCR_WIDTH, SCR_HEIGHT,
- SCR_BPP, video_flags);
- SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 0, 0, 0, 0));
- reshape(SCR_WIDTH, SCR_HEIGHT);
- }
- void
- init_opengl()
- {
- glEnable(GL_TEXTURE_2D);
- glShadeModel(GL_SMOOTH);
- glClearColor(0, 0, 0, 1);
- glClearDepth(1.0f);
- glEnable(GL_DEPTH_TEST);
- //glEnable(GL_LIGHTING);
- glEnable(GL_AUTO_NORMAL);
- glEnable(GL_COLOR_MATERIAL);
- glEnable(GL_LIGHT0);
- glEnable(GL_NORMALIZE);
- glEnable(GL_BLEND);
- //float POS[] = {0, 1, 0, 0};
- //glLightfv(GL_LIGHT0, GL_POSITION, POS);
- glDepthFunc(GL_LEQUAL); /* The Type Of Depth Test To Do */
- /* Really Nice Perspective Calculations */
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
- //glEnable(GL_CULL_FACE);
- //glFrontFace(GL_CW);
- //glCullFace(GL_BACK);
- //glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
- bool
- add_unit (/*TODO type, */ int x, int y, int player)
- {
- unit* u = malloc(sizeof(unit));
- if (u == NULL)
- return(false);
- //exit(1);
- //добавит перца в список
- u->next = UNITS;
- UNITS = u; //теперь список будет начинаться с этого перца
- map_to_real(x, y, &(u->x), &(u->y)); //реальные координаты перца в этой клетке
- u->mx = x;
- u->my = y;
- u->player = player;
- u->rot = (rand()%6)*60+30; // потоврот персонажа. 30, 90, т.д.
- u->frame = (rand()%22)+99; //рандомный кадр из idle анимации
- u->ap = 6;
- u->cost_attack = 2;
- u->rotation_speed = 5;
- u->movement_speed = 0.031; // просто подобрал. хз =)
- u->health = 12;
- u->attack_distance = 3;
- //запомнить, что он находится в этой клетке
- MAP[x][y].unit = u;
- return(true);
- }
- void
- init_map()
- {
- int y, x;
- for (y=0; y<MAP_SIZE_Y; y++) {
- for (x=0; x<MAP_SIZE_X; x++) {
- //нет тут персонажа, т.к. индекс может быть >= 0
- MAP[x][y].unit = NULL;
- MAP[x][y].init_cost = (rand()%2)*3+1; // 1 или 4
- //такого значения не может быть(вроде), так что это значит,
- //что мы еще не трогали эиу клетку
- MAP[x][y].move_cost = 30000;
- if (rand()%10 > 8)
- add_unit (x, y, rand()%2+1); //сторона определяется рандомом.
- }
- }
- }
- void
- move_logic()
- {
- if (MOVE.step_count > 0) { // we have not reached the destination
- MOVE.unit->x += MOVE.step_x;
- MOVE.unit->y += MOVE.step_y;
- MOVE.step_count--;
- } else {
- if (back_path_current > 1) { //если еще точки в маршруте
- // точки пути перечислены в обратном порядке
- float a = get_rot_angle(
- back_path_x[back_path_current-1],
- back_path_y[back_path_current-1],
- back_path_x[back_path_current-2],
- back_path_y[back_path_current-2]);
- //while(a<0) a+= 360; while(a>360) a-= 360;
- //while(UNITS[MOVE.unit_id].rot<0) UNITS[MOVE.unit_id].rot+= 360;
- //while(UNITS[MOVE.unit_id].rot>360) UNITS[MOVE.unit_id].rot-= 360;
- while (a - MOVE.unit->rot > 180) a -= 360;
- while (a - MOVE.unit->rot < -180)a += 360;
- float diff = a - MOVE.unit->rot;
- if (abs(diff) < 6) { //если мы достигли нужной точности. потом довернем
- MOVE.unit->rot = a; //доворачивает перца на нужный угол
- back_path_current--;
- start_move(back_path_x[back_path_current],
- back_path_y[back_path_current],
- back_path_x[back_path_current-1],
- back_path_y[back_path_current-1]);
- MAP[SELECTED_UNIT->mx][SELECTED_UNIT->my].unit = NULL;
- SELECTED_UNIT->mx = back_path_x[back_path_current];
- SELECTED_UNIT->my = back_path_y[back_path_current];
- } else { //rotate it
- if (diff > 0)
- MOVE.unit->rot += 5;
- else
- MOVE.unit->rot -= 5;
- }
- } else { // END
- MODE = MODE_SELECT;
- map_to_real(back_path_x[0], back_path_y[0], &(MOVE.unit->x), &(MOVE.unit->y));
- MOVE.unit->mx = back_path_x[0];
- MOVE.unit->my = back_path_y[0];
- MOVE.unit->frame = 98; //перейти к анимации ничегонеделания
- MAP[SELECTED_UNIT->mx][SELECTED_UNIT->my].unit = MOVE.unit;
- MOVE.unit = NULL; //никто больше не передвигается, так же?
- fill_map(&q, SELECTED_UNIT->my, SELECTED_UNIT->mx); //перезаполнить карту под новую позицию
- }
- }
- }
- //TODO
- void
- atack_logic()
- {
- float a1 = get_rot_angle( FIGHT.u1->mx, FIGHT.u1->my,
- FIGHT.u2->mx, FIGHT.u2->my);
- float a2 = a1 - 180; //второго солдата надо повернуть наоборот
- while (a1 - FIGHT.u1->rot > 180) a1 -= 360;
- while (a1 - FIGHT.u1->rot < -180)a1 += 360;
- float diff1 = a1 - FIGHT.u1->rot;
- while (a2 - FIGHT.u2->rot > 180) a2 -= 360;
- while (a2 - FIGHT.u2->rot < -180)a2 += 360;
- float diff2 = a2 - FIGHT.u2->rot;
- if (abs(diff1) > 6) {
- if (diff1 > 0)
- FIGHT.u1->rot += 5;
- else
- FIGHT.u1->rot -= 5;
- }
- if (abs(diff2) > 6) {
- if (diff2 > 0)
- FIGHT.u2->rot += 5;
- else
- FIGHT.u2->rot -= 5;
- }
- if (abs(diff1) < 6 && abs(diff2) < 6) {
- if (FIGHT.u1->frame < 25 || FIGHT.u1->frame > 48)
- FIGHT.u1->frame = 25;
- if (FIGHT.u2->health > 4) { //выдержит он удар или нет
- //если выдержит - играть анимацию защиты.
- if (FIGHT.u2->frame < 48 || FIGHT.u2->frame > 72)
- FIGHT.u2->frame = 48;
- } else {
- // если не выдержит - играть анимацию смерти
- if (FIGHT.u2->frame < 72 || FIGHT.u2->frame > 96)
- FIGHT.u2->frame = 72;
- }
- // если был сыгран последний кадр. ТО...
- if (FIGHT.u1->frame == 48) {
- MODE = MODE_SELECT;
- FIGHT.u1->frame = 97; // вернуть к анимации ничегонеделания
- if(FIGHT.u2->health > 4){
- FIGHT.u2->health -= 4;
- FIGHT.u2->frame = 97;
- }else{
- unit* tmp = UNITS;
- if(tmp == FIGHT.u2) //если надо удалить первый элемент списка
- UNITS = UNITS->next; //то меняем указатель на начало списка
- else
- {
- while(tmp->next != FIGHT.u2)
- tmp = tmp->next;
- tmp->next = FIGHT.u2->next;
- }
- MAP[FIGHT.u2->mx][FIGHT.u2->my].unit = NULL;
- free(FIGHT.u2);
- }
- }
- }
- }
- bool
- add_button(int x, int y, int W, int H, char* name, char *text)
- {
- unsigned textureID;
- int w, h;
- textureID = generate_texture_from_str(text, &w, &h);
- if (textureID == 0)
- exit(1);
- gui_button b = {name, x, y, W, H, w, h, textureID, text};
- BUTTONS[BUTTONS_COUNT] = b;
- BUTTONS_COUNT++;
- return(true);
- }
- void
- draw_button_for_picking(gui_button b)
- {
- glPushMatrix();
- {
- glTranslatef(b.x, b.y, 0);
- glBegin(GL_QUADS);
- {
- glVertex3d(0, 0, 0);
- glVertex3d(b.sx, 0, 0);
- glVertex3d(b.sx, b.sy, 0);
- glVertex3d(0, b.sy, 0);
- }
- glEnd();
- }
- glPopMatrix();
- }
- void
- draw_button(gui_button b)
- {
- glPushMatrix();
- {
- glTranslatef(b.x, b.y, 0);
- glColor4f(0.3, 0.3, 0.3, 0.8);
- glBegin(GL_QUADS);
- {
- glVertex3d(0, 0, 0);
- glVertex3d(b.sx, 0, 0);
- glVertex3d(b.sx, b.sy, 0);
- glVertex3d(0, b.sy, 0);
- }
- glEnd();
- glColor4f(1, 1, 1, 0.8);
- //glScalef(0.3, 0.3, 0.3);
- //RENDER TEXT
- {
- glEnable(GL_TEXTURE_2D);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBindTexture(GL_TEXTURE_2D, b.textureID);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glBegin(GL_QUADS);
- {
- glTexCoord2d(0, 0);
- glVertex2d(0, 0);
- glTexCoord2d(1, 0);
- glVertex2d(b.textSX, 0);
- glTexCoord2d(1, 1);
- glVertex2d(b.textSX, b.textSY);
- glTexCoord2d(0, 1);
- glVertex2d(0, b.textSY);
- }
- glEnd();
- glDisable(GL_TEXTURE_2D);
- }
- }
- glPopMatrix();
- }
- void
- draw_interface()
- {
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_BLEND);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0, SCR_WIDTH, SCR_HEIGHT, 0, 0, 1);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- {
- glLoadIdentity();
- int i;
- for (i = 0; i < BUTTONS_COUNT; i++)
- draw_button(BUTTONS[i]);
- }
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glDisable(GL_BLEND);
- glEnable(GL_DEPTH_TEST);
- }
- void
- draw_interface_for_picking()
- {
- glDisable(GL_DEPTH_TEST);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0, SCR_WIDTH, SCR_HEIGHT, 0, 0, 1);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- {
- glLoadIdentity();
- int i;
- for (i = 0; i <BUTTONS_COUNT; i++) {
- glColor3ub(0, 0, i+2);
- draw_button_for_picking(BUTTONS[i]);
- }
- }
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glEnable(GL_DEPTH_TEST);
- }
- void
- init_interface()
- {
- if (TTF_Init() == -1) {
- printf("Unable to initialize SDL_ttf: %s \n", TTF_GetError());
- exit(1);
- }
- //font = TTF_OpenFont("font.ttf", 24);
- font = TTF_OpenFont("font.ttf", 18);
- if (font == NULL) {
- printf("Unable to initialize font: %s \n", TTF_GetError());
- exit(1);
- }
- add_button(0, 0, 80, 25, "player identifier", "красный");
- add_button(300, 300, 80, 25, "test button 1", "butt 1");
- add_button(350, 350, 80, 25, "test button 2", "butt 2");
- }
- void
- init_textures()
- {
- texture = load_texture("CUBE_WARRIOR.bmp");
- sky_texture[1] = load_texture("sky1.bmp");
- sky_texture[2] = load_texture("sky2.bmp");
- sky_texture[3] = load_texture("sky3.bmp");
- sky_texture[4] = load_texture("sky4.bmp");
- }
- void
- init_models()
- {
- int i;
- for (i = 0; i < 121; i++) {
- char obj_file_name[100];
- sprintf(obj_file_name, "test3/CUBE_WARRIOR_000%03i.obj", i+1);
- mdl[i] = read_obj_file(obj_file_name);
- }
- }
- void
- camera_logic()
- {
- float lastx = CAMERA.x; //запомним последние координаты.
- float lasty = CAMERA.y; //есл ивыходим за границы - откатимся на них.
- // насколько близко к краям экрана надо придвинутьr
- // мышу, что бы началось перемещение
- int border = 30;
- if (cursorY < border) { // наверху. двигаемся вперед
- CAMERA.x -= sinf(CAMERA.horiz_angle*M_PI/180.0f)*0.1;
- CAMERA.y -= cosf(CAMERA.horiz_angle*M_PI/180.0f)*0.1;
- } else if (cursorY > SCR_HEIGHT - border) { //курсор снизу. двигаемся назад.
- CAMERA.x += sinf(CAMERA.horiz_angle*M_PI/180.0f)*0.1;
- CAMERA.y += cosf(CAMERA.horiz_angle*M_PI/180.0f)*0.1;
- }
- if (cursorX < border) { //лево.
- CAMERA.x += sinf((CAMERA.horiz_angle+90.0)*M_PI/180.0)*0.1;
- CAMERA.y += cosf((CAMERA.horiz_angle+90.0)*M_PI/180.0)*0.1;
- } else if (cursorX > SCR_WIDTH - border) { //право.
- CAMERA.x -= sinf((CAMERA.horiz_angle+90.0)*M_PI/180.0)*0.1;
- CAMERA.y -= cosf((CAMERA.horiz_angle+90.0)*M_PI/180.0)*0.1;
- }
- //проверка границ + откаты на предыдущие позиции
- if (CAMERA.x > 0) CAMERA.x = lastx;
- if (CAMERA.y > 0) CAMERA.y = lasty;
- if (CAMERA.x < -2*HEX_IN*(MAP_SIZE_X-1)) CAMERA.x = lastx;
- if (CAMERA.y < -1.5*HEX_EX*(MAP_SIZE_Y-1)) CAMERA.y = lasty;
- }
- void
- change_frames()
- {
- unit* tmp = UNITS;
- while(tmp != NULL) {
- if (tmp != MOVE.unit) {
- //анимация ничегонеделания.
- if (tmp->frame++ == 120)
- tmp->frame = 97;
- }
- if (tmp == MOVE.unit) {
- //анимация передвижения
- if (tmp->frame++ > 22)
- tmp->frame = 1;
- }
- tmp = tmp->next;
- }
- }
- #undef main //write straight to the cosole
- int
- main(void)
- {
- SDL_Event E;
- Uint32 next_time;
- srand(time(0));
- init_sdl();
- init_opengl();
- init_q(&q, 66000);
- init_models();
- init_textures();
- init_interface();
- generate_hex();
- init_map(); //generate map and units information
- //puts(glGetString(GL_VERSION));
- GQO = gluNewQuadric();
- MOVE.unit = NULL;
- //printf("%i\n", __LINE__);
- next_time = SDL_GetTicks() + 300;
- while (isProgramLooping) {
- //HANDLE EVENTS
- {
- while (SDL_PollEvent(&E))
- hanlde_events(E);
- }
- //PICK
- {
- draw_for_picking();
- draw_interface_for_picking();
- do_picking();
- }
- //DRAW
- {
- draw();
- draw_interface();
- SDL_GL_SwapBuffers();
- }
- //LOGIC
- {
- if (MODE == MODE_MOVE)
- move_logic();
- if (MODE == MODE_FIGHT)
- atack_logic();
- camera_logic();
- }
- // TIME/FPS/animation changes...
- {
- //SDL_Delay(50);
- #if(0)
- if (next_time > SDL_GetTicks())
- SDL_Delay(next_time - SDL_GetTicks());
- else
- next_time += 20; //SHIT
- next_time += 20;
- #endif
- if (MODE != MODE_PAUSE) change_frames();
- }
- }
- return(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement