Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

tkinter - how to build sylvster rockets in python

the following code shows a sylvester fountain: with a black and blue background. i want some colorful rockets and rocketlauncher. the following code shows all details with the physics colors and shows how the fountain is programmed. iam thankful for help.

import tkinter as tk

from time        import time
from random      import choice, uniform
from math        import sin, cos
from dataclasses import dataclass

## Basic Geometric Shapes ######################################################

@dataclass
class TkShape:
    """Common base class for geometric shapes like circles, squares and
    triangles, which can be drawn on the `tk.Canvas` of a window.
    """

    def add_to_canvas(self, cv: tk.Canvas):
        """Add this shape to a canvas. Specific shapes, which inherit from
        TkShape, are expected to override this method.  If we add a shape to a
        canvas, the Tk library gives us an id, which can be used to remove the
        shape again. We store this id in the `cid` attribute, such that the
        `remove_from_canvas` method can remove it again.
        """
        pass

    def remove_from_canvas(self, cv: tk.Canvas):
        """Delete this shape from the canvas. Works the same for any shape."""
        if self.cid != None:
            cv.delete(self.cid)
            self.cid = None

@dataclass
class Circle(TkShape):
    """Class for a circle shape.

    The geometry and appearance of the circle is determined by its position on
    the canvas, its radius and its color.

    Attributes:
        pos_x: The x-coordinate of the circle's center on the canvas.
        pos_y: The y-coordinate of the circle's center on the canvas.
        radius: The radius of the circle.
        color: The color of the circle.
    """
    pos_x:  float
    pos_y:  float
    radius: float
    color:  str

    def add_to_canvas(self, cv: tk.Canvas):
        """Draw the circle on the canvas."""
        self.cid = cv.create_oval(
            self.pos_x - self.radius,
            self.pos_y - self.radius,
            self.pos_x + self.radius,
            self.pos_y + self.radius,
            fill = self.color)

@dataclass
class Square(TkShape):
    """Class for a square shape.

    The geometry and appearance of the square is determined by its position
    of it's center on the canvas, its size and its color.

    Attributes:
        pos_x: The x-coordinate of the square's center on the canvas.
        pos_y: The y-coordinate of the square's center on the canvas.
        size: The size of the square.
        color: The color of the square.
    """
    pos_x: float
    pos_y: float
    size:  float
    color: str

    def add_to_canvas(self, cv: tk.Canvas):
        """Draw the square on the canvas."""
        self.cid = cv.create_rectangle(
            self.pos_x - self.size,
            self.pos_y - self.size,
            self.pos_x + self.size,
            self.pos_y + self.size,
            fill = self.color)

@dataclass
class Triangle(TkShape):
    """Class for a triangle shape.

    The geometry and appearance of the circle is determined by the position of
    its corners on the canvas and its color.

    Attributes:
        pos_x1: The x-coordinate of the object's first corner.
        pos_y1: The y-coordinate of the object's first corner.
        pos_x2: The x-coordinate of the object's second corner.
        pos_y2: The y-coordinate of the object's second corner.
        pos_x3: The x-coordinate of the object's third corner.
        pos_y3: The y-coordinate of the object's third corner.
        color: The color of the circle.
    """
    pos_x1: float
    pos_y1: float
    pos_x2: float
    pos_y2: float
    pos_x3: float
    pos_y3: float
    color:  str

    def add_to_canvas(self, cv: tk.Canvas):
        """Draw the triangle on the canvas."""
        self.cid = cv.create_polygon(
            self.pos_x1, self.pos_y1,
            self.pos_x2, self.pos_y2,
            self.pos_x3, self.pos_y3,
            fill = self.color)

## Physics #####################################################################

@dataclass
class PhysicsObject:
    """Common base class for objects, which are influenced by physics and can be
    drawn on a screen.

    Attributes:
        pos_x: The x-coordinate of the object's position on the surface.
        pos_y: The y-coordinate of the object's position on the surface.
        vel_x: How fast the object moves horizontally.
        vel_y: How fast the object moves vertically.
    """
    pos_x: float
    pos_y: float
    vel_x: float
    vel_y: float

    def update(self, dt: float, gravity: float):
        """Simulate what physically happens to the object in the next `dt`
        seconds. The object's position is changed according to its velocity,
        which in turn is changed according to an external `gravity` constant."""
        self.pos_x += dt * self.vel_x
        self.pos_y += dt * self.vel_y
        self.vel_y += dt * gravity

    def render(self) -> list[TkShape]:
        """Describes how and where to draw this object by returning a list of
        shapes. Subclasses are expected to override this method."""
        return []

    def is_alive(self) -> bool:
        """Check if the object ist still alive. Overwritten by derived
        classes. PhysicsObjects which are dead will be removed from the
        simulation for performance reasons."""
        return True

