Our project goal was to create an improved user interface with the Redhawk Duels game. Readhawk Duels is a game programed onto the FPGA on Alteras DE2 board. It consists of two players who control space ships inside an arena 320 by 240 units. Each player is given a ship that is 10 by 10 units, contains a laser cannon and a laser sensor. Players start the game in opposite corners of the arena. The sensor is used to detect the arena walls and the enemy ship. If you run into a wall with your ship, your ship resets to its starting location. The goal of the game is to shoot the other player with the laser cannon on your ship and thereby reduce their available power. At the same time you want to avoid being shot and maximize your available power. To maximize your available power you have a crystal array which you can rewire to increase power output. The crystal consists of eight nodes, labeled A through H, each of which can connect to every other node. To create a valid crystal setup you must start at node A and go through every other node only once and end back at node A. Each connection between nodes has a randomly generated power value between three and ten. Your current power is calculated by the addition of the path powers through the selected nodes. If you have an invalid crystal setup your total power will be zero.
The game is run by a master board that computes and sends data to the player's DE2 boards. The master board sends limited data to the players. This data includes the x and y location of the ship, what your sensor is detecting and the crystal array powers. Unavailable to you are the enemy ship's location, if you shot them, or where your ship/cannon/sensor is facing. This lack of information requires you to calculate missing data based on starting parameters. The player sends back data including: the power crystal path, ship movement, sensor rate and movement, cannon strength and fire state, and player number.
To give us more control over and information about our ship we planned to create a keyboard interface to more easily and quickly control our ship. We also planned to create an interface with a VGA monitor to display the power crystal configuration to better optimize our ship's power generation. Finally we planned to create an algorithm to track and automatically target our opponent’s ship. If time allowed we also planned to display the arena, our position and our opponent's last known position on the VGA display.
Our final design, which we used to compete against our classmates, included: a keyboard controller, VGA interface, an improved crystal array wire system and modules - to keep track of our ship angle and sensor angle, calculate our total power and available power, our optimal power and optimal crystal path, keep track of time, and record the enemy ship contact angle.
The first step in our design was to interface a PS2 keyboard with the DE2 board. To accomplish this we used John Loomis' ps2lab1 project as a base. Loomis' code provides an ability to read the scan codes the keyboard outputs when the user presses or releases a key and displayes them on the seven segment display. To adapt Loomis' code to our needs we removed the seven segment display and created a state machine to detect if a key was pressed or released. When the user pressed one of the keys we used in our design the PS2 controller module would output a value which was then sent to the games master. We used the W key for acceleration, A for turn left, D to turn right, space to fire, and number keys, one through eight, to control the rate at which our sensor moved. We encountered timing problems with Loomis' code which plagued us throughout the project and which we were unable to resolve. The timing issues caused our keyboard to randomly stop working throughout testing and competition.
Our next step was to interface the VGA display with the DE2. We again used code from John Loomis, in this case we used his vgalab2 project. We also tested the VGA controller found in Mark Stratis' 2D Convolution project but found that it did not meet our needs. To display text on the VGA screen we used the megafunction called sysfont which creates a memory containing a character map. This function and the method for using it was included in Loomis' code but took a lot of time to figure out. Loomis' VGA interface module outputs the X,Y location of the pixel it is currently displaying and takes inputs which indicate the color that pixel should be. Our display module is in essence one huge if-else statement which decides if we want a pixel "on" based on its X, Y location. We used the VGA screen to display the location of our ship in the arena, the boundaries of the arena, the path power between nodes, the angle of our ship and sensor (zero degrees being up on the screen), a 60 second clock, the rate of movement of our sensor, the enemy contact angle, the total power and available power, optimal power and optimal path. We also made the sensor angle value turn red if our sensor detected a ship and the boundaries of the arena red if our sensor detected them.
In order to keep track of our ship and sensor angles we created two modules to calculate and store the two angles. The two modules were virtually identical, except that one kept track of sensor angle and the other the ship angle. The modules consisted of a state machine which would set the angles to their initial values (depending on what player we were), wait until the appropriate key on the keyboard was pressed and our board sent the fact that we wanted to turn (the ship or sensor) and then increment or decrement the angle. We verified that the data had been sent to the game controller by checking if the state machine in the Ethernet module was in one of the "sending data" states. This check was necessary to insure that our angle values did not increment faster than our ship or sensor turned on the game controller. Through testing these modules with the game controller we discovered that we needed our angle values to reset to their initial values when we ran into a wall or the other ship and our ship was reset. We did this by creating a module which consisted of a state machine which checked if our last X, Y coordinates were the same as those of our starting position. If our last coordinates were not the starting position and our current coordinates were, then the module would output a reset signal to the sensor and ship angle modules. We later added to this by storing the last angle of the enemy ship that the sensor contacted. We set it up as multiple registers so that a new angle was stored in the contact angle1 and the previous angle1 would move to 2 and 2 to 3. This gave us a generalized idea of the last location of the enemy ship. A problem occurred since we got false positives and there were timing issues. The timing issues made it so that it was told to store the second it made contact but the next second it stored whatever angle we were currently at.
Because your ship's available power updates on the game controller every minute it was necessary to create a clock which showed the number of seconds since the last minute. This clock would reset every time it reached 60. The module which generated this clock consisted of a combinational block which would increment the clock every 50,000,000 cycles of the DE2's internal 50 MHz clock. We found that it was also necessary to sync our clock to game controllers clock. We did this by checking when the X, Y coordinates of our ship, which the game controller outputs, became non-zero.
We wrote a module that calculated the total power through our selected crystal paths. A state machine was used to accomplish this. First an array that indexed every possible path was created to hold that power for the conditions to reference to. In the first state it would see which node was the first node and store the power from A to that node then the following states would check what the last node was and what the current node is to store the power for that state. On the last state it checked what the last node was and stored the power from that node to A. Then it added them all up and sent out the value to the VGA module. Another module was made to calculate the power. This power would change during a battle so that the user would know what the current available power was. It did this by storing the calculated total power and subtracted the amount for each cannon fired according to the strength. It also subtracted one for every second that you held down the forward key. When the timer module reset to two the power would reset to the maximum power. This module had timing issues and would not always work when calculating after a shot was fired. This was because it didn't take into account that the shots were delayed after the previous shot.
After we had implemented all of the elements of our design discussed above we moved on to creating an algorithm to find the optimal path through the crystal array. We collaborated with Robert Cole on this part of the project. He had an idea for how to find the optimal path so we set about writing the Verilog for it. However for some reason we could not get our code to work properly even though it was virtually identical to Bob's code which did work. In the end Bob gave us his code and we modified it to work with our design.
To make it easier and faster to change the power crystal path we constructed a improved bread board with switches. It was set up to have 56 switches that represent every possible path between nodes. It progresses from A to H, from top to bottom. In addition to this new crystal array we added a display that tells the user the exact switches to flip to get the optimal power. It displays the switch bank number and then the number of the switch in that bank. So that the switches could be found faster the switch banks were labeled on the bread board. We also attempted to use a UP2 to automatically change the crystal array path to the optimal path. This partially worked in that it did output a path that was valid but it was not the optimal path. Because of the time constraints we were not able to get full functionality.
Our improvement to the design made the game easier and more user friendly. The PS2 keyboard allowed the player to use only one hand (without looking) to steer the ship and shoot the cannon so that his eyes could be on the screen. The VGA interface provided the user with all necessary data. Thus they could see where the ship was, when to shoot, if the ship was shot (path powers changed), what the power was at and how to setup the bread board to get optimal power. The improved crystal array allowed the user to quickly make changes to the power so optimal power was always ready.
Many components could have been improved if time permitted. We would have liked to fix the timing issues with the keyboard module. Also the screen desigin could have been re-worked to make it more user friendly, by telling the user when their ship was shot and removing unnecessary information. Another good addition to or design would be an auto tracking or AI type module to fly the ship for you. We would also have liked to get the atomatic power crystal rewireing system on the UP2 board working and fix the available power calculator.
Our project was to design and construct an improved interface to play a simulated space battle with little input from the master board. We used existing code to create a working keyboard controller. We also used existing code to help us display useful game information on a VGA display. We created our own modules to help calculate important information including total power and the ship's angle. We constructed an improved bread board and displayed necessary information to use that board with the game. Some of our code had errors or didn't work properly but the necessary modules worked to our needs. Overall we had a successful demonstration and we were able to achieve most of what we wanted.