|
@@ -1,52 +1,113 @@ |
|
|
from __future__ import annotations |
|
|
from __future__ import annotations |
|
|
|
|
|
|
|
|
from abc import ABCMeta, abstractmethod |
|
|
|
|
|
|
|
|
import sys |
|
|
|
|
|
from enum import Enum, auto |
|
|
|
|
|
from typing import Callable, TypedDict |
|
|
|
|
|
|
|
|
|
|
|
import cv2 |
|
|
import pygame |
|
|
import pygame |
|
|
|
|
|
from cv2 import VideoCapture |
|
|
|
|
|
from pygame import Surface |
|
|
|
|
|
from pygame.time import Clock |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main ( |
|
|
def main ( |
|
|
) -> None: |
|
|
) -> None: |
|
|
pygame.init () |
|
|
pygame.init () |
|
|
game = Game () |
|
|
game = Game () |
|
|
|
|
|
deerjika = Deerjika (game, DeerjikaPattern.RELAXED) |
|
|
while True: |
|
|
while True: |
|
|
deerjika = Deerjika (game) |
|
|
|
|
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Game: |
|
|
class Game: |
|
|
|
|
|
clock: Clock |
|
|
|
|
|
frame: int |
|
|
|
|
|
redrawers: list[Redrawer] |
|
|
|
|
|
screen: Surface |
|
|
|
|
|
|
|
|
def __init__ ( |
|
|
def __init__ ( |
|
|
self, |
|
|
self, |
|
|
): |
|
|
): |
|
|
self.screen = pygame.display.set_mode ((CWindow.WIDTH, CWindow.HEIGHT)) |
|
|
self.screen = pygame.display.set_mode ((CWindow.WIDTH, CWindow.HEIGHT)) |
|
|
self.clock = pygame.time.Clock () |
|
|
|
|
|
|
|
|
self.clock = Clock () |
|
|
|
|
|
self.frame = 0 |
|
|
|
|
|
|
|
|
|
|
|
def redraw ( |
|
|
|
|
|
self, |
|
|
|
|
|
) -> None: |
|
|
|
|
|
for redrawer in sorted (self.redrawers, key = lambda x: x['layer']): |
|
|
|
|
|
redrawer['func'] () |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GameObject: |
|
|
|
|
|
frame: int |
|
|
|
|
|
game: Game |
|
|
|
|
|
width: int |
|
|
|
|
|
height: int |
|
|
|
|
|
x: float |
|
|
|
|
|
y: float |
|
|
|
|
|
vx: float |
|
|
|
|
|
vy: float |
|
|
|
|
|
ax: float |
|
|
|
|
|
ay: float |
|
|
|
|
|
arg: float |
|
|
|
|
|
|
|
|
class GameObject (metaclass = ABCMeta): |
|
|
|
|
|
def __init__ ( |
|
|
def __init__ ( |
|
|
self, |
|
|
self, |
|
|
game: Game, |
|
|
game: Game, |
|
|
|
|
|
layer: int | None = None, |
|
|
): |
|
|
): |
|
|
self.game = game |
|
|
self.game = game |
|
|
self.redrawer.append (self.redraw) |
|
|
|
|
|
|
|
|
self.frame = 0 |
|
|
|
|
|
if layer is None: |
|
|
|
|
|
if self.game.redrawers: |
|
|
|
|
|
layer = max (r['layer'] for r in self.game.redrawers) + 10 |
|
|
|
|
|
else: |
|
|
|
|
|
layer = 0 |
|
|
|
|
|
self.game.redrawers.append ({ 'layer': layer, 'func': self.redraw }) |
|
|
|
|
|
|
|
|
@abstractmethod |
|
|
|
|
|
def redraw ( |
|
|
def redraw ( |
|
|
self, |
|
|
self, |
|
|
) -> None: |
|
|
) -> None: |
|
|
raise NotImplementedError () |
|
|
|
|
|
|
|
|
self.x += self.vx |
|
|
|
|
|
self.y += self.vy |
|
|
|
|
|
self.vx += self.ax |
|
|
|
|
|
self.vy += self.ay |
|
|
|
|
|
self.frame += 1 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Deerjika (GameObject): |
|
|
class Deerjika (GameObject): |
|
|
|
|
|
surfaces: list[Surface] |
|
|
|
|
|
size: int |
|
|
|
|
|
|
|
|
def __init__ ( |
|
|
def __init__ ( |
|
|
self, |
|
|
self, |
|
|
game: Game, |
|
|
game: Game, |
|
|
pattern: DeerjikaPattern = DeerjikaPattern.NORMAL, |
|
|
pattern: DeerjikaPattern = DeerjikaPattern.NORMAL, |
|
|
direction: Direction = Direction.LEFT, |
|
|
direction: Direction = Direction.LEFT, |
|
|
|
|
|
layer: int | None = None, |
|
|
): |
|
|
): |
|
|
super ().__init__ (self) |
|
|
|
|
|
self.game = game |
|
|
|
|
|
|
|
|
super ().__init__ (game, layer) |
|
|
self.pattern = pattern |
|
|
self.pattern = pattern |
|
|
self.direction = direction |
|
|
self.direction = direction |
|
|
|
|
|
match pattern: |
|
|
|
|
|
case DeerjikaPattern.NORMAL: |
|
|
|
|
|
... |
|
|
|
|
|
case DeerjikaPattern.RELAXED: |
|
|
|
|
|
match direction: |
|
|
|
|
|
case Direction.LEFT: |
|
|
|
|
|
self.surfaces = get_surfaces_from_video ('deerjika_relax.mp4') |
|
|
|
|
|
case Direction.RIGHT: |
|
|
|
|
|
... |
|
|
|
|
|
self.size = len (self.surfaces) |
|
|
|
|
|
|
|
|
|
|
|
def redraw ( |
|
|
|
|
|
self, |
|
|
|
|
|
) -> None: |
|
|
|
|
|
surface: Surface = self.surfaces[self.frame % self.size] |
|
|
|
|
|
self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y))) |
|
|
|
|
|
super ().redraw () |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DeerjikaPattern (Enum): |
|
|
class DeerjikaPattern (Enum): |
|
@@ -64,5 +125,34 @@ class CWindow: |
|
|
HEIGHT = 768 |
|
|
HEIGHT = 768 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Redrawer (TypedDict): |
|
|
|
|
|
layer: int |
|
|
|
|
|
func: Callable[[], None] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_surfaces_from_video ( |
|
|
|
|
|
video_path: str, |
|
|
|
|
|
) -> list[Surface]: |
|
|
|
|
|
cap = VideoCapture (video_path) |
|
|
|
|
|
if not cap.isOpened (): |
|
|
|
|
|
return [] |
|
|
|
|
|
|
|
|
|
|
|
fps = cap.get (cv2.CAP_PROP_FPS) |
|
|
|
|
|
|
|
|
|
|
|
surfaces: list[Surface] = [] |
|
|
|
|
|
while cap.isOpened (): |
|
|
|
|
|
(ret, frame) = cap.read () |
|
|
|
|
|
if not ret: |
|
|
|
|
|
break |
|
|
|
|
|
frame = cv2.cvtColor (frame, cv2.COLOR_BGR2RGB) |
|
|
|
|
|
frame_surface = pygame.surfarray.make_surface (frame) |
|
|
|
|
|
frame_surface = pygame.transform.rotate (frame_surface, -90) |
|
|
|
|
|
surfaces.append (pygame.transform.flip (frame_surface, True, False)) |
|
|
|
|
|
|
|
|
|
|
|
cap.release () |
|
|
|
|
|
|
|
|
|
|
|
return surfaces |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
if __name__ == '__main__': |
|
|
main () |
|
|
main () |