PyGame is gone, hello GLFW

I finally got rid of the last legacy software library that I have in The Ditty of Carmeana. The Demo came with a whole slew of open source code that I built off, but it turns out some of them (namely Pango, Cal3D, and PyGame) turned out to be not-so-great decisions.

Cal3D, an open source library to deform models, was the first to go; the vertex shader took over that job. Next came Pango, which I was using for paragraph layout. It is probably the most awful, evil, and saddistic library in existence. I wrote my own layout code on top of Freetype to get rid of that pestilence.

Now I am rid of PyGame. PyGame was actually not so bad, and I’d defintely recommend it for less ambitious games, but eventually my game just outclassed it and I needed something better. Problem is, it’s built on top of another library called SDL, and SDL is good at getting a window open and graphics on the screen, and nothing else. Things like input, operating system and window interaction, and innocuous things handling like screen resizing, are not handled very well in SDL and therefore not in PyGame either. One of my big goals (and one of the reasons people playing the game in Twitch don’t bang their heads on a desk) is for the game to not do insane things like crashing or going blank when you try to resize the window. SDL made that difficult, and I’m not sure I ever managed to work around all those issues.

Now I’ve relaced it with GLFW, which is smooth and sleek, and does all the little things right. It’s also really easy to hack, which is nice because it’s missing a few features (like joystick event callbacks) and had a couple bugs, but overall it’s just a breath of fresh air compared to SDL.

So at last, the Ditty of Carmeana is free of old decisions I now regret, at least on the coding side.

(And yes, I did actually say that my game outclassed something.)

Updated: February 6, 2018 — 7:28 PM

Enemy logic

This is a snippet from the code used to control an enemy. If you have any expertise in computer science concepts, you can probably recognize this as implementing a finite state machine (FSM). Lots of repetitive code. This is why enemies and NPCs in video games often use domain-specific langauges.

I did it the hard way.

def setup_state(self,*args,**kwargs):
    if self.state == "looking":
        self.to_feet()
        self.role = acting.HoldStill(self)
    elif self.state == "returning":
        self.to_feet()
        self.role = acting.MoveToPoint(self,*self.path.get_pointvec(0.0))
    elif self.state == "patrolling":
        self.to_path(self.path,0.0)
        self.role = acting.Pace(self)
    elif self.state == "charging":
        self.to_feet()
        self.role = acting.Chase(self,game.lance,speed=10.0,nearthresh=0.5)
    elif self.state == "swatting":
        self.to_feet()
        self.role = acting.MeleeAttack(self,self.swat_choreo,"goblin_swat",duration=0.667)
    elif self.state == "recoiling":
        self.to_feet()
        self.role = acting.Recoil(self,*args,**kwargs)
    elif self.state == "dying":
        self.to_feet()
        self.role = acting.Shift(self,self.supine_choreo,0.5)
        self.weakness.targetable = False
    else:
        raise ValueError("unknown state %s" % self.state)

def check_transitions(self):
    strikedir = self.strike
    self.strike = None
    if self.state == "looking":
        if self.life <= 0:
            self.transition("dying")
        elif strikedir is not None:
            self.transition("recoiling",strikedir)
        elif self.timer >= 0.4 and self.hero_is_swattable():
            self.transition("swatting")
        elif self.timer >= 0.4 and self.hero_is_visible():
            self.transition("charging")
        elif self.timer > 2.0:
            self.transition("returning")
    elif self.state == "returning":
        if self.life <= 0:
            self.transition("dying")
        elif strikedir is not None:
            self.transition("recoiling",strikedir)
        elif self.hero_is_swattable():
            self.transition("swatting")
        elif self.hero_is_visible():
            self.transition("charging")
        elif self.role.completed:
            self.transition("patrolling")
    elif self.state == "patrolling":
        if self.life <= 0:
            self.transition("dying")
        elif strikedir is not None:
            self.transition("recoiling",strikedir)
        elif self.hero_is_swattable():
            self.transition("swatting")
        elif self.hero_is_visible():
            self.transition("charging")
    elif self.state == "charging":
        if self.life <= 0:
            self.transition("dying")
        elif game.register["lance.life"] <= 0:
            self.transition("returning")
        elif strikedir is not None:
            self.transition("recoiling",strikedir)
        elif self.hero_is_swattable():
            self.transition("swatting")
    elif self.state == "swatting":
        if self.life <= 0:
            self.transition("dying")
        elif strikedir is not None:
            self.transition("recoiling",strikedir)
        elif self.role.completed:
            self.transition("looking")
    elif self.state == "recoiling":
        if self.life <= 0:
            self.transition("dying")
        elif strikedir is not None:
            self.transition("recoiling",strikedir)
        elif self.role.completed:
            self.transition("looking")
    elif self.state == "dying":
        if self.timer > 5.0:
            game.scene.remove_object(self)
