Uncategorized

Because this horse ain’t dead enough… a inquiry into the meaning and purpose of games

Words feel strange to me, and I find them difficult at times.

Years ago, made use of Webster’s/oxford dictionary to give of their definitions and pick it apart pedantically.

I have grown out of that.  I now give greater credence to a word’s origin. In my word origins, I try first to seek a non-Latin, non-Greek source of the word I wish to explore.

In English, after hundreds of years of borrowing, the Old English words often elude us. Old words like game, have such history – related to a old German word that means “glee.”

For the past 1000 years at least, a game gives us joy or causes us glee, if we take to heart the word origin.

At least, until we hit the digital age.

In the modern context, the commonly accepted working definition of “game” can be viewed as “a piece of interactive media.”

When I talk about “games,” I have portions of that definitino that I exclude, even when the Old English “something that makes you happy” definition might still apply or the modern “piece of interactive media” definition might still apply.

As with all beginnings of discussion, when I attempt to define something, I wind up mainly talking about what my definition excludes.

When I talk about games, the things I talk about:

  1. Has an initial state.
  2. Has rules by which that state may mutate.
  3. Requires choices on the part of the player.
  4. Has a way to measure relative success.

Mind you, the purpose of defining what game means provides a starting point for a discussion. Naturally, the definition changes over time.

Really, even the things that look a lot like games, for example jigsaw puzzles(which have an initial state, rules, does not requires choice… the pieces fit where they fit… the activity is finding them, and does not have a notion of relative success… just “done” and “not done” because an incomplete puzzle does not have much merit), can easily become games by setting up a stop watch and competing for time to completion.

You know what has always bothered me about blogs that I have written?

The end. I have made my point, but it feels incomplete somehow. Mainly due to the fact that it wasn’t plotted out in any way. That’s no way to write things. I might as well text or tweet or chat on twitch.

If I manage to keep blogging again, I want to return to the standard three point structure: intro, three points, outro, akin to an essay structure.  I don’t even know if that would work for this topic, and if it doesn’t work for this topic, then why did I write it?

In my writing, I also prefer to use e-prime. So I shall go back and replace forbidden sentences with other sentences that conform to the idiom of e-prime.

Game Development · Roku · Uncategorized

Unicorn and Star… Now With “Levels”

Today, I added the feature of levels to the game.

Each level has an increasing number of stars to gather.

Once all of the stars are gathered, the stairs appear.

Moving onto the stairs moves to the next level, and regenerates the maze.

The game, as such, is still quite fluffy and pointless, but I write for the audience.

Technically speaking, debugging the game on the Roku is primitive, and reminds me quite a bit of the process for writing games for the Cybiko.

Basically, I have my set of scripts written in BrightScript, which I put as somewhere between BASIC and Lua and a little heavier on the BASIC side.

The Roku has a web server on it that allows me to upload a zip file containing my scripts and content. If it upload successfully, it means that the code compiled without error. If not, I have a telnet session that let me know what line was wrong.

Those are straightforward to fix. In the case of a runtime error, however, I get a dump like this from the telnet console:

Current Function:
020: for row=0 to rows - 1
021: y=row*cellheight
022: cell = maze.cells[column][row]
023: screen.drawrect(x,y,cellwidth,cellheight,&h00ffffff)
024: screen.drawrect(x+4,y+4,cellwidth-8,cellheight-8,&h000000ff)
025: if (column=unicorn.x and row=unicorn.y)
026: screen.drawobject(x+4,y+4,context.resources.bitmaps.unicorn)
027: end if
028:* if (cell.star)
029: screen.drawobject(x+4,y+4,context.resources.bitmaps.star)
030: end if
031: for each direction in cell.doors
032: if (cell.doors[direction].open)
Type Mismatch. (runtime error &h18) in pkg:/source/play.brs(28)
028: if (cell.star)
Backtrace:
#1 Function $anon_1f(context As Dynamic, screen As Dynamic) As Void
 file/line: pkg:/source/play.brs(28)
#0 Function main() As Void
 file/line: pkg:/source/main.brs(10)
Local Variables:
context roAssociativeArray refcnt=2 count:2
screen bsc:roScreen refcnt=2
global Interface:ifGlobal
m roAssociativeArray refcnt=3 count:5
maze roAssociativeArray refcnt=2 count:6
columns Integer (2.1 was roInteger) val:16 (&h10)
rows Integer (2.1 was roInteger) val:9 (&h9)
cellwidth Integer (2.1 was roInteger) val:80 (&h50)
cellheight Integer (2.1 was roInteger) val:80 (&h50)
unicorn roAssociativeArray refcnt=2 count:2
column Integer val:0 (&h0)
x Integer val:0 (&h0)
row Integer val:0 (&h0)
y Integer val:0 (&h0)
cell roAssociativeArray refcnt=4 count:4
direction <uninitialized>

There’s a lot of information here, and it is quite informative, but as with dumps like these, one has to learn how to read and interpret them.

Uncategorized

In Which A Grumpy Person Remembers He Has A Blog

Like most blogs ever, I forgot I had this one.

I was reminded this morning when I got a notification that someone subscribed.

Oh yeah…. I had a blog.  Let’s see if I can remember how to log in….

Oh hey… I can.

I should probably post something, but not a “sorry for not posting, and I’ll do better post.”

Here’s a screenshot of the game I’m working on:

ss20200226

And I took it fresh this morning.

You wanna watch me make it? I stream its development.

You wanna play a recent version (still in development, and not complete)? You can find it on itch.io.

And I’ve got other things on itch.io to play.

And I have rejoined Twitter.

I also keep a lot of code on GitLab.

There. Now if I don’t post for another two years, I mentioned pretty much everything.

Raspberry Pi · Uncategorized

Suddenly, I find myself using VIM

From time to time, I wander into very different directions. Last week, on a whim, I decided to buy myself a Raspberry Pi Zero W with the pins soldered in (because while I technically have the capability of soldering the pins, my practice with soldering is practically nil).

Also got a case, the joy bonnet (makes it like a game controller), and an mini HDMI adapter.

And in the last few days, I have done things that I never generally do. I’ve burned images onto SD cards, I’ve dinked with config files. I’ve puTTY’d and sudo’d.

In other words, I’d say I’ve been having a Flintstonian “gay old time.”

Originally, I had been thinking python, and indeed I had been learning python and pygame. After the number of languages I’ve learned and used over the years, I give python the following summation: “it’s a module based language about scope and indentation level(really, the two things are identical in python), and a rather useful ‘in’ operator”, and I’m certain I will be glad I familiarized myself with it.

But ultimately, I said to myself, “Why don’t I just use C?”

With a few brief tutorials, the syntax for gcc is elementary, and after employing a well chosen makefile template unnecessary.

So I now ssh over the network to the pi with puTTY, work in VIM with my .c files in tabs. It works fine, with an occasional :!make. I’ve got tmux on my list of things to get more familiar with.

Mostly, I’m reminded of when I was using Turbo Pascal 5.5 in High School in 1991. No intellisense. No real debugger except printf statements.

I even took a brief look at framebuffer coding. I cleared the screen white and gray.

Normally, especially with my day job, I’m looking for a simple high level library that does all of my work for me.

When I’m doing Pi stuff, I’m the exact opposite. I’ll certainly use a library. Heck, <stdio.h> is a high level of abstraction above the metal. But I like the low level stuff I get to do with ioctl. It dusts off a part of my brain that used to NEED to do these things.

And it’s fun. Plus, I’m not afraid of gcc or VIM or gpio pins or debouncing.

My coworker mentioned that I have all of the skills necessary to come up with a completely new arcade cabinet. I have woodworking tools. I have the ability to write code. I can wire up a breadboard to attach to joysticks and buttons to gpio pins.

I don’t know where this is heading me, but I know I won’t be any worse off for doing these things.

 

 

Roku

Roku GameDev and Me

So, recently, I dusted off the Roku SDK and started making little “games” for my children.

This one is currently unnamed, but my younger daughter says it should be named “Unicorn and Star”. Naming is hard, and she’s 4.

Unicorn and Star it is, then!

ss201806120611

The current version can be installed by clicking here. If that doesn’t work, try here. If that doesn’t work, you are a future person, and it is no longer available.

