3d model experiments

This commit is contained in:
Yonokid
2025-07-26 17:14:03 -04:00
parent fc985ca410
commit e6f2f19c1a
15 changed files with 16794 additions and 38 deletions

View File

@@ -1,11 +1,16 @@
import pyray as ray
class DevScreen:
def __init__(self, width: int, height: int):
self.width = width
self.height = height
self.screen_init = False
self.model = ray.load_model("model/mikudon.obj")
self.model_position = ray.Vector3(-450.0, 100.0, -180.0)
self.model_scale = 1000.0
self.model_rotation_y = 45.0 # Face towards camera (rotate 180 degrees on Y-axis)
self.model_rotation_x = 0.0 # No up/down tilt
self.model_rotation_z = 0.0 # No roll
def on_screen_start(self):
if not self.screen_init:
@@ -13,12 +18,26 @@ class DevScreen:
def on_screen_end(self, next_screen: str):
self.screen_init = False
ray.unload_model(self.model)
return next_screen
def update(self):
self.on_screen_start()
if ray.is_key_pressed(ray.KeyboardKey.KEY_ENTER):
return self.on_screen_end('RESULT')
return self.on_screen_end('GAME')
def draw(self):
pass
def draw_3d(self):
# Method 1: Using draw_model_ex for full control over rotation
rotation_axis = ray.Vector3(0.0, 1.0, 0.0) # Y-axis for horizontal rotation
ray.draw_model_ex(
self.model,
self.model_position,
rotation_axis,
self.model_rotation_y,
ray.Vector3(self.model_scale, self.model_scale, self.model_scale),
ray.WHITE
)

View File

@@ -304,3 +304,6 @@ class EntryScreen:
src = ray.Rectangle(0, 0, self.texture_black.width, self.texture_black.height)
dest = ray.Rectangle(0, 0, self.width, self.height)
ray.draw_texture_pro(self.texture_black, src, dest, ray.Vector2(0, 0), 0, ray.WHITE)
def draw_3d(self):
pass

View File

