Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Nexys 4 DRR Collision Detection for Labyrinth Game

Status
Not open for further replies.

Sputnik12

Newbie level 5
Joined
Apr 4, 2022
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
68
I am very new to FPGA programming in vivado (Verilog), and I am trying to make a simple game. The game has a player traverse through a labyrinth and therefore when the player collides with the walls in the labyrinth the player must stop. I tried the brute force method of hard coding every single wall the player collides with and disabled the relevant movements. However, this is not a very time efficient process.

Therefore, I thought it was best to check whether the VGA controller draws over the player box with the colour of the walls. If this happens then disable a certain button. For example, if the red, green and blue values of the walls held in a 12 bit register called "walls" and if the current pixel on the screen is the middle left pixel of the player sprite, then stop moving. This is shown in the following code:

Code:
if((walls) && (currentX == playerX ) && (currentY == playerY + 20)) begin // The player box is 40x40 pixels, //therefore, playerX = 0 and playerY = 0 is the top left hand corner of the player box.

            coll_left <= 1'b1;

        end

 

else begin

            coll_left <= 1'b0;

        end

So what I am trying to say is: if the player is at the wall set the left collision flag to 1 and if the player is not at the wall the flag should be 0. However, the if statement is never met, and the flag remains at 0 and I am not sure why this is the case. The logic of the statement makes sense to me, so I am thoroughly confused. I understand that this is a debugging problem and I should figure this out on my own, but I am running out of options after being stuck on this for 2 days!

I am happy to provide any code files if needed.

Any help would be greatly appreciated!
Thank you!
 
Last edited:

I think I have narrowed the issue down now, but I still don't know how to fix it. Bascially, this code for the if statements is being updated at the positive edge of the pixel clock which is 106.47 MHz for me right now. So the currentX and currentY registers are updated using pixclk. However, the playerX and playerY are updated using a slower 60Hz clock called game_clk. So the condition is being met but it switches so quickly that game_clk can't output the x and y position of the player. So essentially, I need to assert the flag for collision using pixclk and de-assert it using game_clk. But I really don't know how that would even work.

For reference I have been trying to use the same method as this website. I will attach the relevant code files to this post. The top file contains the collision detection code at the moment.
 

Attachments

  • collision_detection.zip
    6.2 KB · Views: 133

Does hidden surface removal get activated when a player collides with a wall? Then player pixels are erased and your collision flag doesn't get triggered?
I have posted the code I am running for the nexys board in my above post, sorry for all these replies, I am still new to the site.
 

Make the design synchronous instead of having multiple clock domains.

Run everything off the pixel clock and generate a 60 Hz game enable instead of a clock, the game enable will be one pixel clock pulse wide. You use that pulse to update (enable) everything that is run off of the game clock (which will now use the pixel clock).
 

Make the design synchronous instead of having multiple clock domains.

Run everything off the pixel clock and generate a 60 Hz game enable instead of a clock, the game enable will be one pixel clock pulse wide. You use that pulse to update (enable) everything that is run off of the game clock (which will now use the pixel clock).
Hello @ads-ee, thank you for your response. So currently game clock is made like this:

Code:
 always@(posedge clk)
    begin
        if(clk_div == 100000000/120) begin
            clk_div <= 20'd0;
            game_clk <= !game_clk;
        end
        else
        begin
            clk_div <= clk_div + 1;
         
        end
    end

From your reply, I think what you mean is that I should change the above code to something like this:
Code:
 always@(posedge clk)
    begin
        if(clk_div == 100000000/120) begin
            game_clk < =1; // Enable the signal
        end
        else
        begin
            clk_div <= clk_div + 1;
            game_clk <= 0;
         
        end
    end

And then in my movement code I do always@ (posedge pixclk) and have an if statement at the beginning, saying that if (game_clk == 1) //movement code? Currently, the movement code works based on always@ (posedge game_clk).
 

Exactly generate a game_clk_enable instead of an actual clock
 

The enable code if (game_clk == 1) makes sense.

What doesn't make sense is your divider being 100000000/120 = 833333.33333333333.... so you will be comparing the clk_div to a count value of 833333 as the divided value is truncated to an integer. If you must have a divider that is on average 8333333+1/3 then you will need to compare to 833334 every 3rd comparison.
 

The enable code if (game_clk == 1) makes sense.

What doesn't make sense is your divider being 100000000/120 = 833333.33333333333.... so you will be comparing the clk_div to a count value of 833333 as the divided value is truncated to an integer. If you must have a divider that is on average 8333333+1/3 then you will need to compare to 833334 every 3rd comparison.
I understand, so the code should be
Code:
 always@(posedge clk)
    begin
        if(clk_div == 833334) begin
            clk_div <= 20'd0;
            game_clk <= !game_clk;
            game_clk_enable <= 1;
        end
        else
        begin
            clk_div <= clk_div + 1;
            game_clk_enable <= 0;
       
        end
    end

I just want to confirm whether I am asserting and de-asserting the enable register correctly.
 

@BradtheRad I am not sure what you mean by the hidden surface removal?? Is this a verilog function that I don’t know about?

Maybe it's unnecessary if your sprites are two-dimensional only.
To portray three-dimensional objects on a screen, you'd need a routine that draws only surfaces visible from your viewpoint, while hiding unseen surfaces.
 

Maybe it's unnecessary if your sprites are two-dimensional only.
To portray three-dimensional objects on a screen, you'd need a routine that draws only surfaces visible from your viewpoint, while hiding unseen surfaces.
Yes my sprites are only 2D.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top