A website about with topics like programming, math, writing, and pixel art.
Snisac.com is a single-page website that I started in the beginning of 2025, although
there are posts dated older than that because I copied them from an old website of mine.
Snisac has no official affiliation with any accounts on any social media sites.
Pixel art
99 splotches of pixels on the screen, 99 splotches of pixels...
If you want to start learning programming, your purpose for learning determines
how much time you have, what programming topics you want to learn about, the language you want to learn,
and how well to learn (certain parts of) that language.
In the end however, your success depends on your ability finally
to finish and ship the project you want to program.
Programming is yet another thing learned by doing, and experienced by creating many projects (even/especially small ones).
Some useful skills you will want to pick up before or along the way are
touch typing, computer file management, basic understanding of computer some parts, and some math.
Math
Math is good to know because it allows you do less programming.
It's a useful tool and sometimes a shortcut that avoids a need to write more code.
The math you want to know about are algebra, functions, sets, and boolean logic.
Each of these is useful to know at least for avoiding over-complicating your code's math and flow control.
It's useful to know algebra because you need to get very comfortable with variables.
It's useful to know about function domain and range, and about total and partial functions.
It's useful to know about set terms such as membership, union, intersection, and complement.
It's useful to know some boolean logic because that is foundational to understanding conditions and flow control in most programs.
Language recommendations
The type of project could predetermine the programming language.
The language depends on personal preference and what you want to do.
Languages are meant to be general purpose,
but the other people who are using it and the language's paradigm makes it easier or harder to accomplish certain things.
What language to learn if that decision is not already made? I recommend Python, C, Lua, or Common Lisp.
But, if you want to learn C++, learn C first.
C++ is so large and multi-paradigm, that the common reference point of fundamental C really helps.
Baby steps
Start with learning a simpler language such as C or Lua rather than C++ or Java.
And start learning with super small projects such as: print out the numbers 1 through 1000.
I was $today years old when I realized that A.D. (anno Domini), which means "year of the Lord" in Latin,
is in line with the tradition of reckoning the years based on the rule of a king.
You know, like, in the olden days where it would the Nth year of the reign of $king.
Well now, by our convention in dates, it is acknowledged that Jesus Christ is Lord.
We can never escape God or time, can we?
But, sadly for programmers (except Lua programmers),
there is no year 0 A.D. The years of this epoch start at 1.
Time and attention is precious, so the best relationships to have towards videogames are
total avoidance
or to only play games with friends for the purpose of socializing.
Otherwise, you are voluntarily spending time on unnecessary tasks and entertainment that does not give you anything else in life.
These games keeps you in a stasis (or an indoctrination) in the guise of activity and achievement.
It is silly to spend hundreds of hours playing a game alone.
However, tiny little games, like some that I have made myself, tend to not trap people but simply provide a moment of novelty.
These are some rantings on what I've learned from having a website.
The simple static site generator
If you know some programming...
The idea is: just write a specialized program that generates your website,
and just put all of your site content inside of that one program.
There is no need for external data files or parsing a markup language.
Just run your script (and maybe pipe the output to a file) and it is done!
For example, I have successfully done this with Python, Lua, and Common Lisp.
You can just have long string literals for each page and print them out
to the page's destination file path.
So then if you are using Python and you have just one webpage, your command to generate your site would look like this:
python site.py > index.html
Since languages commonly have an easy way to do string interpolation
or concatenation (not you, C!), you can just put functions or variables inside of
or concatenated with your other content strings.
And, if you do this, what have you done in the end?
You have basically just used that programming language as static PHP (not dynamically, server-side)!
Mini-pages
If you want to have the appearance of multiple pages on your website, and you're not using
a CMS,
then you may need to do some extra work to maintain all of those files.
But, there is an alternative: put your "pages" all in the one main page (index.html) as "mini-pages".
The trick is to use the CSS selector called :target.
If you make top-level articles which are all on the same page only show as visible when they are the target link,
you get mini-pages.
Since I am nice, here is the template CSS code, which applies to HTML elements with the "hider" class:
/* Show one article (the currently targeted one) at a time */
.hider { display: none; }
.hider:target { display: block; }
Here's a quick tip for avoiding #DIV/0 errors in Excel spreadsheets…
The tip
In Excel, doing math with cells treats blank cells as zero, so if you are ever dividing by cells values which may be blank, you get #DIV/0 errors.
To avoid this, you can use this function to wrap your original formula, f:
=IFERROR(f, "")
Now if you have blank cells as inputs, whatever calculation uses them will be blank too.
This transmits blank cells over division.
Example
This is useful, for example, if you are calculating price per square foot from a column of prices (column A) and a column of square footage (column B).
Then, when you create a column (C) for the price per square foot with the formula something like:
=A1/B1
If you have some unknown square footage values in column B, so those unknown cells are left blank,
and you want to avoid the ugly error value showing up in your C column, then you can change to formula to:
=IFERROR(A1/B1, "")
so the cells in the C column will be blank in the same row as the blank cells in the B column.
This is what I mean by transmiting blank cells.
The blank values propogate to the result column instead of an error showing up in the result column.
Bonus
If you know some Common Lisp, then you may recognize Excel's IFERROR as being similar in function
to Common Lisp's UNWIND-PROTECTspecial operator.
I see content creation and the content it produces in a negative light.
A friend of mine is a film enjoyer and is studying the art.
One time, he told me how he hates the usage of the word content,
and I did not need to ask why because the moment it was mentioned, I think I knew his pain.
Content is the catch-all term for internet information.
And I mean information in the broad sense,
because in the specific sense of the word, information is actually useful or edifying.
However, the information of internet content often does not have this quality.
Computers, smartphones, and the internet have opened up the realm of sharing creative works to almost everyone.
Some people get into making money off of the attention that people spend consuming the works.
In a sense, content represents how creativity has been turned into a commodity in order to harvest the other commodity of attention.
In the end, this drives a massive overabundance of low-quality materials being hosted online with the goal of gaining something from the people in the role of consumer.
On the side of the new content creator,
this puts pressure on him/her to value the quantity of content produced
over the quality, and this can box him/her into low-grade creativity as a career.
This is a short article about what a game developer should know about the
computer programs that run games. This is not about gameplay loops, which
are loops that game players themselves are put into. This is a simple
concept that I think is taken for granted in game programming tutorials and
needs a more explicit explanation. I think it is necessary to explicitly
state the mechanics of using a game loop in an architecture. The
page at
GameProgrammingPatterns.com and
this page from
GafferOnGames.com are excellent reads. I am assuming that the game in
question is a real-time graphical game that responds to user input
immediately, as opposed to a command line interface game that has buffered
input.
Why use time steps
In a game, you write the code for how the game world behaves over time,
which expands into how each type of game object behaves over time. More
specifically, you break down time into slices, time steps. You program what
each object does at each game update call or frame or tick or time step.
This constraint comes from the fact that you need to display the game world
on the screen at a certain frame rate so that things appear to be moving.
Since the output needs to sliced up into a sequence of frames, like a movie,
you have no choice but to somehow calculate what the game world is like in
those different frames. Also, it is difficult to model the behaviors of many
interesting game objects as a long-term function of time, but it is
simpler to describe what a game object does next in a short period
of time at each step.
How do computer games work with these time slices? Well, there is one
essential idea for game programs. Games can run for a long time or an
indefinitely long time. In programming, running the game for a long time
requires a loop of some kind. Usually this loop is infinite or only broken
out of when the player closes and quits the game. The time steps are then
simulated in this loop as long as the game is running.
So, somewhere in every game program is a loop that in general means the same
thing as the C code below (ignoring the time step for now):
while (!game_should_quit) {
update_game();
}
The elements game_should_quit and update_game
would be substituted with the proper variables or function calls for your
game architecture.
This loop is fine and dandy, but there can be a big problem with just
updating the game like this without a time step duration variable. Typically
you are writing a game that will run on multiple different computers, which
will simulate and run the game at different speeds. The performance of the
computer's hardware that the game will run on affects the speed of the game.
If you adjust speeds solely to work on the computer you are developing on,
then a different player who uses a slightly faster or slower computer will
run the game, and it will feel completely different or could be unplayable
due to being too fast or too slow.
A common solution to this is to introduce a time step variable or parameter,
usually called "delta time", "delta t", or just "dt". This could look like
the following in C code:
while (!is_quit) {
float dt = time_since_last_update();
update_game(dt);
}
While there is some nuance about whether you want a fixed time step or a
variable time step, you usually want the computer that the game is running
on to determine the time step amount before the loop begins or continuously
during each loop tick, like in the example above. This can make the game
physics/simulation updates not run faster or slower based on the computer's
performance. A more performant computer will have a smaller time
step than a less performant computer, and the more performant computer will
execute more of these smaller time steps and thus have a higher FPS but will
still get the same (or at least close enough) result in the physics updates.
Having a smaller time step can lead to more accurate results, but if your
game physics are mostly linear calculations, there should not be much of a
difference between having a few big time steps versus many smaller time
steps.
A simple derivation
So how is the time step dt used in the game update function
update_game? Generally, you use it as a multiplier for physics
steps. Say that you want a bullet to move at 50 pixels in a second. If you
were running at 1 frame per second, the code would then look like this:
bullet_x_pixels += 50.0f;
However, you want way more than 1 FPS. Say that you ideally want 60 FPS.
Then your game_update function runs 60 times in a second. Each
update tick, you move the bullet by how fast it moves in a frame. Ideally
you may want 60 frames per second, so your formula for speed would be
something like the following:
bullet_x_pixels += 50.0f / 60.0f;
The above code will run 60 times in a second, and by the time one second has
passed, the bullet will have moved: (50.0 / 60.0) * 60 pixels, which is 50
pixels. The equivalent math is replacing the division by 60 with a
multiplication by 1/60:
bullet_x_pixels += 50.0f * (1/60.0f);
Then, if we extract the 1/60 into a variable called dt, we get
the following:
Then, the last step would to let dt be a parameter to the
function that the bullet update code resides in. This gets us a general form
that we can apply in any update code. So, in general, we can specify what we
want to happen in our game per second and then multiply by the
fraction of a second that each game tick (a function call to
update_game) represents. The dt value is passed as
a parameter to many other functions that update_game may call.
So, much of your game update logic ends up being a function of
dt, rather than time, t (which starts to look a
lot like function integration)!
A typical strategy is to have a hierarchical function call tree to update
your game:
And then dt is passed to each function, or it is a global
variable, or a larger data structure of game info, including
dt, is passed to every function or is globally accessible. Of
course, if you must passdt as a function parameter to
update_a_fireball, for example, then you will probably end up
having to pass it down from update_enemies, which gets it
passed from update_entities, which gets it passed from
update_world, which gets it passed from
update_game.
Functions of t or dt
However, your game logic might not all depend on dt, or it
could be better to have some logic depend on elapsed game time,
t. A function of time is more numerically stable because
floating point errors do not accumulate on a per-frame basis. Also,
behaviors that are only a function of t instead of
dt do not need to store as much current state from the last
frame. An amazing example that exploits this fact, in a particle system, can
be seen in this YouTube video about
running particle systems efficiently on the PlayStation. Another example is
animation. If you have a sphere that shrinks and grows at a certain rate over
time, you could express it in terms of dt or t. If
you express it in terms of dt, then you specify how much it
changes over a little slice of time and add that to the sphere's radius,
which needs to be stored as state somehow. But, if you express it in terms
of t, then you always just compute the sphere's radius to be
some function of time that does not require knowledge of the sphere's
previous state, the radius.
(I may make a web page of its own about functions of dt versus
functions of t in games, because it seems that a bunch of
people mistakenly think that they should always or only
use dt.)
The most important limiting factor
Depending on your game's technology stack (the game, engine, libraries,
operating system), you may or may not have control of the event loop. In
pygame, for example, you do have main
control, but you need to query the event queue to make sure the main window
keeps functioning. Other setups may require you to provide a callback
function for game updates that gets called at times determined by the OS or
the library, and so game loop is outside of your control.
A Pygame example
Below is an empty example main game loop for use in pygame:
import pygame
ORIGINAL_WIDTH = 1280
ORIGINAL_HEIGHT = 720
TARGET_FPS = 60
pygame.init()
screen = pygame.display.set_mode((ORIGINAL_WIDTH, ORIGINAL_HEIGHT))
def update_game(dt):
# add the start of your game logic here
pass
clock = pygame.time.Clock()
should_quit = False
# This try-finally block makes sure that pygame quits when Python has an error
try:
while not should_quit:
if pygame.event.get(pygame.QUIT):
should_quit = True
dt = clock.tick(TARGET_FPS)
update_game(dt)
pygame.display.flip()
finally:
pygame.quit()
I remember reading an online article about how
headers are very useful
and then feeling inspired to create a program that can use plain text headers at the beginning of files.
So I wrote a program to parse simple headers.
It really is simple.
The computer just has to read the beginning of the file line by line until it
encounters a blank line.
Each line before that blank line is a key-value association between what is on
the left of the colon and what is on the right of the colon.
I use this system for almost all of the pages on div0.com,
and it makes it easy to add whatever metadata I want to any page.
For example, the header for this page looks like this:
I know it is maybe too meta or self-interested to talk about how a blogging
system works on that very same blog, but, this simple header system could be so
useful for many different applications. It gets around the problem of
OS-specific or filesystem-specific metadata fields by putting them at the
beginning of the file's actual data, where it is safe.
Also, take a look at the arguments for writing in plain text at
this page.
Quite a few video games have potions, and it is getting old.
Minecraft and Terraria both have potion crafting.
Potions use potion ingredients collected throughout the game world.
What is the purpose of potions in these games?
There are two main ideas for the purpose: the journey and the destination.
The player goes on a journey through the game world each time they desire to reach the destination.
The journey is a quest to acquire the ingredients for making the potions.
And the destination is that the player gets temporary buffs that make them more powerful and able to complete other goals they may have in the game.
Potions are secondary and are sub-goals for larger ones.
In Minecraft and Terraria, those goals are along the lines of defeating bosses and enemies, and making exploration and building easier.
It is a way for the player to become more powerful temporarily.
It rewards players for putting in effort exploring the game world and acquiring ingredients that prepare them for later stages in the game.
Potions just become yet another item that happen to also be consumable.
Later into the game, potions can become grind-y because the player eventually just realizes that they need to farm potion ingredients.
But I have a different idea that may be implemented somewhere as a form of consumable buff items.
Here is an alternative to potions: enchanted foods.
Enchanted foods open up an opportunity for connecting the game to real-life experience and knowledge.
A game with food enchantment can justify having a whole cooking system... that happens also interacts with magic.
This magic can make the system feel fantastical, and yet be relevant to real life.
The cooking is especially a practical skill that someone playing video games could benefit from.
You could legitimately claim that your game is educational (with the disclaimer that: no, there is no magic food).
This also opens up an interesting door in multiplayer games: deception.
In Minecraft or Terraria, potions aren't very interesting items from a social point of view.
You always know what they will do, because the items say what they are.
If another player gives you a potion and says Here, drink this,
then you can just look at the item and be like, Uh no it's clearly a Potion of Poison, ya goof.
But, if your game has food, and makes eating food a good thing,
then your game can allow enchanted food to appear as not enchanted, or have other tricks that make it harder
to tell exactly what enchantments a food item has.
Then, players will have to build up trust and not rely on the game to tell them everything.
Also, enchanted foods can fit well into your game's story better than potions usually can.
Q: What did the Evil Queen give to Snow White?
A: Not a potion!
Why else are enchanted foods fun?
It's MAGIC FOOD! There are so many more creative possibilities here than for potions.
Well, it's also not as common, so it makes the game more unique.
So, your game's players won't experience yet another potion system.
Of course, enchanted foods and potions are not mutually exclusive.
You can have normal food too.
The in-game item hierarchy would probably go something like this:
Normal food < Enchanted Food < Potions < Really Good™ Enchanted Food.
Q: What did the Evil Queen give to Snow White?
A: An Enchanted Apple!
Yesterday, I was inspired by skimming through Stephen Wolfram's book A New
Kind of Science. He wrote about
cellular automata,
and I thought of another type of system in the genre of
tiles-with-rules that I am calling nested tiles. It's a way of
generating an image like a context-free grammar is a way of generating text.
Alternative names for this concept could be
color pattern substitution,
color pattern rewriting,
color pattern replacement,
image pattern substitution,
image rewriting,
image pattern substitution,
tile pattern replacement,
tile rewriting,
or tile pattern substitution;
and you could stick the word context-free in front and/or stick either of the words system or grammar at the end.
A nested tiles system consists of a set of rules.
Each rule has a type/color of cell that it applies to and a rectangle of cells that the cell is replaced with.
The nested tiles process is applied to an initial image and produces a new image according to the rules.
In this way, the next step of applying the rules for each tile is independent of any other tile.
My simplest example is for a ruleset where each tile is substituted with a 2x2 rectangle,
which implies that the image size grows with each step.
In my implementation, if a multiple rules apply to a tile, one of the rules is chosen at random.
Example nested tile rule:
Gallery of nested tile results:
(click on images to see full details)
Each of the previous images in the gallery started with the initial state of a single 1x1 image.
At the moment, I haven't heard of a image system like this, so if you know about one,
please let me know. I think that this is a nice technique for making generative art.
I plan on making a dedicated nested tiles page soon!