The Mezunian

Die Positivität ist das Opium des Volkes, aber der Spott ist das Opium der Verrückten

Let’s Code a Crappy 2D Platformer Like Millions o’ Other People on the Internet & Lose Interest & Give Up Only a Few Months In, Part V

Nothing too radical today: mostly just a bunch o’ gimmicks I added in.

Simplified Sprites

Nothing exciting: just merged the SpriteMovement class into the Sprite class, since I found the difference ’tween the 2 too hard to find. Also, SpriteMovement oft had to manipulate a lot o’ Sprite’s stuff, requiring me to make too much public.

Updated Level-Select Screen

Now there’s a li’l checkmark next to levels beaten, as well as the highest gem score & lowest time ’pon beating a level.

Sloped Ground

The rightward slope’s a bit buggy, but the left slopes work perfectly. They e’en slow you down as you go up slopes & allow you to slide down them by pressing down. All that’s needed, other than fixing the right slopes, is to change Autumn’s graphics ’pon sliding downward & a way to kill enemies ’pon sliding into them.

Sloped ground is split into 2 blocks: “low” & “high.” You can see the pattern here:

Vertically-tiled Backgrounds

As mentioned earlier, the backgrounds only tiled horizontally before. Adding vertical tiling was just as simple as I expected: simply had to pull the horizontal code into a separate method, & then copy that code & replace all the horizontal variables with vertical variables, replacing the graphic-drawing functions with calls to the renderX function, pushing in sy, dy, & h.

I also added in a way to have animated backgrounds—though this is limited. Basically, there’s an extra parameter to the constructor that allows one to change the # o’ frames. In this case, the width given to the constructor is s’posed to be the width o’ a frame, & for the 1st “cycle” o’ the renderX function, ( width_ * current_frame_ ) is added to sx & subtracted from right.

Finally, I added “foregrounds” to the map class, which is just ’nother vector o’ Background objects, ’cept these are drawn ’bove all o’ the blocks & sprites (though not the UI). This & the animated background are used in a new level I’m starting called “The Streets o’ Storms” to make falling rain appear in front o’ everything.

The rain animation isn’t particularly good; but it’s passable for now.

As a bonus, this level has the light-gray background flash white every so oft. This was done by setting the bg_ variable in the palette to 7, which is ’bove the limit, & changing the code that disallows colors ’bove the range to make colors ’bove the range use some custom code. Right now this extra code is hard-coded to use the 3rd & 1st (white) colors for the background, which is fine for now, since it’s just a rare extra used for only 1 level so far. If I need to use this in any other level, I can always change it. I did consider doing some complex thing where the # ’bove the limit determines the 2 colors (7-12 has colors 1 & 1-6, 13-18 has colors 2 & 1-6, & so on…), but for now I’ll stick to the “You Ain’t Gonna Need It” principles. It’s not as if it’d be harder to implement later than it would be to implement it now.

Sawdust Crush Gimmick

“Sawdust Crush” is a horizontal version o’ the Donkey Kong Country 3 level, “Ripsaw Rage,” but without the stupid bullshit where you can’t scroll too far ’head, which I ne’er liked in autoscrollers1. ¿What’s keeping me back? ¿The great Camera God? The gimmick is entirely programmed in the saw’s sprite code: it sets itself a flag so that it doesn’t fall, constantly moves rightward, & automatically adjusts the camera if its x coordinate ends up lower than the saw’s so that the saw pushes the camera forward if the player lags too far ’hind. This & the way the saw acts solid if the player runs into it prevents the player from letting the saw pass them. Finally, the saw hurts the player ’pon touch & automatically kills the player if it finds that the player has collided into something solid to the right ’pon touch—essentially squishing them ’tween it & a block.

(A li’l detail I noticed: I should probably make it so that the player’s hearts in the UI automatically disappear ’pon death.)

Wind

“Windy Woods” is a short demo o’ the wind mechanic, which simply subtracts a certain # from the player’s vx_ every frame, making it hard to move forward & making movement backward go extra quickly. Not hard @ all.

Auto-Run Gimmick

