Advertisement
Guest User

Untitled

a guest
Apr 26th, 2025
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.07 KB | None | 0 0
  1. let song;
  2. let notes = [];
  3. let columns = [870, 980, 1090, 1200]; // x positions for each column
  4. let speed = 9; // speed of falling notes
  5. let score = 0; // score from hitting notes/missing notes
  6. let combo = 0;
  7. let currentSong = null;
  8. let nextNoteIndex = 0;
  9. let currentState = 0;
  10. let highlightedSongIndex = 0; // which song is currently selected
  11. let timingOffset = 0; // milliseconds
  12.  
  13. const gameState = {
  14. MENU: 0,
  15. GAME: 1,
  16. END: 2,
  17. };
  18.  
  19. let songs = [
  20. {
  21. name: "It's Going Down Now",
  22. file: "song1.mp3",
  23. timings: [527.9791666666666, 1327.9791666666667, 2010.6458333333333, 2559.9791666666665, 3199.9791666666665, 3797.3125, 4431.979166666666, 4949.3125, 5471.979166666666, 5951.979166666667, 6570.645833333334, 7178.645833333333, 7717.3125, 8341.3125, 8927.979166666666, 9471.979166666668, 10047.979166666666, 10650.645833333334, 11237.3125, 11839.979166666666, 12469.3125, 13077.3125, 13631.979166666668, 14101.3125, 14629.3125, 15178.645833333332, 15738.645833333332, 16261.312499999998, 16810.645833333332, 17397.3125, 17919.979166666668, 18559.979166666668], // milliseconds of when notes spawn
  24. columns: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // initially all 1, change them to 0, 1, 2, 3 for four columns
  25. durations: [180.10000000149012, 115.10000000149012, 209.80000000447035, 205.29999999701977, 290, 264.59999999403954, 274.79999999701977, 240, 235, 199.89999999850988, 264.5, 235.10000000149012, 209.70000000298023, 195, 204.69999999552965, 195, 205.19999999552965, 224.69999999552965, 169.79999999701977, 164.60000000149012, 180.20000000298023, 190.20000000298023, 175.20000000298023, 118.30000000447035, 140.20000000298023, 180.40000000596046, 125.10000000149012, 144.89999999850988, 120.10000000149012, 124.70000000298023, 89.5, 125.20000000298023] // note durations. 0 = tap note, > 0 = hold note
  26. },
  27. {
  28. name: "No More What Ifs",
  29. file: "song2.mp3",
  30. timings: [],
  31. columns: [],
  32. durations: [] // note durations. 0 = tap note, >0 = hold note
  33. }
  34. ];
  35.  
  36. function preload() {
  37. songs.forEach(song => {
  38. song.sound = loadSound(song.file); // Load sound files
  39. });
  40. }
  41.  
  42. function setup() {
  43. createCanvas(1280, 720);
  44. }
  45.  
  46. function draw() {
  47. background(0); // Always clear screen
  48.  
  49. if (currentState === gameState.MENU) {
  50. drawMenu();
  51. } else if (currentState === gameState.GAME) {
  52. drawGame();
  53.  
  54. // Draw score and combo if in game
  55. fill(255);
  56. textSize(32);
  57. textAlign(LEFT);
  58. text("Score: " + score, 20, 40);
  59. text("Combo: " + combo, 20, 80);
  60. }
  61. }
  62.  
  63. function drawMenu() {
  64. textSize(48);
  65. fill(255);
  66. textAlign(CENTER, CENTER);
  67. text("Song Select", width / 2, 100);
  68.  
  69. textSize(32);
  70. songs.forEach((song, i) => {
  71. let y = 250 + i * 60; // spacing songs vertically
  72.  
  73. if (i === highlightedSongIndex) {
  74. fill(255, 200, 0); // highlighted
  75. text("> " + song.name, width / 2, y);
  76. } else {
  77. fill(255); // normal
  78. text(song.name, width / 2, y);
  79. }
  80. });
  81. }
  82.  
  83. function drawGame() {
  84. // Draw hit zones
  85. columns.forEach((col, i) => {
  86. fill(50);
  87. rect(col - 25, height - 100, 50, 10);
  88. });
  89.  
  90. // Manage notes
  91. if (song.isPlaying()) {
  92. let currentTime = (song.currentTime() * 1000) + timingOffset; // Correcting timing offset
  93.  
  94. // Adjust for note fall time
  95. let fallTimeMs = (height - 100) / speed * (1000 / 60);
  96.  
  97. // Spawn new notes based on the current time
  98. while (nextNoteIndex < currentSong.timings.length && currentTime >= currentSong.timings[nextNoteIndex] - fallTimeMs) {
  99. spawnNote(
  100. currentSong.columns[nextNoteIndex],
  101. currentSong.timings[nextNoteIndex],
  102. currentSong.durations[nextNoteIndex]
  103. );
  104. nextNoteIndex++;
  105. }
  106. }
  107.  
  108. // Update and show notes
  109. for (let i = notes.length - 1; i >= 0; i--) {
  110. notes[i].update();
  111. notes[i].show();
  112. if (notes[i].y > height + 100) { // give some grace before removing
  113. notes.splice(i, 1); // remove missed notes
  114. combo = 0; // break combo if missed
  115. score -= 25; // reduce score for missed note
  116. }
  117. }
  118. }
  119.  
  120. function spawnNote(column, startTime, duration) {
  121. notes.push(new Note(columns[column], startTime, duration));
  122. }
  123.  
  124. class Note {
  125. constructor(x, startTime, duration) {
  126. this.x = x;
  127. this.startTime = startTime; // when the note spawns
  128. this.duration = duration; // how long you must hold
  129. this.y = 0;
  130. this.size = 40;
  131. this.holding = false; // if player is holding it
  132. this.heldTime = 0; // how long the player held
  133. }
  134.  
  135. update() {
  136. this.y += speed;
  137. if (this.holding) {
  138. this.heldTime += deltaTime;
  139. }
  140. }
  141.  
  142. show() {
  143. fill(255);
  144. if (this.duration > 0) {
  145. rect(this.x - this.size / 2, this.y - this.size / 2, this.size, this.duration / 10); // Longer rectangle for hold notes
  146. } else {
  147. rect(this.x - this.size / 2, this.y - this.size / 2, this.size, this.size); // Normal tap note
  148. }
  149. }
  150. }
  151.  
  152. function keyPressed() {
  153. if (currentState === gameState.MENU) {
  154. // Navigating through songs
  155. if (key === 'q' || key === 'Q') {
  156. highlightedSongIndex = (highlightedSongIndex - 1 + songs.length) % songs.length;
  157. }
  158. if (key === 'e' || key === 'E') {
  159. highlightedSongIndex = (highlightedSongIndex + 1) % songs.length;
  160. }
  161.  
  162. // Check ENTER key to select song
  163. if (keyCode === ENTER) {
  164. selectSong(highlightedSongIndex);
  165. }
  166. } else if (currentState === gameState.GAME) {
  167. // Handle key presses during the game state
  168. for (let i = notes.length - 1; i >= 0; i--) {
  169. if (keyMatches(notes[i])) {
  170. checkHit(notes[i], i);
  171. return;
  172. }
  173. }
  174. }
  175. }
  176.  
  177. function keyReleased() {
  178. for (let i = notes.length - 1; i >= 0; i--) {
  179. if (notes[i].holding) {
  180. if (notes[i].heldTime >= notes[i].duration - 100) { // allow small error
  181. score += 50; // Good hold
  182. combo++;
  183. } else {
  184. score -= 25; // Released too early
  185. }
  186. notes.splice(i, 1); // Remove the hold note
  187. }
  188. }
  189. }
  190.  
  191. function checkHit(note, index) {
  192. if (isNearTarget(note)) {
  193. if (note.duration > 0) {
  194. note.holding = true; // Hold notes are marked holding
  195. } else {
  196. notes.splice(index, 1); // Tap notes are deleted immediately
  197. }
  198. score += 25;
  199. combo++;
  200. } else {
  201. combo = 0; // Reset combo if missed
  202. score -= 25; // Decrease score for missed note
  203. }
  204. }
  205.  
  206. function selectSong(index) {
  207. currentSong = songs[index];
  208. notes = [];
  209. nextNoteIndex = 0;
  210. song = currentSong.sound;
  211. song.play();
  212. song.jump(0); // ensure it starts from 0
  213. currentState = gameState.GAME;
  214. }
  215.  
  216. // helpers
  217. function keyMatches(note) {
  218. if (note.x === columns[0] && ['d', 'D'].includes(key)) return true;
  219. if (note.x === columns[1] && ['f', 'F'].includes(key)) return true;
  220. if (note.x === columns[2] && ['j', 'J'].includes(key)) return true;
  221. if (note.x === columns[3] && ['k', 'K'].includes(key)) return true;
  222. return false;
  223. }
  224.  
  225. function isNearTarget(note) {
  226. return abs(note.y - (height - 100)) < 75;
  227. }
  228.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement