Sign in to follow this  

Python checking list collision

This topic is 3581 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've been hopelessly trying to add collision detection in my Tetris game in Python for about a week now. I was really close one time but in the end everything just became totally messed up. I've made a Tetris clone before in C++, but Python is driving me crazy honestly (I don't know why, it feels quite simple). I have some sort of deadline tomorrow and if I don't finish the collision detection I cannot continue with the other things. I would appreciate some help. The blocks are built with a list of lists, example. LBlock = [[0,0,5], [5,5,5]] LongBlock = [[6], [6], [6], [6]] The gameboard is also a list of lists which is 10x20. I want to check if collision occurs in the vertical-lead first. That is if a block collides with another, the program will store the block into the gameboard and generate a new one. The horizontal collision will not store the blocks, only check if collision occurs so I can remove the horizontal movement code if a block is there. I don't want the player to move the block right trough another block in other words. The only collision detection that works right now, is the block and the floor of the gameboard.
    def isCollision(self, gameboard):
        xCoord = (self.x-BOARDPOS[0])/BLOCKSIZE
        yCoord = (self.y-BOARDPOS[1])/BLOCKSIZE
        width  = len(self.block[0])
        height = len(self.block)

        # if the block touches the floor, 20 is the max y-value
        # and self.block is the current block (list of lists)
        if yCoord+height > 20:
            gameboard.add(xCoord, 20-height, self.block)
            self.generateBlock()
            return True
        
        return False

The current horizontal collision detection function looks something like this, but doesn't really work 100% yet.
    def horCollision(self,board):
        xCoord = (self.x-BOARDPOS[0])/BLOCKSIZE
        yCoord = (self.y-BOARDPOS[1])/BLOCKSIZE

        for y in range(len(self.block[0])):
            # check horizontal collision on the left size
            if board[xCoord-1][yCoord] > 0 and self.block[y][0] > 0:
                return True
            
        return False

The reason I check if their values are greater than 0 is because 0 is an empty slot and any value greater than that is a solid block slot. How would you implement collision in a similiar game? Thankful for help.

Share this post


Link to post
Share on other sites
The way I would approach it is:
- move the block to where it wants to go
- superimpose the block's grid onto the board's grid
- if there's any overlap, there's a collision, so move it back

To check the superimposition, using your structures, I might do it this simple way at first:

for each row of the block:
for each column of that block's row:
find the corresponding part of the board
compare the board part to this block part
if it's a collision:
we have a collision - stop here


It's not the quickest or even best way, but it is the simplest. Finding the part of the board that corresponds to a given part of the block is mildly awkward - you need to add its offset within the block to the block's position, and that'll be the part of the board you need.

Other stuff:
What is this line doing?
xCoord = (self.x-BOARDPOS[0])/BLOCKSIZE

Surely self.x and xCoord would mean the same thing? And why divide by BLOCKSIZE? And what is BLOCKSIZE, for that matter?

And, this is bad Python: for y in range(len(self.block[0]))
This is good Python: for y in self.block[0]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kylotan
The way I would approach it is:
- move the block to where it wants to go
- superimpose the block's grid onto the board's grid
- if there's any overlap, there's a collision, so move it back

To check the superimposition, using your structures, I might do it this simple way at first:

for each row of the block:
for each column of that block's row:
find the corresponding part of the board
compare the board part to this block part
if it's a collision:
we have a collision - stop here


It's not the quickest or even best way, but it is the simplest. Finding the part of the board that corresponds to a given part of the block is mildly awkward - you need to add its offset within the block to the block's position, and that'll be the part of the board you need.


I've done something similiar before. I'll try what you said and post my code.

Quote:

Other stuff:
What is this line doing?
xCoord = (self.x-BOARDPOS[0])/BLOCKSIZE

Surely self.x and xCoord would mean the same thing? And why divide by BLOCKSIZE? And what is BLOCKSIZE, for that matter?


self.x is the x-position in pixels while xCoord is the x-position in units on the board. BLOCKSIZE is equal to 22 in my case and represents the width/height of each block.

Quote:

And, this is bad Python: for y in range(len(self.block[0]))
This is good Python: for y in self.block[0]


Thanks for the tip.

[Edited by - password on February 28, 2008 10:54:04 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by password
Quote:

Other stuff:
What is this line doing?
xCoord = (self.x-BOARDPOS[0])/BLOCKSIZE

Surely self.x and xCoord would mean the same thing? And why divide by BLOCKSIZE? And what is BLOCKSIZE, for that matter?


self.x is the x-position in pixels while xCoord is the x-position in units on the board. BLOCKSIZE is equal to 22 in my case and represents the width/height of each block.


That's backwards. The object should store the data that's important for updates, and calculate on the fly what's needed for drawing. That lets you draw the same block in multiple contexts, and avoids having to update every block if something changes about the rendering (say, for example, that you want the window to be resizeable with blocks scaling up proportionately).

Also, adding 'Coord' after 'x' doesn't make it that much more descriptive. I would store self.x_tile, and calculate x_pixel (or something like that) for rendering.

Quote:
Quote:

And, this is bad Python: for y in range(len(self.block[0]))
This is good Python: for y in self.block[0]


Thanks for the tip.
[/quote]

That needs a little more explanation.


# bad
for y in range(len(self.block[0])):
doSomethingWith(self.block[0][y])

# good
for block in self.block[0]:
doSomethingWith(block)


The second form is obviously cleaner, and the only thing you can't easily do that way is replace the object in the list with another one.

BTW, you might find it easier to manipulate your blocks if you "pad" them fully (i.e. make a 4x4 grid of numbers for each, with zeros to fill the empty space). Then, for example, rotation works the same way for each of them.

Share this post


Link to post
Share on other sites

This topic is 3581 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this