Thursday, 24 July 2014

Custom AIs and whatnot: Parsnip Theory Alpha 11 released!

I've done another update to Parsnip Theory, which you can get... at, well, the link in this sentence.

Aside from the change in the table graphics so you don't accidentally mistake them for vents (yeah, they don't sit well with me, perhaps I could do some palette changes), I've given the AI system an overhaul.

By that I mean I've made it possible to write your own AIs in Lua.

Currently there's a crouching-aware version of the AI that's been there since I put AI in.

If you'd rather revert back to the old AI, just make the Lua side throw an error and it will jump back to that. Be very aware of this when writing your own AIs, because it can catch you out.

There are two functions that are added:
  • game.astar_layer(layer_index, x1, y1, x2, y2) - returns a list of directions (order is: 0=south, 1=east, 2=north, 3=west) to get from point 1 to point 2, or nil if you can't get there. WARNING: While point 1 can contain a player, point 2 cannot! So you'll want to find a neighbouring cell for point 2.
  • game.line_layer(layer_index, x1, y1, x2, y2) - returns a tuple (success, xt, yt) where (xt, yt) is where something thrown would actually land, and success is a boolean indicating if you actually managed to hit point 2.
The AI is called from time to time via a function called hook_tick. It takes one argument, conventionally "gstate". This is a table containing:
  • tid: The ID number of your team, useful for identifying who in the object table is actually in your team.
  • ocount: Number of objects in the object table.
  • layers: A table containing tables of the form:
    • x, y: Top-left corner of the layer. Do not assume this is 0, 0.
    • w, h: Width and height of the layer. Do not assume this is 40 x 40.
    • data: A 2D table in order [y][x] (not relative to x,y, so [0][3] really does mean (3, 0) in space!) containing cell data of the form:
      • ctyp: Type of cell. This is a string. Valid types are: "oob", "floor", "solid", "backwall", "table", and "layer" (which is unused and intended for transitions between layers.
      • tset, tidx: Tileset and tile index respectively - what the tile actually looks like.
      • p1: A parameter for specific kinds of tiles. Currently unused.
      • has_ob: A boolean indicating if there is an object on that tile or not.
  • objects: A table containing tables of the form:
    • otyp: What type of object this is. Valid types are: "player", "food_tomato". Note, you will probably never see food_tomato as while that object exists, the AI tends to not be called. Still, don't assume everything is a player.
    • layer: Which layer this object belongs to.
    • cx, cy: Which cell this object belongs to on its respective layer.
    • ox, oy: The pixel offset of this object. Note, this probably shouldn't be here, so don't rely on it, and expect me to remove it.
    • steps_left: How many steps this object can take - undefined for things that aren't players, but it's there.
    • health: How much health this thing has - once again, undefined for nonplayers.
    • flags: A table of certain things:
      • flags.crouch: True if this object is crouching.
    • fd: A table containing things specific to a given object. The stuff this contains for a player is:
      • team: Which team this player belongs to.
      • face: Which direction this object is facing (0=south, 1=east, 2=north, 3=west). Mostly irrelevant in terms of strategy.
gstate is generated every single time the function is called, and it's a copy of the current state. Modifying it will not allow you to cheat, as it won't affect the actual state of the game.

hook_tick must return one of these things:
  • "idle": Do nothing.
  • "newturn": Move onto the next player. You may need to return this several times, due to the turn change delay (which is there to prevent desyncs)
  • "move", x1, y1, x2, y2: Moves player at point 1 to point 2. You MUST ensure that the player at point 1 belongs to you, and it's YOUR responsibility to ensure there is a valid path. Use game.astar_layer to get the exact path.
  • "attack", x1, y1, x2, y2: Uses player at point 1 to attack point 2. You MUST ensure that the player at point 1 belongs to you, and it's YOUR responsibility to ensure there is a valid line of sight. Use game.line_layer to check this.
  • "crouch", x1, y1: Crouches player at point 1. You MUST ensure that the player at point 1 belongs to you and it isn't already crouched.
  • "stand", x1, y1: Stands player at point 1. You MUST ensure that the player at point 1 belongs to you and it is currently crouched.
That's the API, anyway.

So whether or not you read or understood any of that, go ahead and give Parsnip Theory a whirl today!
http://fanzyflani.itch.io/parsnip-theory

If you have any issues, there's always the comment section and my twitter @fanzyflani, and there's also a Facebook page for Parsnip Theory.

Have fun!

Friday, 11 July 2014

How to write a game in assembly/machine code in a small number of hours

Coding games in assembly ("machine code" isn't quite accurate but it gives an idea) is viewed in many different lights. On one hand, there are people who will view it as useless and outdated and point you to the nearest compiler game development system that they've heard of. In other words, they'll tell you to use Unity, Game Maker, Construct 2, or whatever other buzzwords they've heard of lately.

However, you may be constrained by certain limits. Yes, I can make a game for Windows which fits on a floppy disk and has music and sound and stuff (if you strip away the non-Windows stuff from Parsnip Theory, I suspect it will actually fit, although you may need to remove the server), but it sure won't use Unity, and it sure won't use Game Maker either (barring maybe Game Maker 4.2a if I decide to take the piss).

Either way, it's more fun writing it in 80186 assembly. Pure 8086/8088 assembly is a bit limited for my tastes, and the oldest x86 CPU I have is 80186-compatible, so the 80186 is actually a really good target if you're taking the x86 route.

Or you may be doing it for the challenge. Which brings us to the next group: There are people who are genuinely shocked that it's actually possible to write software in assembly machine code techno whizz-kid language and will revere you as a god. The upside is that you get praise. The downside is that they'll refuse to listen to you when you try to explain it.

It's not as hard as people think it is. It's just something you have to try.

But it is a little bit harder than what you're used to. Yet if you program it well, get a bit of practice, and follow these principles, you'll be very surprised at how quickly things will come together.

It will also make you a better programmer.

... well, it'll teach you how to comment properly, at the very least.

Use a modern assembler and a modern emulator on a modern computer.
That way, you won't be wasting time rebooting, burning media, trying to remember what address "draw_box" is, trying to remember the format of the ModR/M byte, or any of that crap.

Of course, this part is pretty easy. Your whole toolchain is, at the time of writing, smaller than any Unity game ever produced... barring maybe your text editor, shell, terminal emulator, IDE, and all that crap - but let's just assume you have those already. Either way, it'll be smaller than Titanfall. That game has no right to be 15GB. Heck, it's even bigger than the Unity IDE itself!

But enough ranting about how everything is complete and utter bloatware. Let's get on with the other tips.

Comment your code properly.
Make a comment at every logical step ("Calculate video pointer", "Draw pixels", "Return" for example). You will completely and utterly lose your sanity otherwise.

Also, put a comment before every subroutine call in your code to point out the input registers/flags, output registers/flags, and which registers get trashed. Always assume that, when you call your code, the flags will be trashed - and thus, you don't have to note that the flags will be trashed.

If you've done this before, use your old code as much as necessary.
Another way to word this is "I really, really do not want to have to waste another 24 hours getting scrolling working properly on a Sega game console". If you have a good framework, keep it.

Know a very high-level language and use that to assist with tables and calculations and whatnot.
Python is my weapon of choice, but as a VIM user, I also tend to use some of its nicer features to generate at least some of the tables.

Still, sometimes you need to make a sine table.

Define named constants instead of using magic numbers everywhere.
You're using a modern assembler. If you need to change something like, for example, the maximum number of objects you can have (you probably will), or the address where something is stored (assuming you aren't letting your assembler handle the addresses or if your assembler sucks), it will be far easier if you have a constant you can change.

Don't prematurely optimise your code.
1MHz is a lot faster than you think.

Either way, good code is more important than fast code. You can make it go faster later.

If you do need to optimise, the general rule is to only optimise the innermost loop. Oh, and comments will help you make sense of it later.

Make lots of things into subroutines.
Not only does this make your code easier to manage, it also tends to make it smaller, too! Are you doing something twice in two different places? See if you can rewrite it as a subroutine.

Make structs, arrays, and function pointers.
Those of you who don't realise that C doesn't always have a ++ or a # after it may not know what I mean, so I'll explain them.

A struct (short for "structure") is, well, a structure. It's basically a definition for a block of memory which has certain values in certain places. I'll give you an example in C:

struct obj {
  short x, y;
  char vx, vy;
  char sprite_slot, sprite_tile, sprite_count;
  char flags;
  char timer_stun;
  char timer_shot;
  void (*f_tick)(struct obj *);
}


And a similar example with the WLA-DX assembler:

.struct obj
  x  dw
  y  dw
  vx db
  vy db

  sprite_slot  db
  sprite_tile  db
  sprite_count db

  flags db

  timer_stun db
  timer_shot db

  f_tick dw
.endst


An array (and if you haven't heard of this, you do not know how to code well, so put your "but I know C#" shades down and listen because this is fundamental) is a usually-fixed-size list of... something. It can be a list of numbers. But it can also be a list of structs.

See that f_tick thing? If that confuses you, then I guess it would be new information for me to remind you that it's called a function pointer. Now, if you're going to be programming in assembly, chances are you already know what a pointer is. So, of course, this is a pointer which points to a bit of code. Yep.

Here, have some code. This one's for 68000, sorry, because the Z80 equivalent is a bit ugly... and the x86 equivalent is even worse.
(Mind you, the 68000 version is pretty ugly, too.)

tick_object:
  ; Push registers to stack
  movem.l d0-d7\a0-a6, -(a7)

  ; Call function
  movea.l OBJ_f_tick(a0), a1
  jsr (a1)

  ; Pop registers off stack and return
  movem.l (a7)+, d0-d7\a0-a6
  rts


... actually, that's pretty ugly. Here's the 16-bit x86 version.

tick_object:
  ; Push registers to stack
  pusha

  ; Call function
  mov ax, .fromcall
  push ax
  jmp [bp + obj.f_tick]

  .fromcall:

  ; Pop registers off stack and return
  popa
  ret


...ok, that was actually much less ugly than I thought it would be.

Yeah. That's one of the rare cases where x86 looks nicer than 68000.

Anyway, using an array of structs which have function pointers in them will make your life much, much easier.

Speaking of arrays...

Don't write malloc(). Just use arrays, and a subroutine to look for a free slot.
I've done this plenty of times.

Of course, you have to find some way to denote if a slot is unallocated, but once you've done that, it'll save you a lot of pain!

Using instructions which write immediate values to RAM makes it much easier.
I've done this several times before. I'll point out the ones for several CPUs:
  • x86: mov word [address], value ;;| you can use byte, word, dword, qword, although some aren't available in certain CPU modes
  • 68000: move.w #value, address ;;| .b, .w, .l can be used, also did I mention this syntax is backwards? Because it's backwards.
  • Z80: ld (ix + offset), value ;;| OK, there are limits to doing this. offset is a signed byte, and IX is a 16-bit pointer to somewhere. But if you're modifying a structure, this helps a lot.
For some CPUs, however, you'll need at least two instructions - one to load the value, and one to store it in RAM. 6502, MIPS, and ARM are all like this.

If you have local labels, use them.
NASM (x86) has the .label syntax. I'll give an example here:

  ; Input:
  ; ES:DI = pointer to video memory for top-left corner
  ; CX = vertical length of line
  ; AL = color of the line (of course it's actually spelt "colour" but by convention we have to spell it wrong)
  ;
draw_vline:
  push di
  push cx

  .lp_y:
    stosb
    add di, 319
    loop .lp_y

  pop cx
  pop di
  ret


In this case, the .lp_y label is actually draw_vline.lp_y, but doing stuff this way really saves you pain.

The WLA-DX multi-CPU assembler (highly recommended!) has the + and - series of labels. These are amazing, especially when you're doing stuff like this (Z80 given as an example):

    ld de, SCREEN_WIDTH_BYTES - WIDTH_BYTES
    ld c, HEIGHT


--: ld b, WIDTH_BYTES
 -: ld a, (ix+0)
    ld (hl), a
    inc ix
    inc hl
    djnz -

    add hl, de
    dec c
    jp nz, --


By the way, when I say "don't prematurely optimise"... I kinda did a little. The improvement is minimal, but simple enough that we can get away with it. See that jp opcode? It takes up 10 cycles regardless of whether it is taken or not, and a jr takes up 12 cycles when taken, but only 7 when it isn't. Seeing as the branch is taken more than 40% of the time, I'm using jp here.

Which leads us to another tip.

Knowing your cycle counts and other timings can be helpful for when you do need to optimise.
The cycle times for Z80 are kinda hard to memorise, but the main points are:
  • 4 cycles for M1 access (first op OR the byte after a DD/FD, ED, or CB)
  • 3 cycles for regular memory access
  • 4 cycles for I/O access
  • 5 cycles for (IX+dd), (IY+dd) or JR/DJNZ PC+dd calculation (the calculation for JR only takes place if the condition succeeds)
The cycle times for 6502 are easier, but there are still some snags. Main points:
  • 2 cycles for first byte of an opcode
  • 1 cycle for memory access
  • 1 cycle to calculate a 16-bit carry if need be
Often there are other cycles used, though, so be wary!

But this isn't a tutorial on how to calculate cycle timings. Look elsewhere if you want the timings for your CPU. As for x86 cycle timings... I don't even try.

-

Anyway, there's a lot of things that can be talked about, but that should be enough to give get you somewhere.

Tuesday, 8 July 2014

Adventures in voice synthesis, part 1

Drake M. @DMODP:
@fanzyflani Ugh. I hope you're writing this effort down and plan to make a tutorial on it. Super-curious.
I think that would be a good idea.

I'm working on a new game with a working title of "HeroGraze". The name isn't exactly the best, but at the time I came up with it, putting it in quotes yielded no results on Google, so there we go!

The idea: You're a girl who wants to be a superhero, and a song plays in the background with words saying what you're doing, what you need to do (worded as what you're going to do), and how awesome and brave and heroic you are.

Basically, I'm making a real "feel good" game.

The catch is I have to write a voice synthesiser. At the moment, what I have is 6 vowels being sung at about C4, fed through AutoTalent, and clipped into small loops.

And then I have these terrible consonant samples. These are played as one-shot samples.

I then use a custom mixer for sackit (my .it playroutine) which detects when a particular sample is played, sets the sample volume to 0, and steals the pitch and note-on status and stuff so it can mix the voice synth over the top.

Steps required

There's a few steps that need to be done to make this work. This paragraph is pretty useless, but I really feel like there should be some text here before I drop in a subheading.

Music

This is created with SchismTracker, and the samples mostly created with SunVox. These fly out of my arse like a hot curry. I put annotations on the lyric line to point out which notes have to rhyme with which notes, at what point a phrase starts, and when to reset the rhyming pattern. These annotations aren't read yet, sadly.

Dictionaries

Lists of verbs and nouns and adjectives and whatnot. There's a bit of overlap with these. There are a lot of words to add,

Facts

This step is still being worked on. Facts will be stored in a tagged tree sort of structure.

Bullshitter

This step hasn't been started on yet. The idea is that it can take facts and exaggerate things and can even conjure up complete untruths.

Phrase generator

This step is still being worked on. Basically, you give it facts and it spits out valid phrases in different forms.

Pronouncer

But of course, you need to take these sentences and work out their pronuncations. Firstly, so the speech synth can actually do something. Secondly, so you can tell what rhymes with what.

This uses a dictionary to accept English words and spit out Lojban-esque syllables. No, Lojban isn't going to be used for the reasoning - we're trying to make the song not sound Lojbanic here!

Poeticiser

This step hasn't been started on yet. It gets stuff from the phrase generator and works out pronunciations, and then matches it up with the annotations and gets it to fit and rhyme.

I'll need a synonym dictionary for maximum effect.

Synthesiser

It accepts syllables starting with optional consonants, having one or two vowels in the middle (I'll need to raise this limit), and ending with optional consonants. For example, several possible pronunciations of "heroically":
  • 'iro,ykyl,i
  • 'iro,yk,li
  • 'yro,ykal,i
 The quote is an "h" sound, and the "y" is the vowel you get when you let your mouth rest (kinda like an "uh" sound).

Issues

The code for the phrase generator is a complete and utter mess and I'm struggling to get my head around it, so I'll need to do some rewriting of it. But I'm happy with the form the facts are being stored as.

I really should be treating "n" and "m" as vowels. This would mean that I would have to be able to handle more than two vowels in a row.

And of course, the best way to fix that is to move the vox synth control to the Lua side.

For the other consonants, while stuff like k/p/t would be best done as one-shots, stuff like c/f/s/'/x (note, "c" is a "sh" sound, and "x" is just plain weird!) would be best done with the vowel engine.

And of course, let's not forget that there are voiced and unvoiced consonants.  j/c, f/v, s/z for the vowel engine, and k/g, p/b, t/d for the consonant engine.

I could possibly change the samples and make a Karplus-Strong synth.

My main foci at this stage, however, are the sentence generation step, and, well, the game itself.

At least I'm using Lua this time. Makes it much easier.

Tuesday, 1 July 2014

Alpha 9 is out! Sorry about the radio silence.

I've mostly been saying everything on my twitter account @fanzyflani, and so I got a little carried away and forgot about this blog. Oops.

Anyway, Parsnip Theory alpha 9 is out. Most of what happened during 5 through 8 has been cosmetic or bug-related, and as you can tell from the screenshot I've done some huge improvements to the graphics since then.

Oh yeah, I also added in an AI. And an 8-player map which I tend to show off all the time these days.

However, alpha 9 adds in a new gameplay mechanic: Crouching. The idea is that you can crouch behind a table for cover. Suddenly, those white things are no longer just obstacles.

I'm looking for people to test this mechanic (mostly so it's not stupidly lopsided), so contact me on twitter if you're interested in a netgame. Because I'm up for it.

Download: https://fanzyflani.itch.io/parsnip-theory
Twitter: @fanzyflani

Thursday, 19 June 2014

Parsnip Theory Alpha 4 released - usability + sound

I've pushed a new update for Parsnip Theory. It makes it less annoying to play, although currently you can't turn the music off so it might be more annoying. Oh well, the setup screen stuff can happen in Alpha 5 - I'm mostly just trying to test usability at the moment.

No fancy picture, but here's the music rendered to an .ogg: https://dl.dropboxusercontent.com/u/32094129/parsnip/trk1-dem1.ogg

Download: http://fanzyflani.itch.io/parsnip-theory

Monday, 16 June 2014

Parsnip Theory Alpha 3: This Time You Can Actually Play It Networked

Since Alpha 2, it's possible to play Parsnip Theory over a network.

But with Alpha 3 out the door, it's now feasible.

I've added a "game setup" menu to the game. This allows each player to pick which players they want to play as, and also allows for a higher playercount (I've capped it at 16, although the editor only goes up to 8 at the moment).

No more "only stuck with two players".
No more "stop ending my turns for me".
No more "stop making my moves for me".
No more "don't move until I've joined".
No more "make sure you have the right version of the map".

Although this did require a couple of #ifdef WIN32 lines simply because Windows. But of course, there's no such special code required to get this to behave on both BSD and Linux. I could rant about this all day but whatever.

As usual, the HTML5 version is updated (although I haven't added in the new map): https://dl.dropboxusercontent.com/u/32094129/parsnip/index.html

It also runs notably worse than it used to. If you find it's driving you nuts, it would be a good idea to download the real version.

Anyway, enjoy! And if you have any issues, please prod me on Twitter: https://twitter.com/fanzyflani

Download away: http://fanzyflani.itch.io/parsnip-theory

Thursday, 12 June 2014

Parsnip Theory Alpha 2 released!

Featuring a Linux build, flimsy but playable 2-player network support, and it's a bit easier to run stuff now.

Not convinced this is the game for you? Here's a gameplay video.


Download for free here! http://fanzyflani.itch.io/parsnip-theory

Sunday, 8 June 2014

Parsnip Theory alpha 1 released!

Yes, suprisingly, I actually got it playable and winnable today. Not only that, but it also has a little bit of polish. Not too much, just enough so it's usable.

It helps if you read the README.txt file in the zip.

Have fun, and send me some useful feedback so I can make this even more awesome. Also, give it to all your friends and get their feedback, too.

Download: http://fanzyflani.itch.io/parsnip-theory
My Twitter: https://twitter.com/fanzyflani
My blog: You're reading it right now

Friday, 6 June 2014

Just in case you wanted to know

Y'know that weird bug with A* not working properly?

I fixed it.

You can breathe now.

Thursday, 5 June 2014

Well, that was a bit of a stretch


Having been overly optimistic after a really good run yesterday, I managed to overpromise on what I would do today.

What you see on the right is a screenshot demonstrating an overly favourable outcome of my broken A* implementation (it always gives a path when possible but it's usually not the best). I suspect I'm doing the priority queue wrong, but nothing seems to be jumping out at the moment.

But I do have turn taking implemented, and A*, and you can't have two units on the same spot anymore.

I also got a little bit bored of implementing gameplay, so I decided to make a 16x16 font! Currently it's just digits and upper-case letters, and the rest of the ASCII set is either just dupes of the upper-case letters, or placeholders. Took about 30 minutes to get the font to where it is now.

Tomorrow, I'll... be taking a break because it'll be Saturday then. But on Monday I'll make it possible to delete objects (read: 2- and 3-player games will be doable on this map), hopefully fix the broken A* stuff, and have food slinging and "health" in place.

Oh, and of course, we might as well have a video:


Enjoy.

Change of plan

I assumed today was actually Wednesday. It's actually Thursday. Alpha should be done by the end of Monday.

Derp.

Wednesday, 4 June 2014

Level editor complete enough

Keyword "enough". Basically, I can put player objects down for 4 teams, and... well, the next thing to do is to work on getting the players moving around.

Casualties? The code to add an object to a level is atrocious. Not that it's big or anything, but that it just... sucks. I really need to get a linked list going, or if I'm going to use a dynamic list, make sure it doesn't realloc() the list every time it adds or removes an object. (But quite frankly I should just use a linked list.)

I really don't have much more to say here, other than tomorrow I'm going to make it so players can move according to A*, and hopefully all of but nevertheless at least one of these things:
  • Turn-taking
  • Food throwing
  • Damage
  • The food fight equivalent of "death": Fleeing.
If I knuckle down I'll have all 4 sorted.

The day after that I plan to have a font in place (might just grab the one I'm using for pixra for the time being), a simple UI, a main menu, and a 2-4 player hotseat alpha test.

By the way, if you let me know how crap the player colour combinations are in that screenshot, please suggest some good ones - I'm using an algorithm which is SUPPOSED to give 128 unique combinations from a set of 8^3, but sometimes it spits out crap.

And of course, this game is called Parsnip Theory.

Tuesday, 3 June 2014

Mode 13h is fun (for some standard of "fun")

Oh boy, let's have a look at what we've got today.

I actually have a game idea now! It involves cafeterias, food, and the sorts of stuff that gets you into trouble with your teachers. I even have a name for it, thanks to the advice of drnick on #ludumdare.

Basically, it's a turn-based food fighting strategy game. Main reason for making it turn-based is I intend this to be playable as a hotseat multiplayer game, and this is the best way to have everyone in the room able to play.

I've also just realised that in that screenshot made with a big chain of "draw this tile" calls, the player sprites should be 12 pixels higher. Or lower. Either way the feet should end at the centre of a 32x24 tile.

In other news, it turns out pixra doesn't suck, but:
  • It could really do with a palette interpolation feature, and
  • Rect fills don't seem to add anything to the undo stack. Looks like we have a bug!
But enough about pixra, back to this game.

My plan of attack:
  • Make a level editor, and of course make some levels.
  • Get player movement working properly.
  • Get A* working properly.
  • Get team colour assignment working properly.
  • Add some weapons. By weapons, I mean food items.
  • Add some shields. By shields, I mean tables.
  • Add some health. By health, I mean cleanliness... denoted by a cute-looking bottle of liquid soap.
  • Make it so teams can win.
After that, I can work on the finer aspects, such as food splatter graphics, more weapons food items, and - most importantly - the ability to slip up on food. I have experienced first-hand the aftermath of a potato fight, and trust me, you have no idea how slippery the floor gets.

I can also work on making it look good. Animation, shading, and nifty tooltips which tell the other people in the room how to actually play the damn game. If I'm going to convince people to buy this game, I'm going to make it as easy as I possibly can to make them want to part with their money.

Oh, and of course I'd need to add fonts. A 16x16 font will allow for 20 x 12.5 characters at a 320x200 resolution, while an 8x8 font will allow for 40 x 25. Basically, the reason for adding in a 16x16 font is that it gives me room to make it look awesome. But something like an 8x8 is also a must, because tooltips are just going to be impossible to fit in at 16x16. I could also invest in some smaller sizes; 6x6 seems plausible (53 x 33 characters).

I hate bad caching

I've successfully pushed an update to the Raspi build of pixra. Unfortunately, I can't test the Windows build because the client keeps grabbing outdated files. I've rebuilt the installer 3 or 4 times already and it still refuses to give me what I want.

From experience, this is usually because my ISP does really, really stupid things. So stupid, that every now and then I have to use Tor just to get stuff working.

So some actual cases:
  • From time to time an image or animation on mspaintadventures would only partially load. I stop it, and refresh. Reloads exactly up to the point where it gets stuck.
  • On some people's websites, I have to get updated .zip files. I have to either download them via a shell server, or get them to rename the file so I can get an updated version.
  • Not really caching related, but sometimes I end up with weird routing loops while trying to access obscure websites such as Google. (In reality, it's almost always something like Cloudflare or Akamai.) This is when I resort to using Tor.
However, it's only the Windows client that's giving me the weird caching issues - Firefox is fine, and Pi Store is fine. So it may actually be a clash between the Windows client and Wine.

Anyway, if you're running Windows, or can run Windows programs, mind doing me a favour?
  • Install the IndieCity Client.
  • Create an account.
  • On the Explore tab, filter by "In-progress", then select the "Dev Tools" subtab.
  • Select pixra, and install it.
  • Run it.
  • Enter in some random filename like "butt.tga" and hit Enter.
There should be a message up the top saying something like "Welcome to pixra! Press F1 for quick help at any time." If there isn't, IndieCity is giving you the old files, so please tell me about that. If there is, please tell me about that too so I can put it forward for approval.

My twitter account is @fanzyflani (oddly enough) if you want to get in touch. And of course, there's a comments box down there (I think), and a few on IndieCity.

Monday, 2 June 2014

Undo, Flood fill, In-app help

So as I wait patiently for the Windows version stuff to sort itself out, I might as well show you the power of flood fill by producing this image I totally did not just cheese together in 5 minutes.

Once this tool finally downloads properly (as opposed to constantly grabbing the old version instead of the current version) I'm kinda keen to mark it as released, because quite frankly it has enough grunt to be used in production. (I hope so, at least.) I've flicked IndieCity an email as I don't think this is going to resolve itself in a hurry.

Anyway, I have a game idea. Tomorrow, I think I'll focus on implementing that.

pixra now on Indiecity! (in-progress)

Well, it didn't take long to finally get something out.

That image you see to your right? I had to make an image for the Windows installer, otherwise it wouldn't build. So I spent about an hour drawing something in pixra, and found myself longing for flood fill. But there we go, a fairly simple image drawn entirely using pixra (and I am ashamed to be using that marketing cliche).

I then proceeded to use Gimp to crop and convert the image.

The frustrating things is that you never actually see that image. Effort wasted... apart from the fact that it makes a nice addition to this blog post.

Although that really bright star just really irks me. Oh well. I'll figure out how to do stuff properly as time goes on.

The build process

Now, I have a Windows build, and a Raspi build. They each have their own quirks.

Windows

This was what I did second. Zipped everything up, all good... oh right, now I have to make an installer image. I kinda explained that one. But wait! I need minimum system requirements! And libraries to install! Well, there were no libraries to install, so I just ticked the box and moved on.

The minimum system requirements have yet to be established but the one thing for certain is that they are all below the minimum minimum system requirements IndieCity let you put (except maybe the CPU speed). The one thing I can establish is you need an SVGA card at minimum capable of outputting 800x600 16bpp, which requires almost 1MB of VRAM. However, I'm pretty sure this will run on a system with 32MB of RAM, and I'm also pretty sure that SDL will quite happily use GDI, so no DirectX required.

Of course, this has been demonstrated to run fine on a 700MHz ARM with 512MB of RAM, but that doesn't run Windows, and we're going to get to that system around about... now.

Raspberry Pi

I did this step first. Made a launcher script, copied the libSDL.so file from my Raspbian install, zipped it up, and once it was all built I tried to run it. Didn't work. Re-ran Pi Store in a terminal, and it was giving me a "./pixra: permission denied" message.

After spending about 5-10 minutes trying to work out where Pi Store actually installs stuff, I decided I would add a "chmod 755 pixra" line to the launcher script. Tried again. Still failed, but this time it gave me an "chmod: pixra: Operation not permitted" which is just chmod's variant of the "permission denied" message.

I then proceeded to make an installer script which simply sets all the permissions to what they should be, and then was forced to work out exactly where to install things. I was considering doing a symlink, but that would be a bit obscure for some people so I decided to just make a "/home/pi/pixra" directory, modify the launcher, and run the program from there.

dirname is a lovely program.

Gave it one more go, this time with the install script. Huzzah! It worked.

Now that my project is marked as "In Progress", the Raspberry Pi Foundation have to check the program to make sure it doesn't contain the skeleton of some family's cat before it actually appears on the store. But if you're impatient, there's always the pixra source code. Just remember to install git and libsdl-devel (or whatever it's called).

Where to from here?

Flood fill.

But before I add that, I should point out that a lack of flood fill is pain, but flood fill without undo is suicide. So undo will be next.

There needs to be a bit more visual feedback when saving. There's a 12px-high section of the screen which is unused, so I could put status messages up there.

An in-app key/mouse reference would be good, too. Kinda like how ImpulseTracker has the F1 menu.

Oh, and finally, I need to use this tool to help me make a game. This means I need to have some ideas...

The inevitable yet undecided game

Here's what I've established so far.
  • It has to be awesome, so people will play my game.
  • It has to be fairly unique, so we don't have people who are already playing something similar refusing to play my game.
  • It has to run well on a Raspberry Pi.
  • It has to have a hotseat multiplayer mode. Not many people have a Raspi, but hotseat multiplayer games make the Raspi great to bring to places and convince people to get a Raspi.
  • It has to have a networked multiplayer mode.
  • It has to have a singleplayer mode. Because you aren't with your friends all the time.
  • It has to be 2D.
  • For nostalgia reasons, it should also be 256-colour w/ an upscaler.
  • It cannot be a 3D voxel game. I'm sick of those, and they won't work well on the Pi. Plus, they're not 2D.
  • It cannot look like a stereotypical indie game. That is, it can't look like someone said "im so 8bit lol" as an excuse to put in minimal effort, it can't use sfxr, and it can't just consist of the many single-colour vector rectangles that I see all the time. (I prefer MS Paint art these days.)
  • It cannot be a typical platformer. Those have been done to death.
  • It cannot be too puzzle-heavy. Those will drive a lot of people away.
  • It cannot be too reaction-heavy. Those will drive a lot of other people away.
  • It has to have a functional demo. This is so people can try it out, see if it works, and hopefully fall in love with me and throw money at me.
  • It has to have a dedicated server, which works with both the demo and the full version, and does not use a GUI.
  • It has to have a server accessible by a menu. This is to make it easier to use at LANs and whatnot.
  • If any DRM is used, it has to be along the lines of how Minecraft does it - that is, auth check on the servers is optional, and the client will still run even if you aren't authenticated. (Might rely on DSFM - Digital Sad Face Management - where if it detects it's unauthed... well, you can guess how this goes.) This is mostly so people can try it out at LAN parties without having to go through some dodgy crack websites.
Anyway, here's my expected toolkit.
  • Code: C, SDL, zlib, ENet, and some .it playroutine called sackit. May chuck in some Lua, too. Who knows.
  • Tools: SchismTracker for music, SunVox for synthesised samples (mostly for said music), Audacity for recorded samples, and of course pixra for graphics. Will probably use some python scripts and ImageMagick to slap all the graphics together.
So give pixra a whirl and let me know what it needs! Just don't tell me to add flood fill - that's coming.

Sunday, 1 June 2014

obligatory welcome post

In order to make it anywhere I'll need a few ways to communicate with everyone and whatnot. OK, let's start with a blog.

So far, fanzyflani is a "group" of... one person who, unfortunately, didn't start this life with five years of commercial experience. Not just any commercial experience, proven commercial experience. So I'm going down the avenue of game development.

With that said, what are my goals? Well, I want to...
  • Get used to a 9-to-5 schedule. Although to be blunt it's been more like 10-to-6. But hey, this is only my third day so far.
  • Learn some discipline. For this I'm staying off Twitter for the time being, because it's really easy to get distracted. (During the work period, that is.)
  • Suss out the New Zealand tax system. Well, OK, that's impossible, but I'm going to have to make enough sense of it to not get stung. Because of this, I can't exactly take on any paid team members unless they're able to help me with this.
  • Learn how to make graphics properly. Coding and music are my strong points. Actually drawing graphics, not so much. But I know how to do graphical effects well enough, so don't you worry about that side of things ;)
  • Get at least one of the Desura clients working on FreeBSD. The Windows one just crashes, and the Linux one is missing a library in my Linux emulation tree so the pages don't draw (ugh). Yes, I am actually developing on FreeBSD. It's better than having to put up with systemd and pulseaudio, and that includes the fact that I have dodgy graphics drivers.
  • Learn how to market things. This will be necessary if I'm going to get anywhere in this industry.
  • Finally, get paid.
So what have I been doing in the past 3 work days (OK, more like 2-and-a-bit)?

Well, I've been making an image editor for the Raspberry Pi. Because, well, have you ever tried using GIMP on that thing? If not, I strongly encourage that you try. (It will teach you patience.)

It's called pixra, which of course is the Lojban word for "picture". It's designed for editing 256-colour images. If you think 256 colours is a huge limitation, well, most "indie" games I've seen have trouble getting close to using 16, and I'm pretty sure Minecraft doesn't quite hit 256 in its textures (or could be adjusted to stay below it), so it's not that hard!

Despite the code being poorly optimised in places, it's actually pretty fast!

Here's the code on GitHub, of course:
https://github.com/fanzyflani/pixra

So far it does these things:
  • Create images
  • Load images
  • Save images
  • Draws with pencil
  • Picks colours from image
  • Edits colours in the palette
  • Selects boxes
  • Fills boxes
  • Shows a grid you can easily define and align
  • Zooms in/out
  • Scrolls
  • Copy/Cut/Paste (transparent or oblique)
  • Automatically scrolls while you draw/zoom and hit the edges. I cannot express how awesome this feature is, and I'm suprised I forgot this point and had to edit it in.
And what it does NOT do, which you might expect from the editor you use:
  • Pops up a main menu when you double-click on it, letting you pick your drawing size and/or filename. At the moment you need to put stuff into the commandline.
  • Undo. (Don't worry, I fully intend to add this.)
  • Edits 15/16/24/32bpp hi-colour/true-colour images. No, you will need a paletted image.
  • Edits images with 32bpp (alpha) palettes. Or anything that isn't a 24bpp palette.
  • Edits anything other than uncompressed .tga. (I intend on there being .png support at some stage, but for now you'll have to convert the .tga files you get with, say, ImageMagick.)
  • Edits more than one image at once.
  • Lets you resize images.
  • Lets you resize the window.
  • Actually uses the system clipboard.
  • Draws any text in the UI whatsoever.
That last point is mostly because I intended to use pixra itself to draw the font. I managed to do exactly that on an actual Raspi, which I've kindly converted to .png here:


You can use that for whatever you want. I'm mostly saying this because it kinda sucks. But it's a font, and that's what matters. (I intend to chuck in lower-case letters later.)

And here's an in-development build: https://dl.dropboxusercontent.com/u/32094129/pixra/pixra-indev1.zip
If the link doesn't work, I'll work something out - Dropbox accidentally flagged SDL.dll as a copyright violation.

Enjoy!