The goal of the game is to move the unicorn onto the star. At that point, the star then moves to a random spot, and you can move the unicorn to it again.

It challenged my concept of “game,” because it has no success metric, but I am reminded that game in the current use of the word encompasses all forms of digital interactive media, for which this certainly qualifies.

I got the graphics from http://game-icons.net, to no one’s surprise. The Unicorn is by Delapouite, and the Star is by Lorc.

The maze generation is, as usual, my homegrown implementation of Prim’s Algorithm.

My older daughter played for a good ten minutes this morning, so it is successful for now. Methinks it will need enhancements before too long, however.

 

 

Uncategorized

F# is bad for Game Development

Yes. The title is misleading. I will explain.

It isn’t just F# that is bad for Game Development. It is just the functional programming language I’m most familiar with and can actually use “effectively”.

To be more complete…. functional languages are bad for game development.

I had two main problems with the F# community. First, I was told a number of times that my code wasn’t pure enough, functional enough, etc. Because it wasn’t, and could not be, because I was making games.

The second is because the group used terms like inclusiveness like a banner of pride, but is really a cult that expects normative behavior. This will be my final mention of this. Don’t talk to me about it, you will get a “cool story bro” at best or a “get off my lawn” at worst.

Back to functional languages being bad for games. Why do I say this?

It would be more accurate, and less accusative, if I were to state “game projects are a poor choice for functional languages”.

And even so, you might ask why.

Let us explore, for a moment, some of the things that F# and other functional languages are principally against:

  • Global state
  • Side effects

Games are pretty much nothing but state, and must be considered often as a whole. Even in a simple game like checkers, the state of the game must be considered as a whole. You don’t perform operations on pieces without regard for the rest of the board.

And video games primarily communicate with the user via graphics and sound, which are both side effects.

So games are made up of nothing but state and make all sorts of side effects as their very purpose.

This is not to say that it is impossible to make a game using F# or another functional language, but its sort of like making an imperative language do functional things. It wasn’t built with that in mind.

So like I said:

F# is bad for game development.

 

 

lua

A Lua Snippet for Describing Tables to a File

function describeTable(t,indent,cache,f)
 indent = indent or ""
 cache = cache or {}
 cache[tostring(t)]=true
 for k,v in pairs(t) do
 local value=""
 if type(v)=="string" then
 value = "[value=\""..v.."\"]"
 elseif type(v)=="number" or type(v)=="boolean" then
 value = "[value=\""..tostring(v).."\"]"
 end
 f:write(indent..k.." = "..tostring(v).."("..type(v)..")"..value.."\n")
 if type(v)=="table" and not cache[tostring(v)] then
 describeTable(v,indent.."\t",cache,f)
 end
 end
 return result
end

local f = io.open("output.txt","w")
describeTable(_G,"",{},f)
f:close()
love2d · lua

Bootstrapper Lua Library – Overengineered Love2D

In the games I am writing in Love2D, I tend to use various sorts of “managers” to cache things for me.

One of the more notable managers I use is an image repository. I want to simply do the following:

--loads the library

local images = require "game.images"

--caches the images

images.load() -- during love.load

--retrieves an image

local img = images.get("imageName") -- during love.draw

Typically, I don’t lazy load my images, but I could easily configure my images.lua file to do so.

I find myself faced with a number of these managers, however. I’ll have one for images, one for sound effects, one for music, one for options, one for image regions, and so on.

What I like to use for this is a meta-manager called a bootstrapper, which each of my managers will automatically add themselves to, and then during love.load, I only have to call bootstrapper.load().

So let us overengineer this solution. I’ve got my current implementation for bootstrapper:

local bootstrapper = {}

local loaders={}

function bootstrapper.add(loader)
 assert(type(loader)=="function","bootstrapper.add - loader must be a function")
 --TODO: idempotency?
 table.insert(loaders,loader)
end

function bootstrapper.load()
 for _,v in ipairs(loaders) do
 v()
 end
end

return bootstrapper

And I want to add a few more bits of functionality:

  • I only want calls to bootstrapper.add to work before a call to bootstrapper.load.
  • I want to enforce only one call to bootstrapper.load.
  • I want calls to bootstrapper.add to be idempotent, as in my TODO
  • Do unit tests
  • Make bootstrapper use a proxy object, to keep it from being subverted by client code