@@ -1,6 +1,7 @@
import bisect
import math
import sqlite3
from collections import deque
from pathlib import Path
from typing import Optional
@@ -103,22 +104,26 @@ class GameScreen:
self.textures['onp_renda_dai'][0], self.textures['onp_renda_dai'][1],
self.textures['onp_fusen'][0]]
self.tja = TJAParser(song, start_delay=self.start_delay, distance=self.width - GameScreen.JUDGE_X)
if self.tja.metadata.bgmovie != Path() and self.tja.metadata.bgmovie.exists():
self.movie = VideoPlayer(self.tja.metadata.bgmovie)
self.movie.set_volume(0.0)
if song == Path(''):
self.start_ms = get_current_ms()
self.tja = None
else:
self.movie = None
session_data.song_title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
self.tja = TJAParser(song, start_delay=self.start_delay, distance=self.width - GameScreen.JUDGE_X)
if self.tja.metadata.bgmovie != Path() and self.tja.metadata.bgmovie.exists():
self.movie = VideoPlayer(self.tja.metadata.bgmovie)
self.movie.set_volume(0.0)
else:
self.movie = None
session_data.song_title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
if not hasattr(self, 'song_music'):
if self.tja.metadata.wave.exists() and self.tja.metadata.wave.is_file():
self.song_music = audio.load_sound(self.tja.metadata.wave)
audio.normalize_sound(self.song_music, 0.1935)
else:
self.song_music = None
self.start_ms = (get_current_ms() - self.tja.metadata.offset*1000)
self.player_1 = Player(self, 1, difficulty)
if not hasattr(self, 'song_music'):
if self.tja.metadata.wave.exists() and self.tja.metadata.wave.is_file():
self.song_music = audio.load_sound(self.tja.metadata.wave)
audio.normalize_sound(self.song_music, 0.1935)
else:
self.song_music = None
self.start_ms = (get_current_ms() - self.tja.metadata.offset*1000)
def on_screen_start(self):
if not self.screen_init:
@@ -146,6 +151,8 @@ class GameScreen:
return next_screen
def write_score(self):
if self.tja is None:
return
if global_data.config['general']['autoplay']:
return
with sqlite3.connect('scores.db') as con:
@@ -173,14 +180,15 @@ class GameScreen:
if self.transition is not None:
self.transition.update(get_current_ms())
self.current_ms = get_current_ms() - self.start_ms
if (self.current_ms >= self.tja.metadata.offset*1000 + self.start_delay - global_data.config["general"]["judge_offset"]) and not self.song_started:
if self.song_music is not None:
if not audio.is_sound_playing(self.song_music):
audio.play_sound(self.song_music)
print(f"Song started at {self.current_ms}")
if self.movie is not None:
self.movie.start(get_current_ms())
self.song_started = True
if self.tja is not None:
if (self.current_ms >= self.tja.metadata.offset*1000 + self.start_delay - global_data.config["general"]["judge_offset"]) and not self.song_started:
if self.song_music is not None:
if not audio.is_sound_playing(self.song_music):
audio.play_sound(self.song_music)
print(f"Song started at {self.current_ms}")
if self.movie is not None:
self.movie.start(get_current_ms())
self.song_started = True
if self.movie is not None:
self.movie.update()
else:
@@ -228,6 +236,9 @@ class GameScreen:
if self.result_transition is not None:
self.result_transition.draw(self.width, self.height, global_data.textures['shutter'][0], global_data.textures['shutter'][1])
def draw_3d(self):
self.player_1.draw_3d(self)
class Player:
TIMING_GOOD = 25.0250015258789
TIMING_OK = 75.0750045776367
@@ -239,7 +250,10 @@ class Player:
self.difficulty = difficulty
self.visual_offset = global_data.config["general"]["visual_offset"]
self.play_notes, self.draw_note_list, self.draw_bar_list = game_screen.tja.notes_to_position(self.difficulty)
if game_screen.tja is not None:
self.play_notes, self.draw_note_list, self.draw_bar_list = game_screen.tja.notes_to_position(self.difficulty)
else:
self.play_notes, self.draw_note_list, self.draw_bar_list = deque(), deque(), deque()
self.total_notes = len([note for note in self.play_notes if 0 < note.type < 5])
self.base_score = calculate_base_score(self.play_notes)
@@ -275,12 +289,23 @@ class Player:
self.input_log: dict[float, tuple] = dict()
self.gauge = Gauge(self.difficulty, game_screen.tja.metadata.course_data[self.difficulty].level, self.total_notes)
if game_screen.tja is not None:
stars = game_screen.tja.metadata.course_data[self.difficulty].level
else:
stars = 0
self.gauge = Gauge(self.difficulty, stars, self.total_notes)
self.gauge_hit_effect: list[GaugeHitEffect] = []
self.autoplay_hit_side = 'L'
self.last_subdivision = -1
self.model = ray.load_model("model/mikudon.obj")
self.model_position = ray.Vector3(-475.0, 160.0, -180.0)
self.model_scale = 850.0
self.model_rotation_y = 30.0 # Face towards camera (rotate 180 degrees on Y-axis)
self.model_rotation_x = 0.0 # No up/down tilt
self.model_rotation_z = 0.0
def get_result_score(self):
return self.score, self.good_count, self.ok_count, self.bad_count, self.total_drumroll, self.max_combo
@@ -383,9 +408,10 @@ class Player:
else:
note_type = game_screen.note_type_list[note.type][0]
self.combo += 1
if self.combo > self.max_combo:
self.max_combo = self.combo
if note.type < 7:
self.combo += 1
if self.combo > self.max_combo:
self.max_combo = self.combo
self.draw_arc_list.append(NoteArc(note_type, get_current_ms(), self.player_number, note.type == 3 or note.type == 4) or note.type == 7)
#game_screen.background.chibis.append(game_screen.background.Chibi())
@@ -710,6 +736,20 @@ class Player:
anim.draw(game_screen)
#ray.draw_circle(game_screen.width//2, game_screen.height, 300, ray.ORANGE)
def draw_3d(self):
'''
rotation_axis = ray.Vector3(0.0, 1.0, 0.0) # Y-axis for horizontal rotation
ray.draw_model_ex(
self.model,
self.model_position,
rotation_axis,
self.model_rotation_y,
ray.Vector3(self.model_scale, self.model_scale, self.model_scale),
ray.WHITE
)
'''
pass
class Judgement:
def __init__(self, type: str, big: bool, ms_display: Optional[float]=None):
self.type = type

View File

@@ -112,3 +112,5 @@ class LoadScreen:
if self.fade_in is not None:
ray.draw_rectangle(0, 0, self.width, self.height, ray.fade(ray.WHITE, self.fade_in.attribute))
def draw_3d(self):
pass

View File

@@ -1,4 +1,3 @@
import math
from pathlib import Path
import pyray as ray
@@ -252,6 +251,9 @@ class ResultScreen:
if self.fade_out is not None:
self.fade_out.draw(self.width, self.height)
def draw_3d(self):
pass
class Crown:
def __init__(self):
duration = 466

View File

@@ -264,3 +264,5 @@ class SettingsScreen:
else:
# Draw exit instruction
ray.draw_text("Press Don to exit settings", 250, 100, 20, ray.GREEN)
def draw_3d(self):
pass

View File

@@ -314,6 +314,9 @@ class SongSelectScreen:
if self.game_transition is not None:
self.game_transition.draw(self.screen_height)
def draw_3d(self):
pass
class SongBox:
OUTLINE_MAP = {
555: ray.Color(0, 77, 104, 255),

View File

@@ -127,6 +127,9 @@ class TitleScreen:
dest = ray.Rectangle(0, 0, self.width, self.height)
ray.draw_texture_pro(self.texture_black, src, dest, ray.Vector2(0, 0), 0, ray.fade(ray.WHITE, self.fade_out.attribute))
def draw_3d(self):
pass
class WarningScreen:
class X:
DELAY = 4250