Arcade 碰撞实例1

python 复制代码
"""
Use Pymunk physics engine.

For more info on Pymunk see:
https://www.pymunk.org/en/latest/

To install pymunk:
pip install pymunk

Artwork from https://kenney.nl

If Python and Arcade are installed, this example can be run from the command line with:
python -m arcade.examples.pymunk_box_stacks

Click and drag with the mouse to move the boxes.
"""

import arcade
import pymunk
import timeit
import math

SCREEN_WIDTH = 1800
SCREEN_HEIGHT = 800
SCREEN_TITLE = "Pymunk test"


class PhysicsSprite(arcade.Sprite):
    def __init__(self, pymunk_shape, filename):
        super().__init__(filename, center_x=pymunk_shape.body.position.x, center_y=pymunk_shape.body.position.y)
        self.pymunk_shape = pymunk_shape


class CircleSprite(PhysicsSprite):
    def __init__(self, pymunk_shape, filename):
        super().__init__(pymunk_shape, filename)
        self.width = pymunk_shape.radius * 2
        self.height = pymunk_shape.radius * 2


class BoxSprite(PhysicsSprite):
    def __init__(self, pymunk_shape, filename, width, height):
        super().__init__(pymunk_shape, filename)
        self.width = width
        self.height = height


class MyGame(arcade.Window):
    """ Main application class. """

    def __init__(self, width, height, title):
        super().__init__(width, height, title)

        arcade.set_background_color(arcade.color.DARK_SLATE_GRAY)

        # -- Pymunk
        self.space = pymunk.Space()
        self.space.iterations = 35
        self.space.gravity = (0.0, -900.0)

        # Lists of sprites or lines
        self.sprite_list: arcade.SpriteList[PhysicsSprite] = arcade.SpriteList()
        self.static_lines = []

        # Used for dragging shapes around with the mouse
        self.shape_being_dragged = None
        self.last_mouse_position = 0, 0

        self.draw_time = 0
        self.processing_time = 0

        # Create the floor
        floor_height = 80
        body = pymunk.Body(body_type=pymunk.Body.STATIC)
        shape = pymunk.Segment(body, [0, floor_height], [SCREEN_WIDTH, floor_height], 0.0)
        shape.friction = 10
        self.space.add(shape, body)
        self.static_lines.append(shape)

        # Create the stacks of boxes
        for row in range(10):
            for column in range(10):
                size = 32
                mass = 1.0
                x = 500 + column * 32
                y = (floor_height + size / 2) + row * size
                moment = pymunk.moment_for_box(mass, (size, size))
                body = pymunk.Body(mass, moment)
                body.position = pymunk.Vec2d(x, y)
                shape = pymunk.Poly.create_box(body, (size, size))
                shape.elasticity = 0.2
                shape.friction = 0.9
                self.space.add(body, shape)
                # body.sleep()

                sprite = BoxSprite(shape, ":resources:images/tiles/boxCrate_double.png", width=size, height=size)
                self.sprite_list.append(sprite)

    def on_draw(self):
        """
        Render the screen.
        """

        # This command has to happen before we start drawing
        self.clear()

        # Start timing how long this takes
        draw_start_time = timeit.default_timer()

        # Draw all the sprites
        self.sprite_list.draw()

        # Draw the lines that aren't sprites
        for line in self.static_lines:
            body = line.body

            pv1 = body.position + line.a.rotated(body.angle)
            pv2 = body.position + line.b.rotated(body.angle)
            arcade.draw_line(pv1.x, pv1.y, pv2.x, pv2.y, arcade.color.WHITE, 2)

        # Display timings
        output = f"Processing time: {self.processing_time:.3f}"
        arcade.draw_text(output, 20, SCREEN_HEIGHT - 20, arcade.color.WHITE, 12)

        output = f"Drawing time: {self.draw_time:.3f}"
        arcade.draw_text(output, 20, SCREEN_HEIGHT - 40, arcade.color.WHITE, 12)

        self.draw_time = timeit.default_timer() - draw_start_time

    def on_mouse_press(self, x, y, button, modifiers):
        if button == arcade.MOUSE_BUTTON_LEFT:
            self.last_mouse_position = x, y
            # See if we clicked on anything
            shape_list = self.space.point_query((x, y), 1, pymunk.ShapeFilter())

            # If we did, remember what we clicked on
            if len(shape_list) > 0:
                self.shape_being_dragged = shape_list[0]

        elif button == arcade.MOUSE_BUTTON_RIGHT:
            # With right mouse button, shoot a heavy coin fast.
            mass = 60
            radius = 10
            inertia = pymunk.moment_for_circle(mass, 0, radius, (0, 0))
            body = pymunk.Body(mass, inertia)
            body.position = x, y
            body.velocity = 2000, 0
            shape = pymunk.Circle(body, radius, pymunk.Vec2d(0, 0))
            shape.friction = 0.3
            self.space.add(body, shape)

            sprite = CircleSprite(shape, ":resources:images/items/coinGold.png")
            self.sprite_list.append(sprite)

    def on_mouse_release(self, x, y, button, modifiers):
        if button == arcade.MOUSE_BUTTON_LEFT:
            # Release the item we are holding (if any)
            self.shape_being_dragged = None

    def on_mouse_motion(self, x, y, dx, dy):
        if self.shape_being_dragged is not None:
            # If we are holding an object, move it with the mouse
            self.last_mouse_position = x, y
            self.shape_being_dragged.shape.body.position = self.last_mouse_position
            self.shape_being_dragged.shape.body.velocity = dx * 20, dy * 20

    def on_update(self, delta_time):
        start_time = timeit.default_timer()

        # Check for balls that fall off the screen
        for sprite in self.sprite_list:
            if sprite.pymunk_shape.body.position.y < 0:
                # Remove balls from physics space
                self.space.remove(sprite.pymunk_shape, sprite.pymunk_shape.body)
                # Remove balls from physics list
                sprite.remove_from_sprite_lists()

        # Update physics
        # Use a constant time step, don't use delta_time
        # See "Game loop / moving time forward"
        # https://www.pymunk.org/en/latest/overview.html#game-loop-moving-time-forward
        self.space.step(1 / 60.0)

        # If we are dragging an object, make sure it stays with the mouse. Otherwise
        # gravity will drag it down.
        if self.shape_being_dragged is not None:
            self.shape_being_dragged.shape.body.position = self.last_mouse_position
            self.shape_being_dragged.shape.body.velocity = 0, 0

        # Move sprites to where physics objects are
        for sprite in self.sprite_list:
            sprite.center_x = sprite.pymunk_shape.body.position.x
            sprite.center_y = sprite.pymunk_shape.body.position.y
            sprite.angle = math.degrees(sprite.pymunk_shape.body.angle)

        # Save the time it took to do this.
        self.processing_time = timeit.default_timer() - start_time


