-
Notifications
You must be signed in to change notification settings - Fork 0
/
scale_quiz.js
111 lines (96 loc) · 3.45 KB
/
scale_quiz.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
// TODO print canvas with open circles for all the necessary notes
// so the player can see them getting gradually filled in, and knows when the end is
// going up and down steadily with the notes of the scale.
let scale, scale_type, scale_notes, scale_base, scale_array;
let id, x // id of the canvas clearing interval, and initial drawing coordinate
let scale_length; // default length of a 2 octave scale
// fix these numbers, make it look good
let x_step = Math.floor(canvas.width/(scale_length+1));
let y_step = Math.floor(canvas.height/((scale_length)/2)) - 2;
let dot_coordinates = [];
let dot_idx = 0;
function refresh_timer(){
if ( Date.now() - last_note_time > 2000 ){
refresh();
}
}
function refresh(){ // this seems like wasteful repetition
clear_canvas();
open_dots();
dot_idx = 0;
note_sequence = [];
}
function open_dots(){ // this function is messy and it sucks, simplify it
// also it doesn't work right for shorter scales.
let x_ = 0;
ctx.fillStyle = "#123";
dot_coordinates = [];
for (let y_ = 0; y_ < (scale_length-1)/2; y_ ++){
x_ += x_step
ctx.beginPath();
h = canvas.height - 20 - y_*y_step;
dot_coordinates.push([x_, h]);
ctx.arc(x_, h, 10, 0, 2*PI, false)
ctx.fill();
}
for (y_ = (scale_length-1)/2 ; y_ >= 0; y_--){
x_ += x_step
ctx.beginPath();
h = canvas.height - 20 - y_*y_step;
dot_coordinates.push([x_,h]);
ctx.arc(x_, h, 10, 0, 2*PI, false)
ctx.fill();
}
}
function draw_dot(color){
ctx.fillStyle = color;
ctx.beginPath();
[x, h] = dot_coordinates[dot_idx++];
ctx.arc(x, h, 10, 0, 2*PI, false);
ctx.fill();
}
function generate_octaves(s){ // should be an option to change number of octaves
rev = s.slice().reverse();
up_down = [...s, ...s, 0, ...rev, ...rev];
scale_length = up_down.length;
x_step = Math.floor(canvas.width/(scale_length+1));
y_step = Math.floor(canvas.height/((scale_length)/2)) - 2;
refresh();
return up_down;
}
function random_scale(){
refresh();
if ( (scale = scales.get_random()) == null) return;
if ( (scale_base = notes.get_random()) == null) return;
scale_type = scale.name;
scale_notes = scale.notes;
scale_array = generate_octaves(scale_notes);
scale_array = addConstantModulo12(scale_array, scale_base.number)
cprint(scale_base.name + ' ' + scale_type);
}
function scale_listener(event){
const [type, key, intensity] = event.data;
if (type == KEYDOWN){
if (key%12 != note_sequence[note_sequence.length -1]%12){ // allows scales to be played in octaves
note_sequence.push(key);
let i = note_sequence.length - 1;
if (note_sequence[i]%12 == scale_array[i]%12){ // messy to check eq this way still
draw_dot("green");
} else {
draw_dot("red");
};
}
} else if (type == KEYUP && key%12 == scale_array[scale_array.length -1]%12 ){ // only finish on a keyup
if (arraysEqualMod12(note_sequence, scale_array)) random_scale();
} // should also clear the sequence if it does not match the first part of the scale ?
}
function scale_cleanup(){ // is this ever used?
clearInterval(id);
refresh();
}
function init_scale(){
canvas.style.display = 'block';
id = setInterval(refresh_timer, 50);
init_quiz(random_scale, scale_listener);
}
add_game_button('scales', init_scale);