• 【006期】用Processing写一个根据音乐变化的黑白格游戏


    简述

    为了创建一个简单的根据音乐变化的黑白格游戏,我们将利用Processing的简洁性和直观操作来实现。游戏的核心思想是:屏幕上呈现多个黑白格,随着音乐的播放,格子会根据音乐的节奏和强度变化颜色。这个游戏将使用Processing的sound库来分析音乐,根据音乐的节奏强度来触发不同的视觉效果。

    准备工作

    首先,确保你已经在Processing环境中安装了sound库。这可以通过Processing的“导入库…”功能完成,搜索并安装sound库。

    游戏设计

    • 游戏界面:屏幕被划分为多个小格,每个格子可以是黑色或白色。
    • 音乐分析:游戏会实时分析正在播放的音乐的节奏强度,并根据这个强度改变格子的颜色。
    • 互动性:玩家可以通过键盘操作影响某些游戏效果(例如,按下特定按键可以改变格子的排列方式或颜色变化的速度)。

    实现代码

    import processing.sound.*;
    
    SoundFile file;
    Amplitude amp; // 用于测量音乐的振幅
    int gridSize = 10; // 网格尺寸
    float[][] grid; // 存储每个格子的音频响应值
    
    void setup() {
      size(800, 600);
      background(255);
      
      // 加载音乐并播放
      file = new SoundFile(this, "yourMusicFile.mp3");
      file.loop();
      
      amp = new Amplitude(this);
      amp.input(file);
      
      // 初始化格子数组
      grid = new float[width/gridSize][height/gridSize];
    }
    
    void draw() {
      background(255);
      
      float currentAmp = amp.analyze(); // 获取当前音频的振幅
      
      // 更新每个格子的状态
      for (int x = 0; x < width/gridSize; x++) {
        for (int y = 0; y < height/gridSize; y++) {
          grid[x][y] = lerp(grid[x][y], currentAmp*100, 0.05); // 根据音频振幅更新格子状态
          fill(grid[x][y] > 50 ? 0 : 255); // 根据格子状态填充颜色
          rect(x*gridSize, y*gridSize, gridSize, gridSize); // 绘制格子
        }
      }
    }
    
    void keyPressed() {
      // 添加键盘互动,例如,按下空格键重新排列格子
      if (key == ' ') {
        // 重新排列格子的代码
      }
    }
    
    • 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

    注意事项

    1. 音乐文件:确保你有权使用的音乐文件放在Processing的data文件夹中,并且在SoundFile对象的构造函数中正确指定了文件名。
    2. 性能:根据你的计算机性能,可能需要调整gridSize或其他参数,以确保游戏运行流畅。
    3. 增强体验:考虑添加更多的视觉效果(如根据音乐节奏改变格子的颜色或大小)以及更复杂的用户互动(如不同的按键执行不同的视觉效果)。

    优化

    为了优化这个黑白格游戏,我们可以进行以下改进:

    1. 我们将采用更高效的方式来更新格子颜色,避免在每一帧中重绘整个网格。
    2. 我们可以添加一个阈值,当音频的振幅超过这个阈值时才更改颜色,从而创建更有节奏感的视觉效果。
    3. 我们可以添加一些动画效果,如渐变等,使视觉效果更平滑。
    4. 我们可以提供一个简单的用户界面,让用户能够控制音乐播放和停止,以及更改网格的尺寸和其他参数。

    下面是一段改进后的代码:

    import processing.sound.*;
    
    SoundFile file;
    Amplitude amp; 
    int gridSize = 20; 
    float[][] grid;
    float threshold = 0.01f; // 阈值
    int cols, rows;
    
    void setup() {
      size(600, 400);
      cols = width / gridSize;
      rows = height / gridSize;
      grid = new float[cols][rows];
      
      file = new SoundFile(this, "yourMusicFile.mp3");
      file.loop();
      
      amp = new Amplitude(this);
      amp.input(file);
      
      noStroke();
    }
    
    void draw() {
      float currentAmp = amp.analyze();
      
      for (int x = 0; x < cols; x++) {
        for (int y = 0; y < rows; y++) {
          // Simple animation effect using lerp
          grid[x][y] = lerp(grid[x][y], currentAmp > threshold ? 1 : 0, 0.1); 
          
          // Determine color based on amplitude
          fill(grid[x][y] * 255);
          rect(x * gridSize, y * gridSize, gridSize, gridSize);
        }
      }
    }
    
    void keyPressed() {
      if (keyCode == UP) {
        threshold += 0.005; // Increase the threshold
      } else if (keyCode == DOWN) {
        threshold -= 0.005; // Decrease the threshold
      } else if (keyCode == LEFT) {
        gridSize = max(gridSize - 5, 5); // Decrease grid size
        updateGrid();
      } else if (keyCode == RIGHT) {
        gridSize = min(gridSize + 5, 100); // Increase grid size
        updateGrid();
      } else if (key == ' ') {
        if (file.isPlaying()) {
          file.pause();
        } else {
          file.loop();
        }
      }
    }
    
    void updateGrid() {
      // Update grid dimensions based on new gridSize
      cols = width / gridSize;
      rows = height / gridSize;
      grid = new float[cols][rows]; // Reset grid
    }
    
    • 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

    上述代码对原有的黑白格游戏进行了优化,添加了对音量阈值的控制,并提供了通过键盘控制音乐播放、格子大小和阈值的功能。特别是,增大和减小网格的尺寸可以通过左右方向键来控制,改变音频阈值可以通过上下方向键来进行调节,空格键用来控制音乐的播放和暂停。这些改进使得游戏的互动性和可玩性大大增强。

    二次优化

    在这个游戏版本中,我们将创建一个游戏,其中黑白格子将从屏幕顶部随机生成,并且会根据音乐的节奏下落。玩家的任务是在格子到达屏幕底部前按下相应的键来消除它们。格子的大小和下落速度将随着音乐的节奏和强度变化。

     import processing.sound.*;
    
    SoundFile file;
    Amplitude amp;
    ArrayList<GridSquare> squares;
    float speedMultiplier = 1.0; // 下落速度倍数
    float lastAmp = 0; // 存储上一帧的振幅
    float ampChangeThreshold = 0.01; // 定义触发新格子生成的振幅变化阈值
    
    void setup() {
      size(800, 600);
    
      file = new SoundFile(this, "yourMusicFile.mp3");
      file.loop();
      
      amp = new Amplitude(this);
      amp.input(file);
    
      squares = new ArrayList<GridSquare>();
    }
    
    void draw() {
      background(255);
    
      float currentAmp = amp.analyze();
      
      // 如果振幅变化大于一定阈值,则生成新的格子
      if (Math.abs(currentAmp - lastAmp) > ampChangeThreshold) {
        float size = map(currentAmp, 0, 0.1, 10, 100); // 根据音量大小映射格子大小
        squares.add(new GridSquare(random(width - size), -size, size, speedMultiplier));
        lastAmp = currentAmp; // 更新上一帧的振幅值
      }
    
      // 更新并绘制所有格子
      for (int i = squares.size() - 1; i >= 0; i--) {
        GridSquare square = squares.get(i);
        square.update();
        square.display();
        if (square.isOffScreen() || square.isCleared()) { // 如果格子被清除或移出屏幕
          squares.remove(i);
        }
      }
    
      // 根据当前振幅更新下落速度倍数
      speedMultiplier = map(currentAmp, 0, 0.1, 0.5, 5);
    }
    
    void keyPressed() {
      // 检查每个格子是否与按键匹配的颜色
      for (int i = squares.size() - 1; i >= 0; i--) {
        GridSquare square = squares.get(i);
        if ((key == 'w' && square.isWhite()) || (key == 'b' && !square.isWhite())) {
          square.setCleared(true);
        }
      }
    }
    
    class GridSquare {
      float x, y, size, speed;
      boolean isWhite, cleared;
    
      GridSquare(float x, float y, float size, float speedMultiplier) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.speed = size / 20 * speedMultiplier; // 根据大小调整速度
        this.isWhite = random(1) > 0.5; // 随机决定颜色
      }
    
      boolean isWhite() {
        return isWhite;
      }
    
      boolean isOffScreen() {
        return y > height;
      }
    
      boolean isCleared() {
        return cleared;
      }
    
      void setCleared(boolean status) {
        cleared = status;
      }
    
      void update() {
        y += speed; // 根据速度下落
      }
    
      void display() {
        fill(isWhite ? 255 : 0);
        rect(x, y, size, size);
      }
    }
    
    
    • 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

    在这个游戏中:

    • GridSquare 类代表落下的格子。
    • 当检测到音乐节拍时,会创建一个新的 GridSquare 对象,并加入到 squares 列表中。
    • 格子的大小是根据音乐的振幅动态计算的,速度也根据格子的大小和音乐的振幅进行调整。
    • 按键 'w' 对应白色格子,按键 'b' 对应黑色格子。当按下相应的键时,格子会被标记为清除,并在下一帧中从列表中移除。
    • 游戏会持续生成新的格子并让它们下落,直到玩家按下相应的键来消除它们。

    你可以根据自己的喜好进行细节调整,比如调整格子生成的频率,或者增加更多的按键来消除不同颜色的格子。这个游戏框架提供了一个很好的起点来创建一个交互性强的音乐游戏。

  • 相关阅读:
    【Java万花筒】服务网格:微服务世界的交通管制中心
    最短Hamilton路径( 二进制 + 状态压缩dp)
    大数据分析案例-基于随机森林算法构建二手房价格预测模型
    python数据分析绘图
    《数据资产管理实践白皮书》5.0版--数据资产管理保障措施
    网站为什么要备案?网站备案流程是什么?
    leetcode.无重复字符的最长字串(刷题日记)
    Linux 下最主流的文件系统格式——ext
    MQTT 资源
    [附源码]计算机毕业设计汽配管理系统Springboot程序
  • 原文地址:https://blog.csdn.net/weixin_46339668/article/details/138144280