Showing posts with label Engine. Show all posts
Showing posts with label Engine. Show all posts

Tuesday, July 3, 2012

Windows Console Game: AsciiEngine

I've been creating a series of posts about creating a Window's console game from scratch in C. This post will act as a culmination of many different posts throughout my blog in the form of an open source game engine called AsciiEngine.

AsciiEngine is a game engine for Windows XP, Vista, and Win7 that allows the user to easily create and display images within a Windows console. The engine also automates the tedious task of customizing aspects of the console, such as a font or palette color.

Here's the link for AsciiEngine (visual studio 2010 project + source files): LINK


Man with sword!

Screenshot from older included demo~~

By using AsciiEngine, users can easily construct interactive programs (games!) without the overhead of setting up all of the various system components required to run a game within the Windows console.


Screenshot of the old AsciiEngine demo. Pressing enter pastes
sun images onto random locations.

AsciiEngine is documented heavily in-code and is open source - I want anyone willing to be able to learn from the example code provided.

Features include:
  • Complete game loop
    • Game loop integrated into Game State Manager via function pointers
  • Game State Manager
    • Allows for easy management/creation/deletion of game states
  • Functioning framerate controller
    • Allows the setting of framerate with a #define macro
    • Prevents large timesteps from passing through the program with a cap
  • Various console related functions for easy customization of the console window
  • Complete graphics functions set for drawing 2D images
  • Input template complete for simple keystroke detection and mouse event handling
  • Complete and very simple PRNG
  • Simple image format that allows for variable size
  • Integrated hash table for storing images
    • Allows for an optimized lookup, e.g.: TableLookup( "ImageName" )
    • Extremely simple creation/deletion of images
  • Implementation of my simple 2D collision library
  • Implementation of my simple 2D vector library
  • Highly organised object manager using the factory pattern
    • Allows for easy creation/handling/deletion of game objects
    • Incredibly simple to create new object types
  • Implemented my Tile mapping -- Binary Collision library
  • Image editor
  • file output
  • Automatic image file loading and parsing
  • Messaging system Object to object + global messaging system
  • Component base game object system (now renamed to game entity)
  • New button class for easy UI creation
  • Integration of generic Hash Table and Linked Lists
  • Simple serialization and deserialization support.

Here's the link for AsciiEngine (visual studio 2010 project + source files): LINK

Now hopefully I can see some console games created with true Ascii art! Please let me know if anyone creates a console game, or uses AsciiEngine to create a console game. I would be thrilled to see some projects from other people, as I just love Ascii art games, especially ones within the Windows console.

Series on creating a Windows Console game:
How to use AsciiEngine:
Using AsciiEngine is very easy. It's available here on github.

Almost all code creation you'll do with AsciiEngine will be in creating/modifying game state files. Since AsciiEngine uses a GameStateManager (GSM) you'll have to create your own states. More information about what a GSM can be found here. Creating a state is as easy as copy/paste from the example state within the download archive of AsciiEngine. Integrating a new state into the GSM should be straightforward if you examine the currently existing code.

Once a state is created all that is left to do for the user is to simply write code within the state! Almost all code written will be within the Update function. During the Update function all game logic will occur. Drawing specific functions should occur only with the stat's Draw function - this allows for easy implementation of the Painter's Algorithm.


To switch states there are three global variables within the GameStateManager.c file. These are nextState, currentState and previousState. In order to switch states simply change nextState to the desired state to switch to. The main loop will then call the Unload and Free function automatically of the current state you are in, and then load and initialize the next state automatically as well.

Creation of Game Objects can be handled any way by the user, I've written documentation on a very simple way of creating and handling Game Objects here, and it works extremely well with the GSM organization throughout AsciiEngine. I've implemented my own method of handling objects with the Factory pattern! Using the ObjectFactory within AsciiEngine it's very easy to handle game objects, as well as create new ones. See code for documentation -- it should mostly be copy/paste to create a new object. UPDATE: Game objects are now called Game Entities. As such, all game entities are now component based! Please see the source on github for details. A post in the future about component-based architecture will likely be written.


Creating Images:
Creating images in Ascii art will require a good tool for more complicated images. Here's an interesting thread on a few different programs for such. Perhaps it might be a good idea to create your own tool in the Windows console with AsciiEngine! Here's some additional documentation to pursue the idea of creating your own drawing tool: link.

Updating AsciiEngine
I'm completely open to most all suggestions on AsciiEngine. I've never written anything open-source before, so there may be good insight that'd help the project out! Feel free to contact me about questions on how to use AsciiEngine, or for feature requests, or just to talk/show off thing you've made :)

Wednesday, February 22, 2012

Basic 2D Vector Physics: Acceleration, Orientation and Friction

This post aims at covering the basics of 2D vector physics, that of which can be used in application to create something like this Asteroids project for my CS230 class.



The simplest way I know of to move an image across the screen over time is by using a static velocity and apply it to the the position of an image every time-step:

pos += vel * dt;

dt should be calculated every frame loop and passed to this equation, this way your displacement will be time-based instead of frame-based. To calculate dt you can use the following flowchart:




In order to have variable velocity you can apply the same idea from our displacement (position) equation. To change velocity over time and have acceleration and deceleration you can use:

