Implemented features: ball moving, platform moving, showing scores on digital table, game reset.
399 lines
8.2 KiB
Verilog
399 lines
8.2 KiB
Verilog
module Arkanoid
|
|
|
|
`include "arkanoid_header.v"
|
|
`include "int_to_digital.v"
|
|
`include "vga_sync.v"
|
|
|
|
task GameRestart;
|
|
begin
|
|
ball_x = FIELD_WIDTH/2;
|
|
ball_y = FIELD_HEIGHT-1;
|
|
ball_direction = RIGHT_UP;
|
|
platform1_position = (FIELD_WIDTH-PLATFORM_WIDTH)/2; // central position
|
|
platform2_position = platform1_position;
|
|
game_state = 1'b1;
|
|
end
|
|
endtask
|
|
|
|
// Main logic
|
|
always @ (posedge clk25MHz)
|
|
begin
|
|
|
|
// Processing button presses
|
|
|
|
if (button1 != button1_state)
|
|
begin
|
|
if (button1 == 1'b1)
|
|
begin
|
|
led_[7] = 1'b1;
|
|
led_[6] = 1'b1;
|
|
|
|
if (game_state == 1'b0)
|
|
GameRestart;
|
|
else if (platform1_position > 0)
|
|
platform1_position = platform1_position - 1;
|
|
end
|
|
else
|
|
begin
|
|
led_[7] = 1'b0;
|
|
led_[6] = 1'b0;
|
|
end
|
|
button1_state = button1;
|
|
end
|
|
|
|
if (button2 != button2_state)
|
|
begin
|
|
if (button2 == 1'b1)
|
|
begin
|
|
led_[5] = 1'b1;
|
|
led_[4] = 1'b1;
|
|
|
|
if (game_state == 1'b0)
|
|
GameRestart;
|
|
else if (platform1_position < FIELD_WIDTH-PLATFORM_WIDTH-1)
|
|
platform1_position = platform1_position + 1;
|
|
end
|
|
else
|
|
begin
|
|
led_[5] = 1'b0;
|
|
led_[4] = 1'b0;
|
|
end
|
|
button2_state = button2;
|
|
end
|
|
|
|
if (button3 != button3_state)
|
|
begin
|
|
if (button3 == 1'b1)
|
|
begin
|
|
led_[3] = 1'b1;
|
|
led_[2] = 1'b1;
|
|
|
|
if (game_state == 1'b0)
|
|
GameRestart;
|
|
else if (platform2_position > 0)
|
|
platform2_position = platform2_position - 1;
|
|
end
|
|
else
|
|
begin
|
|
led_[3] = 1'b0;
|
|
led_[2] = 1'b0;
|
|
end
|
|
button3_state = button3;
|
|
end
|
|
|
|
if (button4 != button4_state)
|
|
begin
|
|
if (button4 == 1'b1)
|
|
begin
|
|
led_[1] = 1'b1;
|
|
led_[0] = 1'b1;
|
|
|
|
if (game_state == 1'b0)
|
|
GameRestart;
|
|
else if (platform2_position < FIELD_WIDTH-PLATFORM_WIDTH-1)
|
|
platform2_position = platform2_position + 1;
|
|
end
|
|
else
|
|
begin
|
|
led_[1] = 1'b0;
|
|
led_[0] = 1'b0;
|
|
end
|
|
button4_state = button4;
|
|
end
|
|
|
|
|
|
// Update field (move platforms)
|
|
for (i = 0; i < FIELD_WIDTH; i = i + 1)
|
|
begin
|
|
if ((i >= platform2_position) && (i <= platform2_position+PLATFORM_WIDTH))
|
|
field[0][i] = PLATFORM_CELL;
|
|
else
|
|
field[0][i] = EMPTY_CELL;
|
|
|
|
if ((i >= platform1_position) && (i <= platform1_position+PLATFORM_WIDTH))
|
|
field[FIELD_HEIGHT-1][i] = PLATFORM_CELL;
|
|
else
|
|
field[FIELD_HEIGHT-1][i] = EMPTY_CELL;
|
|
end
|
|
|
|
|
|
//Update field (move ball)
|
|
if (game_state)
|
|
if (ball_clock_counter < BALL_DELAY)
|
|
ball_clock_counter = ball_clock_counter + 1;
|
|
else
|
|
begin
|
|
ball_clock_counter = 0;
|
|
|
|
field[ball_y][ball_x] = EMPTY_CELL;
|
|
|
|
case (ball_direction)
|
|
|
|
LEFT_UP:
|
|
begin
|
|
|
|
if ((ball_x > 0) && (ball_y > 1))
|
|
begin
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
else if ((ball_x > 0) && (ball_y == 1))
|
|
if ((ball_x >= platform2_position) && (ball_x <= platform2_position + PLATFORM_WIDTH))
|
|
begin
|
|
ball_direction = LEFT_DOWN;
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
else
|
|
begin
|
|
// Goal
|
|
player1_score = player1_score + 1;
|
|
game_state = 1'b0;
|
|
end
|
|
|
|
else if ((ball_x == 0) && (ball_y > 1))
|
|
begin
|
|
ball_direction = RIGHT_UP;
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
|
|
else
|
|
begin
|
|
ball_direction = RIGHT_DOWN;
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
|
|
end
|
|
|
|
RIGHT_UP:
|
|
begin
|
|
|
|
if ((ball_x < FIELD_WIDTH-1) && (ball_y > 1))
|
|
begin
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
else if ((ball_x < FIELD_WIDTH-1) && (ball_y == 1))
|
|
if ((ball_x >= platform2_position) && (ball_x <= platform2_position + PLATFORM_WIDTH))
|
|
begin
|
|
ball_direction = RIGHT_DOWN;
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
else
|
|
begin
|
|
// Goal
|
|
player1_score = player1_score + 1;
|
|
game_state = 1'b0;
|
|
end
|
|
|
|
else if ((ball_x == FIELD_WIDTH-1) && (ball_y > 1))
|
|
begin
|
|
ball_direction = LEFT_UP;
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
|
|
else
|
|
begin
|
|
ball_direction = LEFT_DOWN;
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
|
|
end
|
|
|
|
LEFT_DOWN:
|
|
begin
|
|
|
|
if ((ball_x > 0) && (ball_y < FIELD_HEIGHT-2))
|
|
begin
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
else if ((ball_x > 0) && (ball_y == FIELD_HEIGHT-2))
|
|
if ((ball_x >= platform1_position) && (ball_x <= platform1_position + PLATFORM_WIDTH))
|
|
begin
|
|
ball_direction = LEFT_UP;
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
else
|
|
begin
|
|
// Goal
|
|
player2_score = player2_score + 1;
|
|
game_state = 1'b0;
|
|
end
|
|
|
|
else if ((ball_x == 0) && (ball_y < FIELD_HEIGHT-2))
|
|
begin
|
|
ball_direction = RIGHT_DOWN;
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
|
|
else
|
|
begin
|
|
ball_direction = RIGHT_UP;
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
|
|
end
|
|
|
|
RIGHT_DOWN:
|
|
begin
|
|
|
|
if ((ball_x < FIELD_WIDTH-1) && (ball_y < FIELD_HEIGHT-2))
|
|
begin
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
else if ((ball_x < FIELD_WIDTH-1) && (ball_y == FIELD_HEIGHT-2))
|
|
if ((ball_x >= platform1_position) && (ball_x <= platform1_position + PLATFORM_WIDTH))
|
|
begin
|
|
ball_direction = RIGHT_UP;
|
|
ball_x = ball_x + 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
else
|
|
begin
|
|
// Goal
|
|
player2_score = player2_score + 1;
|
|
game_state = 1'b0;
|
|
end
|
|
|
|
else if ((ball_x == FIELD_WIDTH-1) && (ball_y < FIELD_HEIGHT-2))
|
|
begin
|
|
ball_direction = LEFT_DOWN;
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y + 1;
|
|
end
|
|
|
|
else
|
|
begin
|
|
ball_direction = LEFT_UP;
|
|
ball_x = ball_x - 1;
|
|
ball_y = ball_y - 1;
|
|
end
|
|
|
|
end
|
|
|
|
endcase
|
|
|
|
if (game_state)
|
|
field[ball_y][ball_x] = BALL_CELL;
|
|
|
|
end
|
|
|
|
|
|
// Update scores
|
|
IntToDigital(player1_score, hex3_, hex2_);
|
|
IntToDigital(player2_score, hex1_, hex0_);
|
|
|
|
|
|
// VGA output
|
|
h_cell = (h_counter-143)/CELL_SIZE;
|
|
v_cell = (v_counter-34)/CELL_SIZE;
|
|
if ((v_counter > 34) && (v_counter < 514) && (h_counter > 143) && (h_counter < 783))
|
|
begin
|
|
|
|
current_cell = field[v_cell][h_cell];
|
|
|
|
case(current_cell)
|
|
|
|
EMPTY_CELL:
|
|
begin
|
|
red_ = BK_COLOR_R;
|
|
green_ = BK_COLOR_G;
|
|
blue_ = BK_COLOR_B;
|
|
end
|
|
|
|
STABLE_CELL:
|
|
begin
|
|
red_ = STABLE_COLOR_R;
|
|
green_ = STABLE_COLOR_G;
|
|
blue_ = STABLE_COLOR_B;
|
|
end
|
|
|
|
BALL_CELL:
|
|
begin
|
|
red_ = BALL_COLOR_R;
|
|
green_ = BALL_COLOR_G;
|
|
blue_ = BALL_COLOR_B;
|
|
end
|
|
|
|
PLATFORM_CELL:
|
|
begin
|
|
red_ = PLATFORM_COLOR_R;
|
|
green_ = PLATFORM_COLOR_G;
|
|
blue_ = PLATFORM_COLOR_B;
|
|
end
|
|
|
|
endcase
|
|
|
|
end
|
|
else
|
|
begin
|
|
red_ = 4'b0000;
|
|
green_ = 4'b0000;
|
|
blue_ = 4'b0000;
|
|
end
|
|
|
|
end
|
|
|
|
|
|
// Initialization of all module variables
|
|
initial
|
|
begin
|
|
|
|
game_state = 1'b0;
|
|
|
|
// Reset scores
|
|
player1_score = 0;
|
|
player2_score = 0;
|
|
|
|
// Place ball to the center of the screen
|
|
ball_clock_counter = 0;
|
|
ball_x = FIELD_WIDTH/2;
|
|
ball_y = FIELD_HEIGHT-1;
|
|
ball_direction = RIGHT_UP;
|
|
|
|
// Place platforms at the center of the borders
|
|
platform1_position = (FIELD_WIDTH-PLATFORM_WIDTH)/2; // central position
|
|
platform2_position = platform1_position;
|
|
|
|
// Clear field
|
|
for (i = 0; i < FIELD_HEIGHT; i = i + 1)
|
|
for (j = 0; j< FIELD_WIDTH; j = j + 1)
|
|
field[i][j] = EMPTY_CELL;
|
|
|
|
// Reset buttons state
|
|
button1_state = 1'b0;
|
|
button2_state = 1'b0;
|
|
button3_state = 1'b0;
|
|
button4_state = 1'b0;
|
|
|
|
// Reset VGA counters
|
|
h_counter = 0;
|
|
v_counter = 0;
|
|
|
|
end
|
|
|
|
assign h_sync = ~((h_counter > 0) && (h_counter < 95));
|
|
assign v_sync = ~((v_counter == 0) || (v_counter == 1));
|
|
|
|
assign red = red_;
|
|
assign green = green_;
|
|
assign blue = blue_;
|
|
|
|
assign hex0 = ~hex0_;
|
|
assign hex1 = ~hex1_;
|
|
assign hex2 = ~hex2_;
|
|
assign hex3 = ~hex3_;
|
|
|
|
assign led = ~led_;
|
|
|
|
endmodule
|