-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathletterBoxedClone.js
297 lines (249 loc) · 9.07 KB
/
letterBoxedClone.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
'use strict'
document.addEventListener("keydown", handleKeyPress);
resetButton.addEventListener("click", initGame);
// universal consts
const ALPHABET = Array.from("ABCDEFGHIJKLNNOPQRSTUVWXYZ");
const VOWELS = Array.from("AEIOU");
const ctx = canvas.getContext("2d");
ctx.font = "35px Arial";
ctx.textAlign = "center";
ctx.lineWidth = 6;
const BACKGROUND_COLOR = "#FAA6A4";
const BOARD_VALS = {
x: 400,
y: 100,
width: 300,
height: 300,
}
const LETTER_COORDS = [
[ // top row
{x: BOARD_VALS.x + (BOARD_VALS.width / 6), y: BOARD_VALS.y}, // left
{x: BOARD_VALS.x + (BOARD_VALS.width / 2), y: BOARD_VALS.y}, // middle
{x: BOARD_VALS.x + (BOARD_VALS.width / 6 * 5), y: BOARD_VALS.y} // right
],
[ // right side
{x: BOARD_VALS.x + BOARD_VALS.width, y: BOARD_VALS.y + (BOARD_VALS.height / 6)}, // top
{x: BOARD_VALS.x + BOARD_VALS.width, y: BOARD_VALS.y + (BOARD_VALS.height / 2)}, // middle
{x: BOARD_VALS.x + BOARD_VALS.width, y: BOARD_VALS.y + (BOARD_VALS.height / 6 * 5)} // bottom
],
[ // bottom row
{x: BOARD_VALS.x + (BOARD_VALS.width / 6 * 5), y: BOARD_VALS.y + BOARD_VALS.height}, // right
{x: BOARD_VALS.x + (BOARD_VALS.width / 2), y: BOARD_VALS.y + BOARD_VALS.height}, // middle
{x: BOARD_VALS.x + (BOARD_VALS.width / 6), y: BOARD_VALS.y + BOARD_VALS.height} // left
],
[ // left side
{x: BOARD_VALS.x, y: BOARD_VALS.y + (BOARD_VALS.height / 6 * 5)}, // bottom
{x: BOARD_VALS.x, y: BOARD_VALS.y + (BOARD_VALS.height / 2)}, // middle
{x: BOARD_VALS.x, y: BOARD_VALS.y + (BOARD_VALS.height / 6)} // top
]
];
const LETTER_OFFSETS = [
{x: 0, y: -30}, // top row
{x: 40, y: 10}, // right side
{x: 0, y: 57}, // bottom row
{x: -40, y: 10} // left side
]
const CIRCLE_RADIUS = 10;
const GUESS_LINE_LENGTH = ctx.measureText("LETTER").width; // default width of line
const GUESS_COORDS = {
x: 198,
y: 100
};
const PAST_GUESS_COORDS = {
x: GUESS_COORDS.x,
y: GUESS_COORDS.y + 70
}
// game vars
let guess;
let pastGuesses;
let letters; // size 4 array of size 3 arrays
let lettersUsed; // same dimensions as letters array - holds ints representing # of times used
let current;
let lines;
let gameWon;
initGame();
function initGame() {
// take away focus from button
resetButton.blur();
// clear anything from prev instance of game
ctx.fillStyle = BACKGROUND_COLOR;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// reset game vars
guess = "";
pastGuesses = [];
letters = generateLetters();
lettersUsed = new Array(letters.length).fill(undefined).map(() => Array(letters[0].length).fill(0));
current = {side: -1, index: -1};
lines = [];
gameWon = false;
redraw();
}
// returns an array of arrays of 3 letters each
// currently using static vals for testing purposes
function generateLetters() {
return [
['O', 'Y', 'W',], // top row
['I', 'D', 'T',], // right side
['E', 'V', 'N',], // bottom row
['A', 'R', 'P',] // left side
];
}
function redraw() {
// clear everything
ctx.fillStyle = BACKGROUND_COLOR;
ctx.fillRect(0, 0, canvas.width, canvas.height);
redrawBoard();
// draw guess and line under it
ctx.fillStyle = ctx.strokeStyle = "black";
ctx.fillText(guess, GUESS_COORDS.x, GUESS_COORDS.y);
ctx.beginPath();
var width = ctx.measureText(guess).width;
width = width > GUESS_LINE_LENGTH ? width: GUESS_LINE_LENGTH; // allows for automatically resizing line
ctx.moveTo(GUESS_COORDS.x - width / 2 - 20, GUESS_COORDS.y + 15);
ctx.lineTo(GUESS_COORDS.x + width / 2 + 20, GUESS_COORDS.y + 15);
ctx.stroke();
// draw all old guesses
for (let i = 0; i < pastGuesses.length; i++) {
ctx.fillText(pastGuesses[i], PAST_GUESS_COORDS.x, PAST_GUESS_COORDS.y + (i * 30));
}
}
function redrawBoard() {
// draw the inside of the board (white part where the lines will be drawn)
ctx.fillStyle = "white";
ctx.fillRect(BOARD_VALS.x, BOARD_VALS.y, BOARD_VALS.width, BOARD_VALS.height);
// draw the lines
if (lines.length > 0) {
ctx.strokeStyle = BACKGROUND_COLOR;
ctx.beginPath();
ctx.moveTo(LETTER_COORDS[lines[0].start.side][lines[0].start.index].x, LETTER_COORDS[lines[0].start.side][lines[0].start.index].y);
for (let i = 0; i < lines.length; i++) {
ctx.lineTo(LETTER_COORDS[lines[i].end.side][lines[i].end.index].x, LETTER_COORDS[lines[i].end.side][lines[i].end.index].y);
}
ctx.stroke();
}
// draw the border rectange of the board
ctx.strokeStyle = "black";
ctx.strokeRect(BOARD_VALS.x, BOARD_VALS.y, BOARD_VALS.width, BOARD_VALS.height);
// draw the letters and their circles
for (let side = 0; side < letters.length; side++) {
for (let i = 0; i < letters[side].length; i++) {
ctx.fillStyle = lettersUsed[side][i] > 0 ? "black" : "white";
ctx.fillText(letters[side][i], LETTER_COORDS[side][i].x + LETTER_OFFSETS[side].x, LETTER_COORDS[side][i].y + LETTER_OFFSETS[side].y);
// draw path of circle
ctx.beginPath();
ctx.arc(LETTER_COORDS[side][i].x, LETTER_COORDS[side][i].y, CIRCLE_RADIUS, 0, 2 * Math.PI);
// fill black if this spot is the last entered letter and pink if used
if (current.side == side && current.index == i) {
ctx.fillStyle = "black";
} else if (lettersUsed[side][i] > 0) {
ctx.fillStyle = BACKGROUND_COLOR;
} else {
ctx.fillStyle = "white";
}
ctx.fill();
ctx.stroke();
}
}
}
function handleKeyPress(e) {
if (!gameWon) {
if (e.keyCode >= 65 && e.keyCode <= 90) {
console.log("letter pressed");
handleLetter(e.keyCode);
} else if (e.keyCode == 8) { // backspace
console.log("backspace pressed");
handleBackspace();
} else if (e.keyCode == 13) { // enter
console.log("enter pressed");
handleEnter();
}
}
}
function handleLetter(keyCode) {
// check letter limit
if (guess.length > 15) {
return;
}
// check if letter pressed is exists, and if so act accordingly
let letter = String.fromCharCode(keyCode);
let location = indexOfLetter(letter);
if (location.side >= 0 && location.side != current.side) {
// update guess
guess += letter;
// add line to list
if (current.side >= 0) {
lines.push({ start: current, end: location});
}
current = location;
lettersUsed[location.side][location.index]++;
redraw();
} else if (location.side < 0) {
alert(`${letter} isn't a valid option!`);
} else {
// alert(`Can't repeat letters from the same side!`); //this alert was annoying
}
}
function handleBackspace() {
// check if there is a letter to remove in this word
if (guess.length < 1) {
return;
}
lettersUsed[current.side][current.index]--;
guess = guess.slice(0, -1);
current = indexOfLetter(guess.slice(-1));
lines.pop();
// check if first letter was removed -> and if need to go to prev word
if (guess.length == 0) {
// if this is the first word, there is nothing special to do
if (pastGuesses.length == 0) {
// nothing
} else {
// otherwise go to the last word
guess = pastGuesses.pop();
current = indexOfLetter(guess.slice(-1));
lines = [];
for (let i = 0; i < guess.length - 1; i++) {
lines.push({ start: indexOfLetter(guess[i]), end: indexOfLetter(guess[i + 1])});
}
}
}
redraw();
}
function indexOfLetter(letter) {
// search through all letters
for (let side = 0; side < letters.length; side++) {
for (let i = 0; i < letters[side].length; i++) {
if (letters[side][i] == letter) { // once letter is found, return
return {side: side, index: i};
}
}
}
return {side: -1, index: -1};
}
function handleEnter() {
// if guess is a real word:
if (isWordInDictionary(guess)) {
console.log(`Logging ${guess} as a guess`);
pastGuesses.push(guess); // log guess
guess = guess.slice(-1); // add forced letter
let location = indexOfLetter(guess);
lettersUsed[location.side][location.index]++; // add forced letter to lettersUsed
redraw();
// check if game won
gameWon = true;
for (let side = 0; gameWon && side < lettersUsed.length; side++) {
for (let i = 0; gameWon && i < lettersUsed[side].length; i++) {
if (lettersUsed[side][i] == 0) {
gameWon = false;
}
}
}
// if gameWon (do the fun fun)
if (gameWon) {
guess = "";
current = {side: -1, index: -1};
redraw();
alert("You won! (give this msg more pizzazz later)");
}
}
}