vel += accel * dt;

Pretty simple! However in order to apply this in programming you'll break up the x and y velocities into separate values like so:

pos.x += vel.x * dt;
pos.yx += vel.y * dt;
vel.x += accel.x * dt;
vel.y += accel.y * dt;

Now what about turning, and a sense of orientation? It's no use if your object can only go in a single line, which is all the above equations will support if implemented alone. Your object should have a data member to hold it's orientation in radians. If you don't really have a mental grasp of radians, that's fine. Take a look at the unit circle: link. In order to know the value of any given 2D direction relative to a standard axis (x and y plane not rotated or anything) just look on the graph in that direction. For example straight upward in radians is pi / 2. Straight downwards is 3 * pi / 2. Very simple. The unit circle is just a way of representing directions as a value. The range of this value is 0 through 2 * pi.

You can initialize your object's direction value with a preset or randomized value within the range of zero through 2 * pi. However it's easier to implement calculations in 2D if you set your range of values to pi to -pi (see below psuedo code for reason why). This means, for example, a full 360 degree angle is represented by either zero or -pi. The downward direction, for example, would be -pi / 2. Once you have this set up, you can easily use this radians orientation value to find a direction vector for your object. A direction vector is a vector whose length is 1, which allows you as a programmer to multiply it by a value and easily get a vector in a specific direction of a specific length.

For example say your object has an x velocity of 6 and  y velocity of 10. Every timestep you'll move by a factor of 6 to the right and up by 10. This is all good, and the distance the ship will cover can be found with the Pythagorean theorem: sqrt( 6^2 + 10^2 ). But, what if you want the ship to move 5 units in a direction per timestep? What if you want to be able to easily move your object around in any direction by 5 units per timestep? This is going to be pretty difficult without doing what's called normalization. Normalizing a vector is the process of taking a direction vector, like (6, 10) and generating a vector that points in the exact same direction, whose value is equal to 1.

If you are able to find a direction vector of the direction your object is going, you can easily multiply the x and y components by 5, and achieve your goal. If your direction vector is derived from your radians orientation (like I said we'd do), then you can get the direction vector no matter what direction you are going, all the while you can modify your orientation value however you like! In order to get your normalized direction vector from your angle of orientation, just use:

dirVect.x = cos( radianOrientation );
dirVect.y = sin( radianOrientation );

You now know all the necessary ideas needed to implement some simple 2D vector physics! You can rotate your object's orientation with addition/subtraction on your radians value, and then move your ship according to the angle of orientation by a specific velocity value, all the while updating your velocity with a constant acceleration value.

Here's a (psuedo) code example:

// Find current direction vector
dirVect.x = cos( radianOrientation );
dirVect.y = sin( radianOrientation );

// Apply forward acceleration
if(keypress( UP ))

  vel.x += ACCELERATION_FORWARD * dirVect.x * dt;
  vel.y += ACCELERATION_FORWARD * dirVect.y * dt;
  // Simulate friction
  vel.x *= .99
  vel.y *= .99


// Apply backward acceleration (negative forward)
if(keypress( DOWN ))
  vel.x += ACCELERATION_BACKWARD * dirVect.x * dt;
  vel.y += ACCELERATION_BACKWARD * dirVect.y * dt;

  // Simulate friction
  vel.x *= .99
  vel.y *= .99


// Add a value scaled by dt to rotate orientation
if(keypress( LEFT ))
  radianOrientation += ROTATION_SPEED * dt;
  // Bound checking for pi and -pi
  if radianOrientation > PI

    radianOrientation = -PI
  else if radianOrientation < -PI
    radianOrientation = PI


// Subtract a value scaled by dt to rotate orientation
if(keypress( RIGHT ))
  radianOrientation -= ROTATION_SPEED * dt;
  // Bound checking for pi and -pi
  if radianOrientation > PI
    radianOrientation = -PI
  else if radianOrientation < -PI
    radianOrientation = PI


// Update position with our new calculated values
pos.x += vel.x * dt
pos.y += vel.y * dt

Another thing to try to explain is the reason for the range of pi to -pi. Using a range of pi to -pi allows for easy calculations because it makes the lower half of the unit circle negative, which means you can directly apply resulting values from sin and cos onto your velocity/displacement, and move your image in all four directions (up, down, left, and right).

Now, what if you need to solve for the angle between two points? This could be useful for homing missiles, or AI. Knowing the angle between an enemy and the player, for instance, could be used to let the enemy know which direction to go from there. In order to solve for the angle between two points I used atan2:

angle = atan2( player.y - enemy.y, player.x - enemy.x )

This lets me find the angle between two points, namely between an enemy object and the player. You can then use this result and compare it with the angle of orientation of the enemy in order to deduce of the enemy should turn clockwise or counterclockwise, or anything else you'd want!

You may have noticed those lines that multiply the velocity by .99 after the update calculation was made. This actually simulates friction. The higher the velocity gets the greater the reduction per timestep! This will allow your object to accelerate slower the faster it goes, until it reaches an equilibrium. It should also seem to float friction-less at slower speeds. You can use a larger or smaller value for different amounts of simulated friction.

And there you have it -all the essential concepts required to implement a game using simple 2D vector physics!