Wawacraft:Evolved
LAST UPDATED: [[2/8/24]]
PROJECT START: [[17/7/24]]
Wawacraft:Evolved in short, is a game that aims to be the successor or
sequel of Wawacraft, a game I made before. I want to create a fully functional
3d half-voxel based half-sprite based open world sandbox game where you can
play as one from an array of different 2-foot 2 footed cats, earless or
non-earless, survive, explore a terrain-generated world, and fight different
bosses. The game also aims to have some offbeat design for what essentially is a
minecraft clone. It will have different skill trees, and different characters to
give you a head start in certain skill trees. Every skill gives you a new thing to
craft, a boost in a stat, or a new ability or unlock, such as a new boss or such.
As you can tell, this game is already quite ambitious for a thing of such purpose, but
I have some determination. I had previously written the engineering marvel that is the
original Wawacraft game, and also had programmed a simple wireframe 3d rendering engine
before. Now my task is to create a fully functional game!
This project will have a series of updates, announcing when I hit new milestones, or different
things that I complain of during the game's development. It will also have some screenshots of
some things that I might have made.
So much to do, so much already done, and so little said.
[19/11/24]
So, I am not dead after all! I have been working on this project for
so long, and yet I haven't written much about anything in
general. Well, it was a series of the same excuse to myself: "It'll
never be worthy of a blog." And here I am, achieving so much for the
project.
Firstly, I actually set up a git repository and a github for the
project, and am using git to document the project as far as I can. I
failed a bit in trying to write documentation in the early versions of
the project, and ended up neglecting documentation. I was able to
write complete, and working 3d, alongside a moving camera with
sensible controls, all using the math that it takes to do such things.
Git repository, versioning, boring stuff
You can visit the nitty gritty details of the code progression on
Github, right here at
https://www.github.com/sphurlsmith/wawacraft-evolved. I have been
writing on a steady commit basis since August 25th, with frequent
breaks taken for schoolwork.
I follow semantic versioning for the Wawacraft:Evolved project, and
will continue to. I decided that I will label with more greek letters
after alpha and beta, as I doubt the game will ever be developed so
well that it is worthy to enter release stages. I started in
v0.0.0-alpha, though it isn't the first version of Wawacraft:Evolved
if you want to be terse.
How I got a 3d environment, with an Uni Cube?!
Yep, I did what I promised in the last few blogs. I realized through
all of this development, that 3d environments take a lot of math, and
especially linear algebra, (and QUATERNION ALGEBRA?!!).
Firstly, to understand how 3d works, you have to consider that
everything in computer graphics takes inspiration from linear algebra
for some essential things. Points are represented, sometimes as
coordinates, but most of the time as VECTORS.
Vectors
Vectors are special mathematical objects that are like coordinates in
some ways. They represent transformations in 3d space, and not fixed
points, though vectors are adopted over coordinates for special
reasons. For example, a position 3 units right of the origin, 2 units
above, and 1 unit north is at the position [3, 2, 1].
AS vectors in CG are used to represent transformations AND
coordinates, you can do a lot more awesome things with
vectors. This includes the dot product (which finds the product of
x1*x2, y1*y2, and z1*z2), and the cross product, which gives you a
perpendicular vector to both of the previous factors.
These transformations, while impressive, are FAR TOO SIMPLE to
completely encapsulate the math that goes into 3D space.
Projection and Matrices
In 3DCG, Points in 3 dimensional space cannot be represented in their
true form. To represent 3D on a 2D computer screen, you must
effectively squeeze the 3d view of the camera into a 2d plane, and
draw the 2d plane to the screen in its place. This is called
projection.
Projection comes in two forms for 3DCG:
Orthographic projection
Perspective projection
Orthographic projection, is a type of projection which projects 3d
space in a completely unwarped method. In here, points are just
squeezed - or rather projected - onto a 2d plane perpendicular to the
camera angle. This 2d plane is then drawn directly to the screen.
This type of projection isn't used or paid attention to as much, since
it doesn't show hidden sides or implicit details like depth without
assisting features.
The second form is perspective projection.
In perspective projection, everything is projected just as if it was
from the perspective of your eyes. Things further away are represented
smaller, and closer things larger. Some of you who draw may also
recognise that perspective projection actually generates images with
vanishing points.
In perspective projection, points are projected onto a mediating plane
perpendicular to the camera which stands between the 'eye' and the
point. A line is drawn from the point to the eye, and the intersection
between it and the plane is the point drawn to the screen. It uses
simple interpolation, and is easy to understand in a theoretical
environment, but where it becomes hard is when you have to think of it
in the context of computer graphics.
Bonus Projection method
Remember classic Wawacraft? That game did have 3D mechanics, and a 3d
world, though a bit clumsy. But it didn't project its world like any
of those methods listed before. Wanna know why? It's because the
original Wawacraft uses *Isometric Projection*.
Isometric projection is a projection method where every point is drawn
parallel to the other point. The 'viewing plane' which appears in
every other method appears here too, being a plane perpendicular to
the eye point, which stands infinitely far away in positive x, y, and
z axes. Points are drawn parallel, just like orthographic projection,
onto the 'viewing plane.'
You might have noticed that original Wawacraft looked a bit like a
really detailed mosaic, and it was hard to differ points closer to the
camera than farther. It was so jarring, in fact, that I had to add a
feature which showed you the precise coordinates of the block you were
placing at any time in Build Mode. That's all because Isometric
projection doesn't represent depth at all.
This method is by far the least recommended to use, but the easiest to
make, and it is exactly why Wawacraft has the legacy of causing
migraines after long play sessions. (But unfortunately, nobody was
EPIC enough to play it longer than 15 minutes at a time, other than me
of course).
Matrices
Matrices are another mathematical object. They are grids of vectors
listed together, and allow you to perform larger and more complex
transformations on vectors than vectors themselves.
Of course, I can't go fully in depth about matrices in this blog, but
I'll go just as far as you need to know for you to understand what the
flip a matrix is, and why I have to make 3 of them to make 3d
graphics.
Matrices are consistent of grids of numbers. They can have widths,
heights, and are in many ways like 2-dimensional arrays. They can be
added to each other, and subtracted from each other, but their
greatest use is in multiplication, both with other matrices and with
vectors.
Now because matrices are both wide and long, there are 2 methods to
multiply them. The first is row-major multiplication, wherein each
point is the dot product of the row of the first matrix at the
y-position of the element with the column of the second matrix at the
x-position of the element (or at least that's how I implemented it in
my old code).
The second is column major, wherein multiplication is with the column
of the first matrix with the row of the second.
Column major and row major are not just for multiplication, as they
are also for the types of matrices themselves. If you multiply row
major matrices with column major multiplication, you effectively ruin
the multiplication. Many articles I read use column major matrices,
and don't specify it simply because it is the norm for OpenGL. I
however, preferred row-major, and this is why I had such hard time
with articles and documentation on matrices. I eventually just pushed
through, though.
The 3 Golden matrices
So what will we do with what we have if we want to draw a 3d-model in
relation to a camera? Well, we have to define what coordinate spaces
the model will go through.
A coordinate space is simply a space in which objects must assume
coordinates on a special basis. For example, GPS use a coordinate
space centered around the earth. What if aliens measured our position
not by its relation to Earth, but by its relation to the sun, or the
nearest black hole? That's what a coordinate space.
Remember in its initial form, that 3D models are in local space, or
model space. This means the basis of the coordinate space is the
object itself. The object is at the centre of space.
We want to transition the model from its model space into world-space,
where it is represented in a greater 3d world, maybe amongst other 3d
models as well? Imagine a 3d model of a chick, and us trying to bring
it to world-space, where we want it to be with its other brothers. For
this, we want to know the position and orientation of the chick in
relation to the greater world.
That is done by a special transformation kept in the Model Matrix,
which brings models into real-world space by applying the
transformation and rotations needed to get the position and
orientation of the object in the greater world.
But we must also remember we are viewing the world through a
camera. We must therefore assume the position of the eye or the
camera, and its orientation. We can do this by transferring the models
in world space into models in view space.
You would ask: why not just move the camera into world space like the
other models? Well, it is harder to do, and an equivalent, and much
easier calculation, is to simply transform the world reversely. If you
move north, it is equivalent (from your point of view) to the
entirety of the world moving towards south. Computer graphics
preserves the camera at the origin, and this is where this
transformation comes into use.
To do this, we create the *view matrix* as the inverse of the
transformation needed to give the camera its orientation and position
from its initial orientation and position at the origin of the
world. This applies the reverse effect on the world at large.
After the view matrix, we have the perfect conditions to begin
projecting 3d points onto 2d space. We use perspective projection, and
create a perspective projection matrix, or simply a projection matrix
as the final matrix of the entire transformation.
After the application of these 3 matrices, we can draw a frame of the
3d world to our 2d computer screen.
More to discuss?
Of course, there is always more to discuss with a topic like this, but
with the simple idea of these matrices as enough food for thought, and
with me trying to keep things on topic, I will eventually have to
return to Wawacraft Evolved.
If you are more interested in a subject like this, consider reading
the multitude of books and articles online which explain these kindsjects in detail, as they are plenty for the taking. I myself am
also not satisfied with this explanation of the subject, as it is all
in layman's terms - so to say it is EXTREMELY dumbed down to make it
digestible in a greater form. I might write more blogs in my general
blog about subjects like these, and especially Quaternions, which I
found very ingenious for rotations and 3d space transformations in
general, but for now, this is as far as I can realistically
this subject.
And of course, the development process is almost never like how its
made to look. It was full of bugs, and still is.
What I achieved
I complete 3d world with a working camera and a rotating Uni cube. My
younger brother wanted to see Uni, so that's why I changed it. The
demo is marked v0.0.1-alpha, and can be found on github. I'll show a
couple of fun development screenshots here.
The code is a tad terse, and often times prefers to go in really
square-shaped circles. The cube is constantly rotating, so it is a bit
hard to understand what orientation you're at, but thankfully it
communicates itself a bit better than Classic Wawacraft, so I'm proud
of that significantly. You could fork it to just /not make it rotate/,
which is a completely regular thing. It's only a few lines of code.
If you wonder why the cube rotates so weird, that's because it is
using euler angles, and not quaternions. It does this half-swirl every
time it makes a full rotation in one axis, but it doesn't really
matter that much.
I think I found it pretty impressive that I was able to do all of this
in 2 months under the stresses of school AND learning OpenGL Just for
it, but upon closer inspection of some of the code, you'll find that
it is extremely unprofessional.
What I want to do in the future
Considering the structure of the code, and what I want to do in the
future with Wawacraft:Evolved, the code I have now is not good
enough. It's functional, but just not as good as I need it to be.
For context, I will not only be using Wawacraft:Evolved code for
Wawacraft, but I will probably be porting it into another game project
for a science fair which is due in February. This means the code must
be as flexible, readable, and documented as I need it to be, as I have
tight development on code that will enter 2 projects.
Secondly, I recognise even from this small demo, that
Wawacraft:Evolved is going to be my first venture into programming
large systems. I have had no experience with programming a relatively
large program, and almost all of my knowledge is just in writing small
programs that manage to do a lot more than you might think they do in
that amount of lines, or just exactly what you expect.
And with programming large systems comes a greater reliance on the
behaviour and quality of code. Firstly, it doesn't follow clear
standards. None of it is set in stone - and for the sake of pure
productivity, none of it ever will be - but I want to make sure the
code is easy to debug and easier to work with. I've had many debugging
sessions where I was essentially just fiddling with different parts of
the program to see when it worked, as opposed to actual debugging.
And so instead of trying to fix up my spaghetti code, I'll just
rewrite all of it from scratch, now with the opportunity to do it
better, and cement all my previous knowledge in with a hammer.
What inspired me to adopt a different system of writing? It was a
lecture that I found really interesting, called 'How I program C' by
Eskil Steenberg. You can find it on youtube.
What does this mean?
Just as it says in the git commits, I'm going to be moving
Wawacraft:Evolved into the next version through a complete
rewrite. After that, we can focus on greater features. Maybe we could
consider some of the following:
Block system (generating block meshes from information, etc)
An implementation of raycasting in 3D (I have experience in this)
Deleting and placing blocks in (Easier said than done)
Basic limitations on movement (Gravity, speed, friction)
New Textures
I want to emphasize new textures so heavily. I will be redoing the
32x32 sprites for Wawa and Uni, as I want to perfect the style that I
found in some of my old sketches for Wawa and Uni. I need to perfect
said style to the top, so I can make sure the game is artistically and
technically impressive, as I intend.
Closure
Long blog, I know. But we finally reach the end, and I have some notes
that I want to end on.
Firstly, I always intended for Wawacraft:Evolved to be technically AND
artistically impressive. I want to take ZERO Of the shortcuts that I
did in some of my older projects, and I want to take things Head on.
I also want to emphasize how I am not afraid of rewriting anything,
no matter how big it is. I feel that if I'm not doing something as
well as I can, it's so much easier to throw it all away and do it all
from scratch again. Think of it like this: If you're making an
artpiece, and you realize there are fundamental mistakes wrong with
the piece, will you spend your time incrementally improving a bad
artpiece until it progresses into being a good one, or will you
instead just do it again from scratch? Maybe in the future, I won't
have opportunities to rewrite the project from scratch (imagine it
getting so big that I actually have to consider writing documentation
for new contributors), but now is the best time to rewrite.
And finally, I am always looking for new people eager to help out and
assist in the development of Wawacraft:Evolved. If you can code in
C++, or you can write good documentation, or you can make good music,
or you can make good art, and you are sufficiently passionate about
earless cats as much as I am, then PLEASE, PLEASE, PLEASE, be welcome
to help me.
I will be writing blogs like this, in longer forms over longer
intervals, as it is better to do than small blogs per small
interval. I have a lot more to talk about, and a lot more to explain
in detail. However, considering it truly, I could also say that longer
blogs stress on me to shorten things more, to avoid wasting time or
dwelling on useless things. If you found any of this interesting, and
want to seriously ask me to just converse with me, consider emailing
me about Wawacraft, and I'll be more than glad to talk with you for
years.
One funny detail I want to add before I finish off, is the pattern of
how I deal with commits now. I've found myself signing off commits
with something other than my regular signature. Wawacraft:Evolved
FOREVER!!! I thought it was a fun idea to have that be my signature
for Wawacraft related things, and I allow you too to use this
signature instead of Yours Truly, Gleebshinkle [Enter Last Name
Here]. Let's all make a collective signature independent of names, and
become one group in our shared love of earless cats. I'll be sure to
write another blog quite soon, and I'll surely write more of this
project again as it is the second most fun thing in my life now.
WAWACRAFT:EVOLVED FOREVER!!!!
A Stable Rendering Engine, and some new features
8/8/24
Today is a big day for Wawacraft:Evolved. Today is the day that
a stable rendering engine has been created, the day that we can
now reliably render things, and a day that is ultimately a step
further into the esteemed minimal environment of a Wawa cube.
After several days of rewriting the mesh class and WCRL(the
official moniker for the set of rendering classes and methods
created for Wawacraft:Evolved), I finally got the mesh rendering
working, and established a rendering method that I call instantaneous
rendering.
Instantaneous rendering is a system that I have devised for Wawacraft
after I wrestled with OpenGL and lazied out,and it is a system that involves
refraining from rendering as much as possible, and a system that instead
relies on establishing the important details of a 3D Scene. What happens is
that in the game's code, a "render-friendly" mesh is kept in memory, and an
integrated OpenGL rendering environment is established for a short time in
order to render for a short time a "snapshot" so to say, of that mesh. This
is as opposed to traditional games, where a mesh object is simply binded
to the game data for the model, and used whenever necessary, or often times,
added to a render queue, and rendered alongside every other object in the
scene.
Now you may think this is a baloney system, and it is. There's a reason it's
not exactly established, and that is because while it is more memory efficient
to instantaneously render the mesh, only using the memory for a short amount
of time, it is also quite the performance intensive action, because OpenGL is
specifically built to work with reserving GPU data for an extended amount of
time, with the memory optimization being done by removing the load on the
memory for the real-time graphics. I definitely need a rewrite on the mesh
class back to its old form, now that I understood what the issue was plaguing
it. Speaking of it, let's talk about why I rewrote my mesh class 4 times.
So my mesh class so far isn't very efficient or intelligent. It uses
instantaneous rendering, which isn't very smart in the long term. That is
because it is the 4th revision of the mesh class, with all the previous
implementations being very much better than the new implementations. However,
in a series of bad debugging, I instead chose to rewrite the mesh class as a
clutch instead of actually at least searching for the issue behind the problem
at hand. I initially had a sane mesh class, but for some reason, when I set
the glVertexAttribPointer() attributes, I instead found that linking
the pointer to the list of attributes by sending in a pointer to the first
element of the vertex array doesn't work anymore. Some implementations I've
studied used it, and so I had to use the function std::vector::front()
to the pointer of the vertex. So now I have to rewrite the mesh class back
again to the beginning of the vector. However, I have implemented some cool
features in my new WCRL after 4 rewrites to important elements.
Optionary color overlaying, and simple alpha-blending!
That means we can make textures meshes use the color attributes as an
additional visual effect, and alpha blending means we can use textures with
alpha components to implement transparent regions, allowing for visual effects
such as making sprite billboards with characters that look as if they are
not quads moving around in a 3d environment. In fact some games utilize
transparent quads to simulate grass and vegetation. You can notice this in the
old Call Of Duty games.
But wait, there's more! Textures also now have the choice of being
loaded with different interlacing options, which allows for either linear
gradients between the pixels, or absolutely no gradient between them, which
means I can make the game look pixelated, or allow it to have gradients when
loading images. It's not exactly the best choice to interlace low-res images,
nor is it to remove interlacing on large-res images.
What this Means!
Well, this means we are one step closer to creating a functional 3D
environment, and creating a Wawa cube just like in the development of the
original Wawacraft!. I only really have to study matrix multiplication, which
I already understand to some degree, and study how 3D projection math really
works, which I also somewhat understand due to writing a basic from-scratch
wireframe 3D renderer in SFML previous to this. That renderer did not use
matrices, as I had not yet understood them, but I read some books and
gained some knowledge, which now means I sorta understand it.
I can barely explain it due to how I visualize it quite weirdly, but the
idea is is that every element of the first matrix is equal to the sum of all
the respective elements of its row multiplied with their corresponding
elements within the second matrix's column, of which progresses for each row
in the first matrix. Due to how this is, matrices can only be multiplied with
matrices of similar dimensions, or with only one column, which makes it
easier. What I also learned is that a column vector, like the one I studied in
school last year so we could learn basic 2D transformations, is also
applicable to be a matrix!
Now one thing that I'm not sure what to pick on is whether I would like to
implement all the projection mathematics on my own, or using the often coupled
library GLM, which handles creating projection matrices for you instead of you
dealing with the math. I figure that the GLM approach would be faster and more
stable in the long term, but I can't shake the feeling that I would find it a
more satisfying/fullfilling process to create my own mathematics systems for
the code and write all the projection math myself. I already have the supplies
to, and it would be relatively impressive to say that I coded the 3D myself,
but given that most people who play games don't really care if your 3D library
is in-house or extended, and that it would be defeating of the point of a
library to write your own library instead of making your own and expecting
said library to be used. It is foolish but I take enjoyment in the bragging
rights.
I guess I could use GLM for the moment, and follow the tutorial, and use it
for an extended period of time until I actually feel the need to write my own
3D rendering algorithm or feel that GLM is very limiting(This will never
happen). I think why the choice of writing your own 3D Library as opposed to
the much harder(and perceived impossible) task of programming your own 3D
projection is easy for other people to decide on and hard for me to decide on
is that I know I could realistically succeed with any two of those options,
and that I'm already biased to rebuilding things from the ground up despite
the difficulties associated with that, and because of my central philosophy of being
dependent on yourself to the greatest extent. But we'll see what decision I
decide to take, and how well I implement it. After all, it's all just the
exact same math, right?
Wawacraft:Evolved Art?! Let's Go!
So in celebration of Wawacraft Evolved getting ever so closer to success, I
had the fun idea to redo the sprites for Wawa and his friends in 32x32 instead
of 17x17. You heard it correctly, the old Wawacraft game loaded Wawa and Uni
sprites of the resolution 17x17. That in my opinion isn't a good resolution,
and while I'd love to use the old wawa & uni sprites, I think it would be more
fitting of a game with the subtitle Evolved to have some more developed art.
I
was actually already envisioning some similar images, except they may have had
many more gradients and some muted dark atmosphere to these drawings in some
way. Not dark as in throw a bunch of blood there, but a gritty or unpolished
look to these to make them look as if I just edited a real life photo of the
characters. I would definitely be better at this with the block textures for
the game, I already have the idea of muted colours in my mind, but the
characters are so vibrant in a way that it becomes hard to make their textures
feel unpolished. Some might say that the very fact that your art is not the
best makes it unpolished, but what I mean when I say it's unpolished is that
it should have an aged look to it. Not super intense image compression
artifacts to it, just a bit aged, or like the look of amateur pixel art.
I made the color combinations of this as real gradients, which definitely makes
it look quite vibrant, and the eyes and mouth are not the best, though I like
how they looked in my old drawings. In some of the character sketches for
Wawacraft, Wawa had a more cartoonish look, with the mouth of well a cat in
most cartoons. And he had this special sort of beard-like think around the
bottom part of his cheeks, but I think I didn't have enough space for them.
Regardless, I hope you enjoy these drawings of wawa, but I don't. I will have
to redraw them.
One last thing, I finally have the opportunity to add Floppa and Ploobie, who
are essential parts of the gang, in this new game! Yay!
Conclusion
Much like most other updates, I have a lot to be proud of, and a lot to fix,
and a lot to do. Well, I'll see you in the next update then!
Textures! And a bit of rambling...
2/8/24
Hello again! Wawacraft:Evolved is still a thing I am working on, but not as actively as before. Now, Don't let this
little date mark fool you, I was already done with making textures on the 30th of July, but I just was too lazy to
make an update. But don't worry, I have great news!
We Have Textures!
Yup. I got textures working, and now we can see Wawa's face plastered on top of a triangle. What does this mean? It
obviously means we have succeeded! I have multiple snapshots of the progress I have.
So despite what I previously had in mind with graphics libraries. OpenGL doesnt actually load any textures from files.
It actually requires to load from raw, hardcoded data in the form of a c-style string. This isn't exactly the best kind
of way to store your images for ready change, and in the previous game, I could load in texture resources as separate
files in a resources folder. Luckily, there is a library built to load in images from the filesystem and into the code
as raw data that OpenGL can interpret. This library is called stb-image, and much to my surprise, was all but one header
file.
Programming in the texture interpretation was quite easy. And it wasnt as hard as I believed it to be. Just do the necessary
loading functions, and supply the image parameters for interpretation(how many color channels? RGBA? Resolution? etc.). And
all of this is quite the success. We truly are reaching ever so close to an interactive 3d environment with a cube of Wawa.
But one last thing remains that I have had a lot of issues with this whole time.
The source code has no foresight.
In my early development of the original Wawacraft, I had rewritten the entire game about 3 times before I settled on leaving
the code as it is now. Refactoring is my biggest fear, but for Wawacraft, it's quite obvious that I will have to rewrite the
game from the ground up multiple times. What does this include? The rendering library of course.
My first issue is WCRL. I have named the headers and code that I will use for rendering things on an abstractified layer on top
of OpenGL and its subservient libraries "The WawaCraft Rendering Library." It won't be built like a library, but it could just
as well serve for the base for a framework for abstractifying GLFW and OpenGL for anybody who wants to use it. WCRL right now
is not a good library. It loads in shaders by embedding shader code into the file, which is not at all good practice. It also
can only load a specific file from a specific path, hardcoded in it. And on top of that, the use of C-style structs and helper
functions instead of C++ Classes with encapsulated functionality was a really awful compromise I had to make in the previous
update to get any rendering working, otherwise I would get a thousand segfaults.
One thing that I think I wont change is the windowing system. That had no relative issues, and is very much important. I don't
thing that needs a rewrite. But regardless, if I am going to ever reach the Wawa Cube in perfect form, I will first have to
rewrite WCRL to be better, and more elegant and flexible. That way if I ever need to change anything, I wont need to jump back
into primitive rendering from scratch all over again.
Some cool ideas I wanna talk about
In this post I have shown you a picture of Shawa. I was starting to think of how the advanced game would be like. I have a vision
where the game will randomly throw you to battles against bosses in a convenient time. You would have to defeat these bosses to
get XP and expand your character's skill tree. That will incentivise players to do more things in the game, and trigger boss fights.
And also, I never liked fighting mobs in Minecraft. I think they are an annoyance in general, and the benefits of fighting them are
minimal. You do not get much XP for fighting these mobs, and most people only head to the bosses if they want to progress in the
game. The mobs are an annoying afterthought that makes the game a bit infuriating to play. The idea of only having bosses to fight,
getting a real incentive to fight these bosses (i.e. XP, expansions in the skill tree) as well as most importantly, the ability to
run away and fight the boss another time when they are more prepared, will make combat in the game better. That way there is
less annoyance, and instead places the incentive of challenge on the player, by programming them to always prepare for a boss battle
when playing regularly, and looking forward to meeting the boss, it creates a good loop.
This however does mean I need to create enough bosses to fit the skill trees, which is a lot of bosses. That needs creativity. Wawacraft
is exactly the kind of game where this isn't a problem. Why? Because most games like to keep narrative consistency or a half-serious story.
This makes the player expect the game to take itself seriously or at least keep a common story, and sometimes makes the game boring. But
Wawacraft isn't that kind of game. Wawacraft is, and I will continually refer to it as, a lopsided feverdream game. This means that
any and every boss idea is a good enough boss. Here are some good ideas for different bosses that I have had in mind:
Shawa
A cone with Wawa's texture splattered over it as a boss. It should look somewhat like the shawa blooper earlier in the update. It's
attack pattern I think will be that it circles in orbit around a point that approaches the player straight on using some pathfinding. Shawa
rotates also around his Z axis whilst orbiting, and the closer he gets, the stronger an image of the blooper becomes. The image layering
thing is actually similar to what happens in Slenderman when you look at slenderman for too long, except now the opacity of the screen
becomes higher the closer Shawa becomes to you, and if he touches you, you lose health continually.
the Real Wawa(which I will refer to as Oh The Misery or OTM for short)
A picture of the actual Wawa, the Oh The Misery cat as many call it now. OTM will chase you and upon reaching a certain distance will
explode into many smaller OTMs, who also chase you but now even faster and their explosions less powerful. OTM will also have a song
that plays while you are fighting him. His boss theme will be Enemy by Imagine Dragons but in an epic MIDI remix to avoid legal issues.
The idea to beat this boss is by outsmarting it. Run close to OTM, and continually have OTM explode into smaller versions until you can
chop off each small OTM individually and finally destroy it.
I got this idea from an older game prototype I had called The Museum, which was a game that also featured Wawa before Wawacraft was a thing.
It was called The Museum, and I planned for it to have the gameplay of a horror game where you search for items and the monster searches
for you. All of it would take in a museum, and I had the idea that the player could fight against Wawa, and when they shoot them, it bursts
into smaller wawas, which makes it harder and harder. I actually have a real video of The Museum before I gave up trying to do sprite billboards
in the raycasting engine. But this Idea will live on.
The Helicopter
The Helicopter is a helicopter that circles around your general area, and tries to bomb your approximate location. These bombs will come in the
form of target-lock missiles. These missiles will lock onto a location, that will be communicated to the player through a stylish yellow-red HUD
marking like the one in the final boss of Sonic 2.
The boss music will sort of be like the boss music of Fatman from MGS2. The way to beat The Helicopter is to dip yourself in a half frozen lake
in order to trick the lock-on heat targeting. Or you could throw magnets on the floor to attract the missiles. Throwing a ring of magnets around
a wide enough area will eventually jam the helicopter's navigation system and the helicopter will come crashing down.
But then a second stage of the boss fight happens. The helicopter stands up and begins fist fighting you. This idea came from a prototype of a
scratch fighting game I wanted to make with all the different OCs I had made at the time, and make them fight, called "Puffball And Chicken Legs
Fighting" or something of the sort. I wanted to add some silly characters like "The Rock" which is a rock with the face of Dwayne Johnson on it, and
of course a fisfighting military-grade helicopter that can deal damage with no hands and no feet as if it has invisible limbs.
Coneman
Cone man is a character that I made before. He is a man who is stuck in a cone, who has blotches on his skin(vitiligo) and hairy feet. Coneman has an
RPG launcher. His attack pattern is that he runs about and places himself in the right position to launch RPG missiles at you, after which he has a
reload downtime to load in new missiles.
He will spawn at random locations disguised as a regular traffic cone. If you interact with this cone, coneman's arms and legs will pop out, and his
head will pop out too, with the tip of the cone acting like a hat that conceals a dark face with only the frowning/sleep deprived eyes of Coneman.
Once you beat coneman you will also gain an achievement that says "Rocket Propelled Traffic Violation." How funny would that be?
Conclusion
In short, theres a lot I have in mind for this game, and a lot of effort I'll have to put in to get what I want. I'd rather talk about Wawacraft in practicality
rather than theory. Lets see if this works. See you in the next update.
6000 Segfaults later...
24/7/24
After 6000 segfaults, 3 days with OpenGL, 2 days trying to write a primitive rendering wrapper base for OpenGL
and essentially 2 rewrites of said wrapper base, I finally achieved the amazing Triangle of OpenGL!
This is a greater success because of the kind of things I had to do to get it to work. I initially tried implementing
the rendering library in C++ style classes. That failed quite miserably and is the the cause of the rewrite.
However once I started writing the rendering wrapper with C-style structs and helper functions that passed the
polytri struct via pointer, I actually got my successes with it.
Rewind, rewind rewind.
Given that in the last update quite literally 3 days ago, I was using GLUT and not this weird thing GLFW, you the
reader are probably quite confused how I reached this state. Well it was mostly about me learning that GLUT was
outdated and not the best framework to work around OpenGL with. FreeGLUT and GLUT respectively are apparently only
used to make skeleton projects and don't scale well. As well as that, I found that switching to GLUT meant that I'd
have built-in input detection and management. That's always a good thing if you are developing a videogame, since half
the time you are usually pressing keys to get the game to do things. So I switched to GLFW, and started following the
tutorials on https://www.learnopengl.com/. That site was a treasuer in that
it actually provided some good instructions on how to get started with OpenGL, and they just so happened to use GLFW.
It's a great tutorial series, you should read it if you're starting out with OpenGL or want to get into
graphics programming.
What does this mean for your GLUT build?
Scrapped it and threw it in the trash. Started from scratch and configured GLFW, GLAD, and OpenGL. All of those
were quite easy to set up for a hard library. I'm actually quite happy I'm learning to fade out of IDEs and start moving
towards more close-to-the-metal building systems. Manually writing makefiles for GNU make, running the G++ compiler, from
the terminal, and using a basic(Haha, it is Emacs. In no way is it basic) and versatile text editor(Emacs) to write things.
What about the in-house 3D Renderer built from scratch and the 2D primitives library to support it? Are those simply gone now?
When I got into OpenGL, I thought that it would be so flexible that it had both 2D and 3D parts, all fully supported and
independent. That was simply not true. OpenGL is a 3D library that can be made to look like its running as a 2D Library.
So if I was to start using drawPixel() calls to render each and every pixel on a 800*600 screen with only RGBA colors, I
would need to hack at the library, and use the outdated OpenGL classic pipeline, which isn't very well looked upon, nor
does it scale anywhere near 800*600 times.
So the simple answer is yes, unfortunately. There will be 3D subroutines and 2D subroutines, but they will not operate from
scratch. They are in practical terms only quality-of-life code that neatly encapsulates the ugly OpenGL process, and makes
it easier to develop the game and scale it. This is the case for any game made with OpenGL.
Maybe one day I will see a port
to be made to some archaic architecture or machine, such as in a hypothetical example(Because it usually is quite rare to
think of) a machine like the Sega Saturn or i486 CPU architectures or CPU speeds around 400MHz. In
that case, I could see a real use case where it would probably be better to roll my own 3D renderer rather than using OpenGL,
let alone my own 2D rendering library. But believe me, I have all the right tools to embark on such a project, and I will
not hesitate to given the opportunity.
Considering creating a GIT repository for people to see the source code.
In the tradition of the original Wawacraft(in all of its low-optimization isometric glory), I plan to make Wawacraft:Evolved
Free and Open Source. Many initial versions of Wawacraft in alpha or beta were lacking up-to-date source code, so I could consider
some of it freeware, but because I am the author of that game, and because I never intended to make it "freeware" as it is known
more so "free software" and Free in all the terms, I simply do not consider it freeware nor is it freeware in any sufficient way.
I never protected the game under a real license however, and just said the only rule to follow when creating any mods or
derivative versions of the game, that I be credited in a valid way.
But with all of that said, I probably should be uploading the source code and updating it too. However, it is too basic of a program
and indistinguishable from any other starter OpenGL project, that I would rather get to the task to uploading the source of
Wawacraft:Evolved. However I will be doing it, so no worries.
One step closer...
With all of that said, we are getting one step closer to the Wawa cube that I promised in the last update. One step closer. See you
in the next update. Nya!
Switching over to OpenGL (& FreeGLUT)
21/7/24
So, I did it. I switched to OpenGL, after all that fuss. No API. Just pure OpenGL and FreeGLUT.
In hindsight it made a lot of sense. After 3 days of trying to make SFML do something OpenGL
usually does, I decided to just bite the bullet and switch my game to function on OpenGL. It's
definitely the better choice I made for the long run.
The image you see above is the OpenGL window I spent this morning adding in the game. Speaking of that, let's
talk about the fact that I had to throw out all my old code just because we switched to a more primitive
API. I had to throw out all that hypothetical 3d renderer code into the bin, and start from square zero. This
also includes my 2d renderer. I had to throw it out also. This does give me the opportunity to write my
primitives as close to the bare metal and VRAM as it could possible get, but it also means I get to cheat
my way through a couple of things. What are those things you might ask? Well, only the barycentric coordinate
math needed to make a simple color gradient mix for colored triangles. And also textured triangles if that is
what is used.
So lets go over some of our new opportunities now that we have bit the bullet and switched to OpenGL: better
primitive rendering, native support for a depth buffer and depth buffer testing, the opportunity to use OpenGL's
built in 3d renderer, or simply roll our own 3d renderer on top of OpenGL's 2d rendering abilities. But most
importantly, our game's rendering will reach the honored title of sUPer uLtrA Fast. I like some
things about OpenGL Over SFML, an OpenGL based API, in that OpenGL uses normalized coordinates for the screen buffer,
meaning the center of the screen is labeled (0,0), and not (Width/2, Height/2).
Success?
Yes, success! We made a black window that can close itself if needed, why not call this a success. It's only a minor
success, as we need to implement rendering to the screen to consider any form of success.
But what is our next milestone? To make a 3d environment where we can appreciate a 3d cube, preferrably a picture of
Wawa on every face.
See you in the next update!
AAARGH!
20/7/24
It's been 2 days I'm developing a 3d rendering engine to use in-house for the game. I have built a majority of
things, and for the most part understand almost everything and have - hopefully - made a basic collection of
classes and subroutines that will in theory be able to create simple 3d scenes. I've handled the vector
transformation of an object from one place, its rotation, its rotation to the camera, and its transformation from
the camera. All quite useful things. Just one issue: I don't have a prebuilt depth buffer.
A depth buffer in 3d programming, is an allocated array with the exact same size as the screen. So if the screen,
which is a reality in my case for now: is 800x600 in resolution, the array is 800*600 units long. It stores a number
in each element, of the depth of the pixel drawn. What does this mean? See, in 3d programming, it's important to hide
any surfaces in the back of a mesh from the camera, to create a sensible and realistic image. Otherwise, it will look
quite as if the game is drunk, rendering what should be a hidden surface. Think of it like holding an otherwise opaque
cube, and suddenly seeing its back face on top of it's front face. You'd feel like you're tripping balls.
What a 3d rendering engine must do is to hide any back faces. This is done through 2 methods, the first necessary, and
the second for performance. This method is called a depth buffer. The idea is that for every pixel drawn from a projected
3d point in the world, its distance from the camera(i.e distance along the Z axis), is recorded on the depth buffer. Whenever
a new pixel must be rendered on top, we must first check if the 3d point it was projected from is nearer to the camera than
the original point. If it is, we render it. If it isn't, we don't render it.
Technically we did not render the pixel, but in performance terms: we did everything we were supposed to do for a pixel to be
drawn, but we fell out on the actual DRAWING part of the pixel. So in performance terms: we wasted resources. So the second method
is utilized: backface-culling. What does it do? It does not take place in the later part of the pipeline, but rather in the
very beginning. It checks the normal vector(in regular people terms: the direction of the polygon) of every single polygon on a 3d
mesh for if it faces the player. If it is less than 90 degrees adjacent to the player's direction of sight, it is kept, and if not,
it is pruned off of the mesh, as its rendering is already quite useless.
But my problem, is that SFML, a library built for 2d games, does not have depth buffer support. This means one of two things: either
I configure my rendering window for OpenGL, and link OpenGL into my project as a library and compiler flag, then write in depth tests
for the 3d primitives header, or I make the very slow but easily done in house depth buffer, and begin rebuilding my primitives wrapper
into a primitives library on top of SFML.
This of course whispers death into our project's optimization under certain circumstances. If I rebuild the primitives wrapper and rasterize
triangles in-house via our drawPixel function, I will have solved my game's 3d rendering problem in theory, but in practicality, I will
have also halved its performance. This is because we are rendering pixels not as pixels, but as 1x1 SFML rectangles, which will add a
lot of unnecessary bloat to the instructions we send to the CPU.
There is an easy solution to this, and that is to use the OpenGL library to draw our pixel, which is of course much more optimized
in OpenGL because we aren't using a hack, but actually rendering a single pixel, with only the considerations of writing a pixel to the
screen buffer. This means it all leads back to OpenGL. SFML was just a hurdle in the process.
So my goal for now is to rebuild the primitives library to support my in-house depth buffer, and render pixels with OpenGL instead of SFML,
and then rebuild the 3d primitives for that exact use case. Once we do that, then we can try emulating our first test render from the previous
update, but FASTER. The biggest boulder of this is building my own rasterization algorithm for triangles, which is fine, until I have to configure
textured rasterization, which is also a lot more work. Thankfully, the book I'm studying to build this 3d renderer has a chapter on basically
writing all of this from scratch.
The first step!
17/7/24
So here it is, my first step into Wawacraft evolved. I already have a list of things that need
to be built before we can get into the fun stuff where I build any gameplay-wise things. So what is
it you may ask? Well, I need to roll my own primitives wrapper, and my own basic 3d rendering engine
before we can get a 3d game working.
That's sure a lot of work for something most modern APIs like OpenGL and SDL give you! What
exactly are you using to make Wawacraft? Good question. I'm using C++, and the SFML multimedia
library. I have a lot of experience with it, and I think it will be a good start for the project. If
I ever find some issues with SFML, my first idea is to just switch to SDL, as that is a bit more tied to
OpenGL and is a more flexible library, whilst trading off simplicity or ease of learning. I know SFML
isn't exactly the best library to make a 3d game in(It's a multimedia library for simple 2d games, of
course it isn't), but I'm sure there isn't something we can't build on top of SFML to work out the
quirks.
Now, the interesting part. What have we got? Well I got my build system working on my linux computer, and I
also developed a small primitives library for making use of SFML's graphics capabilities. However, one small
issue: SFML doesn't have any in-house solutions for just drawing ONE pixel. This is going to be needed later
if we ever roll our own rasterizer, but the only good solution isn't really a good solution, its just sizing
down a rectangle and drawing it as one pixel, which is not very quick for something that must be done 800*600
times and even more during our render process. Guess we'll have to rely on SFML's rasterizer.
But with that out of the way, I did build the simple primitives wrapper. It can handle colored pixels, colored
lines, and most importantly: solid and textured triangles. Now just to build a 3d rendering engine! That's
definitely not an extremely difficult task.