I spend the entire day trying to start from scratch since I do need the images resized...
I got maybe 1/2 way there then I had a though...
This morning I took Chrisir's original code and just deleted the img.resize(); lines and modified the
image(images[],x,y) to image(images[],x,y, resizeXval, resizeYval)...LOOK LIKE THATS ALL IT NEEDED!!!
The solution was exactly what Chrisir said in the last post... it had to do with that resize line...
I made it a bit prettier, added enough cards for 10 full levels, added a few soundbites, and a final GAME OVER YOU WON victory screen....
As far as I can tell its completely done!!! Chrisir thanks for all the help!!!
HERE IS A LINK TO THE DATA FILES AND SKETCH:
import ddf.minim.*;
Minim minim;
AudioPlayer player;
AudioPlayer player1;
AudioPlayer player2;
//
// to do (optional): if uneven, place non-existent tile into right lower corner? With 8 tiles.
// have each level twice? Twice two cards, twice 4 cards etc.
//
// global vars and constants
//
// how many images on the hard drive? (this+1) Must be in data folder and named 0.jpg, 1.jpg etc.
final int howManyImages = 18;
//
//
// level stuff
final int maxLevel = 10; // how many levels, e.g. 6
int level = 0; // current level: 0
//
// state of program / game
final int stateGameStartUp = 0;
final int stateGamePlay = 1;
final int stateGameGoToNextLevelPhase1 = 2; // these two provide a small delay
final int stateGameGoToNextLevelPhase2 = 3;
final int stateGameOver = 4;
final int stateGameShowHelp = 5;
//
int state = stateGameStartUp; // current
//
//
// data for tiles
int winningNumberOfTiles;
int TILES_HORZ ;
int TILES_VERT ;
int TOTAL_TILES ;
int tileWidth;
int tileHeight;
Tile[] tiles ;
int imageCode;
//
// allRandomNumberImage is a check list to avoid using the same image twice as long as possible...
String allRandomNumberImage="#";
PImage[] images = new PImage [howManyImages];
//
// image entering stuff
// The var "openImages" is a counter that controls the input logic while making a move (aka opening two tiles).
// It says how many tiles are currently shown? 0, 1 or 2. (before the move, during the move and after the move).
// Only when openImages is == 2 we need to compare the two images (and reset openImages to 0 then).
int openImages = 0; // counter for current move
int lastImage = -1; // which was the last tile? (1st tile opened)
int currentImage = -1; // which is the current tile / image? (2nd tile opened)
int timer;
PImage imgLogo;
PImage imgWin;
PImage imgBackGlobal;
PImage imgBack = new PImage();// image of back of card
//
//
// ------------------------------------------------------------------
// two main funcs
//
void setup()
{
size( 1800, 900);
println("start of setup() ");
//
minim = new Minim(this);
player = minim.loadFile("nfl.wav");
player1 = minim.loadFile("mixdown.wav");
player2 = minim.loadFile("crowd.wav");
imgLogo = loadImage("logo.jpg");
imgBackGlobal = loadImage("cardBack.jpg");
imgBack = loadImage("cardBack.jpg");
imgWin = loadImage("youWon.jpg");
//
for (int x=0; x<howManyImages; x++) {
images[x]=loadImage(str(x)+".jpg");
} // for
//
timer=millis();
println("end of setup()");
}
//
void draw()
{
switch (state) {
case stateGameStartUp:
// start screen and new level
println("STARTUP");
startScreen() ;
- break;
case stateGamePlay:
// play
//println("gameplay");
gamePlay();
break;
case stateGameGoToNextLevelPhase1:
// go to next level but only after a while
println("GTNL1");
goToNextLevel_1();
break;
case stateGameGoToNextLevelPhase2:
// go to next level but only after a while
println("GTNL2");
goToNextLevel_2();
break;
case stateGameOver:
// All levels done
println("gameover");
showWinScreen();
break;
case stateGameShowHelp:
// help - to do
println ( "This is your help / reached by F1 / not done yet...");
break;
default:
// error; shouldn't get here
println ("Error 86: unknown state");
break;
} // switch
//
} // func
// ---------------------------------------------------------------
// all funcs that get called from draw()
//
void startScreen() {
player.play();
player2.play();
// start screen : to do: make a cool start screen image
background(0);
// fill(2, 2, 255);
image(imgLogo, width/4.3, height/3.3);
textSize(80);
fill(255, 255, 255);
text ( " MEMORY GAME", width/3.5+200, height/2.2);
textSize(100);
text ( "LEVEL: "+(level+1), width/2.2, height/1.7);
text ( " ", 140, 301);
text ( " ", 140, 401);
// go next state but only after a while
if (timer + 5200 < millis()) {
initNewLevel();
state = stateGamePlay;
} // if
} // func
//
void gamePlay() {
// play
background(0);
drawTiles();
checkTwoShownTiles ();
} // func
//
void goToNextLevel_1() {
// wait before go to next level but only after a while
background(0);
drawTiles();
if (timer + 1000 < millis()) {
state=stateGameGoToNextLevelPhase2;
timer=millis();
} // if
} // func
//
void goToNextLevel_2() {
// go to next level but only after a while
background(0);
drawTiles();
showHooray();
if (timer + 1000 < millis()) {
// Was this the last level?
if (level==maxLevel) {
// yes, last level, game over.
state = stateGameOver; // won all levels
println("game over (all levels done).");
}
else
{
// no, go to next level.
state = stateGameStartUp;
timer=millis();
}
} // if
} // func
//
void showWinScreen() {
background(0);
drawTiles();
showHooray() ;
// show all levels done
background(0) ;
image(imgWin, 750,100);
fill(0); // black
noStroke();
rect (14, 104, 295, 100);
fill(255, 255, 255); // red
text ( " CONGRADULATIONS YOU FINISHED THE GAME!!!", 40, 160);
textSize(20);
text ( " CLICK MOUSE TO PLAY AGAIN", 40, 190);
player1.play();
} // func
//
// ------------------
//
void showHooray() {
- fill(255);
strokeWeight(3);
stroke(0);
rect (4, 4, 325, 100);
fill(2, 2, 255);
text ( "LEVEL FINISHED!!!", 10, 60);
} // func
// -----------------------------------------------------------
// all funcs for inits
//
void initNewLevel () {
//
- println("Init New Level #"+level);
//
// depending on current level set some basic vars
switch (level) {
case 0:
// just 2 pieces
TILES_HORZ =2;
TILES_VERT =1;
winningNumberOfTiles = 2;
break;
case 1:
// 4 pieces
TILES_HORZ =2;
TILES_VERT =2;
winningNumberOfTiles = 4;
break;
case 2:
TILES_HORZ =3;
TILES_VERT =2;
winningNumberOfTiles = 6;
break;
case 3:
TILES_HORZ =3;
TILES_VERT =3;
winningNumberOfTiles = 9; // is 8
break;
case 4:
TILES_HORZ =4;
TILES_VERT =3;
winningNumberOfTiles = 12; // is 12
break;
case 5:
TILES_HORZ =4;
TILES_VERT =4;
winningNumberOfTiles = 16; // is 16
break;
case 6:
TILES_HORZ =5;
TILES_VERT =4;
winningNumberOfTiles = 20; // is 20
break;
case 7:
TILES_HORZ =5;
TILES_VERT =5;
winningNumberOfTiles = 25; // is 24
break;
case 8:
TILES_HORZ =6;
TILES_VERT =5;
winningNumberOfTiles = 30; // is 30
break;
case 9:
TILES_HORZ =6;
TILES_VERT =6;
winningNumberOfTiles = 36; // is 36
break;
-
default:
println("Error 55: Unknown Level");
break;
} // switch
//
// have other vars based on that defined
if (level>0) {
// level > 0
defineNormalTileSet() ;
}
else
{
// level is 0
defineTileSetForLevelZero() ;
}
textSize(54);
- } // func
//
void defineTileSetForLevelZero() {
// level is 0
//
println ("******************LEVEL ZERO********************************");
// make data for tiles and the tiles
tileWidth=width/2;
tileHeight=height/2;
TOTAL_TILES = 2;
tiles = new Tile [TOTAL_TILES+1];
tiles[0] = new Tile (0, height-tileHeight);
tiles[1] = new Tile (tileWidth, height-tileHeight);
println("ENDTILES");
//
//
// make duplicates ---------------------
tiles[0].hasDuplicate=true; // both tiles have a duplicate now
tiles[1].hasDuplicate=true;
tiles[0].theImageCode=44; // both tiles get the same imageCode
tiles[1].theImageCode=44; // saying: you two are belonging together
int myImageIndex = giveImageIndex(); // get an index
tiles[0].loadImageIntoTile ( myImageIndex ); // same image
tiles[1].loadImageIntoTile ( myImageIndex );
- imgBack.copy(imgBackGlobal,
0, 0, imgBackGlobal.width, imgBackGlobal.height,
0, 0, tileWidth, 0);
- }
//
void defineNormalTileSet() {
//
int i=0;
tileWidth=width/TILES_HORZ-1 ;
tileHeight=tileWidth/2;
TOTAL_TILES = (TILES_HORZ)*(TILES_VERT);
// not even?
if (winningNumberOfTiles%2 != 0 ) {
- winningNumberOfTiles--;
}
tiles = new Tile [TOTAL_TILES+1];
// now define the tiles without the images ------------------
for (int x=0; x<TILES_HORZ; x++) {
for (int y=0; y<TILES_VERT; y++) {
tiles[i] = new Tile (tileWidth*x, tileHeight*y );
i++;
}
}
//
// make duplicates ---------------------
i=0;
// this arraylist "intTileIndexes" serves as a memory which
// cards we already treated
ArrayList <Integer> intTileIndexes = new ArrayList();
intTileIndexes.clear();
// fill the arraylist
for (int x=0; x<TILES_HORZ; x++) {
for (int y=0; y<TILES_VERT; y++) {
intTileIndexes.add( i );
i++;
}
}
// still make duplicates ------
i=0;
imageCode=0;
allRandomNumberImage="#";
for (int x=0; x<TILES_HORZ; x++) {
for (int y=0; y<TILES_VERT; y++) {
makeItHaveAnDuplicate( intTileIndexes, i );
i++;
} // for
} // for
//
// if not even, make one tile inexistent
i=0;
for (int x=0; x<TILES_HORZ; x++) {
for (int y=0; y<TILES_VERT; y++) {
// if our tile doesn't have a duplicate yet
if (!tiles[i].hasDuplicate) {
// we don't show it
tiles[i].exists=false;
} // if
i++;
} // for
} // for
//
imgBack.copy(imgBackGlobal,
0, 0, imgBackGlobal.width, imgBackGlobal.height,
0, 0, tileWidth, 0);
} // func
//
void makeItHaveAnDuplicate( ArrayList <Integer> intTileIndexes, int i ) {
// makeItHaveAnDuplicate
// if our tile doesn't have a duplicate yet, then it's on our to do list:
if (!tiles[i].hasDuplicate) {
// we search a random partner
int safetyCounter = 0; // that avoids that the loop takes too long...
// now we calculate a random number which is a index for intTileIndexes
int j2 = int(random (0, intTileIndexes.size()));
int j = intTileIndexes.get(j2);
// remark: he can't find a partner when the tiles are e.g. 9 (uneven),
// then we get an error here but that's ok
while ( (i==j || tiles[j].hasDuplicate ) &&
(safetyCounter<50) ) {
j2 = int(random (0, intTileIndexes.size()));
j = intTileIndexes.get(j2);
safetyCounter++;
}
// Did he found one?
if ( (i!=j) && (!tiles[j].hasDuplicate) ) {
// yes
// remove those from the arraylist
removeFromArrayList (intTileIndexes, i);
removeFromArrayList (intTileIndexes, j);
tiles[i].hasDuplicate=true; // both tiles have a duplicate now
tiles[j].hasDuplicate=true;
tiles[i].theImageCode=imageCode; // both tiles get the same imageCode
tiles[j].theImageCode=imageCode; // saying: you two are belonging together
int myImageIndex=giveImageIndex(); // get a name
tiles[i].loadImageIntoTile ( myImageIndex ); // same image
tiles[j].loadImageIntoTile ( myImageIndex );
//
imageCode++; // increase the code since it must be unique
}
else {
// println ("error 119");
} // else
} // if
}
//
int giveImageIndex() {
// gives a image file name (that is new)
int randomNumberImage = int (random(0, howManyImages));
int safetyCounter = 0;
// while not a new image keep on searching
while ( (allRandomNumberImage.indexOf ( "#"+ str ( randomNumberImage ) + "#" ) > -1 ) &&
(safetyCounter<30) ) {
randomNumberImage = int (random(0, howManyImages));
safetyCounter++;
}
// found a new one
allRandomNumberImage = allRandomNumberImage + "#" + str( randomNumberImage ) + "#" ;
// return value
// return str( randomNumberImage ) +".jpg";
return randomNumberImage;
} // func
//
void removeFromArrayList (ArrayList<Integer> myArrayList, int iToBeRemoved) {
// removes one item iToBeRemoved.
// With an array, we say balls.length. With an ArrayList,
// we say balls.size(). The length of an ArrayList is dynamic.
// Notice how we are looping through the ArrayList backwards.
// This is because we are deleting elements from the list.
for (int i = myArrayList.size()-1; i >= 0; i--) {
int iFromArrayList = int ( myArrayList.get(i));
if ( iFromArrayList==iToBeRemoved ) {
myArrayList.remove(i);
return;
}
} // for
} // func
//
// Inputs -----------------------------------------------------------------
//
void mousePressed() {
// switch state
switch (state) {
case stateGamePlay:
if (openImages != 2) {
// search
int x=-1;
for (int x2=0; x2<TOTAL_TILES; x2++) {
if (tiles[x2].mouseInside() && tiles[x2].exists
&& !tiles[x2].isSolved && !tiles[x2].isShown ) {
x=x2;
break;
} // if
} // for
//
// found?
if (x>-1) {
// when one image is open make sure that the 2nd is a different one
if ( ((openImages == 1) && ( x != lastImage)) ||
(openImages == 0) ) {
// yes?
if (tiles[x].mouseInside()) {
tiles[x].isShown=true;
openImages++;
if (openImages == 1) {
lastImage=x;
}
else
{
currentImage=x;
timer=millis();
} // else
} // if
} // if
} // if
} // if
break;
case stateGameOver:
level=0;
println("Blammo");
// initNewLevel();
// state = stateGamePlay;
state = stateGameStartUp;
timer=millis();
break;
default:
// do nothing
break;
} // switch
//
} // func
void keyPressed () {
if (state==stateGameOver) {
level=0;
openImages = 0; // counter for current move
lastImage = -1; // which was the last tile? (1st tile opened)
currentImage = -1; // which is the current tile / image? (2nd tile opened)
state = stateGameStartUp;
timer=millis();
}
}
// -------------------------------------------------------
// smaller tools
//
//
void drawTiles() {
// draw it
for (int x=0; x<TOTAL_TILES; x++) {//println("X: "+x+" TOTTILES: "+TOTAL_TILES);
tiles[x].draw();
}
//
}
//
void checkTwoShownTiles () {
// after a move:
// if two images are shown we have to check them
if (openImages == 2) {
// but only after a while
if (timer + 1000 < millis()) {
// two are shown (the user has made his move)
openImages=0; // reset
// check
if ( tiles[currentImage].theImageCode == tiles[lastImage].theImageCode)
{
// correct
println ("Good");
tiles[currentImage].isSolved=true;
tiles[lastImage].isSolved=true;
checkIfSolved();
}
else
{
// not correct: the are hidden again
tiles[currentImage].isShown=false;
tiles[lastImage].isShown=false;
}
}
}
} // func
//
void checkIfSolved() {
// check if this level is complete
int counter = 0;
// Are all shown and solved?
for (int x2=0; x2<TOTAL_TILES; x2++) {
if (tiles[x2].isSolved) {
counter ++;
}
}
//
if (counter==winningNumberOfTiles)
{
state=stateGameGoToNextLevelPhase1; // won this level -> stateGameGoToNextLevelPhase1
println ("You won this level.");
level++;
timer=millis();
}
}
//
// ================================================================
//Tile Class (one image card)
class Tile
{
int imgIndex; // the image index
float px; // position
float py;
// those three (4) could be unified to a var stateOfTile : nonExistent, withoutDuplicate, covered, shown, solved
boolean isShown = false; // shown or covered?
boolean isSolved = false; // the duplicate is not only shown but correct and now permanently shown
boolean exists = true; // does the tile exist at all?
boolean hasDuplicate = false; // while init not all images have a duplicate yet
//
int theImageCode = -1; // the partners are identified with the same number (which is otherwise meaningless, except both have the same).
//
// constr
Tile ( float px_, float py_ )
{
px=px_;
py=py_;
} // constr
//
void loadImageIntoTile ( int imageName_ ) {
imgIndex = imageName_;
} // method
//
void draw()
{
// if it exists at all?
if (exists) {
// we show it.
// uncovered or covered?
if (isShown) {
// open
if (images[imgIndex]!=null){
image(images[imgIndex], px, py,tileWidth,tileHeight);}
else
println ("images[imgIndex] is null");
stroke(255);
noFill();
rect(px, py, tileWidth, tileHeight);
// if tile is solved correctly
if (isSolved)
{
// we show the OK sign
textSize(34);
fill(255);
strokeWeight(4);
stroke(0);
rect(px+tileWidth-170, py+tileHeight-58, 160, 40);
fill(2, 2, 255);
text( "MATCH!", px+tileWidth-150, py+tileHeight-27 );
fill(255);
}
}
else
{println("Tiles not shown");
// not shown / covered tile with a "?" or imgBack
image(imgBack, px, py,tileWidth,tileHeight);
textSize(54);
stroke(255);
noFill();
//fill(0);
rect(px, py, tileWidth, tileHeight);
- } // else
} // if (exists) {
} // method
//
boolean mouseInside()
{
return ((px <= mouseX && mouseX <= px + tileWidth) &&
(py <= mouseY && mouseY <= py + tileHeight));
} // method
//
} // class