def main():
    MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)

    arcade.run()


if __name__ == "__main__":
    main()

这个程序使用了Pymunk物理引擎来模拟物理效果。在游戏窗口中,有一些方块和圆形对象受到重力影响并且可以与鼠标交互。

在初始化方法中,创建了一个Pymunk空间和一个静态地面,然后创建了一些方块对象并添加到空间中。这些方块对象对应的Sprite存储在sprite_list列表中。

在绘制方法中,首先清除屏幕,然后绘制所有的Sprite和静态线条。接着显示处理时间和绘制时间。

在鼠标按下方法中,如果按下的是左键并且点击到了一个对象,就将该对象设置为正在拖动的对象。如果按下的是右键,就在鼠标位置发射一个快速的重物。

在鼠标释放方法中,如果松开的是左键,则停止拖动对象的操作。

在鼠标移动方法中,如果正在拖动一个对象,就将对象的位置设置为鼠标位置,并更新对象的速度。

在更新方法中,首先检查是否有对象掉落出屏幕,如果有则从空间中移除该对象。接着更新物理引擎状态,如果有对象正在被拖动,则将其位置设置为鼠标位置,并将其速度设置为0。最后,将Sprite的位置更新为物理对象的位置,并保存处理时间。

最后,在main方法中创建游戏实例并运行游戏循环。

相关推荐
资源分享助手15 小时前
我!勇者?The Warrior免安装中文版下载与玩法体验
游戏
云起SAAS17 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
津津有味道18 小时前
一键写入启动游戏NDEF复合记录NFC标签vb6源码
游戏·标签·nfc·ndef·复合记录
游乐码19 小时前
Unity基础(四)向量相关
游戏·unity·游戏引擎
阿阳微客21 小时前
网易Buff游戏搬砖,长期可做!
笔记·学习·游戏
Kurisu57521 小时前
探灵直播2026最新官方正版免费下载 一键转存 永久更新 (看到速转存 资源随时走丢)
游戏·游戏引擎·游戏程序·动画·关卡设计
STDD1 天前
Abiotic Factor多人生存建筑游戏《非生物因素》 专用服务器搭建教程
服务器·数据库·游戏
开开心心就好1 天前
带OCR识别的电子发票打印工具
运维·javascript·科技·游戏·青少年编程·ocr·powerpoint
经济元宇宙1 天前
HOPE星火燎原不是希望工程,也不是游戏项目:项目名称与定位澄清
游戏
2601_950316061 天前
XBOX360 KINECT体感游戏合集109个
游戏