Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
How to make a Tetris game?
I want to make a Tetris style game for Div with the "feeling" and appearance of the "9999 in 1" lcd brick games. But I have a problem, I don't know
how to make it. I know that I must use a struct for the rows and the columns, but I don't understand how to use the structs.
|
|
dom cook
Div Pro
Posts: 387
Registered: 4-3-2016
Member Is Offline
|
|
NOTE: In this explanation I've used curved brackets for square ones because the first time I posted it it deleted all the square ones.
Hi Dani, I'd like to help.
Structs are a lot simpler than they seem at first.
For example If I wanted to keep track of a process's previous position I'd need to have variables for storing this information. To do this I might
declare variables and call them 'old_x' and 'old_y'. Alternatively, I could use a struct and declare them thus:
struct old;
x;
y;
end
Now in the code if I want to use these varables I just write 'old.x' or 'old.y'.
Apologies if you already knew this much.
If wanted to create a grid of cells which each needed its own set of data I'd do it a bit like this
grid_height=10;
grid_width=10
grid size=10*10=100
struct cell(100)
id
index;
row;
col;
state;
etc...
end
This struct is one dimensional and a grid is 2D so to assign the correct row and column to each cell you do this
for(i=0; i<grid_size; i+=1)
cell(i).row=i/grid_width;
cell(i).col=i mod grid_width;
end
Next you can create a bunch of processes for the cells
for (i=0; i<100; i+=1)
cell(i).id=cell();
cell(i)index=i;
end
Now you can lay out you cells in a grid like this
for(i=0; i<100;i+=1)
cell(i).id.x=cell(i).col*column_width;
cell(i).id.y=cell(i).row*row_height;
end
If you need to know the neighbours of each cell you can add that into the cell struct
You could even put a struct inside a struct like this
struct cell
struct neighbour_index
up;
down;
left;
right;
end
end
So,
cell(i).neighbour_index.up = i-10
cell(i).neighbour.index.right = i+1
cell(i).neighbour_index.down=i-10
cell(i).neighbour_index.left=i-1
Now you would be able to access these neighbours by writing for example
cell(cell(i).neighbour_index.up)
Anyway that's an intro. It's very generalised and obviously incomplete but it shows one way of doing what you want. If it doesn't help, I'm sure that
if you refine your request I can refine my explanation.
Good luck with the project.
[Edited on 12-3-2017 by dom cook]
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
This is the grid that I want to use. The bricks are sprites, and there are 10 columns x 20 rows. As you can see, the cells are separated by 1 pixel.
I know that:
-First, the computer selects one of 7 pieces (or 12 in the "special version").
For example, "new_piece=rand(1,7)".
-The brick appears on screen (piece (x and y depending on brick shape)).
-The brick begins to fall at the actual level speed, controlled by the user until it reaches the ground or a previous block.
-Then I have to convert the actual brick to a set of cells in the grid, this is one of the things that I don't know how to do.
-The grid cells are updated and the score increases a bit for falling piece (for example, 10 points).
-If a set of 10 horizontal cells are aligned, then this line disappears and the upper cells fall and take the place of the older ones.
-And all the process repeats from the step 1.
But I don't know how to use structs, and how to convert process shapes to cells.
Do you recommend use grouped cells for every piece, or it is okay to use sprites?
Ah, I'm trying to write this into my program:
for(i=0; i<grid_size; i+=1)
cell(i).row=i/grid_width;
cell(i).col=i mod grid_width;
end
But DIV gives me an error message, "expresión sin sentido" ("expression with no sense") with "cell.i".
|
|
CicTec
DIV Pro
Posts: 471
Registered: 6-8-2016
Member Is Offline
|
|
Hi Dani_Karmann,
In DIV arrays are declared using brackets [ ], so:
Code: |
global
struct cell[9] // declare a array of struct of 10 elements
row, col;
end
...
begin
for(i=0; i<grid_size; i+=1)
cell[i].row=i/grid_width;
cell[i].col=i mod grid_width;
end
end
|
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
I've tried to copy and paste your code in my program.
In my grid every block has an 11x11 size, and it begins at the position x=84, y=10, and there are 20 rows and 10 columns. So, the first cell is
located at the position x=89,y=15, the last block of the first row is at position 188,15. The first cell of the second row is located at 89,26, and
the last one at 188,224, and so on. Then, the first block of the 20th row is located at 89,224, and the last one at 188,224.
Then, I need to put every cell from position x=89 separated 1 pixel of its neighbour. Am I right?
Then, I have to create 20x10= 200 cells into the grid, starting from x=89 and y=15, with a separation of 1 pixel for every block.
Then, every cell can be at two states: on(1) or off (0). Every active cell should look as a black square block.
Now, I have to begin to create the STRUCT like in your example. This will look this way:
for (i=0; i<200; i+=1)
cell(i).id=cell();
cell(i)index=i;
end
But I have a doubt: What is "cell" in this example, a variable or the name of the process?
And look at the screenshot, I just create the blocks, so now I have 200 of them in the correct position. Now I have to begin the game routine.
[Edited on 12-3-2017 by Dani_Karmann]
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
Ah, I just realize that it's not necessary the 1 pixel separation, so the blocks can be located at its "natural" position.
|
|
dom cook
Div Pro
Posts: 387
Registered: 4-3-2016
Member Is Offline
|
|
Hi Dani,
Yes you're right it is confusing because I suggested a struct called cell and also a process called cell. They're different things.
Perhaps it would be better to call the struct cell_data.
Alternatively, a cell process isn't actually necessary, you could do the graphics using the map_put() function.
something like
for(i=0; i<grid_size; i+=1)
if(cell(i).state==0)
map_put(grid_graph,cell_graph_empty,cell(i).grid_x,cell(i).grid_y);
else
map_put(grid_graph,cell_graph_full,cell(i).grid_x,cell(i).grid_y);
end
end
where cell_graph_full and cell_graph_empty are your graphics for the 2 states of a cell.
(NB don't forget about the square brackets,
Can someone remind me how to embed code?)
|
|
dom cook
Div Pro
Posts: 387
Registered: 4-3-2016
Member Is Offline
|
|
By the way, am I right in assuming the falling bricks are to be rotatable in 90 degree steps?
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
Do you know the example program included in Div2 called OFUSTRIS? It's a Tetris game with "zeros" and "ones", but the author wrote a very, very
confusing program.
I guess I need to create another struct variable for every piece shape and position.
The idea of using "map_put" seems good, but will it be fast enough to put all the squares in faster levels of falling blocks?
Part of the OFUSTRIS program:
STRUCT QQQ;
STRUCT OQ[3]QO[3];END;END;
STRUCT OOQ;
STRUCT OQ[3]QO[3];END;END;
STRUCT OQQ;
STRUCT OQ[20] QO[14];END;END;
QQOQ,QQQO;QQOQQO;QOQOQ;QQOOS;
LOCAL QOQ,OQO,CQOC,COCQ;
BEGIN
FOR(QOQ=0;QOQ<=17;QOQ++)OQQ.OQ[QOQ].QO[0]=2;OQQ.OQ[QOQ].QO[1]=2;
OQQ.OQ[QOQ].QO[2]=2;
OQQ.OQ[QOQ].QO[12]=2;
OQQ.OQ[QOQ].QO[13]=2;
OQQ.OQ[QOQ].QO[14]=2;
END;
FOR(OQO=0;OQO<=14;OQO++)OQQ.OQ[18].QO[OQO]=DOS;OQQ.OQ[19].QO[OQO]=2;
OQQ.OQ[20].QO[OQO]=2;END;
SET_FPS(QOCQ,0);WRITE(0,0,CQO,0,"OFUSTRIS (C)1998 100% !DEEMO");
WRITE(0,0,CQO+9,0,"www.geocities.com/SiliconValley/Campus/2439/");
As you can see, the author writes a strange and confusing program...
|
|
dom cook
Div Pro
Posts: 387
Registered: 4-3-2016
Member Is Offline
|
|
Wow that's horrible!
The map_put function is pretty fast
Here's some code showing it updating an entire grid every frame. The FPS is set to 60 and it's keeping up
Code: |
/*
* tits.PRG by dom cook
* (c) 2017 sollia 3
*/
PROGRAM tits;
const
grid_wide=10;
grid_high=20;
grid_x0=100;
grid_y0=100;
grid_size=grid_wide*grid_high;
cell_size=10;
global;
struct cell_data[grid_size]
x_pos;
y_pos;
x_coord;
y_coord;
state;
end
graph_cell[1];
private
i;
BEGIN
set_fps(60,0);
set_mode(m640x480);
graph=new_map(120,240,0,0,20);
x=grid_x0;
y=grid_y0;
graph_cell[0]=new_map(cell_size,cell_size,0,0,30);
graph_cell[1]=new_map(cell_size,cell_size,0,0,40);
for(i=0; i<grid_size; i+=1)
cell_data[i].x_coord=i % grid_wide;
cell_data[i].y_coord=i / grid_wide;
cell_data[i].x_pos=cell_data[i].x_coord*cell_size;
cell_data[i].y_pos=cell_data[i].y_coord*cell_size;
cell_data[i].state=rand(0,1);
map_put(0,graph,graph_cell[cell_data[i].state],cell_data[i].x_pos,cell_data[i].y_pos);
end
write(0,40,10,2,"fps: ");
write_int(0,40,10,0,&fps);
loop
for(i=0; i<grid_size; i+=1)
cell_data[i].state=rand(0,1);
map_put(0,graph,graph_cell[cell_data[i].state],cell_data[i].x_pos,cell_data[i].y_pos);
end
frame;
end
END
|
|
|
dom cook
Div Pro
Posts: 387
Registered: 4-3-2016
Member Is Offline
|
|
Hi Dani,
How's the project going? Have you come up with a way to do the falling pieces? I've given it some thought so if you get stuck I think I can help.
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
I'm sorry, but I'm busy due to my job and I did not make any actual progress in the game.
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
Latest news:
-The process "next brick preview" is already done. Now you can see the next piece.
-Now there will be 5 different games: Tetris, Tetris special, Arkanoid, Grand Prix and Space duel.
-Created the title screen with the "9999 in 1" logo on screen (see screenshot).
Some examples (they're not captures of the actual games, they're only previews):
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
For now, I have done this:
When you run the program, the logo "9999 in 1" appears flashing on screen until you press a key. Then the game selection showing the letters from "A"
to "E" starts.
Now I need to make a preview for every game and the selection of the game you want to play.
GAME A: Normal Tetris.
GAME B: Special Tetris (It's just basic Tetris with more types of bricks).
GAME C: Arkanoid.
GAME D: Grand Prix.
GAME E: Space Duel.
The game will save the record for every game. I don't want to make more than these 5 games, at least for now.
Ah, I need the sound effects, of course, and a starting and "game over" melodies.
|
|
Dani_Karmann
DIV Pro
Posts: 87
Registered: 4-8-2016
Member Is Offline
|
|
Before I make the two Tetris games, I will concentrate in the other three games: Arkanoid, Grand Prix and space Duel, and things like the lives
indicator, game selection, etc. I will move this project to the "WIPS" section under the title "LCD brick game simulation".
|
|
MikeDX
|
|
Wow Dani this is amazing
I haven't been online much lately (very busy at work and with home life)
Great to see this
You should take a look at my astro wars DIV game, which is an emulator of an LCD (actually VFD) display game which may give you an idea of how an LCD
game could be done.
|
|