示例#1
0
    def _change_sun_state(self, sun_np, task):
        """Change Sun color and angle with a small step.

        Args:
            sun_np (panda3d.core.NodePath): Sun node path.
        """
        if self._color_step == self._day_part_duration:
            self._color_step = 0

            self._color = self._next_color
            self._next_color = copy.deepcopy(next(SUN_COLORS))

            self._color_vec = self._calc_color_vec(self._color,
                                                   self._next_color,
                                                   self._day_part_duration)
            # start Sun movement interval
            if self._color["name"] == "night":
                self._arch_int = MopathInterval(
                    self._path,
                    sun_np,
                    duration=self._day_part_duration * self._step_duration * 3,
                    name="sun_interval",
                )
                self._arch_int.start()

        # do color changing step
        for field in ("dir", "amb"):
            for i in range(3):
                self._color[field][i] += self._color_vec[field][i]

        self._dir_light.setColor(self._color["dir"])
        self._amb_light.setColor(self._color["amb"])
        self._color_step += 1
        return task.again
示例#2
0
    def _set_day_night_cycle(self, sun_np, day_time):
        """Set intervals and methods for day-night cycle.

        Args:
            sun_np (panda3d.core.NodePath): Sun node path.
            day_time (dict): Day time description.
        """
        taskMgr.doMethodLater(  # noqa: F821
            self._step_duration,
            self._change_sun_state,
            "change_sun_color",
            extraArgs=[sun_np],
            appendTask=True,
        )
        self._arch_int = MopathInterval(
            self._path,
            sun_np,
            duration=day_time["time"]["duration"]
            if day_time else self._day_part_duration * self._step_duration * 2,
            name="sun_interval",
        )

        self._arch_int.start(
            startT=day_time["time"]["current"] if day_time else 0)

        taskMgr.doMethodLater(  # noqa: F821
            0.01,
            self._sun_look_at_train,
            "sun_look_at_train",
            extraArgs=[sun_np],
            appendTask=True,
        )
示例#3
0
    def _jump_and_explode(self, task):
        """Jump to the Adjutant and self-explode."""
        if self.current_part is None:
            return task.done

        for char in base.world.enemy.active_units.values():  # noqa: F821
            if type(char
                    ) == Kamikaze and char.id != self.id and char.is_jumping:
                return task.again

        self.is_jumping = True
        self._stop_tasks("_float_move")
        self._move_int.pause()

        Sequence(
            LerpPosInterval(self.node,
                            2.5, (self._y_pos, -0.5, 0),
                            blendType="easeInOut"),
            Func(self._ignite_the_wick),
            LerpPosInterval(
                self.node,
                4.5,
                (-0.45 if self._y_pos < 0 else 0.45, -0.8, 0),
                blendType="easeInOut",
            ),
            Func(self._jump_snd.play),
            MopathInterval(self._jump_path,
                           self.model,
                           duration=0.8,
                           name=self.id + "_jump"),
            Func(self._die, True),
        ).start()
        return task.done
示例#4
0
    def _jump_and_brake(self, task):
        """Jump over the railway and drop a brake shoe."""
        if not self._brakes or self.current_part is None:
            return task.done

        for char in base.world.enemy.active_units.values():  # noqa: F821
            # if someone is jumping now, don't jump
            if (type(char) == BrakeThrower and char.id != self.id
                    and char.is_jumping) or (base.train.l_brake and
                                             base.train.r_brake  # noqa: F821
                                             ):
                return task.again

        y_target = round(abs(self._y_pos) - 0.55, 2)
        if self._y_pos < 0:
            y_target = -y_target

        if y_target not in self._y_positions:
            return task.again

        self._y_positions.remove(y_target)

        self.is_jumping = True
        self._stop_tasks("_float_move")
        self._move_int.pause()

        taskMgr.doMethodLater(  # noqa: F821
            0.15,
            self._jump_snd.play,
            self.id + "_jump_sound",
            extraArgs=[])
        taskMgr.doMethodLater(  # noqa: F821
            1.5,
            self._fall_snd.play,
            self.id + "_fall_sound",
            extraArgs=[])
        taskMgr.doMethodLater(  # noqa: F821
            1,
            self._drop_brake,
            self.id + "_drop_brake",
            extraArgs=[take_random(self._brakes)],
        )
        self._jump_int = Sequence(
            MopathInterval(
                self._r_mopath if self._y_pos < 0 else self._l_mopath,
                self.model,
                duration=2.5,
                name=self.id + "_low_jump",
                blendType="easeOut",
            ),
            Func(self._finish_jump),
        )
        self._jump_int.start()

        self._y_positions.append(self._y_pos)
        self._y_pos = y_target
