Hello there!
I'm making a Tetris clone that uses the map to save tile data. The program draws the tetraminoes using 2 'for' loops and a table that has start and center information, but also how many columns and rows to draw in this config:
table_x={startx,starty, row1x,row1y,n row1, row2x,row2y,n row2}
The program is supposed to check if it has a second row:
if(table[6]!=nil) then
pos_x,pos_y=0,0
for n=1,table[8],1 do
rot_x,rot_y=rot(table[6]+pos_x,table[7]+pos_y)
for v=0,7,7 do
for b=0,7,7 do
if(op=="gravity") then
flag=fget(mget((p1.x+rot_x+b)/8,(p1.y+rot_y+v)/8),0)
if(flag) then
....
and normally it works, but sometimes out of random i get this error:
runtime error line 146 tab 0
rot_x,rot_y=rot(table[6]+pos_x,table[7]+pos_y)
attempt to perform arithmetic on field '?' (a nil value)
in collision line 146 (tab 0)
in _update line 40 (tab 0)
at line 0 (tab 0)
....
which is super weird, if you print what table was active, it'l usually spit out table: tet_i which doesn't have a second row, meaning that if(table[6]!=nil) should return false, meaning the error code should not be executed.
If you want to force the runtime error you can make a tower so that you would normally get a game over, but since i haven't programmed one the program keeps spitting out tetraminoes, rapidly speeding the process up, and increasing the chance that you get an error.
I have no idea why this is, any ideas is appreciated!
Thanks in advance, Benji.
I'm having a hard time understanding your code, but it seems to me like your collision is breaking, causing the tetromino to make its way outside of the matrix, and thus outside of the table, but I'm not sure why. Your way of doing things seems to be a lot different than my approach, so give me some time to think on this and look over the code.
(EDIT: Hm, no, I got it to happen in the middle of the matrix, so it's not breaking out.)
Alright, so, I couldn't figure it out, but some words of advice:
First off, are you new to programming? If so, Tetris can be a lot more difficult to make than most people expect it to be. I would maybe reconsider this, try something else for now, and maybe tackle it again later on when you learn and improve. My first few attempts at Tetris were a total failure, then coming back to it a year or so later, I managed to pull it off.
Second, in a grid-based game like this, I would recommend working with smaller values (ie, 1 instead of 8, 2 instead of 16, 3 instead of 24, and so on, like the map uses) and multiplying your variables by 8 when you need them for something that uses pixel coordinates (ie, doing things like spr(1,x*8,y*8)) And then for smooth movement, fake it in code by offsetting the sprites using a timer or something.
Third, I'm not really understanding your table here at all, and I'm thinking that might be the root of the problem. Personally, I treated each mino (each block of the piece) separately, treating the first one as the center. So for example, for an O piece, mino 1's x and y would be the main position of the piece, then I'd have a function set mino 2's to mino 1's x+1, same y, then 3 to mino 1's y+1, same x, then 4 to x+1 then y+1, and then running the collision checks four times. If that makes any sense.
Fourth, your soft drop is a bit slow, with your current code. I'd recommend
if(btn(3)) then p1.y+=p1.grav+4 else p1.y+=p1.grav end
As line 95.
Fifth, a debug function can be super handy. just stick
if debug!=nil then print(debug) end
at the end of your _draw() function, (or, if you're not using _draw() like you are here, then the end of your _update() function) then set debug to whatever you need it to be at any point.
I'm sorry I wasn't able to fix the bug, but hopefully I was still some help. And I'm also no authority on any of this, so if someone feels the need to correct me, go right ahead.
Hey! Thanks for your help anyway, and haha no i'm not that new to programming, although i've been going on and off, and in a lot of different languages, what about my code set you off that i was a beginner? Just curious!
Anyway the idea is quit simple, and that's intentional. I looked at other Tetris clones, and most were manually drawing the sprites pixel by pixel, and storing tile data in tables. I wanted to se if you could use the map() function and mset() to set and draw tiles, and drawing the "player tetraminoe" with spr().
I draw the tetraminoe with 2 'for' loops as i mention, and then modify the offset with the rot() function to rotate the pieces. I then use modified versions of this to calculate collision, and set tiles on the map using mapset() function. This meaning that i only use the tables to store tetraminoe shapes.
I understand that this might not be a optimal way of doing it, i just wanted to se if it is possible. I mean isn't this the most simple and ideal way of doing it? Shame you cant scale the map, so that you could fit more map tiles on the map!
@ManlishPotato By all means, I meant no wrong by it, it just was hard to tell. I have trouble reading other's code just due to how I am, plus you only have a couple of simple carts on the BBS. I don't really judge that sort of thing based on code anyway. Personally, I've noticed that everyone kinda programs differently in little ways, and it's hard to judge how skilled someone is based on code alone because of that. At least to me, anyway.
About using the map, the thing is, that's sort of just overcomplicating things, at least the way I see it. I had tried it in the past, but just using a table ended up being a lot easier. And theoretically, you could scale the map, by using mget() to get each tile and sspr() or just smaller sprites with spr() to draw it, but, see, at that point, why not just use a table?
All good man! That other cart is from 3 years ago and i haven't done much in pico8 since then until now.
Anyhow, don't see why i cant make this work, like i said, the !=nil is not supposed to pass a table which doesn't have a second row. Super weird, il'l probably let it breath a little, come back and see if i can come up with anything.
Thanks anyway!
Yeah, that's probably the best thing to do. Sorry I couldn't help more, but feel free to look though the code of my Tetris clone, Tetyis, if it'd be of any help. Most of that was written while I was still pretty inexperienced, and I'm still not exactly any kind of expert by any means, but still, maybe something in there might be helpful. Anyway, Good luck!
Finally figured out what it was! Such a typical thing, had my eyes on the completely wrong place, the error comes when it executes the init_tet() function which changes the table to a random one, here if it gets the first table, which only has one row, it'l continue past the if(!= nil) and get the error. The solution was to add a goto that ends the collision function when the init_tet() function is done. It's a band aid solution i know, but hey, it works! Check out the updated cart at the top to see it working! Of course it still doesn't have a game over screen :)
Looks pretty good so far. I'm working on a version of Tetris using the map and mget functions as well, as that proved to be simpler and more efficient for me vs. an array, so you're not alone in using that method.
I did notice that when you hold down the button to drop a piece, the next piece immediately starts falling as soon as the current one settles, which can rapidly cause a pileup if you're not careful. You could fix this by just adding a slight delay in the response of the down button when a new piece is generated, something like this:
if(new_piece)t=0 if(btn(3) and t>10)y+=1 new_piece=_ t+=1 |
[Please log in to post a comment]