[done!] MEG4kMAN, Mega Man in 4kb

Tomorrow I go to cuba for two weeks. I’m bringing my brand new Eee 901 to possibly get some coding done on the flight… and I’m working on this:

MEG4kMAN, an extremely tiny version of Mega Man.
It’s 1612 bytes so far, and that includes a spectrum graphics like renderer with a single 8x8 1 bit bitmap per tile, with a 5 bit color (r, g, b, intensity, x flip) per tile.

Here’s the raw sheet before processing:

http://www.mojang.com/notch/j4k/meg4kman/sheet.png

Updated, and almost playable!

http://www.mojang.com/notch/j4k/meg4kman/screenie.gif

Just needs some health pickups, a death/game over animation and some more screens. :smiley:

Seriously? … I just wrote I thought about entering. Now that I see this, - maybe not :stuck_out_tongue:

!

We’re just not bloody worthy.

Cas :slight_smile:

On the first screen if you die while holding the jump key you end up jumping through the top of the screen when you spawn. Here’s the exception.

Exception in thread "Thread-10" java.lang.StringIndexOutOfBoundsException: String index out of range: -300
	at java.lang.String.charAt(Unknown Source)
	at S.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

I got the same error.

Exception in thread "Thread-10" java.lang.StringIndexOutOfBoundsException: String index out of range: -300
	at java.lang.String.charAt(Unknown Source)
	at S.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

What is this, can’t you make proper games? :wink: … joking

Wow… just wow… hm… and WOW!

Never played the original or any of its variants so can’t comment on the authenticity, but it looks good =>

bah, completed it in like 30 seconds ::slight_smile:

seriously - very nice job!!!

Awesome!!!

As a rockman fan I am impressed, you even added 4 different enemies with the right logic.

I’ll wait for the final version.

Exception in thread “Thread-7” java.lang.StringIndexOutOfBoundsException: String index out of range: -300
at java.lang.String.charAt(Unknown Source)
at S.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Very impressive, but short. How much space does a screen take you? If it’s a lot you could use some procedural levels to cut size and make it a lot longer.

If you’re interested in trying that, the obvious algorithm is to just make a row of platforms at random heights, with none raising higher than the character can jump. This can be done in a really simple loop (for x, if x > width: width+=random, for y, if y > height: fill) so it should be pretty small. Put an enemy every few platforms and whatnot. But that’s the most boring algorithm you could use, as well.

I feel that your most interesting screens are the 2nd and 3rd ones. There’s an old roguelike algorithm that you should be able to modify to come up with something like these. In it, you divide the screen randomly, adding a door between the halves, then divide the halves each randomly, adding a door, and so forth. I’m not sure how you’d modify this to be non-recursive, mind you, so fitting it in the space could be tough.

Either way, this is a very impressive game. Great job!

Right now, the game is at just over 3kb, and each screen I add is another 300 bytes of raw data that seems to compress down to about 30 bytes per screen. With some additional trickery, I should be able to get the levels down to about 90 raw bytes per screen, but I’m not sure that would compress any better.
I figure I can get about 30 screens of hard coded levels in there. I’m shooting for a Mega Man 9 type experience where the game is bloody hard but speed run friendly.

Since I’m going pretty much the opposite direction of my normal design here (no procedural content, and making a demake of an existing game), I’m tempted not to do any randomly generated levels in this one. =D

Highest priority right now is adding a satisfying death animation in as few bytes as possible. Any ideas?

Some more details:

The graphics are 1 bit per pixel graphics, made up of 8x8 pixel blocks that each have a color (0-15, think EGA) and a x flip bit. Each 8x8 pixel chunk of graphics takes up 8 bytes of raw data, and the sprite sheet is 9x7 tiles, for a total of 504 bytes of raw data (not counting extra bytes used in UTF-8 encoding).

Whenever you leave a screen to the right or down, you move to the next screen, whenever you leave up or left, you move to the previous. That’s why it crashes when you jump after dying (I need to remember to set onGround to false), it tries to change to screen -1.

Each tile in a level contains 2x2 tiles of graphics, and the mega man character is usually 3x4 tiles of graphics (more when jumping or hurt).

Shift (on Kongregate, in the Puzzles section) has a death animation which wouldn’t take many bytes, but it doesn’t really fit your graphical style.

[quote](not counting extra bytes used in UTF-8 encoding).
[/quote]
perhaps you would make a decent space saving by directly embedding the byte data into the class file as an Attribute post proguard/etc optimisation?

It had saved me a significant amount of space with my 2007 entry SubPar.

you can use the undocumented "-addData " of the 4KJO tool’s command line options to insert the data file into the class file. Have a look at the source of my entry as to how i read in the embedded data. (My data did have a unique magic number sequence at the beginning of two bytes equal to “||”.

Will that work in an applet as well?

hmm… dont see why not… the class file is just another resource from the JAR.

Mookie, did you compare doing it that way with just having the file as a separate entry in the .jar? I find it slightly surprising that the extra bytes required to put “a.class” in the constant pool (vs using “a”, which is already in the constant pool), skip past everything you don’t want, and label the attribute don’t more than cancel out the extra bytes required for a second zip entry.

I found in my Kart game that it took up less space to insert the data in a string than to inject it.

My data though was a delta encoded bitmap, with the deltas starting from 1 (not 0) so that the string encoding was as efficient as the data injection.

The major space saving was in not having to scan through the class file to extract the data.

For my game i compared it against a separate entry in the JAR and against encoding the data in a string.

It saved about 80 bytes if i recall correctly when compared against a separate entry.

Of course may not give benefit with different circumstances. :slight_smile: