使用 Pyxel 入门 2D 游戏(第12部分):播放音效

发布: (2026年1月15日 GMT+8 23:00)
4 min read
原文: Dev.to

Source: Dev.to

注册声音

首先,在 Game 类的构造函数中注册一个声音。
pyxel.sound() 的参数指定 声音 ID

  • 声音 ID – 该数字稍后在播放声音时使用。

接下来,将以下数据传递给 set() 方法:

参数描述
notes (score)指定音高
tones波形类型(例如 p = 脉冲波)
volumes音量
effects声音效果(例如 f = 渐弱)
speed播放速度(数值越低播放越快)
# main.py
pyxel.sound(0).set(
    "c4g3",
    tones="p",
    volumes="76",
    effects="f",
    speed=20
)

播放声音

使用 pyxel.play() 时,最多可以同时播放四个声音。

  • 第一个参数指定 通道号(0–3)。
    如果使用相同的通道,新声音会覆盖之前的声音。
  • 第二个参数指定 声音 ID
# main.py
pyxel.play(0, 0)

完整代码

下面是实现本文中介绍的功能的完整代码。
sprite.py 文件与前一章节相同。)

# main.py
import pyxel
import math
import random
import sprite

W, H = 160, 120
SHIP_SPD = 1.4

ASTEROID_INTERVAL = 20
ASTEROID_LIMIT = 30

ASTEROID_SPD_MIN = 1.0
ASTEROID_SPD_MAX = 2.0
ASTEROID_DEG_MIN = 30
ASTEROID_DEG_MAX = 150

BULLET_SPD = 3

# Game
class Game:
    def __init__(self):
        """Constructor"""

        # Game over flag
        self.game_over_flg = False

        # Initialize score
        self.score = 0

        # Initialize player
        self.ship = sprite.ShipSprite(W / 2, H - 40)
        deg = 0 if random.random() < 0.5 else 180
        self.ship.move(SHIP_SPD, deg)

        # Asteroids
        self.asteroid_time = 0
        self.asteroids = []

        # Bullets
        self.bullets = []

        # Initialize Pyxel
        pyxel.init(W, H, title="Hello, Pyxel!!")
        pyxel.load("shooter.pyxres")

        # Sound (shot)
        pyxel.sound(0).set(
            "c4g3",
            tones="p",
            volumes="76",
            effects="f",
            speed=20
        )

        # Sound (hit)
        pyxel.sound(1).set(
            "e4d4c4",
            tones="p",
            volumes="76",
            effects="n",
            speed=20
        )

        pyxel.run(self.update, self.draw)

    def update(self):
        """Update process"""

        # Game over
        if self.game_over_flg:
            return

        # Update player
        self.ship.update()
        self.control_ship()
        self.overlap_spr(self.ship)

        self.check_interval()  # Add asteroids

        # Update asteroids
        for asteroid in self.asteroids:
            asteroid.update()
            self.overlap_spr(asteroid)
            # Collision check (asteroid × player)
            if asteroid.intersects(self.ship):
                self.game_over_flg = True

        # Update bullets (reverse order)
        for bullet in self.bullets[::-1]:
            bullet.update()
            # Remove if outside screen
            if bullet.y < 0:
                self.bullets.remove(bullet)
                continue
            # Collision check (bullet × asteroid)
            for asteroid in self.asteroids[::-1]:
                if asteroid.intersects(bullet):
                    self.score += 1
                    self.bullets.remove(bullet)
                    self.asteroids.remove(asteroid)

                    # Sound (hit)
                    pyxel.play(1, 1)
                    return

    def draw(self):
        """Draw process"""
        pyxel.cls(0)

        # Game over
        if self.game_over_flg:
            msg = "GAME OVER"
            pyxel.text(W / 2 - len(msg) * 2, H / 2, msg, 13)

        # Draw score
        pyxel.text(10, 10, f"SCORE:{self.score:04}", 12)

        # Draw player
        self.ship.draw()

        # Draw asteroids
        for asteroid in self.asteroids:
            asteroid.draw()

        # Draw bullets
        for bullet in self.bullets:
            bullet.draw()

    def control_ship(self):
        """Player action"""
        if pyxel.btnp(pyxel.KEY_SPACE):
            self.ship.flip_x()

            # Fire bullet
            bullet = sprite.BulletSprite(self.ship.x, self.ship.y)
            bullet.move(BULLET_SPD, 270)
            self.bullets.append(bullet)

            # Sound (shot)
            pyxel.play(0, 0)

    def overlap_spr(self, spr):
        """Wrap sprite around the screen"""
        if spr.x < -spr.w:
            spr.x = W
            return
        if W < spr.x:
            spr.x = -spr.w
            return
        if spr.y < -spr.h:
            spr.y = H
            return
        if H < spr.y:
            spr.y = -spr.h
            return

    def check_interval(self):
        # Asteroid spawn interval
        self.asteroid_time += 1
        if self.asteroid_time < ASTEROID_INTERVAL:
            retu```

```python
rn
        self.asteroid_time = 0

        # Limit number of asteroids
        if ASTEROID_LIMIT < len(self.asteroids):
            return

        # Add asteroid
        x = random.random() * W
        y = 0
        spd = random.uniform(ASTEROID_SPD_MIN, ASTEROID_SPD_MAX)
        deg = random.uniform(ASTEROID_DEG_MIN, ASTEROID_DEG_MAX)
        asteroid = sprite.AsteroidSprite(x, y)
        asteroid.move(spd, deg)
        self.asteroids.append(asteroid)

# Run the game
Game()

Kajiru

全屏控制

  • 进入全屏模式
  • 退出全屏模式

结束语

感谢您阅读至此。

我希望本系列能成为您自己游戏开发之旅的起点。

如果您喜欢它,点个 👍 将意义重大!

Back to Blog

相关文章

阅读更多 »