## Particles ###################################################################

@dataclass
class Particle(PhysicsObject):
    """Common base class for fireworks particles, e.g. sparks flying off a
    rocket or coming out of a volcano.

    Any Particle is also a PhysicsObject, since they fly around and can be seen,
    but they also have a life time, after which they burn out, and a certain
    color and size. The precise shape of a Particle is determined by its
    subclasses below.

    Arguments:
        remaining_time: How many seconds until this particle is burnt out.
        color: The color of the particle.
        size: The size of the particle.
    """
    remaining_time: float
    color: str
    size: float

    def update(self, dt: float, gravity: float):
        """A particle is influenced by physics, just like any other
        PhysicsObject, but additionally the passed time `dt` influences the
        `remaining_time` before the particle burns out."""
        super().update(dt, gravity)
        self.remaining_time -= dt

    def is_alive(self):
        """Check if the particle is still alive or already burned out."""
        return self.remaining_time >= 0.0

@dataclass
class CircularParticle(Particle):
    """A Particle which has the shape of a Circle."""
    def render(self) -> list[TkShape]:
        """Draw the particle as a single circle shape."""
        return [
            Circle(
                pos_x = self.pos_x,
                pos_y = self.pos_y,
                radius = self.size,
                color = self.color
            )
        ]

@dataclass
class SquareParticle(Particle):
    """A Particle which has the shape of a Square."""
    def render(self) -> list[TkShape]:
        """Draw the particle as a single square shape."""
        return [
            Square(
                pos_x = self.pos_x,
                pos_y = self.pos_y,
                size = self.size,
                color = self.color
            )
        ]

@dataclass
class TriangleParticle(Particle):
    """A Particle which has the shape of a Triangle."""
    def render(self) -> list[TkShape]:
        """Draw the particle as a single triangle shape."""
        return [
            Triangle(
                pos_x1 = self.pos_x - self.size,
                pos_y1 = self.pos_y - self.size,
                pos_x2 = self.pos_x + self.size,
                pos_y2 = self.pos_y - self.size,
                pos_x3 = self.pos_x,
                pos_y3 = self.pos_y + self.size,
                color = self.color
            )
        ]

## Fireworks ###################################################################

@dataclass
class Firework(PhysicsObject):
    """Common base class for a Firework maintaining a list of Particles.

    Classes inheriting from a Firework, like our Volcano, are expected to
    override the `update` method to dynamically spawn new particles.

    Attributes:
        particles: list of the currently burning Particles, which belong to this
                   firework. At the beginning this should usually be the empty
                   list, because fireworks tend to spawn their own particles.
    """
    particles: list[Particle]

    def update_particles(self, dt: float, gravity: float):
        # Update all particles.
        for p in self.particles:
            p.update(dt, gravity)

        # Remove dead particles.
        alive_particles = []
        for p in self.particles:
            if p.is_alive():
                alive_particles += [p]
        self.particles = alive_particles

    def update(self, dt: float, gravity: float):
        # Simulate the physics for the fireworks object itself.
        super().update(dt, gravity)

        # Simulate the physics for all its particles.
        self.update_particles(dt, gravity)

    def render(self) -> list[TkShape]:
        """A Firework is rendered by rendering all its particles. Subclasses may
        want to override this method to render additional shapes for the
        firework body."""
        shapes = []
        for p in self.particles:
            shapes += p.render()
        return shapes

@dataclass
class Volcano(Firework):
    """A Volcano is a Firework, which continuously emits colored particles and
    has a body that looks like a large triangle.

    Attributes:
        particles_per_second: the number of particles to spawn per second.
        colors: the colors of the particles to spawn. Since our Volcano is
            pretty fancy, it spawns particles of different colors as time passes.
        age: how many seconds the Volcano exists.
        _particles_to_spawn: how many fractions of a particle we still need to
            spawn. This is an implementation detail from the physics simulation:
            if the time steps in `update` are very small, then it could be the
            case, that in each time step we would need to spawn 0.001 particles,
            so we need to accumulate those amounts, such that we notice when it
            goes beyond 1.0 and we actually have to spawn a new particle.
    """
    particles_per_second: float      = 100.0
    colors:               tuple[str] = ("red", "green", "silver", "gold")
    age:                  float      = 0.0
    _particles_to_spawn:  float      = 0.0

    def render(self) -> list[TkShape]:
        """A Volcano is drawn as a big triangle with particles coming out of
        th

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...