This is like the cannon levels in New Super Mario Bros. 2: Autumn constantly runs forward no matter what the player presses & the player needs to jump o’er any obstacles. In levels with this goal, if the game detects the player colliding with a wall to the right, she’s automatically killed.

Adventure Island Gimmick

’Nother simple 1, though not used in e’en a demo level yet: the player starts with 500₧ & loses 25 every frame or so. If it reaches 0, she dies. Thus, the player must repeatedly collect gems to stay ’live.

“Land o’ Communism” Gimmick

This is almost the opposite: if Autumn gets any money @ all, she automatically dies.

Golden Gear Solid Gimmick

There’s also a new enemy that paces left & right & can kill the player just by looking @ it. As this name implies, the goal is to sneak past them without being seen. My only problem is that I can’t figure out how to keep them from looking past solid objects. Right now my main plan is to limit their eyesight to 8 blocks & just ne’er allow the player to be less than 8 blocks in front o’ a guard from ’hind a wall.

The Future

I’ll try to focus a li’l mo’ on finishing some levels, though I did also want to make some moving platform sprites, & maybe a bouncy block like the note blocks in Mario games.

There is this odd glitch that pops up sometimes: sometimes immediately ’pon entering a level, one gets the “¡Failed!” screen, but the game treats it as if one beat the level, giving one the checkmark & a high score o’ 0 gems & seconds. I still have no idea why this happens.

For those who want spaghetti code full o’ stupid gimmicks that only bloat the code, download the source code here.

Posted in Boskeopolis Land, Programming

Let’s Code a Crappy 2D Platformer Like Millions o’ Other People on the Internet & Lose Interest & Give Up Only a Few Months In, Part IV

It’s been so long (a couple days) that I forgot what I’d accomplished last time I wrote.

Block Types

’Stead o’ relying on dumb enums, block types now have 2 corresponding lists: “components” & “conditions”—numerous simple pieces that can be combined into complex block behavior. Components affect what the block does, the corresponding conditions affect what must be true for that affect to happen. Take, for instance, a heart block, which 1, heals, & 2, disappears, both on the 2 conditions that they are touched & touched by the hero sprite. Contrast this with a heart block, which is, 1, solid, & 2, heals; but whereas the 1st action happens simply by being touched, the latter only happens ’pon colliding with it from the bottom.

This allows me to reuse simple behavior oft used in different ways—touching a block, solidity, hitting it from below, disappearing ’pon 1 use—without having to copy & paste too much.

Also, as the “Wasabi Woods” screenshot shows, I added a “priority” flag to graphics, which specify which parts o’ blocks should be drawn o’er the player. This is done simply by drawing blocks onto the screen before & after sprites, drawing those without the priority flag 1st & those with it on afterward.

Level-Select Screen

Level names are gotten from some dumb function in the Level class that spits out a string given a certain level ID (which matches the ID that one goes to ’pon selecting a string) based on a super dumb switch statement. Sorry.

’Course, the reason I’d want a level-select screen is that I’ve added 3 mo’ “levels.” I put that word in quotation marks, since none o’ them are truly finished. Technically they’re all beatable, but only Wasabi Woods is a serious level—& e’en it’s missing sprites. It’s probably next to be finished. Meanwhile, “Skyscraper Caper” is halfway done, & “Soupy Sewers” isn’t e’en a real level, but a way I planned to test vertical scrolling for backgrounds, which I haven’t e’en gotten to yet—in fact, that level, ironically, is the only 1 without a background image.

Look @ that amazing cut-off. This’ll ne’er be accepted @ SMW Central.

Speaking o’ which…

Background Images

As “Wasabi Woods,” shows, multiple background images can be layered. They automatically tile horizontally & can have parallax scrolling o’ multiple speed levels, which “Wasabi Woods” uses for its 2 backgrounds. This was a pain, as I kept getting the math wrong; but after failing to sleep on Christmas Eve night, I was struck by inspiration. Unfortunately, I can’t actually remember what the math flaw was.

Here’s the code:


