summaryrefslogtreecommitdiff
path: root/source/game/game.cpp
blob: 4229483d6d8ad4e99d342bdd8fa52484d10e5192 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "game.h"

Cloth game_cloth = {
    .width = 32,
    .elasticity = 10.0f,
    .padding = 30.0f,
};

void game_init(GameState *state) {
    i32 cloth_rows = NUM_POINTS / game_cloth.width;
    Vec2 start_pos = {
        .x = state->width / 4.0f,
        .y = state->height - state->height/4.0f
    };

    i32 max_rows = NUM_POINTS / game_cloth.width;
    i32 max_cols = game_cloth.width;
    i32 curr_row = 0, curr_col = 0;
    Vec2 running_pos = start_pos;
    for (i32 i = 0; i < NUM_POINTS; i++) {
        Point p = {
            .id = i,
            .active = 1,
            .prev_pos = running_pos,
            .curr_pos = running_pos,
            .force = {0.0f,0.0f}
        };
        {
            // @fixme
            i32 left_ind = i%max_cols == 0 ? -1 : i-1;
            i32 right_ind = i%max_cols == max_cols - 1 ? -1 : i+1;
            i32 top_ind = i/max_cols == 0 ? -1 : i - max_cols;
            i32 bot_ind = i/max_cols == max_rows-1 ? -1 : i + max_cols;
            p.constraints[0] = left_ind;
            p.constraints[1] = top_ind;
            p.constraints[2] = right_ind;
            p.constraints[3] = bot_ind;
        }
        game_cloth.points[i] = p;

        // next position
        i32 next_row = (i+1)/max_cols;
        i32 next_col = (i+1)%max_cols;
        Vec2 next_pos = {
            start_pos.x + game_cloth.padding*next_col,
            start_pos.y - game_cloth.padding*next_row
        };
        running_pos = next_pos;
    }
}

void game_shader_init_uniforms(GameState *state) {
    Mat4 projection = calcify_ortho4m(0.0f, state->width, 0.0f, state->height, 0.1f, 10.0f);

    glUseProgram(state->triangle_sp);
    i32 triangle_proj_loc = glGetUniformLocation(state->triangle_sp, "Projection");
    glUniformMatrix4fv(triangle_proj_loc, 1, 0, projection.buffer);

    glUseProgram(state->line_sp);
    i32 line_proj_loc = glGetUniformLocation(state->line_sp, "Projection");
    glUniformMatrix4fv(line_proj_loc, 1, 0, projection.buffer);

    glUseProgram(0);
};

void game_handle_event(GameState *state, GameEventType type) {
    switch (type) {
        case GAME_EVENT_RESIZE: {
            glViewport(0, 0, state->width, state->height);
            Mat4 projection = calcify_ortho4m(0.0f, state->width, 0.0f, state->height, 1.0f, 10.0f);

            glUseProgram(state->triangle_sp);
            // @step: update triangle sp
            i32 triangle_proj_loc = glGetUniformLocation(state->triangle_sp, "Projection");
            glUniformMatrix4fv(triangle_proj_loc,
                               1, 0, 
                               projection.buffer);
            glUseProgram(state->line_sp);
            // @step: update line sp
            i32 line_proj_loc = glGetUniformLocation(state->line_sp, "Projection");
            glUniformMatrix4fv(line_proj_loc,
                               1, 0, 
                               projection.buffer);
        } break;

        default:
            break;
    }
}

void draw_line(GameState *state, Vec3 position, Vec2 size, r32 rotation, Vec3 color) {
    glUseProgram(state->line_sp);

    Mat4 model = calcify_ident4m();
    Mat4 rotate = calcify_rotation_matrix4m(rotation, {.x=0,.y=0,.z=1});
    Mat4 origin_set = calcify_translation_matrix4m(size.x/2.0f, 
                                            0.0f,
                                            0.0f);
    Mat4 scale = calcify_scaling_matrix4m(size.x, size.y);
    Mat4 pos = calcify_translation_matrix4m(position.x, 
                                            position.y, 
                                            position.z);

    model = calcify_multiply4m(scale, model);
    model = calcify_multiply4m(origin_set, model);
    model = calcify_multiply4m(rotate, model);
    model = calcify_multiply4m(pos, model);

    i32 model_loc = glGetUniformLocation(state->line_sp,
                                         "Model");
    glUniformMatrix4fv(model_loc,
                       1, 0,
                       model.buffer);
    i32 color_loc = glGetUniformLocation(state->line_sp,
                                         "Color");
    glUniform3f(color_loc, color.x, color.y, color.z);

    glBindVertexArray(state->line_vao);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glUseProgram(0);
}

void game_update_and_render(GameState *state) {
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    for (int i = 0; i < NUM_POINTS; i++) {
        Point p = game_cloth.points[i];
        if (!p.active) continue;

        for (int c = 2; c < 4; c++) {
            i32 ci = p.constraints[c];
            if (ci == -1) continue;
            Point constraint = game_cloth.points[ci];
            Vec2 a = p.curr_pos;
            Vec2 b = constraint.curr_pos;
            Vec2 dir_vector = {b.x - a.x, b.y - a.y};
            r32 line_length = sqrt(dir_vector.x*dir_vector.x + 
                                   dir_vector.y*dir_vector.y);
            r32 rot_angle = atan2(dir_vector.y,dir_vector.x);
            draw_line(state, 
                      {a.x, a.y, -1.0f}, 
                      {line_length, 3.0f}, 
                      rot_angle, 
                      {0.4f, 0.5f, 0.7f});
        }
    }
}