#31 き太く陽設置(挙動が不安定)

このコミットが含まれているのは:
2024-12-16 17:50:10 +09:00
コミット 2ce5329aae
2個のファイルの変更223行の追加19行の削除
ファイルの表示

変更前

幅:  |  高さ:  |  サイズ: 554 KiB

変更後

幅:  |  高さ:  |  サイズ: 554 KiB

+223 -19
ファイルの表示
@@ -1,13 +1,15 @@
from __future__ import annotations from __future__ import annotations
import math
import sys import sys
from datetime import datetime from datetime import datetime, timedelta
from enum import Enum, auto from enum import Enum, auto
from typing import Callable, TypedDict from typing import Callable, TypedDict
import cv2 import cv2
import pygame import pygame
from cv2 import VideoCapture from cv2 import VideoCapture
from ephem import Moon, Observer, Sun # type: ignore
from pygame import Rect, Surface from pygame import Rect, Surface
from pygame.font import Font from pygame.font import Font
from pygame.mixer import Sound from pygame.mixer import Sound
@@ -23,14 +25,15 @@ SYSTEM_FONT = pygame.font.SysFont ('notosanscjkjp', 24, bold = True)
USER_FONT = pygame.font.SysFont ('notosanscjkjp', 32, italic = True) USER_FONT = pygame.font.SysFont ('notosanscjkjp', 32, italic = True)
DEERJIKA_FONT = pygame.font.SysFont ('07nikumarufont', 50) DEERJIKA_FONT = pygame.font.SysFont ('07nikumarufont', 50)
def main ( def main (
) -> None: ) -> None:
game = Game () game = Game ()
bg = Bg (game) bg = Bg (game)
KitaSun (game)
deerjika = Deerjika (game, DeerjikaPattern.RELAXED, deerjika = Deerjika (game, DeerjikaPattern.RELAXED,
x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120)
balloon = Balloon (game) balloon = Balloon (game)
balloon.talk ('あいうえおかきくけこさしすせそたちつてとなにぬねの', 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやいゆえよらりるれろわゐうゑを')
CurrentTime (game, SYSTEM_FONT) CurrentTime (game, SYSTEM_FONT)
Sound ('assets/bgm.mp3').play (loops = -1) Sound ('assets/bgm.mp3').play (loops = -1)
while True: while True:
@@ -42,21 +45,49 @@ def main (
class DeerjikaPattern (Enum): class DeerjikaPattern (Enum):
"""
ニジカの状態
Members:
NORMAL: 通常
RELAXED: 足パタパタ
SLEEPING: 寝ニジカ
"""
NORMAL = auto () NORMAL = auto ()
RELAXED = auto () RELAXED = auto ()
SLEEPING = auto () SLEEPING = auto ()
class Direction (Enum): class Direction (Enum):
"""
クリーチャの向き
Members:
LEFT: 左向き
RIGHT: 右向き
"""
LEFT = auto () LEFT = auto ()
RIGHT = auto () RIGHT = auto ()
class Game: class Game:
"""
ゲーム・クラス
Attributes:
clock (Clock): Clock オブゼクト
frame (int): フレーム・カウンタ
redrawers (list[Redrawer]): 再描画するクラスのリスト
screen (Surface): 基底スクリーン
"""
clock: Clock clock: Clock
frame: int frame: int
redrawers: list[Redrawer] redrawers: list[Redrawer]
screen: Surface screen: Surface
sky: Sky
def __init__ ( def __init__ (
self, self,
@@ -65,6 +96,7 @@ class Game:
self.clock = Clock () self.clock = Clock ()
self.frame = 0 self.frame = 0
self.redrawers = [] self.redrawers = []
self._create_sky ()
def redraw ( def redraw (
self, self,
@@ -76,19 +108,46 @@ class Game:
self.clock.tick (FPS) self.clock.tick (FPS)
def _create_sky (
self,
) -> None:
self.sky = Sky ()
self.sky.observer = Observer ()
self.sky.observer.lat = '35'
self.sky.observer.lon = '139'
class GameObject: class GameObject:
frame: int """
game: Game 各ゲーム・オブゼクトの基底クラス
width: int
height: int Attributes:
x: float arg (float): 回転角度 (rad)
y: float ax (float): X 軸に対する加速度 (px/frame^2)
vx: float = 0 ay (float): y 軸に対する加速度 (px/frame^2)
vy: float = 0 enabled (bool): オブゼクトの表示可否
frame (int): フレーム・カウンタ
game (Game): ゲーム基盤
height (int): 高さ (px)
vx (float): x 軸に対する速度 (px/frame)
vy (float): y 軸に対する速度 (px/frame)
width (int): 幅 (px)
x (float): X 座標 (px)
y (float): Y 座標 (px)
"""
arg: float = 0
ax: float = 0 ax: float = 0
ay: float = 0 ay: float = 0
arg: float = 0
enabled: bool = True enabled: bool = True
frame: int
game: Game
height: int
vx: float = 0
vy: float = 0
width: int
x: float
y: float
def __init__ ( def __init__ (
self, self,
@@ -121,6 +180,13 @@ class GameObject:
class Bg (GameObject): class Bg (GameObject):
"""
背景
Attributes:
surface (Surface): 背景 Surface
"""
surface: Surface surface: Surface
def __init__ ( def __init__ (
@@ -139,11 +205,20 @@ class Bg (GameObject):
class Deerjika (GameObject): class Deerjika (GameObject):
surfaces: list[Surface] """
size: int 伊地知ニジカ
width: int
Attributes:
height (int): 高さ (px)
scale (float): 拡大率
surfaces (list[Surface]): ニジカの各フレームを Surface にしたリスト
width (int): 幅 (px)
"""
height: int height: int
scale: float = .8 scale: float = .8
surfaces: list[Surface]
width: int
def __init__ ( def __init__ (
self, self,
@@ -172,18 +247,24 @@ class Deerjika (GameObject):
surface.subsurface (x, 0, self.width, self.height)) surface.subsurface (x, 0, self.width, self.height))
case Direction.RIGHT: case Direction.RIGHT:
... ...
self.size = len (self.surfaces)
def redraw ( def redraw (
self, self,
) -> None: ) -> None:
surface = pygame.transform.scale (self.surfaces[self.frame % self.size], surface = pygame.transform.scale (self.surfaces[self.frame % len (self.surfaces)],
(self.width * self.scale, self.height * self.scale)) (self.width * self.scale, self.height * self.scale))
self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y))) self.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y)))
super ().redraw () super ().redraw ()
class CurrentTime (GameObject): class CurrentTime (GameObject):
"""
現在日時表示
Attributes:
font (Font): フォント
"""
font: Font font: Font
def __init__ ( def __init__ (
@@ -205,13 +286,26 @@ class CurrentTime (GameObject):
class Balloon (GameObject): class Balloon (GameObject):
surface: Surface """
query: str = '' 吹出し
Attributes:
answer (str): 回答テキスト
image_url (str, None): 画像 URL
length (int): 表示する時間 (frame)
query (str): 質問テキスト
surface (Surface): 吹出し Surface
x_flip (bool): 左右反転フラグ
y_flip (bool): 上下反転フラグ
"""
answer: str = '' answer: str = ''
image_url: str | None = None image_url: str | None = None
length: int = 300
query: str = ''
surface: Surface
x_flip: bool = False x_flip: bool = False
y_flip: bool = False y_flip: bool = False
length: int = 300
def __init__ ( def __init__ (
self, self,
@@ -259,20 +353,130 @@ class Balloon (GameObject):
query: str, query: str,
answer: str, answer: str,
image_url: str | None = None, image_url: str | None = None,
length: int = 300,
) -> None: ) -> None:
self.query = query self.query = query
self.answer = answer self.answer = answer
self.image_url = image_url self.image_url = image_url
self.length = length
self.frame = 0 self.frame = 0
self.enabled = True self.enabled = True
class KitaSun (GameObject):
"""
き太く陽
Attributes:
sun (Sun): ephem の太陽オブゼクト
surface (Surface): き太く陽 Surface
"""
alt: float
az: float
sun: Sun
surface: Surface
def __init__ (
self,
game: Game,
):
super ().__init__ (game)
self.surface = pygame.transform.scale (pygame.image.load ('assets/sun.png'), (200, 200))
self.sun = Sun ()
def redraw (
self,
) -> None:
self.game.sky.observer.date = datetime.now () - timedelta (hours = 9)
self.sun.compute (self.game.sky.observer)
self.alt = self.sun.alt
self.az = self.sun.az
print (self.x, self.y)
self.game.screen.blit (
pygame.transform.rotate (self.surface, -(90 + math.degrees (self.arg))),
(self.x, self.y))
super ().redraw ()
self.x = self.new_x
self.y = self.new_y
if abs (self.new_arg - self.arg) > math.radians (3):
self.arg = self.new_arg
@property
def new_x (
self,
) -> float:
return CWindow.WIDTH * (math.degrees (self.az) - 80) / 120
@property
def new_y (
self,
) -> float:
return ((CWindow.HEIGHT / 2)
- ((CWindow.HEIGHT / 2 + 100) * math.sin (self.alt)
/ math.sin (math.radians (60))))
@property
def new_arg (
self,
) -> float:
return math.atan2 (self.new_y - self.y, self.new_x - self.x)
class Jojoko (GameObject):
"""
大月ヨヨコ
Attributes:
phase (float): 月齢
"""
phase: float
def __init__ (
self,
):
...
def redraw (
self,
) -> None:
...
class Sky:
"""
天体に関する情報を保持するクラス
Attributes:
observer (Observer): 観測値
"""
observer: Observer
class CWindow: class CWindow:
"""
ウィンドゥに関する定数クラス
Attributes:
WIDTH (int): ウィンドゥ幅
HEIGHT (int): ウィンドゥ高さ
"""
WIDTH = 1024 WIDTH = 1024
HEIGHT = 768 HEIGHT = 768
class Redrawer (TypedDict): class Redrawer (TypedDict):
"""
再描画処理を行ふゲーム・オブゼクトとその優先順位のペア
Attributes:
layer (int): レイア
obj (GameObject): ゲーム・オブゼクト
"""
layer: int layer: int
obj: GameObject obj: GameObject