示例#5
0
    def move_along_block(self, block, train_np, do_turn):
        """Start the locomotive move intervals for the given block.

        There are two intervals: the locomotive movement
        and synchronous camera movement.

        Args:
            block (world.block.Block):
                The World block to move along.
            train_np (panda3d.core.NodePath): Train node.
            do_turn (int):
                0 if default direction was chosen,
                1 if a turn is needed.
        """
        self.on_et = block.enemy_territory
        self._outing_available = block.outing_available
        # use speed value from the last block
        rate = self._move_par.getPlayRate() if self._move_par else 1

        is_fork = block.name in ("r_fork", "l_fork", "exit_from_fork")

        self._move_par = Parallel(
            MopathInterval(  # locomotive movement
                block.path[do_turn] if is_fork else block.path,
                self._model,
                duration=4.4,
                name="current_path",
            ),
            MopathInterval(  # camera movement
                block.cam_path[do_turn] if is_fork else block.cam_path,
                train_np,
                duration=4.4,
                name="current_camera_path",
            ),
        )
        self._move_par.setDoneEvent("block_finished")
        self._move_par.start()
        self._move_par.setPlayRate(rate)
示例#6
0
    def __init__(self):
        x_coor, side = random.choice(
            ((0.553, "left"), (-0.553, "right"), (0, "top")))

        self._model = Actor(address("rocket1"))
        self._model.reparentTo(base.train.model)  # noqa: F821
        self._model.setPos(x_coor, -7, 0.5)

        self._smoke = ParticleEffect()
        self._smoke.loadConfig("effects/smoke_tail.ptf")
        self._smoke.start(self._model, render)  # noqa: F821

        path = Mopath.Mopath(objectToLoad=loader.loadModel(  # noqa: F821
            address("rocket_{}_path".format(side))))
        path.fFaceForward = True

        self._hiss_snd = base.sound_mgr.loadSfx(
            "sounds/rocket_fly.ogg")  # noqa: F821
        base.sound_mgr.attachSoundToObject(self._hiss_snd,
                                           self._model)  # noqa: F821

        self._hiss_snd2 = base.sound_mgr.loadSfx(
            "sounds/rocket_hiss.ogg")  # noqa: F821
        base.sound_mgr.attachSoundToObject(self._hiss_snd2,
                                           self._model)  # noqa: F821

        self._hiss_snd.play()
        seq = Sequence(
            LerpPosInterval(self._model,
                            7, (x_coor, -0.627, 0.561),
                            blendType="easeOut"),
            Wait(0.7),
            Parallel(
                SoundInterval(self._hiss_snd2),
                MopathInterval(path,
                               self._model,
                               duration=0.5,
                               name="rocket_current_path"),
            ),
            Func(self._explode, side),
        )
        seq.start()
