如何自己製作聲控遊戲?(聲控乒乓球)

出自 NiceChord Wiki
跳至導覽 跳至搜尋
如何自己製作聲控遊戲?(聲控乒乓球)
第 178 集縮圖.jpg
集數 第 178 集
首播/發佈日期 2018 年 6 月 23 日(1 年 3 個月前)

這是好和弦的第 178 集,首播日期為 2018 年 6 月 23 日。
在這一集 Wiwi 示範了如何製作一個聲控乒乓球遊戲。

YouTube 影片

摘要

設定初始數值

color p1_col = #4e84db;
color p2_col = #ab50d8;
color ball_col = #fff435; // ball color
color score_col = #aaaaaa; 
color winner_col = #aaaaaa; 

float pad_acc = 0.1; // pad accel
float pad_len = 140; // pad length
float pad_thick = 12; // pad thickness
float ball_x = 400;
float ball_y = 400;
float ball_xspd = 4;
float ball_startxspeed = 4; // ball x_speed reset
float ball_yspd = 0;
float ball_size = 36;
float ball_angle = 0.1;// ball angle
float ball_acc = 0.5; // ball accel after every hit
float ball_maxxspd = 2.5;
float ball_maxyspd = 4;
float h_margin = 30; // horizontal margin
int score_to_win = 5; // how many points to win
int winner = 0; // who won?

畫球拍和球

void draw_pad() {
  fill(p1_col);
  rect(h_margin, p1_y-(pad_len/2), pad_thick, pad_len); // p1 pad
  fill(p2_col);
  rect(width-h_margin-pad_thick, p2_y-(pad_len/2), pad_thick, pad_len); // p2 pad
}

void draw_ball() {
  fill(ball_col);
  ellipse(ball_x, ball_y, ball_size, ball_size);
}

球的邏輯

void move_ball() {
  ball_x = ball_x+ball_xspd;
  ball_y = ball_y+ball_yspd;
}

void ball_vbounce() {
  if (ball_y < ball_size/2) {
    ball_y = ball_size/2;
    ball_yspd = -ball_yspd;
  } else if (ball_y > height-ball_size/2) {
    ball_y = height-ball_size/2;
    ball_yspd = -ball_yspd;
  }
}

void ball_hbounce() {
  if (ball_x < ball_size/2) {
    // hit left wall, p2 scores
    ball_x = ball_size/2;
    ball_xspd = ball_startxspeed;
    ball_yspd = ball_yspd / 4;

    if (winner == 0) {
      play_sound("score2");
      p2_score++;
    }
  }

  if (ball_x > width-ball_size/2) {
    // hit right wall, p1 scores
    ball_x = width-ball_size/2;
    ball_xspd = -ball_startxspeed;
    ball_yspd = ball_yspd / 4;

    if (winner == 0) {
      play_sound("score1");
      p1_score++;
    }
  }
}

檢查球是否碰到牆壁

void paddle_collision() {
  // ball's moving left
  if (ball_xspd < 0) {
    if (ball_x > h_margin && ball_x < h_margin+pad_thick+ball_size/2) {
      if (ball_y > p1_y-(pad_len/2)-ball_size/2 && ball_y < p1_y+(pad_len/2)+ball_size/2) {
        // ball's touching p1
        ball_x = h_margin+pad_thick+ball_size/2;
        ball_xspd = -ball_xspd + ball_acc; //  reverse ball direction & add speed
        float offset = ball_y - p1_y;
        ball_yspd = ball_yspd + (offset * ball_angle); // ball bounce angle
        play_sound("pong");
      }
    }
  }
  // ball's moving right
  if (ball_xspd > 0) {
    if (ball_x > width-h_margin-pad_thick-ball_size/2 && ball_x < width-h_margin-ball_size/2) {
      if (ball_y > p2_y-(pad_len/2)-ball_size/2 && ball_y < p2_y+(pad_len/2)+ball_size/2) {
        // ball's touching p1
        ball_x = width-h_margin-pad_thick-ball_size/2;
        ball_xspd = -ball_xspd - ball_acc; //  reverse ball direction & add speed
        float offset = ball_y - p2_y;
        ball_yspd = ball_yspd + (offset * ball_angle); // ball bounce angle
        play_sound("pong");
      }
    }
  }
}

聲音辨識

MidiBus.list(); // List all available Midi devices on STDOUT. This will show each device's index and name.
myBus = new MidiBus(this, 0, -1); // Create a new MidiBus with no input device and the default Java Sound Synthesizer as the output device.

int p1_volume = 0;
int p2_volume = 0;
int p1_threshold = 40;
int p2_threshold = 40;

int p1_range_low = 40;
int p1_range_high = 60;
int p2_range_low = 54;
int p2_range_high = 72;

移動球拍

void calculate_target() {
  if (p1_volume > p1_threshold) {
    p1_target = map(p1_note, p1_range_low, p1_range_high, height-(pad_len/2), pad_len/2);
  }
  if (p2_volume > p2_threshold) {
    p2_target = map(p2_note, p2_range_low, p2_range_high, height-(pad_len/2), pad_len/2);
  }
}

void move_pad() {
  p1_spd = p1_target - p1_y;
  p2_spd = p2_target - p2_y;
  p1_spd *= pad_acc;
  p2_spd *= pad_acc;
  p1_y = p1_y + p1_spd;
  p2_y = p2_y + p2_spd;
}

彩蛋及其他

一邊……一邊聽

這次的大包裝 MP3 版可以一邊「打乒乓球」一邊聽。

影片中提及的連結