Updated: December 31, 2016 — 10:02 PM

The Macguffin

A few detailed oriented fans of the original Demo might have noticed in one of the walls of text I included in the game for world-building purposes mentioned an ancient holy artifact known as the Ecrofirt, to serve as the game’s Macguffin.  This was, of course, part of the larger scope of the game, but didn’t come into play, at all, for the demo.

Any idiot can figure out that “Ecrofirt” this is just “Triforce” spelled backwards.  I was using the name more or less as a placeholder until inspiration stuck me with a better one.

For the updated bugfix Demo, I decided that even “Ecrofirt” wasn’t obvious enough.  I renamed it the Triorb (which I pictured as three green glass balls arranged in a triangle) which I hoped would remind people of the Triforce, so they’d know it was important when they saw it mentioned.

 

Recently, in my work to create 1/3 of the game for a general release, two things happened.  First, I had a sudden inspiration for what to call the Macguffin: the Ricohedron (never mind where that term comes from), which is two tetrahedra joined at their bases.  Second, I realized that the way to set up the Ricohedron as the game’s Macguffin is to actually show it being stolen (duh).  Therefore, I am having the game’s opening cut scene show this, and I might as well show Princess Carmeana being kidnapped while I’m at it.

 

Anyway, here is The Ditty of Carmeana’s very own Triforce, the powerful holy relic known as the Ricohedron:

Underwheming, isn’t it?

Updated: March 13, 2016 — 5:37 AM

A Mystery Solved

I’ve watch quite a few playthroughs of Carmeana on Youtube, and one of the things that appeared odd to me is that sometimes the sky seems to go black on the screen captures.

Originally, I figured that the capture software is interfering with the graphics state in some way (and, actually that probably is it), but today I was debugging an issue where the sky wasn’t showing up on my end, and I realized I was doing something astronomically stupid.  The graphics drivers I was using had been “doing the right thing” (which is to say, they were doing something that was either invalid or undefined according to the OpenGL standard, but generally was what you wanted to happen) but they were actually hiding a bug.  I ended up changing something slightly that prevented the drivers from “doing the right thing” and it showed up on my end.

The graphics drivers that some people were playing through on were not “doing the right thing” at all (or were being hindered from “doing the right thing” due to the screen recording), which is to say, what they were doing was perfectly valid.  It’s just that my code was buggy and I didn’t realize it because my own graphics hardware was “protecting” me.

Bah.  I have a little pet peeve for drivers that “do the right thing” even when I do the wrong thing, and this is why.

However, in fairness, one of the lesser graphics drivers that I was testing on was an Intel i910, on a now seven-year-old refurbished laptop that was old for a refurb when I got it.  I keep testing the game on this laptop because A. it keeps me grounded–the game runs full speed on the laptop most of th time, and B. it has crappy graphics so I have an idea what my LCD should be.  But even the lowly Intel i910 drivers have protected me from this bug.

Anyway, bug should be fixed now, and playthroughs of the released game should show blue skies even on older, dumber hardware.

Updated: December 31, 2015 — 7:42 PM

Cal 3D gone

I really should be working on adding content.  But I am “that guy” who has to go and correct regrettable decisions of the past before I can move on.

Anyway I reached a major milestone by eliminating this really old and questionable library called Cal 3D, which I was using to do my character animation.  Cal 3D has three big issues:

  1. It’s written in C++
  2. It uses a terrible representation of quaternions
  3. It does all the vertex skinning calculations on the main CPU

