Category: Uncategorized

  • Conceptualizing an Autotiler

    So, you’ve got a tileset you want to use, but you don’t want to manually place every individual tile on the map. Well, that’s where an autotiler comes into play. Simply setup the mapping between the base tileset you want to use, and the autotiler plate, and you’re good to go, right? Until you look at something like this;

    And if you’re not exactly very visually inclined, you might get lost when trying to figure out exactly what you’re looking at, particularly if your tileset wasn’t designed with this sort of setup in mind.

    The key thing to understand is that what you’re looking at is not a tileset, but rather a binary sequence. 0 for no adjacency, 1 for upper left, 2 (10) for upper right, 4 (100) for lower left, and 8 (1000) for lower right. With all the other tiles being a combination of the 4 primary adjacencies. And once this connection is made, then it’s simple to understand the underlying concept of how autotilers work. Essentually, autotilers need two things to work; a tile bitmask ID that’s calculated based on tile adjacencies, and an underlying data array that defines those adjacencies. For the above example, we’ve got a simple 4 bit ID setup, which can work with an underlying binary array. When “filling” a tile, we set the tiles location in the underlying array to 1. Then we calculate each tile’s ID based on that tile’s surrounding values in the underlying array. So a tile with one adjacent ‘1’ in the upper left will use the 0001 (1) bitmask id. directly above would use 0011 (3) as the bitmask ID.

    Binary based adjacencies

    Which is just a simple example of how this can work. But you can make this more complicated; increasing the scope to an 8-bit ID means the system can handle adjacencies in all 8 directions. Or, you can add other values to the bitmask. As an example; (##)(####) – the first two bits are a randomized value, where the last 4 bits are the adjacency ID calculated by the autotiling algorithm. Which results in an algorithm that produces maps with some randomness in the actual tiles present, rather than just re-using the same 16 tile for every situation. or (#)(####)(####) could represent a multi-environment tileset. With the first bit selecting what environment the tile is, and the other two bitmasks tracking adjacency for each of the underlying environments. Which could potentially be useful if you use Blob or Wang tiles to produce tilesets with multiple environments and adjacencies to handle.

  • Simple App

    Source Code: Github
    Language: Java
    Platform: Android Studio

    The simple app project, is basically my platform for learning more about android app development, and java in particular. Currently, the app is just a basic flocking algorithm done in the android environment. I had done some simple app development in college, one of the assignment’s I did was creating a minesweeper game, but I didn’t really get enough time to understand the language that well, and most of the online tutorials only imparted how to, rather than why to. So, through the simple app project, I learned how android development works, and the unique features of the language. Compared to other programs, Android is very encapsulated. Every state is separate from every other state. The menu would not be coded in the same activity as the main gameplay. I was also annoyed, at first, to discover how much threading plays a part in android development. It was something I never had to consider developing for the PC.

  • The Last Light – Senior Capstone

    Group: MindtreeGames

    Site: https://kpwashere.itch.io/the-last-light

    Code Samples: Github

    Language: C++

    Engine: Unreal

     

    The Last Light was my senior capstone project. I joined the MindtreeGames team at the second semester, and was immediately tasked with creating a lighting system for the game. The key gameplay element of The Last Light was having to interact with switches and circuit breakers to power on the lights to various sections of the level. The darkness was the enemy, How the team had been coding this, was to hard code events in the level blueprint to handle when lights should turn on/off. However, as development continued, this would produce a lot of back-end work for the designers and programmers. In addition, Unreal’s blueprint files are largely incompatible with git, or other repositories.My solution was to, utilize a singleton data object to keep track of all the various elements; lights and gates, that could be modified by the breakers/switches. Each object would know what “circuits” it was on, and switches would simply tell the singleton to turn on “circuit 2”, and all the lights on that circuit would come on. However, when I designed the system, I made a rather big blunder. Instead of conceptualizing the registering object as a component, I conceptualized it as another object. This meant that whenever a new element was supposed to be added to the circuit system, I had to invest more time on creating a new object. Instead, like in the code sample, I should have made better use of Unreal’s entity-component system (ECS), and instead have used simple components, instead of new objects.

  • Procedural Dungeon Generation

    Code Link: Github

    Language: C++

    Libraries: SFML and Box2D

    An aspect of programming that I’ve long wanted to experiment with was procedural generation, the act of using an algorithm to produce maps, or other assets, for a game. I believe the simplest form of procedural generation is dungeon map generation. So, for this project, I took inspiration from TinyKeep, a dungeon crawler that used a unique combination of tools to produce it’s dungeon generation. The end goal of the project was to see if I could use a similar method to create an algorithm for the generation a dungeon with different parameters; such as size of the dungeon, desired room size, and number of dead-end corridors. The process I used can be broken down into three steps:

    1. Map randomization
      1. Spawn x number of randomly sized rooms a small distance around (0,0)
      2. Use Box2D physics to randomly spread the rooms, such that none touch.
      3. Remove all unneeded rooms.
    2. Room Connection
      1. Use a spanning tree to determine what rooms should connect, ignoring dead end rooms.
      2. Create corridors between rooms
    3. Finish up
      1. Go back, and connect rooms classified as dead ends, and create a corridor between them and the nearest room/corridor.

    This method worked well. Each dungeon was unique, had a number of dead ends, and there were no real problems. However, the dungeons produced were not very aesthetically pleasing, and sometimes the corridors were a bit odd. However, the biggest problem seems to be the use of procedural generation to produce a “wide” variety of potential results, rather than a small number of consistent results. While the algorithm could be refined, some problems would still remain as a result of it being a general method, rather than specialized.

  • Simple Neural Network

    Code Link: Github

    Code: C++

    Library: Unreal

    One of the aspects of A.I. programming I’ve always found fascinating was the Neural Network. The concept of having a program that learns how to accomplish a task, rather than having it be hard coded, was always interesting one. This project is one done for one of my senior classes at Champlain College. I wanted to experiment with a simplistic neural network, or basically a network with static neurons and connections, that just altered the weights on those connections. The scenario was simple:

    1. Organisms have the ability to move forward/backwards, and move while rotating left/right. (4 output nodes)
    2. Organisms also have the ability to see an object, food or other organisms, in front or to the side of them. (6 input nodes)
    3. Organisms use energy over time, replenish energy by colliding with food objects, and die when energy = 0.
    4. One round consists of 100 organisms being dropped at the same position on a plane, with food randomly spawning around them.
    5. Each organism is then weighted by an evolution algorithm, based on how long it lived. The longer it lived, the more likely it is to contribute for the next simulation.

    Overall, the neural network does work. Over time, organisms become better able to discover the fastest way to find food. There are some areas that could be improved upon. First, having a single generation spawn at the same time is not the best method for accurate results, as slower organisms may be able to survive due to luck, faster organisms will survive due to fitness, but organisms in the middle may fail because their food is stolen first. I originally chose this method because it was better for presenting with a small amount of time, as more generations could be processed during a presentation.