1.块场划分
苹果的大小为1616个像素,和后面要讲的一节蛇身/蛇头是一样的。
在640480的分辨率下,可以看做是40*30的块场,坐标范围为[39:0],[29:0];因为墙壁厚度的原因,苹果可产生的坐标范围为:[38:1],[28:1]。
parameter APPLE_X_MAX = 38 ;
parameter APPLE_Y_MAX = 28 ;
2. 随机数产生
根据复位结束开始游戏的总运动时间+一段由蛇的运动情况产生的随机时间 来设计产生新苹果坐标的算法,具有很好的随机性。
//利用加法产生随机数,蛇吃苹果的时刻不同,随机数就不一样,所以给人随机的感觉
//cnt0为苹果x坐标的随机数
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt0 <= 0;
end
else if(add_cnt0)begin
if(end_cnt0)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
end
assign add_cnt0 = 1'b1;
assign end_cnt0 = add_cnt0 && cnt0 == APPLE_X_MAX-1;
//cnt1为苹果y坐标的随机数
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt1 <= 0;
end
else if(add_cnt1)begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 = 1'b1;
assign end_cnt1 = add_cnt1 && cnt1 == APPLE_Y_MAX-1;
/*这部分的意思是:复位后cnt3和detection_time设置为1MS并保持,让cnt2开始逐1累加至1MS,
其间end_cnt2保持为0,add_cnt3保持为0,end_cnt3保持为0,
等到cnt2==1MS-1了,end_cnt2和add_cnt3拉高一个脉冲,cnt3自加20赋给新的detection_time(1MS+20)
以此类推,直到detection_time超过5MS,这点时间里苹果生成稍微有一点点滞后,但不妨碍观感
后面只要(end_cnt2 && head_x == apple_x && head_y == apple_y)
则将此时的计时(cnt0,cnt1)赋给(apple_x,apple_y)用以生成新的苹果
*/
//cnt2
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt2 <= 0;
end
else if(add_cnt2)begin
if(end_cnt2)
cnt2 <= 0;
else
cnt2 <= cnt2 + 1;
end
end
assign add_cnt2 = 1'b1;
assign end_cnt2 = add_cnt2 && cnt2 == detection_time-1;
//cnt3范围在1ms到5ms之间,为的就是让苹果产生的地址更加随机一点,这部分不太好理解,但也比较重要
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt3 <= TIME_1MS;
end
else if(add_cnt3)begin
if(end_cnt3)
cnt3 <= TIME_1MS;
else
cnt3 <= cnt3 + 20;
end
end
assign add_cnt3 = end_cnt2;
assign end_cnt3 = add_cnt3 && cnt3 >= TIME_5MS-1;
assign detection_time = cnt3;
//apple_x,apple_y
//当蛇头吃到苹果时,就将随机产生一个新的苹果坐标
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
apple_x <= 6'd10;//苹果默认出现的位置
apple_y <= 5'd13;
end
else if(end_cnt2 && head_x == apple_x && head_y == apple_y)begin
apple_x <= cnt0 + 1;//墙的厚度为1个苹果宽度
apple_y <= cnt1 + 1;
end
end
/*这部分的意思是:复位后cnt3和detection_time设置为1MS并保持,让cnt2开始逐1累加至1MS,
其间end_cnt2保持为0,add_cnt3保持为0,end_cnt3保持为0,
等到cnt2==1MS-1了,end_cnt2和add_cnt3拉高一个脉冲,cnt3自加20赋给新的detection_time(1MS+20)
以此类推,直到detection_time超过5MS,这点时间里苹果生成稍微有一点点滞后,但不妨碍观感
后面只要(end_cnt2 && head_x == apple_x && head_y == apple_y),则将此时的计时(cnt0,cnt1)赋给(apple_x,apple_y)用以生成新的苹果
也可以采用伪随机码生成器来实现
https://blog.csdn.net/limanjihe/article/details/52400969?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1
如果追求完美可以使用M序列、Gold序列等近乎完全随机的序列
最后是吃到苹果后下一个上升沿立刻生成标志信号让蛇身加长,即flag_body_add
//flag_body_add
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
flag_body_add <= 1'b0;
end
else if(end_cnt2 && head_x == apple_x && head_y == apple_y)begin
flag_body_add <= 1'b1;
end
else begin
flag_body_add <= 1'b0;
end
end