Checkoff 02: Doing Pong
You're a Game Developer Now
Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.
Overview
For a final thing we're going to build pong.
Uncomment the portion of the pong logic in your top_level
file to integrate the Pong game into your system.
We're giving you a starting skeleton, which should at least get you working with a rendered ball and paddle in their starting positions (first few seconds of video below), but the game logic itself is missing and it needs to be good to be working.
The game should look like the following
The game itself is comprised of a module that takes in the following inputs:
pixel_clk_in
: The 74.25 MHz clock corresponding to pixels on the screen.rst_in
: An active-high game-reset signal. Note this is different than system reset.[1:0] control_in
: Two bits controlling the up and down movement of your player paddle.[3:0] puck_speed_in
A four bit number specifying the movement speed of the puck in pixels per frame[3:0] paddle_speed_in
: A four bit number specifying the movement speed of the paddle in pixels per frame (assuming they are being commanded to move viacontrol_in
.nf_in
: A single-cycle enable signal indicating the start/end of a new frame (useful for game logic)[10:0] hcount_in
The current x location on the screen[9:0] vcount_in
The current y location on the screen
The game is what would be termed an "old-school" design. It "lives on the beam", meaning there is no frame buffer or anything like that. It takes in all the information above and decides what pixel to draw in real time as the screen is being drawn. That pixel is conveyed through the three eigh-bit outputs, with the hopefully self-explanatory names:
[7:0] red_out
Red output[7:0] green_out
Green output[7:0] blue_out
Blue output
The Block Sprite
The game should be a sea of black with two shapes moving around, a paddle, controlled by you and a puck, controlled by nature. In order to modularize the drawing we have provided a block_sprite
module that in addition to using the specified WIDTH
and HEIGHT
parameters, will take in:
- The x,y location of a shape "concept" you want to draw on screen
- A
hcount
andvcount
And will determine what color the output should be at (hcount, vcount)
. If the hcount
and vcount
are within the bounds of the block, it'll output the block's color on the red, green, and blue channels. If not, it'll output black.
module block_sprite #(
parameter WIDTH=128, HEIGHT=128, COLOR=24'hFF_FF_FF)(
input wire [10:0] hcount_in,
input wire [9:0] vcount_in,
input wire [10:0] x_in,
input wire [9:0] y_in,
output logic [7:0] red_out,
output logic [7:0] green_out,
output logic [7:0] blue_out);
logic in_sprite;
assign in_sprite = ((hcount_in >= x_in && hcount_in < (x_in + WIDTH)) &&
(vcount_in >= y_in && vcount_in < (y_in + HEIGHT)));
always_comb begin
if (in_sprite)begin
red_out = COLOR[23:16];
green_out = COLOR[15:8];
blue_out = COLOR[7:0];
end else begin
red_out = 0;
green_out = 0;
blue_out = 0;
end
end
endmodule
The bounds of the block sprite are done using rectangular collision detection. Note x and y locations of the sprite are inputs (not parameters) so they can change. This would allow the sprite represented by this module to move around the screen.
Game Logic
The game should involve the user controlling the paddles using the two input bits (which are tied to buttons 2 and 3 in the top level file).
- The game logic should use the periodic new frame signal to increment/step. You should not be updating game logic every cycle of the pixel clock. That's far too fast and there's no point in doing that. Use the 60 fps signal from the video signal generator to give a single-cycle periodic signal for controlling the game logic.
- The paddle should be bound by the edges of the game and remain on the left side. You can only move it up or down.
- The puck should bounce around on its own and reflect off the top, bottom, and right fields of the display as well as the paddle (if it intersects it). We're doing simple physics so as a hint, the X and Y movement of the puck can largely be considered independently.
- Speed of the puck and the paddle should be based off of their respective speed control inputs and should vary from 0 to 15 pixels per frame.
- For keeping track of speed, do not used signed numbers. Instead use magnitude and a sign bit (and change that bit when reflections occur).
- The puck should properly reflect off the walls as shown in the video, it should not overflow/or go out of bounds or reflect large distances before the walls. Same with the Paddle. It should not go above/below the screen.
- If the puck gets further left than
PADDLE_WIDTH
without a paddle collission happening, othen the game is over and should freeze, only restarting when the restart button is pushed. - Reflection of the puck off of the paddle should occur if any part of the paddle overlaps the puck. This overlap condition happening in the y dimension is shown in red in the video below. Faiure to carry out reflection like this will result in no checkoff. There is a brute-force way to do this and a tricksy way to do this, which uses calculations already done for you. Either is fine. Regardless, the paddle-puck reflection must be good.
For checkoff 2, show pong working. Walk the staff member through your logic.
Once you're done, move onto drawing some basic shapes in Checkoff 02 :D