void Background::render( Graphics& graphics, Camera& camera )
{
	if ( texture_ >= 0 && texture_ < Graphics::SpriteSheet::LIMIT )
	{
		int sl = offset_x_ + ( (int)( camera.x() * scroll_speed_x_ ) % width_ );
		int dl = 0;
		int right = std::min( width_ - sl, camera.widthPixels() );
		int far_right = 0;

		SDL_Rect dest = { dl, 0, right, camera.heightPixels() };
		SDL_Rect source = { sl, 0, right, camera.heightPixels() };

		graphics.renderObject( texture_, source, dest );

		while ( far_right < camera.widthPixels() )
		{
			far_right += right;
			dl += right;
			right = std::min( width_, camera.widthPixels() - dl );

			dest = { dl, 0, right, camera.heightPixels() };
			source = { 0, 0, right, camera.heightPixels() };

			graphics.renderObject( texture_, source, dest );
		}

	}
};

The vital issue is the difference ’tween the source & destination, & how these 2 differences affect how things are drawn. The destination determines where the graphic is drawn, the source from where in the graphical file. Thus, we start by looking for how the left size o’ the source, “sx” here, should change. We know for a fact that we want the background to span from the far left side to the far right side, regardless o’ where one is in the level; the question is what part o’ the image is on that far left side. You’ll notice that the 2 right variables have no mention o’ source & destination; & as you’ll notice below, it’s ’cause they both turn out to have the same right values, which is either the end o’ the graphical file (the width o’ the graphical file – where we started, sx), or the end o’ the level width (the width o’ the screen – where we’re starting, which in this case is 0, thus making it just the width o’ the screen), depending on which is smaller. There’s no reason to go past the width o’ the screen, & to draw a wider destination than source width will stretch the graphic, which is hideous. If we hit the latter, then we can stop, since there’s no mo’ that needs to be drawn; but if we hit the former, then we go through this while procedure till we finally do, saving our building right variable in the “far_right”1 variable, while placing the right variable o’ the previous cycle as the current left—logically, we start out where we left off. Obviously we’re drawing just after where we’d drawn before, since we’re building the illusion o’ a continuous backdrop; meanwhile, we always start our source now @ 0; as mentioned, we stop @ either the end o’ the source, @ which point we want to restart @ 0, or we stop @ the end o’ the screen, @ which point we quit. Meanwhile, we get our new right based on the same as before,—either the end o’ the source or the end o’ the screen, depending on which is smaller—& continue the cycle till the far right = the screen width2, @ which point we’ve reached the end o’ the screen.

When I was 1st figuring this out, I drew a graph to help see this—though now it’s probably e’en mo’ incomprehensible than the word vomit I spewed earlier.

@ the top you’ll see my plans for sprite collision detection, & to the left, the edge o’ some dumb haiku.

I still haven’t finished doing this vertically. Hopefully, that won’t be too complicated to add: should just be a copy o’ the horizontal version, just used with y & height variables & an extra loop layer.

Funds

A funds total, which shows on the level-select screen & is increased by whatever money you have ’pon beating a level.