If that all seems like a bit of overkill for something like a bootstrapper, then you are going to not like this series of articles.

The changes to the main part of the code are minor:

--bootstrapper library object
--initialize to empty object, as is my habit
local bootstrapper = {}

--static data for this library is hidden from the outside
--starts as empty table
--gets changed to nil after a call to bootstrapper.load
local loaders={}

--bootstrapper.add
--adds a function to the bootstrapper
--requires that the loader parameter is a function
--will throw an exception when called after bootstrapper.load
function bootstrapper.add(loader)
  assert(type(loader)=="function","bootstrapper.add - loader must be a function")
  assert(type(loaders)=="table","bootstrapper.add - cannot call after bootstrapper.load hase been called")
 
 --idempotency...
 --if the loader already exists in loaders, don't re-add it and just return
 for _,v in ipairs(loaders) do
   if v == loader then
     return
   end
 end
 
 table.insert(loaders,loader)
end

function bootstrapper.load()
 assert(type(loaders)=="table","bootstrapper.load - cannot call multiple times")
 
 --perform the load actions
 for _,v in ipairs(loaders) do
   v()
 end
 
 --eliminate loaders to keep from being re-called
 loaders=nil
end

I decided to make use of the static variable loaders instead of having a separate boolean flag for whether or not load has been called. There was no reason to hold on to that array after the call anyway.

Unit tests were a wholly different thing. Firstly, I don’t always want to run unit tests. I do when I’m developing, but not in release code. Of course, the scope of my activity today does not include any sort of unit testing framework, so I decided to at least mock out what I needed, with a plan to augment it later.

--runTests library
--This will eventually be a require that returns a function, so that I can turn off unit tests in one place
local runTests = function(f) f() end

