We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hey guys, I've been working on a simple Tetris clone with the help of my teacher for an art assignment and since he is unable to help at the moment, I thought it might be best to turn to a forum which could help! I've got the basic layout but I'm new to Processing and coding in general and so can't figure out how to properly implement the keyPressed function to move the current falling object left/right, and I also want to pause the reset function that occurs when the blocks reach the top, so there's some string that says 'Your completed object' or something along those lines (I can edit later obviously).
My Tetris clone doesn't wipe lines of blocks, as it's all about the completed object at the end. I just need help with the implementation of these two things, can anyone help me out, pretty please? :) Code is below, apologies, can't figure out 'code' button:
int griDim = 40; //grid dimension
boolean trigger = false; // triggers the trigger() function to create a new block
int count = 1; // count of number of blocks
tetshap [] tetShaps = new tetshap[1000]; //creates an array of objects called tetShaps of class tetshap
void setup()
{
size(600, 600);
frameRate(40);
tetShaps[0] = new tetshap(); //create a first shape
}
void draw() {
background(255); //always draw a new background
for (int x=0; x < tetShaps.length; x++){ //go through all shapes in the array
if (tetShaps[x] != null){ // check to make sure there is a shape at this address
tetShaps[x].drawTetShap(); //for the object in tetShaps[x] call the function drawTetShap()
tetShaps[x].checkposition();}
if (tetShaps[x] != null){ //needed to check for null again here in order to cope with refreshed state
tetShaps[x].update(); //for the object in tetShaps[x] call the function update()
}
}
}
void trigger(){ // this function is called once a collision is detected
println(count); // just keeping track of the number of objects
tetShaps[count] = new tetshap(); //make a new shape
count++; //add to the count of blocks
}
void emptyArray(){ //this function clears the array when a block reaches the top
for(int x=0; x < tetShaps.length; x++){ // go through the array and set all to null (erasing all shapes)
tetShaps[x] = null;
}
tetShaps[0] = new tetshap(); //create a new shape to start again
count=1; // reset count
return; //return a way of breaking out of the existing loo
}
class tetshap {
int[][] tetShapArr = new int[4][3];
int speed;
color col = color((int)random(255),(int)random(255),(int)random(255));
boolean status = true;
int side = width/(griDim);
tetshap (){ //constriuctor that is called to make a new shape
speed = 1; //this is one to keep collision simple for the moment
int ypos = -10;
int xpos = (int)random(griDim+1);
for(int x=0; x< tetShapArr.length; x++){ //creating the tetris object
tetShapArr[x][0] = xpos;
tetShapArr[x][1] = ypos;
tetShapArr[x][2] = (int)random(4);
if (tetShapArr[x][2] == 0){
ypos--;}
if (tetShapArr[x][2]==1){
xpos++;}
if (tetShapArr[x][2]==2){
ypos++;}
if (tetShapArr[x][2]==3){
ypos++;}
}
}
void drawTetShap() { //draws all the shapes in the array every frame
fill(col);
for(int x=0; x< tetShapArr.length; x++){
int xDim = tetShapArr[x][0]*(width/(griDim+1));
int yDim = tetShapArr[x][1]*(height/(griDim+1));
side = width/(griDim+1);
rect(xDim,yDim,side,side);
}
}
void update() {
if (status==true){
for(int x=0; x< tetShapArr.length; x++){
tetShapArr[x][1]++;
}
}
}
void checkposition() {
if (status==true){ // this section checks for collisions if there was a collision it calls triiger to create a new shape
for(int i=0; i < tetShapArr.length; i++){
for(int x=0;x < count-1;x++){
for(int y=0; y < tetShaps[x].tetShapArr.length; y++){
if (tetShaps[x].tetShapArr[y][0] == tetShapArr[i][0]
&
tetShaps[x].tetShapArr[y][1] == tetShapArr[i][1]+1
){
status = false;
trigger();
return;
}
}
}
}
}
if (status==true){
for(int x=0; x < tetShapArr.length; x++){
if (tetShapArr[x][1]*(height/(griDim+1)) >= height-side){
status = false;
trigger();
return;
}
}
} else { // this section check for the object reaching the top and calls
if (status==false){
for(int x=0; x < tetShapArr.length; x++){
if (tetShapArr[x][1]*(height/(griDim+1)) <= 0){
emptyArray();
return;
}
}
}
}
}}
Answers
Please proper format the code.
http://forum.processing.org/two/discussion/8045/how-to-format-code-and-text#latest
in short: a skipped line before and after, select it, hit
ctr o
Thanks _vk, ended up just highlighting it all and ctr + o. Is this the right place to post my question by the way?
Any help guys?
I did not really understand the second question, sorry. But for handling the key-events, you could do it similar to this:
This moves them only once per key-press, if you want them to move as long as you press the key, then you could change your update-function to something like this:
These examples do not check if the tiles leave the screen, but maybe it's a start.
Thank you for your contribution benja, appreciate it. I understand that function now, thanks :) . In regards to my second point, I was wondering how I would go about pausing this section: 'emptyArray(); return;' So instead of immediately refreshing the game screen, it could display some text on top of the screen on a 5 second timer or something? Any thoughts on that?
Instead of calling "emptyArray" directly, you could set a boolean, indicating, that the game is over. In draw() you could then decide what shall be done when the game is over. Here is a small example that should show the concept:
Hey benja, thanks again. I'm having more trouble implementing this; not sure where to make these changes without destabilizing the rest of the code. Did you manage to get it working?
Yes, i could post a working code, but it was better if we could lead you to solve it yourself.
So as a start:
Create variables to store the state of the game and the time when the game ends:
At the point where you have resetArray() at the moment, you can write this instead:
Then in draw() you can do things depending on the state of "gameOver"
And important, when gameOver is true, then you have to check if enoght time has passed and if that is the case, you can reset the game:
Please try if you get it working, and post your code, if you have problems.
Thanks, that extra explanation helped a lot and I was able to work it in a lot easier than before :) The 'emptyArray();' function still doesn't seem to be working, it says 'game over' but doesn't clear the screen/reset after 5 seconds. Here's my code, perhaps I falsely installed those parts you suggested:
You are almost there.
First advice is to use CTRL-T ot CMD+T to auto-indent your code in processing. That helps to see where functions and conditional blocks end.
Then you would want to make update() and checkPosition() only be called when "gameOver" is false. You can try this:
It's telling me 'Duplicate local variable: x' in the
for (int x=0; x < tetShaps.length; x++) {
line. I know the problem but not sure how to fix it... Code below, (sorry for poor formatting):It's because you are nesting for-loops and declare the same variable "x" in both of them.
Actually, i have the impression that you just mixed my code with yours without understanding what it does. You don't need more than one loop there. Look at your original code and compare it to mine. What has changed? Do you understand why? What parts of the code are executed when gameOver is true or false?
Yes, I admittedly shoehorned your last contribution in without giving it as much thought as I should have; sorry, it's been a long day and I'm finding it hard to concentrate properly. Nevertheless, I went back through it and put in the 'if gameOver' clauses but it still doesn't display the ''game over'' text at the end, nor does it emptyArray. Probably some basic oversight on my part but I can't quite pin it down, sorry to have to ask:
It's how you put your if-clauses one into another. And you have this part double:
What about my prior code? Does it work if you just replace your draw()-function with mine?
Okay thanks for pointing that out, not sure how I missed that. Seems to be working well now, thanks benja! Sorry for being a tough case haha.
Another question if you're willing; would you know how to create (effectively) a barrier in the 'grid' which would prevent the objects in the array from being able to move past the left and right sides of the screen? I'd imagine it would be part of the drawTetShap() function?:
No, you have to check for borders when you change the x-position for your tiles. And only change the x-position when the new position is on screen.
I just saw, that you included both of the versions for key-handling that i posted. You should only use one of them ( in update() OR in keyPressed() ).
The way that you create and store your tiles makes the check a little difficult, but you could i.e. just check if tetShapArr[0][0] is between
0
andgriDim
and only change the x-positions if that is true.If that works, you could do the next step and find the lowest/highest x-position in your tile and check against that.