Speaking o’ funds, they’ve been changed from just “gems” in the inventory to ₧, which fits better with Boskeopolis’s world & fits better with the video-game parody aspect o’ that world’s currency, & each regular gem gives 100, with a brighter & darker gem added, which give 250 & 500, respectively (thanks to the new block component system, I only had to change a # plugged into the component added to each block). Using these, I revamped the 1st level, increasing the money requirement to 10,000 (I also added an auto-comma function for #s converted into text, which is used in the message that appears in front o’ the 1st level, regardless o’ how one changes the funds requirement).

I also added a nifty li’l detail wherein the ₧ counter in the inventory spins up ’pon gaining ₧, rather than automatically jumping up to its new value, using a technique from Super Mario 64 that this video shows off, wherein one separates the actual funds # & the funds shown on the inventory screen, & have the game check every frame if the funds shown is less than actual funds & have it increase by a small # if so. The 1 difference is that my game doesn’t have the glitches & o’ersights Super Mario 64 does, ’cause I focus mo’ on that anal shit mo’ than actually making mo’ than 1 complete level.

Scrolling Marquee

This is the kind o’ useless trinket that keeps me from making real levels. Now, in every level, @ the bottom o’ the UI scrolls random strings o’ text. They’re inspired by the news tickers in SimCity 30003. In fact, the message ’bout Kitty Kibble shortages was taken straight out o’ SimCity 3000.

Clock

One can also see that there’s a clock added to the level UI, which counts up in most levels, ending @ 9:59 (which no player should e’er reach, considering how small these levels will be). While this clock is useless in most levels, in “Skyscraper Caper” it counts down & causes the player to fail if it reaches 0.

A Hydrant Enemy

¡Finally the 1st enemy! This enemy disguises itself as 1 o’ the hydrant blocks you’ve probably seen in other screenshots, only to blink ’wake when the player gets close to it & starts bouncing toward the player, hurting her ’pon touch, ’course.

This is the place where the problems o’ components came ’bout: namely, that any data specific to specific components (such as the Hydrant movement component) can’t be used by other parts, such as the graphics component or other sprite movement components (such as the player’s) ’pon interaction, ’cause the nature o’ the polymorphism that the generic sprite’s ownership o’ these components makes it so that these other things can’t be guaranteed to get a Hydrant component, simply some child o’ the abstract “MovementComponent” pointer.

This is a big deal ’cause the Hydrant sprite has 2 forms: @ 1st, when it’s indistinguishable from a hydrant, & when it’s ’wake & dangerous. To ensure that the enemy only hurts the player when it’s ’wakened, I had to put the damage code in its movement component, which wasn’t too bad; but I can’t get the player to interact with it like a block, ’cause that relies on code in the collision object output by the collision function that runs automatically by interaction in the player’s interaction code, which is different from the enemy’s. I actually tried this with the collision object in the enemy’s interaction function, only for the player to strangely get sucked into the enemy, till I finally realized the vital difference ’tween the player’s collision with the enemy & the enemy’s collision with the player, & how this affects the overlap values. Also, I had to put the hydrant’s graphics code in its movement code, since its graphics also react to its wakening, which makes its graphics component do nothing but decide what graphic file it uses—which could already be done in the constructor o’ the parent SpriteGraphics class, meaning that the HydrantGraphics class is redundant & that the only reason I haven’t replaced it with a regular SpriteGraphics object is that I can’t be bothered & I feel I may want the HydrantGraphics class for later.

Some Dumb Message Box

It e’en comes with automatic line-changing, as seen, though it doesn’t come with any nifty auto-hyphening or any other way to keep words from awkwardly splaying out halfway onto the next line. There are apparently ways to do that, as some SNES RPGs used that kind o’ technology, but it sounds too complicated to bother with now—’specially when this message box has only been used once so far. Maybe when I’ve completed like 5 levels a’least.

(Note: Hilariously, I only just noticed while looking @ the screenshot I took that the message block dips down into the UI. Oops.)

The Future

I mainly want to work on levels & sprites now. Hopefully, I’ll finish “Wasabi Woods” & “Skyscraper Caper” soon. The problem is, most o’ the cool ideas I have require a lot o’ extra coding. For instance, for the “Skyscraper Caper” level I actually wanted have ’nother character, controlled by AI, running through the level, & the idea was that you had to beat her to the end (touching her would probably hurt you). However, I don’t think I have the capabilities to do the kind o’ sophisticated AI that could make ’nother player move through this level full o’ holes without falling off & make it look like natural gameplay.

2 other level ideas that should be mo’ manageable are a level wherein the player has to avoid being seen by guards & a level covered in gold, where touching any o’ the gold causes the player to fail. This latter level will probably be near the end, since it’ll probably be relatively hard.

Download this mo’ interesting but messy source code.

Posted in Boskeopolis Land, Programming

AUF DAS EINDRINGLICHE GERÄUSCH DER MONSTRÖSEN UHR (PORQUE LOS CRANGREJOS DE DA-TRANG SIN FIN SACAR ARENA)

The stories presented in this section explain, among other things, how the earth was formed and people were made; why the sun is so bright; how the tiger got his stripes; how the mosquito came to be; and why the Da-Trang crabs endlessly scoop up sand.

Faurot, J. Asian-Pacific Folktales and Legends, (p. 12).

I tried to scoop the crusty, blackened leaf into my ice-dry granite hands,

only to see pieces fly off

to be devoured by the wind.

I’m shivering,

but too frozen to tighten my jacket.

I’m tired,

but too tired to move my body to lay down,

too fearful…

I’m full o’ energy,

but can’t budge to use it.

It’s night early,

but I can’t see anything in it anymo’.

We’re not seeing each other anymo’.

I ne’er ’splained why…

I don’t think I understand myself.

It’s moved on since then.

It’ll survive for many millenia mo’.

Huh…

It snuck up on me in the middle o’ the night:

Face it.

It's going to happen,

& it's going to happen soon,

& you can't stop it.

Accept it.

You haven't changed a god damn thing.

You thought it'd be gone.

But it comes 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain 'gain.

What the (lumpen)proletariat (Da-Trang crabs) produces, above all, are their own graves.

Posted in Poetry

Let’s Code a Crappy 2D Platformer Like Millions o’ Other People on the Internet & Lose Interest & Give Up Only a Few Months In, Part III

¡So much done!

Title Screen & Messages

As shown ’bove, a title screen, as well as a message screen that pops on ’pon starting the game, to say what you should do to beat the level, & 1 that appears ’pon beating the level.

Game States

In relation to this, a game state system, which can not only change states, but also “pop” & “push” states as a way to interrupt states & still be able to go back to them.

Since I’m terrible @ ’splaining what I’m doing—it’s mostly just me breathlessly talking ’bout something I did, as if by magic—here’s a much better explanation. In fact, I recommend reading most o’ those articles; they were an immense influence o’er the past year or so.

Pause Menu

Speaking o’ which, the latter is used in the pause screen I made, as well as the level-beginning aforementioned message. (Unlike the victory message, this message must pop up after the LevelState has already started so it can get info from its Goal—mo’ on that later).

Levels with Multiple Maps

The level class with submaps held by it, as well as fully-working warps that allow the player to move throughout the entire level.

Level Goals

Within the level class is also a goal class that determines how to beat the level (in addition to touching the goal block, which always completes the level). For this level, the goal is to collect 75 gems.

Palettes

A palette system. With so many things turning out easier than expected, this surprised me by how long it took to get right, simply due to my inability to decide how to organize the code. I finally elected to keep the actual palette file in the Graphics class, since it works directly with it. I then added a PaletteSet, which is just the name o’ the hue & the background # that can be used to create a palette, to GameState & Map. A GameState automatically creates a PaletteSet when created, & the Game engine automatically changes Graphics’s palette ’pon changing states & the Graphics automatically reloads graphics to apply the palette. This keeps the palette that’s applied in LevelState from continuing to any other states, other than the pause menu, which has its palette pushed to it in its constructor from the level state. Meanwhile, GameState also has a method that allows for changing its palette manually, which filters through to graphics with the same automation, which is used for map-switching (since that doesn’t actually change the game state).

It should be obvious that the palette system wasn’t created out o’ necessity or practicality, since SDL can easily load images with a full range o’ colors; I simply chose it for stylistic purposes. I don’t know: sometimes monochrome looks nice, specially when contrasted with other monochrome hues. Plus, Super-Game-Boy-like monochrome graphics is a form o’ retro callback that doesn’t seem to be o’erused yet, like most.

Text

A text system, which includes some frills, such as auto-aligning text lines & blinking text. This is not done by loading a font, since I actually find that that would add a bunch o’ complications that I don’t want to deal with, but just by using a graphic file & making a simple conversion map that outputs a frame # for a given character & functions for getting the x & y coordinates from that frame, which corresponds to the position o’ that character in the graphic file.

This reminds me that I didn’t go into much detail ’bout some o’ the things I’ve already done, ’specially the level construction, which is 1 o’ the most complex aspects.

1 programming pattern I’ve noticed a lot is breaking 2d grids into a single line o’ #s—what I usually call “frames.” For example, the text system I mentioned earlier did that, as well as the tilemaps for level maps (Tiled outputs 1d arrays). The best way to deal with that is with these 2 formulae that I’ve used countless times in programming:

1: x = n % width

2: y = floor( n / width )

“x” & “y” refer to their respective cardinal positions. For example, if one wants to find out where to place a block from the 28th ([27]) element in a 1d array for a 128-block-wide map, simply look for 27 % 128, while its vertical position is floor( 27 / 128 ). (Note: if this position is in pixels & not blocks, you’ll need to multiply the answer by the width & height respectively in pixels o’ blocks.

The 1st formula uses remainders, which, going up in #s, counts up the #s up to the 2nd # (the width, which is, logically, the maximum x position), & then back to 0 (the minimum x position), counting up ’gain & ’gain till the last block:

012345678
012345678
012345678
012345678

The y formula, meanwhile, stays @ the same # for every width # o’ blocks, & then rises 1 for ’nother width # blocks, & so on:

00000000
11111111
22222222
33333333

Looking @ these graphs, one can hopefully see how these formulae make sense, since I certainly can’t ’splain it logically.

I don’t know what I’ll do next. Maybe sleep.

Download the source code to this e’en less sloppy program.

Posted in Boskeopolis Land, Programming

You Fucked It Up

You fucked it up.

I warned you not to do it.

But you did.

You were s'posed to be Mr. Jekyll, ¿remember?

¿Where did you hide?

You were s'posed to say hi every morn,

but look @ how low the quotas are;

you were s'posed to keep calm

e'en under the glare o' a ticking bomb.

But you were all wrong--

& I can see that you'll always be wrong

till the setting o' all dawns.

Your body rejects all the improvements like foreign blood.

¿So now what?

Mo' 'scuses, that's what.

Not a lot o' market for 'scuses, Jude.

Perhaps it's time to discontinue.

Yes, you fucked it up,

& once you've fucked it up,

you'll ne'er fix it down.

Now dinner's o'er,

& it's time to take your deserts--

'cause you deserve it.

Posted in Crazy, Poetry

Let’s Code a Crappy 2D Platformer Like Millions o’ Other People on the Internet & Lose Interest & Give Up Only a Few Months In, Part II

Accomplished so much in the last few days:

  • Fully-working camera that automatically adjusts to player position (if she goes past its inner boundaries) & map boundaries & can be moved independently with certain buttons.

  • Block & Map system with tileset. After the slight tedium o’ creating the tileset, the need to create a hundred sprites was replaced by the simple need to paste in an array o’ numbers spewed out by a map made in Tiled. The player’s collision code was changed to respond to the blocks’ types ’stead o’ sprite types. New block types include gems that disappear ’pon being collected & add to a funds # (see next point), a hurt block that causes you to lose health & warps you to the start o’ the room if you lose all health, & a goal block, which now justs closes the program with a printed message in the console that says “YOU WON”—an amazingly worse victory reward what you got from beating Ghosts ’n Goblins for the NES.

  • Inventory system with simple text printing system, used to print the # o’ gems the player collects.

  • A few mo’ animations, including blinking for Autumn when she’s standing or crouching round & an animation from holding up. O yeah, & I finally added the climbing animation; I thankfully already had a climbing graphic for Autumn from some sprite comic I made for later.

’Cause I was so tired & yet also so buzzed on coffee in the last article, for some reason though I mentioned using C++ to make this game, I forgot to mention using SDL2, which makes it look like I did everything from scratch, which would be ridiculous. O well: if anyone cared, they could’ve looked @ the code themselves.

I should also point out that I’m tired & buzzed on coffee today, too, so this article’ll probably be just as incoherent—’specially as I’m publishing it right after writing it, rather than waiting half a year, as is my wont.

I think I’ll next work on developing the Map class into a Level class with multiple maps & ways to warp round these levels. That’s what the open manhole @ the end’s s’posed to be used for.

& where there’s an unsightly hole under it—that’s s’posed to be a warp block with the same graphics as the rest o’ the lower dirt, which I simply neglected to add to the tileset. I should also add that the open manhole’s technically s’posed to be nonsolid—’nother slight o’ersight.

As these screenshots also show, I also changed the resolution o’ the game a bit to fit the wider screens o’ modern computers—from 256 x 192 to 320 x 176, which is the closest approximation to 16:9 that fit within multiples o’ 16 & didn’t make the game space too big or small. Thankfully, I was halfway decent with programming, so changing this resolution only required me to change 2 variables. Changing the camera to fit in the inventory bar only required me to decrease the camera’s height by 2 bars.

After doing the level & map stuff, I’ll probably move on to doing game states & a level state & crapping together some halfway decent victory screen, as well as a less jarring death animation & maybe an intro screen. @ that point I’ll technically have a complete game; it’ll be a lame, immensely short game, but it’ll technically be a fully-working game, & that’s better to finish ’fore finishing the palette system, which is inessential (& the plan to make this, by the way, should ’splain why all these graphics are grayscale).

Download latest source code & see it in its slightly less-sloppy glory.

Posted in Boskeopolis Land, Programming

Let’s Code a Crappy 2D Platformer Like Millions o’ Other People on the Internet & Lose Interest & Give Up Only a Few Months In, Part I

After days o’ not being able to do anything useful, I had a certain programming binge the past day or 2, which involved restarting a 2D platformer game I’d been starting o’er & o’er ’gain since 2014, since I’m anal-retentive. I’d always tell myself I should blog ’bout it, since it’s obvious that this fiddling isn’t going to be useful in any other way, & this is the best opportunity.

This time, rather than my usual anal-retentive strategy o’ carefully crafting complex class & component systems that were elegant, but empty o’ content, I started simple, focusing primarily on getting the player’s physics right, with the only extra tinkering being visuals, since they’re important for seeing reactions to physics (the screen-magnification system, so I don’t have to squint to see everything, & movement animation, so I can better gauge the player’s movements—I don’t know). This is based on a principle I read ’bout called “YAGNI”: “You Ain’t Gonna Need It,” which I read ’bout from some great website full o’ nifty programming tips whose URL I sadly can’t remember anymo’. That’s the perfect time to show off my code so everyone can see what a sloppy mess it is.

This project’s done in C++, the sloppiest o’ programming languages, but 1 I’m strangely better @ understanding than s’posedly “easier” languages, like JavaScript.

The problem is, e’en in only a day, I’ve done so much—& by “done so much,” I mean copied & pasted a lot o’ code I already did from my earlier projects (this experience o’ copying & pasting the good parts from older projects is what taught me that refactoring isn’t nearly as hard as I 1st imagined, which makes YAGNI easier to apply).

  • Master graphics object that holds basic SDL graphical junk, as well as simple spritesheet system for loading graphical files, which can easily be referenced by sprites through simple enums (androgyn, do I love enums).

  • Includes simple magnification system I’ve been copying & pasting since 2014 that simply reads the computer’s resolution & uses that to automatically magnify the 256 x 192 pixel screen to as big as will fit evenly in the monitor, as well as automatically centering it.

  • Simple graphics & movement components for sprites, which are only used by the player. To make things ’specially wasteful & redundant, sprites have a built in simple rendering function & variables that are used if said sprite doesn’t have a graphical component, for blocks, since I didn’t feel like making a graphical component for them, when they probably won’t be sprites later in development, anyway. It’ll take a minute or so to delete the redundant function & variables.

  • Input system that abstracts button presses from actions.

Most o’ the code is crammed into the sprite class, & almost all o’ it is the physics o’ the player & collision with sprites o’ other types. So far, the player can run, jump, & duck as well as I can imagine, & has working collision for solid blocks, those strange blocks that are only solid on top (those cloud platforms from Super Mario World), & ladders (ladders are still somewhat wonky in that the player falls off if she climbs ’bove the ladder & has no climbing graphics).

I have mixed feelings ’bout the collision code. I used to use this simple formula I got from some book years ago, but I found that finicky, so I replaced it with a mo’ complex collision system I borrowed from Sonic games. In this case, the sprite has collision dots for each side & tests whether those dots are within a certain boundary box within the other sprite. The way this is actually done is immensely messy, with many probably-redundant integers; but I’ll worry ’bout cleaning that up later. It does seem to work well: so far I’ve yet to see clipping while walking o’er flat land (bumping into the sides o’ the corners o’ the blocks) or being able to land on the corner o’ a block in a vertical wall, which took far longer than one might expect to fix.

Also, since I kept changing the collision system, the collision class is full o’ redundant variables that’ll need to be cut out later, when I decide which collision method to stick with.

1 problem while trying to research solutions is that I can only find the most basic tutorials on the internet, not any advanced problems, such as handling trying to stand up from a crouch while in a small vertical space, which took almost the whole day fixing, or the best way to handle climbable blocks.

Also, much o’ the advice given is terrible or inaccurate. Don’t get me started on the tutorials I’ve seen that advise creating enemies like Red Koopas by putting invisible blocks solid only to enemies on the edges o’ every platform to keep them from falling off, rather than actually programming the enemies to detect edges. That’s god awful, & one can be assured that no Mario game e’er did something so dreadful.

Other than fixing the ladder quirks & cleaning up my code a bit, I’m not sure what to move onto next. Most likely creating a block system, which’ll ’ventually be a pain in the ass, since it’ll probably require creating tilesets o’ block types, as well as graphical & collision components. ’Gain, I want to keep myself from building too much architecture @ once, so I’ll probably just start with a simple block system.

& after all that, we have a map system, a camera system, & the fun that is a system that reads an array o’ #s & creates blocks in the right places.

I had the idea o’ putting this up on Github, only to realize that that’s based on, duh, Git, & I don’t actually know how to use Git, despite how useful it apparently is. Perhaps I should learn how to do that later. For now, I have just a dumb archive file with all the code. I would’ve also attached a video ‘stead o’ a lame screenshot, but I can’t get my capture software to make videos that don’t look like slideshows.

Download code & see it in all its sloppy glory.

Posted in Boskeopolis Land, Programming

Die Anti-Haiku

Buddha could not be more wrong:
Though we plug ourselves tight together,
We are not compatible.

Posted in Poetry

Lemme Drunkenly Rant @ You ‘Bout the Conclusions & Intros

Someone left the cake out in the rain.
I don’t think that I can take it,
‘Cause it took so long to bake it;
& I’ll ne’er have that recipe ‘gain—¡oh, no!

-Jimmy Webb

‘Pon reading many o’ my nonfiction work, one would see that I rarely write conclusions, & rarely write introductions, too. This is due to my literal-mindedness causing me to write precisely what I want to say: my “intro” is the beginning o’ what I want to say, & the end is simply the end.

This contrasts the usual intros & conclusions, which: 1, repeat what is already said in the heart o’ the article, where the info truly belongs, insulting readers’ intelligences by assuming they have the memory o’ a 1950s computer; 2, spew rhetorical cliches like irrelevant quotes or stories.

But the worst problem with conclusions is that they represent a perniciously common intellectual failure, identified by their name: they focus on conclusions. Indeed, people—westerners, a’least—focus too much on conclusions, which are the weakest aspect o’ an argument. It’s the reasoning ‘hind the conclusions that should be focused on, for they are the key to the conclusions in the 1st place.

What conclusions do is they enable a bad habit: glazing o’er reasoning so one can snatch the conclusions quickly & then spew it to others like the plague without understanding the why ‘hind the conclusion, much less whether the conclusion is truly correct.

Thus, rather than conclusions improving the understanding o’ those too lazy to read the body, they make them mo’ ignorant o’ their lack o’ understanding. ¿What’s better, that one can’t comprehend an article & knows one can’t understand it, or that one can’t understand an article, but can understand the conclusion, & thus is fooled into thinking one understands it when one truly doesn’t?

So in conclusion, conclusions are superfluous. They obnoxiously repeat content that you’ve already read & help people ignore the reason for believing the conclusion. & as Lord Crocomire says, “That’s the news you can choose.”

Posted in Literature Commentary