Now we tie everything back together.
Hangman hm;
Button[] alpha_buttons = new Button[26];
void setup() {
size(600, 400);
hm = new Hangman();
int t = 0;
for ( int j = 0; j < 3; j++) {
for ( int i = 0; i < 9; i++ ) {
if ( t < 26 ) {
alpha_buttons[t] = new Button(110 + 40 * i + (j==2?20:0), 280 + 40 * j, char(int('A'+t++)) );
}
}
}
}
void draw() {
background(0);
pushMatrix();
translate(100,0);
textSize(16);
textAlign(CORNER);
hm.show_debug_info();
popMatrix();
draw_man( hm.get_damage() ); //int(map(mouseX, 0, width, 0, 14)) );
for( int i = 0; i < 26; i++){
alpha_buttons[i].draw();
}
}
void mousePressed() {
for( int i = 0; i < 26; i++){
alpha_buttons[i].on_click();
}
}
void draw_man(int d) {
pushMatrix();
translate(10, height-10);
strokeWeight(4);
stroke(255);
int dm = 0;
if ( d > dm++ )
line(0, 0, 80, 0);
if ( d > dm++ )
line(0, 0, 0, -380);
if ( d > dm++ )
line(60, 0, 0, -60);
translate(0, -380);
if ( d > dm++ )
line(0, 0, 40, 0);
if ( d > dm++ )
line(40, 0, 40, 10);
translate(40, 40);
noFill();
if ( d > dm++ )
ellipse(0, 0, 60, 60);
translate(0, 30);
if ( d > dm++ )
line(0, 0, 0, 120);
if ( d > dm++ )
line(0, 20, -30, 120);
if ( d > dm++ )
line(0, 20, 30, 120);
if ( d > dm++ )
line(0, 120, -30, 220);
if ( d > dm++ )
line(0, 120, 30, 220);
popMatrix();
}
class Button {
float x, y, w, h;
char t;
int index;
Button( float ix, float iy, char it ) {
x = ix;
y = iy;
w = 30;
h = 30;
t = it;
index = int(t - 'A');
}
void draw() {
textAlign(CENTER);
textSize(28);
stroke(255);
strokeWeight(1);
noFill();
rect(x, y, w, h, 4);
fill(255);
text( t, x+15, y+25);
}
void on_click(){
if( over() ){
hm.cope_with_letter(t);
}
}
boolean over(){
return( x < mouseX && mouseX < x + w && y < mouseY && mouseY < y + h );
}
}
///// ----- You could even put the rest of this in a different tab!
class Hangman {
// A list of random words that could be used.
String [] words = {"telephone", "bull", "London", "Wales", "moon", "couch"};
// Which random word we are currently using.
int random_word_index;
// An array that tracks which letters are revealed.
boolean[] is_letter_revealed = new boolean[26];
// A counter that tracks how dead the hanging man is.
int deathometer;
Hangman() {
reset_game();
}
void reset_game() {
// Pick a new random word.
random_word_index = int(random(words.length));
// Reset all the revealed letters.
for ( int i = 0; i < is_letter_revealed.length; i++) {
is_letter_revealed[i] = false;
}
// Reset the deathometer counter.
deathometer = 0;
// Other things to reset game here.
}
void show_debug_info() {
//background(0);
// Show the current random word.
text( "Our random word is: " + words[ random_word_index ], 20, 20 );
// Show the currently revealed letters.
for ( int i = 0; i < is_letter_revealed.length; i++) {
if ( is_letter_revealed[i] ) {
text( char(int('A')+i), 10 * i, 40 );
}
}
// Show the hidden word with revealed letters.
for ( int i = 0; i < words[random_word_index].length(); i++) {
int letter_value = int(words[random_word_index].charAt(i));
// Deal with different cased letters in our hidden words.
if ( letter_value >= int('a') ) {
letter_value -= int('a');
} else {
letter_value -= int('A');
}
// Draw this letter or a blank space.
if ( is_letter_revealed[letter_value] ) {
text( char(int('A')+letter_value), 20 + 10 * i, 60 );
} else {
text( '_', 20 + 10 * i, 60 );
}
}
// Display the deathometer counter.
text( "Deathometer: " + deathometer, 20, 80 );
}
//void mousePressed() {
// reset_game();
//}
void cope_with_letter(char in_key) {
int letter_index = -1;
// Detect lowercase letters.
if ( in_key >= 'a' && in_key <= 'z' ) {
letter_index = int(in_key - 'a');
}
// Detect uppercase letters.
if ( in_key >= 'A' && in_key <= 'Z' ) {
letter_index = int(in_key - 'A');
}
// If a letter was detected, deal with it.
if ( letter_index != -1 ) {
// If this letter was already revealed, the player is dumb for picking the same letter again.
if ( is_letter_revealed[letter_index] ) {
// Punish player.
deathometer++;
return; // Nothing else to do about it!
}
is_letter_revealed[letter_index] = true;
// Was that letter in the hidden word? If not, deathometer increases!
if ( !word_has_letter( letter_index ) ) {
// Punish player.
deathometer++;
}
// Other things to do when a letter becomes revealed go here.
}
}
// Does the hidden word contain that letter?
boolean word_has_letter( int to_find ) {
for ( int i = 0; i < words[random_word_index].length(); i++) {
int letter_value = int(words[random_word_index].charAt(i));
if ( letter_value >= int('a') ) {
letter_value -= int('a');
} else {
letter_value -= int('A');
}
if ( to_find == letter_value ) {
return( true ); // We found it!
}
}
return( false ); // Not found in this word!
}
int get_damage() {
return( deathometer );
}
}
But alas, out tidy setup()
and draw()
functions are becoming a mess again!
Maybe the class Button is not enough. We can encapsulate the entire set of buttons into a single object too! Let’s take a moment now to tidy things up.
Hangman hangman;
Keyboard keyboard;
void setup() {
size(600, 400);
hangman = new Hangman();
keyboard = new Keyboard();
}
void draw() {
background(0);
hangman.draw();
keyboard.draw();
}
void mousePressed() {
keyboard.click();
}
///// ----- LINE OF TIDY
void draw_man(int d) {
pushMatrix();
translate(10, height-10);
strokeWeight(4);
stroke(255);
int dm = 0;
if ( d > dm++ )
line(0, 0, 80, 0);
if ( d > dm++ )
line(0, 0, 0, -380);
if ( d > dm++ )
line(60, 0, 0, -60);
translate(0, -380);
if ( d > dm++ )
line(0, 0, 40, 0);
if ( d > dm++ )
line(40, 0, 40, 10);
translate(40, 40);
noFill();
if ( d > dm++ )
ellipse(0, 0, 60, 60);
translate(0, 30);
if ( d > dm++ )
line(0, 0, 0, 120);
if ( d > dm++ )
line(0, 20, -30, 120);
if ( d > dm++ )
line(0, 20, 30, 120);
if ( d > dm++ )
line(0, 120, -30, 220);
if ( d > dm++ )
line(0, 120, 30, 220);
popMatrix();
}
class Keyboard {
Button[] alpha_buttons = new Button[26];
Keyboard() {
int t = 0;
for ( int j = 0; j < 3; j++) {
for ( int i = 0; i < 9; i++ ) {
if ( t < 26 ) {
alpha_buttons[t] = new Button(110 + 40 * i + (j==2?20:0), 280 + 40 * j, char(int('A'+t++)) );
}
}
}
}
void draw() {
for ( int i = 0; i < 26; i++) {
alpha_buttons[i].draw();
}
}
void click() {
for ( int i = 0; i < 26; i++) {
alpha_buttons[i].on_click();
}
}
}
class Button {
float x, y, w, h;
char t;
int index;
Button( float ix, float iy, char it ) {
x = ix;
y = iy;
w = 30;
h = 30;
t = it;
index = int(t - 'A');
}
void draw() {
textAlign(CENTER);
textSize(28);
stroke(255);
strokeWeight(1);
noFill();
rect(x, y, w, h, 4);
fill(255);
text( t, x+15, y+25);
}
void on_click() {
if ( over() ) {
hangman.cope_with_letter(t);
}
}
boolean over() {
return( x < mouseX && mouseX < x + w && y < mouseY && mouseY < y + h );
}
}
class Hangman {
// A list of random words that could be used.
String [] words = {"telephone", "bull", "London", "Wales", "moon", "couch"};
// Which random word we are currently using.
int random_word_index;
// An array that tracks which letters are revealed.
boolean[] is_letter_revealed = new boolean[26];
// A counter that tracks how dead the hanging man is.
int deathometer;
Hangman() {
reset_game();
}
void reset_game() {
// Pick a new random word.
random_word_index = int(random(words.length));
// Reset all the revealed letters.
for ( int i = 0; i < is_letter_revealed.length; i++) {
is_letter_revealed[i] = false;
}
// Reset the deathometer counter.
deathometer = 0;
// Other things to reset game here.
}
void show_debug_info() {
//background(0);
// Show the current random word.
text( "Our random word is: " + words[ random_word_index ], 20, 20 );
// Show the currently revealed letters.
for ( int i = 0; i < is_letter_revealed.length; i++) {
if ( is_letter_revealed[i] ) {
text( char(int('A')+i), 10 * i, 40 );
}
}
// Show the hidden word with revealed letters.
for ( int i = 0; i < words[random_word_index].length(); i++) {
int letter_value = int(words[random_word_index].charAt(i));
// Deal with different cased letters in our hidden words.
if ( letter_value >= int('a') ) {
letter_value -= int('a');
} else {
letter_value -= int('A');
}
// Draw this letter or a blank space.
if ( is_letter_revealed[letter_value] ) {
text( char(int('A')+letter_value), 20 + 10 * i, 60 );
} else {
text( '_', 20 + 10 * i, 60 );
}
}
// Display the deathometer counter.
text( "Deathometer: " + deathometer, 20, 80 );
}
void draw(){
draw_man( damage() );
pushMatrix();
translate(150, 50);
textSize(32);
// Show the hidden word with revealed letters.
for ( int i = 0; i < words[random_word_index].length(); i++) {
int letter_value = int(words[random_word_index].charAt(i));
// Deal with different cased letters in our hidden words.
if ( letter_value >= int('a') ) {
letter_value -= int('a');
} else {
letter_value -= int('A');
}
// Draw this letter or a blank space.
if ( is_letter_revealed[letter_value] ) {
text( char(int('A')+letter_value), 20 + 30 * i, 60 );
} else {
text( '_', 20 + 30 * i, 60 );
}
}
popMatrix();
}
//void mousePressed() {
// reset_game();
//}
void cope_with_letter(char in_key) {
int letter_index = -1;
// Detect lowercase letters.
if ( in_key >= 'a' && in_key <= 'z' ) {
letter_index = int(in_key - 'a');
}
// Detect uppercase letters.
if ( in_key >= 'A' && in_key <= 'Z' ) {
letter_index = int(in_key - 'A');
}
// If a letter was detected, deal with it.
if ( letter_index != -1 ) {
// If this letter was already revealed, the player is dumb for picking the same letter again.
if ( is_letter_revealed[letter_index] ) {
// Punish player.
deathometer++;
return; // Nothing else to do about it!
}
is_letter_revealed[letter_index] = true;
// Was that letter in the hidden word? If not, deathometer increases!
if ( !word_has_letter( letter_index ) ) {
// Punish player.
deathometer++;
}
// Other things to do when a letter becomes revealed go here.
}
}
// Does the hidden word contain that letter?
boolean word_has_letter( int to_find ) {
for ( int i = 0; i < words[random_word_index].length(); i++) {
int letter_value = int(words[random_word_index].charAt(i));
if ( letter_value >= int('a') ) {
letter_value -= int('a');
} else {
letter_value -= int('A');
}
if ( to_find == letter_value ) {
return( true ); // We found it!
}
}
return( false ); // Not found in this word!
}
int damage() {
return( deathometer );
}
}