如何自己製作聲控遊戲?(聲控乒乓球)
跳至導覽
跳至搜尋
這是好和弦的第 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 版可以一邊「打乒乓球」一邊聽。