示例#7
0
class Sun:
    """The game Sun. Includes ambient and directional lights.

    Sun changes its color according to game day time.
    Simulates real Sun movement as well.

    Args:
        day_part_desc (dict): Day part description.
    """
    def __init__(self, day_part_desc):
        self._path = Mopath.Mopath(objectToLoad=address("sun_path"))

        self._color = copy.deepcopy(next(SUN_COLORS))
        self._next_color = copy.deepcopy(next(SUN_COLORS))
        self._color_step = 0

        if day_part_desc:
            while self._color["name"] != day_part_desc["name"]:
                self._color = self._next_color
                self._next_color = copy.deepcopy(next(SUN_COLORS))

            self._color = day_part_desc["time"]["color"]
            self._color_step = day_part_desc["time"]["step"]

        # day duration = 90 steps * 10 sec/step = 15 min/part
        # 15 min/part * 4 parts = 1 hour/day
        self._day_part_duration = 90
        self._step_duration = 9

        self._arch_int = None

        self._color_vec = self._calc_color_vec(self._color, self._next_color,
                                               self._day_part_duration)

        self._amb_light, self._dir_light, sun_np = self._set_general_lights(
            base.train.node  # noqa: F821
        )
        self._set_day_night_cycle(sun_np, day_part_desc)

    @property
    def day_part(self):
        """Day part name.

        Returns:
            str: day part name.
        """
        return self._color["name"]

    @property
    def day_part_time(self):
        """Exact day part step.

        Returns:
            int: Day part step.
        """
        return {
            "step": self._color_step,
            "duration": self._arch_int.getDuration(),
            "current": self._arch_int.getT(),
            "color": self._color,
        }

    @property
    def is_dark(self):
        """Returns True if it's too dark to shoot."""
        if self.day_part == "evening" and self._color_step > 45:
            return True

        if self.day_part == "night" and self._color_step < 45:
            return True

        return False

    def _set_general_lights(self, train_np):
        """Set initial Sun lights.

        Args:
            train_np (panda3d.core.NodePath): Train node.

        Returns:
            panda3d.core.AmbientLight: Sun ambient light.
            panda3d.core.DirectionalLight: Sun directional light.
            panda3d.core.NodePath: NodePath of the Sun.
        """
        amb_light = AmbientLight("sun_amb")
        amb_light.setColor(self._color["amb"])
        render.setLight(render.attachNewNode(amb_light))  # noqa: F821

        lens = PerspectiveLens()
        lens.setNearFar(1, 100)
        lens.setFov(20, 20)

        sun_light = Spotlight("sun_dir")
        sun_light.setColor(self._color["dir"])
        sun_light.setShadowCaster(True, 8192, 8192, sort=-2000)
        sun_light.setLens(lens)
        sun_light.setExponent(0.5)
        sun_light.setCameraMask(0b0001)
        sun_np = train_np.attachNewNode(sun_light)

        render.setLight(sun_np)  # noqa: F821
        return amb_light, sun_light, sun_np

    def _set_day_night_cycle(self, sun_np, day_time):
        """Set intervals and methods for day-night cycle.

        Args:
            sun_np (panda3d.core.NodePath): Sun node path.
            day_time (dict): Day time description.
        """
        taskMgr.doMethodLater(  # noqa: F821
            self._step_duration,
            self._change_sun_state,
            "change_sun_color",
            extraArgs=[sun_np],
            appendTask=True,
        )
        self._arch_int = MopathInterval(
            self._path,
            sun_np,
            duration=day_time["time"]["duration"]
            if day_time else self._day_part_duration * self._step_duration * 2,
            name="sun_interval",
        )

        self._arch_int.start(
            startT=day_time["time"]["current"] if day_time else 0)

        taskMgr.doMethodLater(  # noqa: F821
            0.01,
            self._sun_look_at_train,
            "sun_look_at_train",
            extraArgs=[sun_np],
            appendTask=True,
        )

    def _sun_look_at_train(self, sun_np, task):
        sun_np.lookAt(base.train.model)  # noqa: F821
        return task.again

    def _change_sun_state(self, sun_np, task):
        """Change Sun color and angle with a small step.

        Args:
            sun_np (panda3d.core.NodePath): Sun node path.
        """
        if self._color_step == self._day_part_duration:
            self._color_step = 0

            self._color = self._next_color
            self._next_color = copy.deepcopy(next(SUN_COLORS))

            self._color_vec = self._calc_color_vec(self._color,
                                                   self._next_color,
                                                   self._day_part_duration)
            # start Sun movement interval
            if self._color["name"] == "night":
                self._arch_int = MopathInterval(
                    self._path,
                    sun_np,
                    duration=self._day_part_duration * self._step_duration * 3,
                    name="sun_interval",
                )
                self._arch_int.start()

        # do color changing step
        for field in ("dir", "amb"):
            for i in range(3):
                self._color[field][i] += self._color_vec[field][i]

        self._dir_light.setColor(self._color["dir"])
        self._amb_light.setColor(self._color["amb"])
        self._color_step += 1
        return task.again

    def _calc_color_vec(self, color, next_color, steps):
        """Calculate vector to change color in given steps number.

        Args:
            color (dict): Ambient and directional current colors.
            next_color (Vec4): Next ambient and directional colors.
            steps (int): Number of steps to change color.

        Returns:
            dict: Directonal and ambient lights change vector.
        """
        vects = {}
        for field in ("dir", "amb"):
            vects[field] = Vec4(
                (next_color[field][0] - color[field][0]) / steps,
                (next_color[field][1] - color[field][1]) / steps,
                (next_color[field][2] - color[field][2]) / steps,
                1,
            )
        return vects

    def ignore_shadows(self, model):
        """Don't cast shadow of the given model.

        Args:
            model (panda3d.core.NodePath):
                Model, which shadow must be hidden.
        """
        model.hide(self._dir_light.getCameraMask())