This repository has been archived on 2023-10-25. You can view files and clone it, but cannot push or open issues or pull requests.
Arkanoid2PDE1/Arkanoid.v
Kirill Kirilenko baf891d878 Version 1.0 released.
Implemented features: ball moving, platform moving, showing scores on digital table, game reset.
2012-05-28 19:06:42 +04:00

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