I really don’t like C++, and now that Cal 3D is gone, The Ditty of Carmeana is Certified C++ Free, and I am happy about that.  It now uses only Python and plain C.  (Unfortunately, I’ll have to add C++ code back in when I add Steam interactions.)

Cal 3D for some reason uses a representation of quaternions that no one else uses.  (I have my suspicions that this representation was the result of some coder with too much time on his hands trying to optimize away a single addition instruction and realizing he could do that by shifting the sign and order of the components.)  Anyway, I now use normal quaternions and that’s spiffy.

But those were just annoyances.  The real benefit of this move is that I can start animating poses using the vertex shader, which is no small thing seeing how I need the CPU for the slowness of Python.  I haven’t actually added the shader yet (that’s another milestone) but everything’s finally set up for it.

Pango, you’re next.

Updated: October 22, 2015 — 1:01 AM

Work/Life Balance

In the year or so leading up to the release of the Demo of The Ditty of Carmeana, I worked a full-time job but managed to find plenty of time to work on the game to get it ready for a release.

Now that I’m planning to turn the demo into a full release, I can’t manage it.  Figures, right?

Actually it does, non-ironically.  When I was finishing up the demo, I had frozen all features and the problems I was facing were narrowly-focused: testing, controls, fixing bugs, stuff like that.  Now that I’m back into full development mode (or trying to be at least) the problems I face are very open, and it’s a lot harder to focus and find time with a full work schedule.

This is not a major roadblock though.  In a few weeks I am reducing my hours to 50%.  (This was made easier for me because some changes at work made it into not quite as nice a job as it used to be.  Also, depending on stuff, my reduction in hours will either be perfect timing or the worst timing imaginable, but either way I’m doing it.)  So, hopefully I reduce hours and tip the scale of work/life balance in a direction than can accommodate game development, I’ll start to make some real progress.

Updated: August 11, 2015 — 10:31 PM

New “job posting” for an artist

I’ve created a job posting for a new artist.  Please visit the following page to view it:

[Edit: I took it down. Might put a similar one back up.]

Updated: March 31, 2016 — 2:19 AM

Greenlight

Well, it appears that Valve has come to their senses and greenlit The Ditty of Carmeana.  Which means I am now allowed to sell it on Steam, just as soon as I finish it….

Honestly I am surprised it was greenlit so soon.  I was expecting it at some point; it was hovering around the top 30 for awhile.  But part of the point behind Greenlight is not just to test the game concept but also the marketing, and I’ve still done very little (myself) to market it.  It still has the cheap teaser trailer I made that shows absolutely nothing about gameplay, for instance.

And yet there are graphs that show other games with more votes than mine, that have been on Steam Greenlight longer than mine.  I suppose having a working demo helped (also that I never traded anything for votes).

Updated: September 30, 2015 — 4:14 AM

Future plans

So, after a lot of thought, and a fair degree of confidence I will be allowed to sell the game on Steam at some point, I’ve decided that I will make a run at releasing at least a few more levels of The Ditty of Carmeana.

I’ve decided to stick with Python and my homemade game engine, while modernizing some things.  (I had previously considered porting the game to C# and the Unity engine, but after a little investigation, I decided Python wasn’t so bad.  Of note, I learned that many graphically-intensive games only use a relatively small amount of the main CPU since they’re constrained by graphics mostly.  If Call of Duty can get away with 50% CPU, The Ditty of Carmeana can get away with Python.)  This means that a large effort I was anticipating to port the game isn’t needed.

The only two things I do need to bring The Ditty of Carmeana to reality are:

1. Time, and

2. Artwork that isn’t distractingly bad.

I don’t really even need money.  Except, perhaps, to help procure time and art.  And time is something I can borrow pretty easily; I’ve been paying forward on it for years.

Artwork is the tricky one.  I am sure I could up my level of art to “not pathetic” if I wanted to, but I don’t, and I could spend better time elsewhere.  So I am looking either to partner up or subcontract, or both.

I will update this spot as soon as I create my ad.

Updated: April 23, 2015 — 12:22 AM
Tampered Evidence Software © 2015 Frontier Theme