runTests(function()  
  --save off old static state 
  local oldLoaders = loaders 
  loaders = {} 
  local start = os.clock() 

  --bootstrapper.add with non-function 
  local status, err = pcall(function() bootstrapper.add(nil) end) 
  assert(not status) 

  local counter = 0 
  local called1 = false 
  local called2 = false 

  function f1()  
    called1 = true 
    counter = counter + 1  
  end 
  function f2()  
    called2 = true 
    counter = counter + 1  
  end 

  --bootstrapper.add with function 
  bootstrapper.add(f1) 
  assert(#loaders==1) 
  --bootstrapper.add with same function 
  bootstrapper.add(f1) 
  assert(#loaders==1) 
  --bootstrapper.add with second function 
  bootstrapper.add(f2) 
  assert(#loaders==2) 
  --bootstrapper.load 
  bootstrapper.load() 
  assert(loaders==nil) 
  assert(called1) 
  assert(called2) 
  assert(counter==2) 

  --bootstrapper.add after load 
  status, err = pcall(function() bootstrapper.add(f1) end) 
  assert(not status) 
  --bootstrapper.load after load 
  status, err = pcall(function() bootstrapper.load() end) 
  assert(not status) 

  local elapsed = os.clock()-start 
  print(string.format("bootstrapper unit tests - %f",elapsed)) 
  --restore original static state 
  loaders = oldLoaders 
end)

I set up my runTests function to call whatever function is passed to it. Eventually, this can be a library that I load instead, and I can configure that library to either run or not run the functions it passed depending on whether or not I am in “release” mode.

Before you go out and comment something about “pcall is inefficient!”, let me give you the results of these unit tests on each run of my application:

ss03-unittests

That’s right… the unit tests do not take up enough time to actually register time passing.

Finally, I make a protected proxy using a metatable:

local mt = { 
  __index=function (t,k)  
    return bootstrapper[k] 
  end, 
  __newindex=function(t,k,v) end,  
  __metatable="bootstrapper"
}
local proxy = {}
setmetatable(proxy,mt)

return proxy

From what I read, this is all I need to do in order to protect bootstrapper from casual changes from outside code.

It occurs to me that this is going to be a common pattern I want to use, and so a more generic version of this code is likely to wind up in a utility library.

So, this concentration on making a robust bootstrapper seems to fly in the face of how I normally develop code. Almost invariably, I will recommend that one writes exactly the code that one needs, and once it is “good enough” then stop.

Actually, that is exactly what I am doing. The main difference is that this code has been deemed useful enough (by me) to be part of the framework I use in other games going forward, which means it needs to be library code – as bulletproof as I can make it.

Game Development

Click the Yellow Rhombus

So yeah. Missed adding this here, but I added Click the Yellow Rhombus over at itch.io.

This is the second in a series of getting back to basics using Love2D.

In particular, CTYR required me to get good with handling mouse events. I wound up having to make simplistic controls on screen, which generally pushed me in a direction of needing a scene graph, which I have been working to build slowly since.

If you would like the source code, you can find it here.

Some of the things that got developed/advanced as compare to JetLag during this project:

Graphics

I’m using actual images in CTYR, as compared to rectangles in JetLag. Some of the more simple graphics I made with InkScape.

I made the following graphics:

  • The rhombus
  • The background
  • The start button

Other graphics I got from game-icons.net.

I get my fonts from dafont.

State Machine

CTYR has five states, so a full on state machine was an absolute need.

Controls

JetLag was keyboard only. Yes, I could have put in GamePad controls, but it would still be “hit a button on an external device” controls.

CTYR is completely mouse controlled, so controls are contextual based on where the mouse pointer is.

For this, I created a single control: the button. The start button is one. The mute and info icons are buttons. The rhombus is a button. It was all I needed.

In fact, the rhombus in CTYR is considered “clicked” if you get within its bounding box. Could I have been pixel perfect about it? Yep! Why didn’t I? I don’t need to.

 

 

Game Development

JetLag 2017

ss01

I have truly lost count of the number of times I have made more or less this exact same game.

Currently, it may be found on itch.io. It requires Love2D to play it, as will all of my games for the next little while. If you are interested in the source code, you can find it here.

There is a reason I start with JetLag. When done correctly, it has all of the components of a much more sophisticated game in miniature.

Graphics

I admit, the graphics are rudimentary. I use filled rectangles and text. These things are not earth shattering.  The point here is that this game draws onto the screen, and to quote Andre LaMothe: “if you can draw a pixel, you can make a game.”

Controls

It’s not quite true, about the pixel I mean. It is true that being able to draw a pixel gets you halfway to making a game. The other half is being able to get input from a player. However, once you have the ability to draw something on the screen and the ability to get any sort of input from the user, it makes game creation possible.

In JetLag, the controls are keyboard only, although I am considering supporting the gamepad as well.

Timing

Not all games require this, but enough of them do such that it may as well be a required thing. In JetLag, the love.update function hands me a time delta, from which I can calculate when to scroll the display.

Music

JetLag can be enjoyed on mute. The music is merely there for ambiance. I’ve got some mixed feelings about game music.

When I am playing a game on my desktop computer, I may leave the music on, but this is for games like Minecraft or Yonder, where a great deal of thought has been put into the music for the game.

When I am playing a game on my phone, I immediately look to turn off the music and sound effects.  Why? because I want to be able to play the game when I’m “indisposed”, and it making noise is the last thing I want.

So I require of myself when adding music and/or sound effects that I provide a means by which it may be conveniently turned off.

Also, I’m not a composer, so while I do try to select music appropriate to the game, I’m not engineering an immersive experience here. I’m tacking on music because tacking on music is the thing to do.

Sound Effects

Sound effects I pull from sfxr/bfxr/some other sound effect generator. I’m not engineering realistic sounds.

Same deal applies for sound effects as does music. I want it there, but I want to be able to turn it off.

Persisted Preferences

And that brings me to persisted preferences. During a play session, if I turn off the audio, the next time I play, it better stay off!

So I save my preferences to disk somewhere. Love2D has a nice set of functions for saving and loading little files, and I found a usable json library for lua that suits my needs.

I also store the high score achieved in the game, just to add a little self-competition.

State Machine

JetLag has exactly two game states: game over and play, but it still qualifies as a state machine, and is a shadow of the more formalized state machines that I’ll wind up developing later.

The internal state of JetLag might look like it is a grid. It is not, because it doesn’t need to be. The renderable state is two arrays: one for block locations and one for tail locations. In fact, the only really important block/tail location is the head.