Today I created, from scratch, a new website (http://www.pastsnap.com/). It crawls puu.sh and retrieves some of the latest images that people are sharing (public only, of course). It's basically like 4chan's /b/, but with: less gore, less comments, more images, more interesting stuff. Check it out if you'd like, but remember: due to the nature of the site, it can very well be NSFW (Not Safe For Work) from time to time.

Edit: Now has Infinite scrolling! Still need to add adult filter.
More
You can now place blocks by clicking and dragging the mouse, sort of like in Paint, except instead of pixels you draw with blocks. You can only place "dirt blocks" for now until I finish the GUI for block placement.



You may also notice a few changes to the game loading. I moved a lot of loading from being up front to "when requested." This is known as lazy loading, and you should see a pretty drastic improvement in startup time. There's a bit more of a pause than I'd like when logging into the game because of this, and I'm trying to come up with an equitable solution for this. I'm thinking about simply stretching the loading across a number of frames, but we'll see how it goes.

You may notice that you can only place blocks close to your character. This is intentional. As you level up in mining, you will gradually be able to place blocks farther away from your character.

What's coming next? Specific "mining" of blocks. It's intertwined with block placement, and works the exact same way. The only difference is that you'll click on a block other than air to begin.

Note: If you're crafty and decide to use a packet editor, you can skip the wait for placing different blocks by changing the item ID in the "block placement" packet to something other than a dirt block. You will still need to actually have the block that you're trying to place in your inventory, though. This isn't an exploit, I just haven't gotten around to adding it to the client yet.
More
Not too much to talk about with this update. Below are the patch notes:


  • Clouds now move in the login and registration screens.
  • Added a title to the login and registration screens.
  • Bunnies have eaten many a fallen hero, and are now much larger and fatter.
  • Monsters should be more prone to kicking your butt (more monster spawns).
  • Monsters will now go after the player with the highest aggro instead of the least.
More
I added a revive frame, so you can now revive when you die! Yay!

In other news, I adjusted the experience received from being hit by monsters and I fixed some bugs related to monsters.

Monsters should no longer hang around without despawning when a player logs out or goes offline.

When a monster is deleted from the server without being killed by a player, the server should now properly tell the client about the monster ceasing to be.
More
Monsters have been finished, and are now fully implemented in the game. The AI is pretty stupid right now, but it'll still kick your butt. When you die (when -- not if), you'll have to reload the page to revive. I'll add a little box that pops up (WoW style) for reviving soon.

More
The next version of the game that will be going live will have... shadows! Yay!


I actually managed to do this without any noticeable change in loading times (ha!) for chunks. Slick has this really neat thing that lets you pass a "filter" color when rendering an image, like a block. The filter is perfect for things like rendering underwater, rendering special glow effects, and rendering shadows. I stumbled upon it out of necessity today when my previous implementation was too slow.

On another note, can anyone tell me what algorithm this is? I'm not naive enough to believe I was the first to come up with this. It's what I use for rendering the shadows:
Code:

    /**
    * A recursive helper for the relaxation algorithm.
    * Note:  There is an optimization available.  We don't need to check the direction
    * that we're coming from.
    * @param superLightMatrix
    * @param x
    * @param y
    */
    private void relaxLightMatrixHelper(int [][]superLightMatrix, int x, int y) {
        // Correct top
        if (y > 0 && superLightMatrix[x][y-1] > superLightMatrix[x][y] + 1) {
            superLightMatrix[x][y-1] = superLightMatrix[x][y] + 1;
            relaxLightMatrixHelper(superLightMatrix, x, y-1);
        }
       
        // Correct bottom
        if (y + 1 < superLightMatrix[x].length && superLightMatrix[x][y+1] > superLightMatrix[x][y] + 1) {
            superLightMatrix[x][y+1] = superLightMatrix[x][y] + 1;
            relaxLightMatrixHelper(superLightMatrix, x, y+1);
        }
       
        // Correct left
        if (x > 0 && superLightMatrix[x-1][y] > superLightMatrix[x][y] + 1) {
            superLightMatrix[x-1][y] = superLightMatrix[x][y] + 1;
            relaxLightMatrixHelper(superLightMatrix, x-1, y);
        }
    }
   
    private void relaxLightMatrix(int [][]superLightMatrix, int x, int y) {
        // Do special case
        for (int i=y; i > 0 && superLightMatrix[x][i-1] > superLightMatrix[x][i] + 1; --i) {
            superLightMatrix[x][i-1] = superLightMatrix[x][i] + 1;
        }
        // Recursively correct top, bottom, and left after moving left
        if (x > 0 && superLightMatrix[x-1][y] > superLightMatrix[x][y] + 1) {
            superLightMatrix[x-1][y] = superLightMatrix[x][y] + 1;
            relaxLightMatrixHelper(superLightMatrix, x-1, y);
        }
    }
   
    /**
    * Populates the light matrix with my own algorithm.  (Does it have a name?)
    * Is this the best way to do it?
    */
    private void populateLightMatrix() {
        final int depth = WorldConstants.WORLD_BLOCK_SHADOW_DEPTH; // The max depth that light penetrates.
        final int chunkWidth = WorldConstants.WORLD_CHUNK_WIDTH;
        final int chunkHeight = WorldConstants.WORLD_CHUNK_HEIGHT;
        int [][]superLightMatrix = new int[chunkWidth + depth * 2 - 2][chunkHeight + depth * 2 - 2];
        TerrainSession ts = Game.getInstance().getClient().getTerrainSession();
        final long baseX = getX() * WorldConstants.WORLD_CHUNK_WIDTH;
        final long baseY = getY() * WorldConstants.WORLD_CHUNK_HEIGHT;
       
        for (int x=0; x < superLightMatrix.length; ++x) {
            for (int y=0; y < superLightMatrix[x].length; ++y) {
                Block b = ts.getBlock(new BoundLocation(baseX + x - depth + 1, baseY + y - depth + 1), false);
                if (b != null && !b.isCollidable()) { // Light source
                    relaxLightMatrix(superLightMatrix, x, y);
                } else { // Not a light source
                    superLightMatrix[x][y] = y > 0 && superLightMatrix[x][y-1] < depth-1 ?
                            superLightMatrix[x][y-1] + 1 : depth;
                    if (x > 0 && superLightMatrix[x-1][y] < superLightMatrix[x][y]-1) {
                        superLightMatrix[x][y] = superLightMatrix[x-1][y] + 1;
                    }
                }
            }
        }
        // Copy from the super matrix
        for (int i=0; i < lightMatrix.length; ++i) {
            for (int j=0; j < lightMatrix.length; ++j) {
                lightMatrix[i][j] = superLightMatrix[i + depth - 1][j + depth - 1];
            }
        }
    }

Note: I am certainly aware that this method could be improved by keeping track of the source of the light when relaxing the light matrix and then calculating with the hypotenuse instead of just doing +1 and -1. I might do this later, because it makes a big difference on looks (you'll get what you see in the screenshot above) without any change in O-complexity.
More
After a lot of work, I have finished most of the stuff needed for monsters. This includes adding monsters to my resource editor so I can create new monsters easily, writing all of the networking code needed for monsters, and creating a bunch of monster-related classes.

So what's left before monsters are fully finished?
  • Add collision detection for player attacks to monsters (easy to do -- just need to do the same stuff I'm already doing for PvP)
  • Add monster AI (hopefully easy to do)
  • Clean up a bit of stuff, and add animations to my resource editor


I expect to have this finished within a few days. Hopefully I actually get it finished this time instead of procrastinating a few more months! Once I get this part of the code behind me, I'll be able to breathe a sigh of relief. The rest of the code is very easy to write for me. Well, except for water and... okay, so there are still a few more complicated tasks to do! However, I doubt they compare to monsters.

Here's a teaser:

More
It's been a long time without much update or progress. However, I'm back once again to work on MeleeCraft.

This time I've implemented character saving and server configuration files. The configuration files are behind the scenes, and you'll never actually see them. They just tell the server some important stuff that could change depending on where it's being hosted.

What does this mean for end users? It means that you can now register, and keep your stats after you log out. No more wasted mining experience!



In other news, your HP will now slowly restore over time. You still can't revive from death, though. So... don't die. I swear I'll get this added soon(TM)!
More
The loot frame is now fully functional. It displays items "MapleStory-style" in the bottom-right corner of the screen. Items are color-coded by rarity, and the quantity is also color-coded and abbreviated for quantities over 99,999.

I also added notifications in the chat box for when you level up in a skill.


More
Today I switched to a server based in the United States. Notice the latency in the below pic. It's about 3x faster (at my location). This is good news for people based in the US and Canada, but not so much for people in the Netherlands or on the other side of the world. ;)

On another note, I've been working on some important bug fixes as well as mining experience! You can now level your mining by breaking blocks, which now have more than 1 HP each. You will have to hit blocks several times to break them. The higher your mining level, the easier it is to break blocks (you'll see a pretty noticeable increase in your block damage).

More