© Fan Yang © Chang Su © Ziwen Wang
Warning: The use of this program for Academic Plagiarism will be severely condemned. However, we encourage you to borrow ideas and use them in your final project
Dad ‘n Me is a fighting game from Newgrounds released in 2005. It was originally a game based on computer, and we plant the game into FPGA. We copy the photos from the original game and deal them with algorithms, which will be introduced behind detailedly, to reduce their size considering the memory limitation of FPGA. The algorithms allow us set more photos , in both quality and quantity, including the stickers and the backgrounds to make the game more vivid and interesting. And the logic of the game is totally coded by ourselves, we play the game then know how the game is constructed, and try to realized it by FPGA.
When demoing, we manage to achieve mosts of functioanlities of the original game. We can control the character by W, A ,S, D to have it move upwards, leftwards, downwards and rightwards. The character is live with a “shaking body” rather than a sticked photo, and it will change direction depends on the direction of movement. There are two normal enemies moving randomly in the whole map with a blood bar having no ability to attack and a boss chasing our character based on the relative direction of it and our character with the ability to fight. Similar to the character, the normal enemies and boss are also live with shaking bodies. Besides, the map of the game is bigger than the screen so the picture will moving as the character moving.
Our game Dad 'n me requires a keyboard to operate. We just use the normal USB keyboard. We support up to two keys for simultaneous input, which is enough for this game. As a result of that, our main character could move diagonally. Keyboard input determines the states and movement of the main character. Here we use a module called key_control to output the signal for other parts of the project.
As an action game, I'd like to focus on our action aspect. Just like the ball module in lab8, W key means moving up; S key means moving down; A key means moving left; D key means moving right. And the main character will move only a little distance instead of moving constantly. When you press J key on the keyboard, key_control module will output a signal attack, then the attack signal will enter the ISDU module, which is the main state machine module for the main character. Then ISDU module will output the state signal. It will enter the Me_ROM module and control the animation of the main character. Then the main character will show strike animation. At the same time, the attack signal will also enter the enemy module along with the data about the position of the main character. If they are close, then the state machine in the enemy module will enter the BEIDA state. And the signal output from it will enter the En_ROM module and then the normal enemy will show the being attacked animation. Besides, we could press the J key repeatedly and quickly, then the main character will perform combos (lianji in Chinese), which is very different from only one J input. This is achieved through the proper design of the state machine inside the ISDU module. Combos operation is very like the original game.
In addition, one of the highlights of our game is the colorful, expansive background that can move the camera as the main character moves. You can also switch between two large scenes. The detailed introduction to this part is in the part 5 of this report, namely the algorithm part.
Besides, in our game, there will be one mini boss who is always chasing for the main character. And when it is very close to the main character, it will enter the DA state. Then it should display the attack animation and output a signal which will make the main character enter the BEIDA state. But the time is limited, and the memory is also limited, so the attack of the mini boss is deleted at last. In any case, its presence increases the psychological pressure on the player.
With the addition of the sound and the win screen and the fail screen, our game is very close to the original Dad ‘n me.
(1). Addition of sound
Just as what I wrote above, we add the sound to our game. The sound is just the original background music of the Dad ‘n me. And we store that in the Flash. Then we also build the Flash interface inside the top-level entity: lab8.sv. And the sound will just loop itself.
(2). Score keeping in game
Every enemy in our game has its own blood bar. And every time the enemy loses its blood, the score in our game will increase. However, when we add this function to the project, the game interface is getting pretty sluggish. So we have to delete this at last. You can still find this in our code.
(3). Multi-key input at the same time for USB keyboard
To achieve it, we add another PIO part called keycode_2 in the platform designer which is the similar to the keycode. And I also change the C code to let it be the part two of the keyboard input. As a result of that, for example, if you press “w” and “a” key at the same time, the main character will move to the upper left.
(4). AI
The mini boss I mentioned in part 2 is really an AI. It will choose the moving direction and its speed according to the position relative to the main character. Every clock it will calculate the new speed and direction according to its specific algorithm.
(5). Sprite
There are about 10 different kinds of sprites in our game. The theory of sprite is based on the state machine. At different state, the main character and the enemy will show different illustrations. Controlling the timing of state transitions, the sprite will show in the screen.
(6). Sophisticated graphics drawing
The original Dad ‘n me is created after 2007. And it’s created based on the flash. As a result of that, the image is not pixelated. Then it’s very hard for us to drawing sophisticated graphics especially for the background picture. Because of many different kinds of colors, the memory of the background picture is very big. And we use the palette to solve this problem. And we use SRAM to store the two big backgrounds.
(7). Movable viewing angle
In our game, if you move the main character. If it’s not in the corner of the background, the viewing angle will move after it. We achieve it by the output signal roll from the ball.sv. Then it will enter the background.sv and it will make a judgement that whether the viewing angle should change.
(8). Use of multiple storage methods
Our audio is stored in the Flash. Our background picture is stored in SRAM. The illustrations for the sprite of our characters are stored in the ROM.
(9). Short Compile time
With two big background pictures, victory picture and lose picture, and dozens of illustrations, our original compile time is about 20 minutes, which is inconvenient for debug and demo. And then we figure out some algorithm to manipulate pictures. And then finally our compile time is only 4 minutes.
(10). Complicated state machine
This has been shown in other sections especially for the sprite part. In part 6, it will be explained more detailed.
(11). Combos (lianji in Chinese)
As an action game, if you only have one attack sprite then the hit feel of the game will be bad. Thus our goal is to achieve the combos operation when you press “J” key repeat in a short time. In the keycode module, we use many states for the output of the attack signal. Then in the ISDU module, we use about ten states for the transformation of the sprite.
(12). Image mirror flipping algorithm
As a 2D horizontal version of action games, every character could face right and face left. Importing an image into memory after it is processed symmetrically consumes both time and memory. So we make out the image mirror flipping algorithm to process the data from .txt file to save both time and memory.
(1). Image storage in ROM
Initially if we want to store an image in ROM, we need to use a ROM with width*height addresses and 24 bits for each address. To reduce the usage of space, we apply the method “one specific palette for one figure”. Thus the palette can only hold few types of colors and we can limit the bit depth of the ROM within 8 or even 4. It significantly reduce the time for compiling.
(2). Image mirror flipping algorithm
The character in our game can face right or left. Thus pairs of symmetrically processed image needed to be stored into memory, consuming both time and memory. Therefore, we design a mirror image flipping algorithm to flip the image. It will take the position of the character as the “center”, recording the width_left and width_right. It will first judge the range of the flipped image and then do a mapping of reflection.
3). Tiled and rolled background
The whole background is stored in the SRAM. We record the left side x coordinate of the screen and display the required range. By updating the Screen_X_Min, we can roll the background and let it follow the motion of the main character. **
Although there are multiple state machines in our project, here I just introduce 3 state machines and the connection between them. First one is the state machine in the key_control module. When you press different key on the keyboard, the inner signals inside this module will change, and these signals will make the state change. And the output of each state will enter the ISDU module to control the transformation of the state machine in ISDU.sv. ISDU state machine is used to control the sprite of the main character through the output of each state. Besides, these states will also enter the enemy module. Inside enemy.sv, there is also one state machine, which controls not only the behavior of the enemy, but also controls the sprite of the normal enemy. The state transformation of the enemy module is controlled by the output of the ISDU state machine. In this way, all the three state machines are connected and one complicated total state machine is formed.
This project is redesigned based on the lab 8 so that many modules are from or similar to the lab 8. Due to the respect to the copyright, many modules are not even renamed.
-
Inputs: Clk, read_address
-
Outputs: data_Out
-
Description: this module will read the memory of address at read_address and save it into data_out as the Clc running.
-
Purpose: this module will load information from read_address to data_Out.
-
Inputs: Clk, success, DrawX, DrawY
-
Outputs: success_rgb, show_success
-
Description: this module will draw the success interface when success signal is received as the Clk running. The success interface will be drawn base on singal DrawX, DrawY so that the drawwing zone can be at the exact center of the monitor region.
- Purpose: this module will draw success logo at the center of the monitor.
-
Inputs: next,frame_clk,Reset, pass, ok
-
Outputs: offset, level_reset, success, fail, level
-
Description: this module is a statemachine that will run a state loop as frame_clk running to play the animation of interface. And some - inputs will change the - outputs.
-
Inputs: Clk, Reset, data_over, FL_DQ
-
Outputs: Audio_Data, FL_OE_N, FL_RST_N, FL_WE_N, FL_CE_N, FL_ADDR
-
Description: this module will read the information from data_over to synthesize the Audio_data that is readable for the microphone as the Clk running until receiving the Reset siginal.
- Purpose: this module will generate the signal to play music.
-
Inputs: Clk,frame_clk, blood, DrawX, DrawY,
-
Outputs: is_blood_bar, blood_bar_rgb_index
-
Description: this module will draw a blood bar with length from signal blood to given character as clk running. The DrawX, DrawY signals will make the drawwing zone at the top of the given character.
- Purpose: this module will draw a blood bar at the top of given character.
-
Inputs: frame_clk,Clk,Reset,left,attack,thump, keycode,keycode_2,
-
Outputs: state, me_state_out, fly
-
Description: this module is a state machine that will run a state loop to animate the character as the signal clk running. The state machine will go to brances as different signals are received.
- Purpose: : this module will running the animation of the character.
-
Inputs: Clk, Reset, frame_clk, keycode,keycode_2,
-
Outputs: left,attack,thump,next,ok
-
Description: this module will interpret the signal of keycode into the logic of game. Different keycodes have different functionalities that will be visualized by this module.
-
Inputs: Clk, tristate_output_enable, Data_write
-
Outputs: Data_read, Data
-
Description: this module will interpret the data from Mem2IO, Data_write back to the bus into the Mem2IO, Data_read.
- Purpose: this module will interpret data circling the bus.
-
Inputs: rgb_index
-
Outputs: rgb_out
-
Description: this module will interpret the 8-bit rgb_index into a 24-bit rgb_out to make the drawwing successfully as well as reduce the size of given pictures. And the transparent pixel will be especially marked.
-
Inputs: Clk, Reset, ADDR, WE, Data_from_CPU, Data_from_SRAM,
-
Outputs: Data_to_CPU, Data_to_SRAM
-
Description: this module will interpret the Data_from_CPU, Data_from_SRAM, with effects of Reset, ADDR, WE, into Data_to_CPU and Data_to_SRAM respectively.
-
Inputs: Clk, Reset, frame_clk, left, roll,offset, DrawX, DrawY,
-
Outputs: relative_address, Screen_X_Min
-
Description: this module will draw the backgrounds into the monitor as clk running. The offset, DrawX, DrawY will make the drawing region desired, relatively centerring the character.
-
Inputs: state, relative_address, Clk,frame_clk, Reset,
-
Outputs: data_Out
-
Description: this module will read the memory of address at relative_address and save it into data_out as the Clk running.
- Purpose: this module will load information from read_address to data_Out.
-
Inputs: Clk, Reset, from_sw_address, from_sw_data_out, from_sw_r, from_sw_w, from_sw_cs, from_sw_reset, OTG_DATA,
-
Outputs: from_sw_data_in, OTG_ADDR, OTG_RD_N, OTG_WR_N, OTG_CS_N, OTG_RST_N
-
Description: switch It’s the module that generates interface between NIOS II and EZ-OTG chip. Specially, OTG_DATA should be high Z (tristated) when NIOS is not writing to OTG_DATA inout bus.
- Purpose: It’s used to generate interface between NIOS II and EZ-OTG chip.
-
Inputs: Clk, Reset, VGA_CLK
-
Outputs: VGA_HS, VGA_VS, VGA_BLANK_N, VGA_SYNC_N, DrawX, DrawY
-
Description: It divides the whole monitor to 800*525 pixels. And signal is registered to ensure clean output waveform.
Modules: lab8
-
Inputs: CLOCK_50, OTG_INT, [3:0] KEY
-
Outputs: HEX0, HEX1, [7:0] VGA_R, VGA_G, VGA_B, VGA_CLK, VGA_SYNC_N, VGA_BLANK_N, VGA_VS, VGA_HS, [1:0] OTG_ADDR, OTG_CS_N, OTG_RD_N, OTG_WR_N, OTG_RST_N, [12:0] DRAM_ADDR, [1:0] DRAM_BA, [3:0] DRAM_DQM, DRAM_RAS_N, DRAM_CAS_N, DRAM_CKE, DRAM_WE_N, DRAM_CS_N, DRAM_CLK
-
Description: This is a top-level module for lab8 project that connects interface between NIOS II and EZ-OTG chip and other parts, including vga, ball and so on.
-
Purpose: This module is used to build interface between NIOS II and EZ-OTG chip. In it we build every part for lab8, includes vga, ball and also the HexDriver for keyboard.
-
Inputs: In0
-
Outputs: Out0
-
Description: it’s a module that control what will be show on the led according to the input.
- Purpose: it’s used to control what will be show on the led.
-
Inputs:is_ball,is_enemy,is_enemy3,is_blood_bar,is_en_blood_bar,show_success, show_fail, DrawX, DrawY, success_rgb, fail_rgb, en_rgb, me_rgb, en_rgb3, bg_rgb_index, blood_bar_rgb_index,
-
Outputs: VGA_R, VGA_G, VGA_B, color_index
-
Description: It’s a module that decides which color to be output to VGA for each pixel.
-
Inputs: Clk, Reset, frame_clk, DrawX, DrawY, keycode,keycode_2, Screen_X_Min, state, left,level,
-
Outputs: is_ball, roll, relative_address, Ball_X_Pos,Ball_Y_Pos, me_dead, r
-
Description: this module is coded based on the movement of ball. It’s a module that controls the behavior of character, including the bounce, advance and the initial condition.
-
Inputs: read_address, Clk,beida,frame_clk, enemy_left, en_move,
-
Outputs: data_Out
-
Description: this module will read the memory of address at read_address and save it into data_out as the Clc running.
- Purpose: this module will load information from read_address to data_Out.
-
Inputs: Clk, Reset, frame_clk, DrawX, DrawY, Screen_X_Min, S_X_Pos, S_Y_Pos, Ball_X_pos, Ball_Y_pos, attack, fly,left
-
Outputs: is_enemy,enemy_left,beida,is_en_blood_bar,en_dead, relative_address, en_move, curr_state1
-
Description: this module is coded based on the movement of ball. It’s a module that controls the behavior of enemy, including the bounce, advance and the initial condition.
-
Inputs: Clk, Reset, frame_clk, DrawX, DrawY, Screen_X_Min, S_X_Pos, S_Y_Pos, Ball_X_pos, Ball_Y_pos, attack, fly,left
-
Outputs: is_enemy,enemy_left,beida,is_en_blood_bar,en_dead, relative_address, en_move, curr_state1
-
Description: this module is coded based on the movement of ball. It’s a module that controls the behavior of boss, including the bounce, advance and the initial condition.
PIO: keycode
-
Inputs: clk, reset
-
Outputs: [7:0] keycode_export
-
- Base Address: 0x0000_0080
-
Description: It’s the stored data for the key press.
-
Purpose: pass the data from the keyboard to FPGA board.
PIO: keycode_2
-
Inputs: clk, reset
-
Outputs: [7:0] keycode_2_export
-
Base Address: 0x0000_0100
-
Description: It’s the stored data for the second key press when you press two keys at the same time.
-
Purpose: pass the data from the keyboard to FPGA board.
PIO: otg_hpi_address
-
Inputs: clk, reset
-
Outputs: [1:0] otg_hpi_address_export
-
Base Address: 0x0000_0090
-
Description: It will output one signal to give address so that we know which register will be used.
-
Purpose: Output address signal so that we know which register will be used.
PIO: otg_hpi_data
-
Inputs: clk, reset, [15:0] otg_hpi_data_in_port
-
Outputs: [15:0] otg_hpi_data_out_port
-
Base Address: 0x0000_00a0
-
Description: It will output data that will be stored in the hpi register.
-
Purpose: it’s used to transfer data between NIOS II and USB chip.
PIO: otg_hpi_r
-
Inputs: clk, reset
-
Outputs: otg_hpi_r_export
-
Base Address: 0x0000_00b0
-
Description: It will output signal that controls whether to read data from hpi register or not.
-
Purpose: it will be 1 when reading data from hpi register.
PIO: otg_hpi_w
-
Inputs: clk, reset
-
Outputs: otg_hpi_w_export
-
Base Address: 0x0000_00c0
-
Description: It will output signal that controls whether to write data to hpi register or not.
-
Purpose: it will be 1 when writing data to hpi register.
PIO: otg_hpi_cs
-
Inputs: clk, reset
-
Outputs: otg_hpi_cs_export
-
Base Address: 0x0000_00d0
-
Description: It will output signal that controls whether to do IOWrite or IORead.
-
Purpose: it will be 0 when needing to do IOWrite or IORead.
PIO: otg_hpi_reset
-
Inputs: clk, reset
-
Outputs: reset_reset_n
-
Base Address: 0x0000_00e0
-
Description: It will output signal that controls whether to reset or not.
-
Purpose: it will be 1 when doing reset.
LUT | 13629 |
---|---|
DSP | 70 |
Memory (BRAM) | 820224 |
Flip-Flop | 2644 |
Frequency | 119.25MHz |
Static Power | 214.83mW |
Dynamic Power | 0.75mW |
Total Power | 106.14mW |
The game is the largest achievement that we explore in our academic career. It makes us know the complexity of a even very looks simple game if it’s FPGA based. Besides, it makes us appreciate the splendid achievement and the fast development speed of TTL Chips and computers. Using the codes based on the bottom structures we also understand the computer better.
The complexity of the design also force us to split work into small pieces and force us to understand what others are doing, which strengthens our ability of coworking, commutation. Due to the overwhelming dues in the final weeks, we have to assign time well to deal with all the jobs. Our management also builds our confidence of facing hard work.