Computer Programming 1 Independent Project - Week One
The beginning of a new series ment to last until December 5
What did you do this week?
Tuesday, Nov. 4 - Boilerplating
On this day, I began work on the project, making a quick OpenGL wrapper and ensuring it can show certain colors. I implemented a fading color feature where the clear color (the background color) would change based on the time the window has been opened.
Wednesday, Nov. 5 - Restructuring the backend
On this day, I abstracted the window structure, implemented buffers, and texture loading.
The first example would be a single color quad, seen here.
The second example would be a textured quad, seen here.
Thursday, Nov. 6-7 - Linear Algebra (..ish)
On this day, I needed a math library, and at first, didn’t want to use an external one. So, like any programmer, I decided to make my own, though I didn’t know that I would need a lot of time and patience to do so, in which I had neither.
I started working on minor parts of the math system, making 2-4 component vector classes, like so.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct vector3 {
float x = 0;
float y = 0;
float z = 0;
vector3 operator+(const vector3& v) {
return vector3{x + v.x, y + v.y, z + v.z};
}
vector3 operator-(const vector3& v) {
return vector3{x - v.x, y - v.y, z - v.z};
}
vector3 operator*(const float& v) {
return vector3{x *v, y * v, z * v};
}
vector3 operator/(const float& v) {
return vector3{x /v, y / v, z / v};
}
};
At first, it was going well, and wasn’t too difficult. However, I really only needed this library for the matrices and 4-vector components, so I began working on that, as seen below.
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
struct matrix4x4 {
vector4 v1, v2,v3,v4;
vector4& operator[](int idx) {
idx = idx % 4;
switch (idx) {
case 0:
return v1;
case 1:
return v2;
case 2:
return v3;
case 3:
return v4;
default:
return v1;
}
}
...
matrix4x4& operator*=(const matrix4x4& s) {
// store original values since we'll be modifying the matrix in-place
matrix4x4 temp = *this;
// for every row
for (int row = 0; row < 4; ++row) {
// iterate through every column
for (int col = 0; col < 4; ++col) {
float sum = 0.0f;
for (int k = 0; k < 4; ++k) {
sum += temp[k][row] * s[col][k];
}
(*this)[col][row] = sum;
}
}
return *this;
}
};
As I began working longer with it, it became more tedious. I realized halfway in, that my matrices were column-ordered and not row-ordered. Did this stop me, though? Absolutely not! I added transformation functions like so.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static matrix4x4 scale(matrix4x4 m, vector3 s) {
m[0][0] = s.x;
m[1][1] = s.y;
m[2][2] = s.z;
}
static matrix4x4 translate(matrix4x4 m, vector3 s) {
m[3][0] = s.x;
m[3][1] = s.y;
m[3][2] = s.z;
}
When I got to transformations, it was rotations that were really messing me up, as I had realized I would have to add a separate class, Quaternions which I especially do not understand. (I barely even understand matrices, but Khan Academy said I would get the hang of it as I use it more)
After contemplating, I realized this would be too much of a feat for me to overcome, as I am only a High School Sophomore, who won’t have to do Linear Algebra for at least 2 more years (senior year, maybe?). Anyways, I caved and decided to use glm for linear algebraic operations, as I have used for my previous projects.
Friday, Nov. 7 - Framebuffering
After finishing the Linear Algebra “saga”, I moved onto framebuffering as I knew that I would have to deal with it in the future. I redirected the draw calls from the main window into cameras, which then hold framebuffers which the draw calls are then used on. Here is some pseudocode to represent this process
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
struct GfxEngine {
list<GfxDrawCall> drawCalls;
GfxCamera camera;
void update() {
camera.draw(drawCalls);
}
};
struct GfxFramebuffer {
void showOnScreen();
void openFramebuffer();
void draw(list<GfxDrawCall> drawCalls) {
openFramebuffer();
for (GfxDrawCall call in drawCalls) {
call.cameraPosition = position;
call.draw();
}
}
}
struct GfxCamera {
GfxFramebuffer framebuffer;
vector3 position;
void draw(list<GfxDrawCall> drawCalls) {
framebuffer.draw(drawCalls);
framebuffer.showOnScreen();
}
}
This code makes no sense, I know, list is meant to represent std::vector, and the for loop is incorrect
Saturday, Nov. 8 - Entity Component System, Resource Packing, Model Loading
On this day, I implemented an entity component system (ECS) , though not an exact ECS.
Instead of an entity having components, there are different types of entities.
Traditional ECS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct Component {
void update();
void init();
void destroy();
Entity* entity;
};
struct Entity {
list<Component> components;
Entity parent;
list<Entity> children;
};
My Implementation
1
2
3
4
5
6
7
8
9
10
11
12
struct BaseEntity {
BaseEntity parent;
list<BaseEntity> children;
};
struct ComponentEntity : BaseEntity {
// implementation here
};
Not only this, but I also refactored the code, splitting the code into different files, and I somehow ended up with this (can’t remember what I was doing when trying to get this result, I think I was trying to test multiple draw calls)
On this day, I also created a resource packer, which iterates through a folder, and compresses/packs the files into a single binary file, which is easier to transport, allowing me to pack models, textures, shaders, and more into a single file.
Speaking of models, I implemented 3D Model loading using Assimp. This was slightly diffcult, mainly because it is one of the most tedious and tiring parts of the game engine process. I really only added it because I might have to load 3d models for this project, but I’m only using 2D sprites and primitive shapes, which are either loaded in textures, or generated at runtime.
Here is a screenshot of what I got as a result (I reused models from my Congressional App Challenge Project)
Sunday, Nov. 9
On this day, I was mainly focused on completing the material translator for the model loader, which would “translate” material data from models into materials for the engine, though I spent most of my day procrastinating, because this part was honestly getting tiring, so I decided to move onto what I actually was going to make with this project, which could have saved a lot of time had I switched over earlier.
I added orthographic projection to the cameras, where the 3D scene would be seen from a 2D perspective.
At the end of this day, I realized I would need to start working with spritesheets, or texture atlases, so I wrote code (which didn’t work) for a spritesheet cutter, which would split the sheet into individual sprites and load them into textures. As stated previously, the code didn’t work, moving onto the next day.
Monday, Nov. 10
On this day, I tried to get the code I had done on the weekends to work on the school computers, which was a hassle, and I had little to no time to get actual work done, not only because I was compiling libraries for the two periods I had to work on this, but the compilation was drastically slower on the school computers than my home computer.
When I got home I fixed the spritecutting issue, allowing for me to have individual sprites rendering, though I wanted to restructure the way the sprites worked.
I decided to use texture arrays instead of individual textures, which would pack the entire sprite sheet into a single texture “object”, that would be pushed to a shader, allowing me to switch between individual textures, or “layers” at will.
I used this new texture array feature to implement animations, which were powered by a new input system that I implemented, as well, which allowed me to check if a mouse was pressed, released, etc, and also if a key was pressed, or released.
What is your plan for next week?
Here are some things I plan on finishing by next week (Monday, Nov. 17)
- Finish the player controller
- Start work on an enemy controller
- Resource file compression
- Implement a UI system
Are you on track to finish on time?
With what I have finished at the moment, most likely, yes.
What obstacles are your facing?
Some obstacles I am facing are;
- Issues with build speed on school computers




