So after passing the CCNA exam recently, I have come to recognize it as a sort of crossroads in my tech journey. For nearly four years I've been casually studying computer programming, spending a considerable sum on programming related books, and living in a relatively negative mental state as a result of beating myself up constantly for not having become a software engineer. As I've written previously (and rather repetitively), much of the hold-up has been my own inconsistency in focus, although I have to admit a considerable challenge has been a tech related social media addiction that has consistently left me feeling inadequate by comparison to others in the field, causing me to rip up any project I begin in search of something more "worthy" of HackerNews. My previous post about breaking the chains of social media addiction actually did eventually yield some results. I've been off HackerNews for at least a couple of months now and have recently (about two weeks ago) began denying the urge to check news headlines. I wiped my YouTube search and watch history and have been consistently avoiding tech related videos.
The fruits of these exercises were somewhat slow to arise (if you call a couple of months slow compared to years of habit) and quite subtle, yet amazingly powerful. For one, I have actually been able to maintain a focus on a project idea without coming to find it stupid after looking at what others are doing. I've come to accept that I have a certain line of interests, and that's a good thing. I like classic video games. I like old computers. I want to create 2D "pixel" styled games from scratch although there are frameworks and libraries and engines that I could use. I want to write emulators of old computer hardware from scratch even though others already have done so. I want to learn the internals of the web that are "unnecessary" to learn because there are frameworks that take care of those functions. Now, it may seem like the same old spiel, that every geek out there feels the same way. The thing is that I'm starting not to care what others are doing or what they feel. I like these things because the interest me. This opens the door to something powerful: I'm beginning to separate the career stuff from the personal interests. This means that I can finally begin to utilize the knowledge I've gained.
I've long been afraid to even apply for a job as anything programming related even though I was competent at the technologies in the job description for fear of either not hearing anything back or being laughed out of an interview because of my utter incompetence. Even jobs requiring basic HTML/CSS/Javascript skills, which obviously I possess to some degree as I've built this site from scratch, intimidated me because although I could be up to speed on a technology I haven't used such as Bootstrap or some Javascript framework in a couple of days, I don't have a dense portfolio of projects to demonstrate those skills. Anytime I'd try to begin building one of those sorts of projects, I'd get bored or irritated because say, using a framework for a relatively simple web app seems like overkill and my app wasn't looking as good as everyone else's out there, I'd give up and go hide myself in an MS-DOS book. It was either the career work aligned perfectly with my interests or I felt it was a waste of time. I recognize that this was really just a lack of discipline. It takes time to master anything. You will always encounter challenges along the way. The habit I'd developed was giving up when those challenges arose, which was precisely when the actual learning was beginning.
Today, I'm issuing myself a "do-or-die" challenge. This website is supposed to be a programming related blog/journal and to date, there is no code here. It's time for me to "put up or shut up". I have had this little idea for a program I want to build for a while. It's fairly simple: it's an implementation of Pong. The idea is to create a GUI program in which the screen is divided into a grid of "pixels". These pixels though, will not be the same size as the pixels of the display or relate in any way to the operating system's display resolution. The game screen will be made up of essentially a grid of squares (of a size of say, 25x25) that will more or less emulate an old, low-res game console connected to a CRT monitor with each row being sequentially being drawn/updated many times per second. This will yield very blocky graphics with an old-school kind of "Tetris-y" feel. To me this will allow me to gain a deeper understanding of the concept of building 2D games in that I will have to define the "screen" from scratch, figuring out how to "address" each pixel to turn it on or off and set its color. The ultimate goal is to create a sort of game system that I can use to create many different simple blocky games. The plan is to build it first in Java, my professional language and platform of choice, and then port it to this website using JavaScript and the HTML5 Canvas element. This will allow me to prove a couple of things to myself: 1. that I'm able to quickly get up to speed on a previously unfamiliar API or development platform, using only the API documentation, and 2. that I am capable of understanding and modeling problems and planning and building solutions to them using available tools; those are pretty much the qualifications of a software engineer, at least an entry level one. Also, this project provides a chance to test my ability to explain my thinking when problem-solving or developing solutions, which will be a huge obstacle when interviewing for engineering jobs. Even more, I'm limiting myself to using only the platform docs and books I own for research. I'm using my Fedora laptop with an Intel Core Duo (32-bit) and only 2GB of RAM running the OpenBox window manager which makes frivolous web browsing slower and rather impractical thus limiting distraction.
I need to engineer some way of storing the "pixels" in such a manner that I may write an algorithm for quickly accessing any pixel likely via offset from some set point much as with memory addressing in Assembly language programming (gush!). Naïvely, I imagine a single dimensional array of pixels (if the gameboard is 80x80 there will be 640 pixels) and some math that will divide them into rows. For instance, given a screen of 80x80 the first row will consist of pixels 0 to 79. If I need to know which row a pixel is in, I could take the index of the pixel and divide it by 80, if it yields a number less than 1, I know it's in the first row, if it's greater than 1 but less than 2, it's in the second row and so on. The question becomes whether this constant computation will be efficient enough to allow rapid re-drawing, which brings about the mention of the offset. Since the position of my "pixels" will relate to the actual display's pixels, I'll have to use the bounds of each square (defined in actual display pixels) to set the location of the next pixel. The math to do this could lead to the "addressing" method in that a square's location (it's top left corner in Java) could act as its "address", allowing me to re-draw via a simple loop that draws a square (a "pixel") at each location ("address") with the specified properties such as color as dictated by the game's state. I'll have to define the timing of the game loop and when and how the drawing/updating occurs. Right now I imagine, re-drawing each row sequentially from top to bottom at least 30 times per second. This likely is a fairly inefficient way of redrawing the screen, however my goal for this initial iteration of the project is to be as procedural as possible. I want to use as little OOP as possible, there will be enough already as I'm using the Java Abstract Window Toolkit (AWT) and I'll have to comply with its inheritance structure. The squares or "pixels" will likely have some relationship to the Graphics2D class, with custom fields and properties added for utility. Choosing to use AWT rather than Swing or JavaFX is a part of a larger goal of working my way into understanding GUI development in Java from the beginning. I don't want to get into things like double-buffering right up front, I'd like to naturally get to see why those techniques are necessary and how they work.
The rest of this post will read like a live journal. There will be revisions and a lot of thinking out loud. I will post the code on my GitHub page.
This isn't really what I'd call progress but it's an important step. I'm using the book Java: Complete Reference, Ninth Edition by Herbert Schildt as one of my references. Using it I've got a built a basic frame with a keyListener that calls the Frame's paint() method, drawing filled rectangles sequentially continuing on the next line after reaching a certain x position. As I said, this isn't really progress, as the code to do this isn't at all useful in itself. However, it has allowed me to become familiar with the fundamental elements that will compose the gameboard, namely, the fillRect(), paint(), and repaint() methods. I'm now proceeding to begin to engineer the game loop. One technique I intend to use in building this project is to build little mini-projects as I go along that accomplish some sub-task necessary to the whole. Right now, the sub-task is to understand timing and build a drawing loop that draws the gameboard one "pixel" at a time from top to bottom at a rate of five pixels per second. This may sound painfully slow, but the goal for this mini-project is to precisely understand the mechanism of the game loop, I can speed it up to the proper frame rate later. Upon completing this sub-task, I will have understood how to update the screen, how to control and define the timing of re-draws, exactly when any necessary updating tasks need to occur, and how to clear the screen of the old contents before beginning the next iteration. There are likely aspects of a game loop I'm unaware of right now, or some that I don't grasp quite correctly, but my hope is that this mini-project will help clear those things up.
I've made some headway into understanding the game loop. I've referred to several books, Programming 2D Games by Chris Kelly, Fundamental 2D Game Programming with Java by Timothy M. Wright, and to a degree Game Coding Complete, Fourth Edition by Mike McShaffry. I have always struggled to comprehend the sequence of events that lead to the game screen being drawn and redrawn. A part of this confusion comes in large part from the nature of my platform of choice. To draw on a Component you must override its paint() method. You may then update the game state and have those changes drawn via a call to repaint(). However, there are subtle differences in how these methods work that may effect drawing performance. For one, calling paint() or repaint() leaves the decision of when the drawing actually happens up to Java so just because you call the method from your code doesn't actually mean the drawing will happen precisely then. According to the Wright book this is called passive rendering, as opposed to active rendering where you control precisely when drawing occurs. Active rendering though, brings in more complexity than I am prepared to comprehend for this simple project. Secondly, the Wright book uses the Swing library while I intend to use the older AWT. Wright's method of calculating the frame rate and his sequencing of the paint() method were very helpful however. The Kelly book uses C++ and Microsoft DirectX. Kelly's description of the components of timing finally brought some clarity to the logic behind calculating the frame rendering time. An additional reference, Game Programming Patterns by Robert Nystrom has proven the most helpful so far in that he begins his explanation of a game loop with an over-simplified, inefficient game loop, improving it incrementally explaining why as he proceeds. This has given me a general idea of the sequence of events that lead to proper on-screen animation. I will begin sketching out my own game loop from here.
Initial Post 01/05/2019 03:18:00PM