About Andromeda 3000

Andromeda 3000
Toolset: Love2D/Lua
Concept: Andromeda 3000 is a prototype proof-of-concept single-player side-scrolling shooter built from a basic Lua-based shooter framework with the goal of increasing my proficiency in Lua, in coding as a whole, and as a matter of design curiosity. The features I created range from the simple such as adding a mouse-controlled turret to the base ship to the complex such as setting up a hierarchical animation system to handle basic animation. Of the various features I developed, the one I most enjoyed is an attribute-driven weapon framework which allows for easily expandable and customizable weapons.

Key Features:

  • Scripted a mouse-controlled turret weapon
  • Implemented 2D grid that deformed in real-time
  • Created simple scoring system with leaderboard
  • Differentiated ships through movement capabilities and health/lives balancing
  • Developed hierarchical animation system to handle various additional features and visual effects
  • Developed attribute-driven weapon framework for extensive weapon modularity usable with both forward firing and turret weapons

Mix-And-Match Gameplay with Data-Driven Attributes

I implemented a data-driven framework for weapons in order to ease development. Rather than explicitly scripting weapon behavior, weapons reference attributes within the framework and combine them to create the desired behavior. The result is faster iteration time and the potential for unique but otherwise difficult to implement mechanics.

Simply by changing the weapon type and the spread type, we can turn the Gatling Pod into a Sine Wave laser.

Sine Wave Laser

Setting wpType = 'missile', num = 6, spread = 6, and a few other attribute changes allows us to change the Sine Wave laser into a cluster of Micro Missiles.

…to Micro Missiles

For instance, creating a new weapon that fires bullets at a high rate of fire but with low accuracy, high spread looks like:
{
name = "Gatling Pod",
wpType = "projectile",
rateOfFire = 0.02,
speed = 800,
cost = 4,
damage = 0.15,

drawScale = 0.5,
spread = 8,
inaccuracy = 64
}

Changing wpType = "projectile" to wpType = "laser" along with changing spread = 8 to spread = "sine" modifies the weapon to consume laser ammo and shoot in a sine wave pattern while leaving the other attributes identical. Likewise, adding drop = 20 and num = 6 to the weapon causes six lasers to fire per shot with all six lasers having some initial downward movement. Furthermore, as the weapons are simply a set of characteristics, they work with both the static forward firing weapon and rotating turret.

Planning for Differing Ship Capabilities

Ships with different characteristics was a future feature I wanted to support. This meant having enough distinguishing features and characteristics on ships for each to feel unique. More overt additions included a mouse-controlled secondary weapon system with adjustable characteristics and the use of a physics-based movement system. A more invisible change was an algorithm that automatically balanced a ship’s health against it’s starting and current number of lives. The more lives a ship began with, the less health each life had and the more life a ship lost when it died. This would allow balancing of ships to be tougher per life at the expense of less room for poor overall play and vice versa.

Hierarchical Animation

I was interested in providing extensive player feedback and that included animation-based feedback. Given the scope of the project, hand animating every action was impractical. In place of hand animation, I set up a simple hierarchical animation system and drove animations through simple linear interpolation between data points. The end result was basic animation for an array of player activity including movement in any direction and spawning.

Real-time Deformation of a 2D Grid

As an exploratory exercise in the project, I created a 2d grid overlay which deforms in real-time. Given a point’s distance from the player’s position and their current shield strength, the algorithm adjusts the offset from a rest point for each point in the grid.