From 2ce5329aaeed220c24da3fddf255d21183283823 Mon Sep 17 00:00:00 2001 From: miteruzo Date: Mon, 16 Dec 2024 17:50:10 +0900 Subject: [PATCH] =?UTF-8?q?#31=20=E3=81=8D=E5=A4=AA=E3=81=8F=E9=99=BD?= =?UTF-8?q?=E8=A8=AD=E7=BD=AE=EF=BC=88=E6=8C=99=E5=8B=95=E3=81=8C=E4=B8=8D?= =?UTF-8?q?=E5=AE=89=E5=AE=9A=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sun.png => assets/sun.png | Bin test.py | 238 +++++++++++++++++++++++++++++++++++--- 2 files changed, 221 insertions(+), 17 deletions(-) rename sun.png => assets/sun.png (100%) diff --git a/sun.png b/assets/sun.png similarity index 100% rename from sun.png rename to assets/sun.png diff --git a/test.py b/test.py index 79f4b71..a7d2703 100644 --- a/test.py +++ b/test.py @@ -1,13 +1,15 @@ from __future__ import annotations +import math import sys -from datetime import datetime +from datetime import datetime, timedelta from enum import Enum, auto from typing import Callable, TypedDict import cv2 import pygame from cv2 import VideoCapture +from ephem import Moon, Observer, Sun # type: ignore from pygame import Rect, Surface from pygame.font import Font 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) DEERJIKA_FONT = pygame.font.SysFont ('07nikumarufont', 50) + def main ( ) -> None: game = Game () bg = Bg (game) + KitaSun (game) deerjika = Deerjika (game, DeerjikaPattern.RELAXED, x = CWindow.WIDTH * 3 / 4, y = CWindow.HEIGHT - 120) balloon = Balloon (game) - balloon.talk ('あいうえおかきくけこさしすせそたちつてとなにぬねの', 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやいゆえよらりるれろわゐうゑを') CurrentTime (game, SYSTEM_FONT) Sound ('assets/bgm.mp3').play (loops = -1) while True: @@ -42,21 +45,49 @@ def main ( class DeerjikaPattern (Enum): + """ + ニジカの状態 + + Members: + NORMAL: 通常 + RELAXED: 足パタパタ + SLEEPING: 寝ニジカ + """ + NORMAL = auto () RELAXED = auto () SLEEPING = auto () class Direction (Enum): + """ + クリーチャの向き + + Members: + LEFT: 左向き + RIGHT: 右向き + """ + LEFT = auto () RIGHT = auto () class Game: + """ + ゲーム・クラス + + Attributes: + clock (Clock): Clock オブゼクト + frame (int): フレーム・カウンタ + redrawers (list[Redrawer]): 再描画するクラスのリスト + screen (Surface): 基底スクリーン + """ + clock: Clock frame: int redrawers: list[Redrawer] screen: Surface + sky: Sky def __init__ ( self, @@ -65,6 +96,7 @@ class Game: self.clock = Clock () self.frame = 0 self.redrawers = [] + self._create_sky () def redraw ( self, @@ -76,19 +108,46 @@ class Game: 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: + """ + 各ゲーム・オブゼクトの基底クラス + + Attributes: + arg (float): 回転角度 (rad) + ax (float): X 軸に対する加速度 (px/frame^2) + ay (float): y 軸に対する加速度 (px/frame^2) + 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 + ay: float = 0 + enabled: bool = True frame: int game: Game - width: int height: int - x: float - y: float vx: float = 0 vy: float = 0 - ax: float = 0 - ay: float = 0 - arg: float = 0 - enabled: bool = True + width: int + x: float + y: float def __init__ ( self, @@ -121,6 +180,13 @@ class GameObject: class Bg (GameObject): + """ + 背景 + + Attributes: + surface (Surface): 背景 Surface + """ + surface: Surface def __init__ ( @@ -139,11 +205,20 @@ class Bg (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 scale: float = .8 + surfaces: list[Surface] + width: int def __init__ ( self, @@ -172,18 +247,24 @@ class Deerjika (GameObject): surface.subsurface (x, 0, self.width, self.height)) case Direction.RIGHT: ... - self.size = len (self.surfaces) def redraw ( self, ) -> 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.game.screen.blit (surface, surface.get_rect (center = (self.x, self.y))) super ().redraw () class CurrentTime (GameObject): + """ + 現在日時表示 + + Attributes: + font (Font): フォント + """ + font: Font def __init__ ( @@ -205,13 +286,26 @@ class CurrentTime (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 = '' image_url: str | None = None + length: int = 300 + query: str = '' + surface: Surface x_flip: bool = False y_flip: bool = False - length: int = 300 def __init__ ( self, @@ -259,20 +353,130 @@ class Balloon (GameObject): query: str, answer: str, image_url: str | None = None, + length: int = 300, ) -> None: self.query = query self.answer = answer self.image_url = image_url + self.length = length self.frame = 0 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: + """ + ウィンドゥに関する定数クラス + + Attributes: + WIDTH (int): ウィンドゥ幅 + HEIGHT (int): ウィンドゥ高さ + """ + WIDTH = 1024 HEIGHT = 768 class Redrawer (TypedDict): + """ + 再描画処理を行ふゲーム・オブゼクトとその優先順位のペア + + Attributes: + layer (int): レイア + obj (GameObject): ゲーム・オブゼクト + """ + layer: int obj: GameObject