0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amazon Q Developer for CLI De GameをつくらNight でミサイルコマンドを作ってみた。

Last updated at Posted at 2025-06-11

Geminiを使ってプロンプトを検討

AIエージェントにゲームを開発させるにあたって最初期のビデオゲームの模倣がいいと思うんだけど、ミサイルコマンドをubuntu上で実行するpython3のスクリプトとしたらどんなプロンプトにするのがいいだろうか
  • 作成したプロンプト
# Role: Python Game Developer

# Objective:
あなたはプロのPythonゲーム開発者です。レトロアーケードゲームの名作「ミサイルコマンド」を模倣したデスクトップゲームを、Python 3とPygameライブラリを使って開発してください。

# Environment:
- OS: Ubuntu
- Language: Python 3
- Library: Pygame

# Core Specifications:
以下の仕様に厳密に従って、単一のPythonスクリプトファイルとしてコードを生成してください。

## 1. ゲームウィンドウ
- ウィンドウサイズ: 幅800ピクセル x 高さ600ピクセル
- 背景色: 黒 (`#000000`)
- 地面: 画面下部に緑色の長方形を描画する。

## 2. プレイヤーの砲台 (Bases)
- 画面下部の地面の上に、3つの砲台を均等な間隔で配置する。
- 各砲台は三角形または四角形で表現する。
- 各砲台には弾数(例: 10発)の制限があり、弾がなくなるとその砲台からは発射できなくなる。

## 3. 都市 (Cities)
- 3つの砲台の間に、合計6つの都市を配置する。
- 都市は小さな四角形で表現する。
- 都市は健在な状態(例: 青色)と破壊された状態(例: 灰色)を持つ。

## 4. 照準 (Crosshair)
- マウスカーソルの位置に、十字のマーク(クロスヘア)を描画する。マウスの動きに追従させること。

## 5. 敵ミサイル (Enemy Missiles)
- 画面の上部からランダムなX座標で出現する。
- 各敵ミサイルは、地上にある6つの都市または3つの砲台の中から、ランダムに1つを目標として設定する。
- 細い線として軌跡を描きながら、目標に向かって一定速度で落下する。
- 時間経過やステージクリアに応じて、落下速度と出現頻度を少しずつ上昇させる。

## 6. 迎撃ミサイル (Player Missiles)
- プレイヤーがマウスの左ボタンをクリックすると発射される。
- クリックされた照準の位置に最も近い、弾が残っている砲台から自動的に選択されて発射される。
- 砲台から照準の位置に向かって、敵ミサイルより速い速度で飛んでいく。
- 目標地点(クリックされた位置)に到達すると爆発する。

## 7. 爆発 (Explosions)
- 迎撃ミサイルが目標地点に到達すると、円形の爆発エフェクトを生成する。
- 爆発エフェクトは、生成されてから一定時間(例: 1秒)かけて徐々に大きくなり、その後消滅する。
- この爆発エフェクトの円の中に敵ミサイルが入ると、その敵ミサイルは破壊される。

## 8. ゲームロジック
- **スコア:** 敵ミサイルを1つ破壊するごとにスコアが加算される(例: 25点)。
- **ゲームオーバー:** 6つの都市がすべて破壊された時点でゲームオーバーとする。
- **ゲームオーバー表示:** ゲームオーバー時には、画面中央に "GAME OVER" と表示し、最終スコアを表示する。
- **リスタート:** ゲームオーバー画面で特定のキー(例: 'R'キー)を押すと、ゲームが初期状態に戻り、再スタートできるようにする。

# Code Requirements:
- 全てのロジックを単一の `missile_command.py` というファイルに記述してください。
- オブジェクト指向プログラミングの原則に従い、以下のクラスを使用してください:
  - `Game`: ゲーム全体の管理(ゲームループ、イベント処理、状態管理など)
  - `Base`: プレイヤーの砲台
  - `City`: 都市
  - `EnemyMissile`: 敵ミサイル
  - `PlayerMissile`: 迎撃ミサイル
  - `Explosion`: 爆発エフェクト
- 色、画面サイズ、速度などの設定値は、コードの先頭で定数としてまとめて定義してください。
- コードには、各クラスや関数の役割を説明する適切なコメントを加えてください。

# Execution Instructions:
- 最後に、このスクリプトを実行するために必要なPygameのインストールコマンドと、実行コマンドをコメントとして記載してください。

amazon q developper に開発依頼

  • 出来上がったソース
missile_command.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Missile Command Game (Version 2)
A recreation of the classic arcade game using Python and Pygame.
Added wave-based gameplay with increasing difficulty.

Installation:
    pip install pygame

Run:
    python missile_command.py
"""

import pygame
import sys
import random
import math
from typing import List, Tuple, Optional

# Initialize pygame
pygame.init()

# Constants
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60

# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
GRAY = (128, 128, 128)
ORANGE = (255, 165, 0)
CYAN = (0, 255, 255)
PURPLE = (128, 0, 128)

# Game settings
GROUND_HEIGHT = 30
BASE_WIDTH = 30
BASE_HEIGHT = 20
CITY_WIDTH = 20
CITY_HEIGHT = 15
MISSILE_SPEED = 5
ENEMY_MISSILE_SPEED_INITIAL = 0.5
ENEMY_MISSILE_SPAWN_RATE_INITIAL = 2500  # milliseconds
ENEMY_MISSILE_SIZE = 5
EXPLOSION_MAX_RADIUS = 30
EXPLOSION_GROWTH_RATE = 0.5
EXPLOSION_DURATION = 1000  # milliseconds
MISSILES_PER_BASE = 10
SCORE_PER_HIT = 25
MISSILES_PER_WAVE = 20  # 各ウェーブの隕石数
SPEED_INCREASE_PER_WAVE = 0.1  # ウェーブごとの速度増加


class Base:
    """Player's missile base that can fire interceptor missiles."""

    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y
        self.width = BASE_WIDTH
        self.height = BASE_HEIGHT
        self.missiles_left = MISSILES_PER_BASE
        self.destroyed = False

    def draw(self, screen):
        """Draw the base on the screen."""
        if not self.destroyed:
            # Draw a triangle for the base
            pygame.draw.polygon(screen, GREEN, [
                (self.x - self.width // 2, self.y),
                (self.x + self.width // 2, self.y),
                (self.x, self.y - self.height)
            ])

            # Draw missile count
            font = pygame.font.SysFont(None, 20)
            text = font.render(str(self.missiles_left), True, WHITE)
            screen.blit(text, (self.x - 5, self.y + 5))

    def fire_missile(self) -> bool:
        """Attempt to fire a missile from this base."""
        if self.missiles_left > 0 and not self.destroyed:
            self.missiles_left -= 1
            return True
        return False

    def refill_missiles(self):
        """Refill missiles at the end of a wave."""
        if not self.destroyed:
            self.missiles_left = MISSILES_PER_BASE


class City:
    """A city that needs to be protected from enemy missiles."""

    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y
        self.width = CITY_WIDTH
        self.height = CITY_HEIGHT
        self.destroyed = False

    def draw(self, screen):
        """Draw the city on the screen."""
        color = GRAY if self.destroyed else BLUE
        pygame.draw.rect(screen, color,
                        (self.x - self.width // 2,
                         self.y - self.height,
                         self.width,
                         self.height))


class EnemyMissile:
    """Enemy missile that targets cities or bases."""

    def __init__(self, target_x: int, target_y: int, speed: float):
        # Start from a random position at the top of the screen
        self.start_x = random.randint(0, SCREEN_WIDTH)
        self.start_y = 0
        self.x = self.start_x
        self.y = self.start_y
        self.target_x = target_x
        self.target_y = target_y
        self.speed = speed
        self.destroyed = False

        # Calculate direction vector
        dx = self.target_x - self.start_x
        dy = self.target_y - self.start_y
        distance = math.sqrt(dx * dx + dy * dy)
        self.dx = dx / distance * self.speed
        self.dy = dy / distance * self.speed

        # Trail points
        self.trail = [(self.x, self.y)]

    def update(self):
        """Update the missile position."""
        if not self.destroyed:
            self.x += self.dx
            self.y += self.dy
            self.trail.append((self.x, self.y))
            # Keep only the last 10 positions for the trail
            if len(self.trail) > 10:
                self.trail.pop(0)

    def draw(self, screen):
        """Draw the missile and its trail on the screen."""
        if not self.destroyed:
            # Draw the trail
            if len(self.trail) > 1:
                pygame.draw.lines(screen, RED, False, self.trail, 2)

            # Draw the missile head (隕石を大きくする)
            pygame.draw.circle(screen, ORANGE, (int(self.x), int(self.y)), ENEMY_MISSILE_SIZE)
            # 隕石の内側を描画して立体感を出す
            pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), ENEMY_MISSILE_SIZE - 2)

    def has_reached_target(self) -> bool:
        """Check if the missile has reached its target."""
        return (abs(self.x - self.target_x) < ENEMY_MISSILE_SIZE + 3 and
                abs(self.y - self.target_y) < ENEMY_MISSILE_SIZE + 3)


class PlayerMissile:
    """Player's interceptor missile."""

    def __init__(self, start_x: int, start_y: int, target_x: int, target_y: int):
        self.start_x = start_x
        self.start_y = start_y
        self.x = start_x
        self.y = start_y
        self.target_x = target_x
        self.target_y = target_y
        self.speed = MISSILE_SPEED
        self.exploded = False

        # Calculate direction vector
        dx = self.target_x - self.start_x
        dy = self.target_y - self.start_y
        distance = math.sqrt(dx * dx + dy * dy)
        self.dx = dx / distance * self.speed
        self.dy = dy / distance * self.speed

        # Trail points
        self.trail = [(self.x, self.y)]

    def update(self) -> bool:
        """Update the missile position. Returns True if reached target."""
        if not self.exploded:
            self.x += self.dx
            self.y += self.dy
            self.trail.append((self.x, self.y))
            # Keep only the last 10 positions for the trail
            if len(self.trail) > 10:
                self.trail.pop(0)

            # Check if reached target
            if (abs(self.x - self.target_x) < 5 and
                abs(self.y - self.target_y) < 5):
                self.exploded = True
                return True
        return False

    def draw(self, screen):
        """Draw the missile and its trail on the screen."""
        if not self.exploded:
            # Draw the trail
            if len(self.trail) > 1:
                pygame.draw.lines(screen, YELLOW, False, self.trail, 1)

            # Draw the missile head
            pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), 2)


class Explosion:
    """Explosion effect created when a player missile reaches its target."""

    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y
        self.radius = 0
        self.max_radius = EXPLOSION_MAX_RADIUS + 10
        self.growth_rate = EXPLOSION_GROWTH_RATE
        self.duration = EXPLOSION_DURATION + 200
        self.start_time = pygame.time.get_ticks()
        self.finished = False

    def update(self):
        """Update the explosion state."""
        current_time = pygame.time.get_ticks()
        elapsed = current_time - self.start_time

        if elapsed < self.duration:
            # Grow the explosion
            progress = elapsed / self.duration
            self.radius = self.max_radius * min(progress * 2, 1)
            if progress > 0.5:
                # Start shrinking after half the duration
                self.radius = self.max_radius * (2 - progress * 2)
        else:
            self.finished = True

    def draw(self, screen):
        """Draw the explosion on the screen."""
        if not self.finished:
            # 爆発をより目立たせるために、外側と内側の2重の円を描画
            pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), int(self.radius), 2)
            pygame.draw.circle(screen, ORANGE, (int(self.x), int(self.y)), int(self.radius * 0.7), 1)

    def check_collision(self, missile_x: float, missile_y: float) -> bool:
        """Check if a missile is within the explosion radius."""
        if self.finished:
            return False

        distance = math.sqrt((missile_x - self.x) ** 2 + (missile_y - self.y) ** 2)
        return distance <= self.radius


class Game:
    """Main game class that manages the game state and logic."""

    def __init__(self):
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption("Missile Command - Version 2")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.SysFont(None, 36)
        self.small_font = pygame.font.SysFont(None, 24)

        self.reset_game()

    def reset_game(self):
        """Reset the game to its initial state."""
        self.game_over = False
        self.score = 0
        self.wave = 1
        self.enemy_missile_speed = ENEMY_MISSILE_SPEED_INITIAL
        self.enemy_missile_spawn_rate = ENEMY_MISSILE_SPAWN_RATE_INITIAL
        self.last_enemy_spawn_time = pygame.time.get_ticks()

        # Wave system
        self.missiles_in_wave = 0
        self.missiles_destroyed = 0
        self.wave_complete = False
        self.wave_message_time = 0
        self.show_wave_message = False

        # Create bases
        ground_y = SCREEN_HEIGHT - GROUND_HEIGHT
        base_positions = [SCREEN_WIDTH // 4, SCREEN_WIDTH // 2, 3 * SCREEN_WIDTH // 4]
        self.bases = [Base(x, ground_y) for x in base_positions]

        # Create cities
        city_positions = [
            SCREEN_WIDTH // 8,
            SCREEN_WIDTH // 8 * 3,
            SCREEN_WIDTH // 8 * 5,
            SCREEN_WIDTH // 8 * 7
        ]
        self.cities = [City(x, ground_y) for x in city_positions]

        # Add two more cities between bases
        self.cities.append(City(SCREEN_WIDTH // 4 + SCREEN_WIDTH // 8, ground_y))
        self.cities.append(City(3 * SCREEN_WIDTH // 4 - SCREEN_WIDTH // 8, ground_y))

        # Game objects
        self.enemy_missiles = []
        self.player_missiles = []
        self.explosions = []

        # 初期状態でミサイルを発射しないための遅延
        self.initial_delay = pygame.time.get_ticks() + 1500

    def start_new_wave(self):
        """Start a new wave with increased difficulty."""
        self.wave += 1
        self.enemy_missile_speed += SPEED_INCREASE_PER_WAVE
        self.missiles_in_wave = 0
        self.missiles_destroyed = 0
        self.wave_complete = False

        # Refill missiles for all bases
        for base in self.bases:
            base.refill_missiles()

        # Show wave message
        self.show_wave_message = True
        self.wave_message_time = pygame.time.get_ticks()

    def spawn_enemy_missile(self):
        """Spawn a new enemy missile targeting a random city or base."""
        current_time = pygame.time.get_ticks()

        # 初期遅延が終わるまでミサイルを発射しない
        if hasattr(self, 'initial_delay') and current_time < self.initial_delay:
            return

        # ウェーブメッセージ表示中は敵ミサイルを発射しない
        if self.show_wave_message:
            if current_time - self.wave_message_time > 3000:  # 3秒間表示
                self.show_wave_message = False
            return

        # ウェーブ完了時は新しいミサイルを発射しない
        if self.wave_complete:
            # すべての敵ミサイルが破壊されたか画面外に出たら次のウェーブを開始
            if len(self.enemy_missiles) == 0:
                self.start_new_wave()
            return

        # ウェーブの最大ミサイル数に達したら、それ以上発射しない
        if self.missiles_in_wave >= MISSILES_PER_WAVE:
            self.wave_complete = True
            return

        if current_time - self.last_enemy_spawn_time > self.enemy_missile_spawn_rate:
            self.last_enemy_spawn_time = current_time

            # Choose a random target (city or base)
            targets = []
            for city in self.cities:
                if not city.destroyed:
                    targets.append((city.x, city.y))

            for base in self.bases:
                if not base.destroyed:
                    targets.append((base.x, base.y))

            if targets:
                target_x, target_y = random.choice(targets)
                self.enemy_missiles.append(
                    EnemyMissile(target_x, target_y, self.enemy_missile_speed)
                )
                self.missiles_in_wave += 1

    def fire_player_missile(self, target_x: int, target_y: int):
        """Fire a player missile from the nearest available base."""
        # ウェーブメッセージ表示中は発射できない
        if self.show_wave_message:
            return

        # Find the closest base with missiles left
        available_bases = [base for base in self.bases
                          if base.missiles_left > 0 and not base.destroyed]

        if available_bases:
            # Sort bases by distance to target
            available_bases.sort(key=lambda base:
                               abs(base.x - target_x))

            closest_base = available_bases[0]
            if closest_base.fire_missile():
                self.player_missiles.append(
                    PlayerMissile(closest_base.x, closest_base.y - BASE_HEIGHT,
                                target_x, target_y)
                )

    def check_collisions(self):
        """Check for collisions between explosions and enemy missiles."""
        # Check if enemy missiles hit cities or bases
        for missile in self.enemy_missiles[:]:
            if missile.has_reached_target():
                # Check if it hit a city
                for city in self.cities:
                    if (not city.destroyed and
                        abs(missile.x - city.x) < CITY_WIDTH // 2 and
                        abs(missile.y - city.y) < CITY_HEIGHT):
                        city.destroyed = True
                        break

                # Check if it hit a base
                for base in self.bases:
                    if (not base.destroyed and
                        abs(missile.x - base.x) < BASE_WIDTH // 2 and
                        abs(missile.y - base.y) < BASE_HEIGHT):
                        base.destroyed = True
                        break

                missile.destroyed = True
                self.enemy_missiles.remove(missile)

        # Check if explosions hit enemy missiles
        for explosion in self.explosions:
            for missile in self.enemy_missiles[:]:
                if not missile.destroyed and explosion.check_collision(missile.x, missile.y):
                    missile.destroyed = True
                    self.enemy_missiles.remove(missile)
                    self.score += SCORE_PER_HIT
                    self.missiles_destroyed += 1

        # Check if all cities are destroyed
        if all(city.destroyed for city in self.cities):
            self.game_over = True

    def update(self):
        """Update the game state."""
        if not self.game_over:
            # Spawn enemy missiles
            self.spawn_enemy_missile()

            # Update enemy missiles
            for missile in self.enemy_missiles[:]:
                missile.update()
                # 画面外に出たミサイルを削除
                if missile.y > SCREEN_HEIGHT or missile.x < 0 or missile.x > SCREEN_WIDTH:
                    self.enemy_missiles.remove(missile)

            # Update player missiles
            for missile in self.player_missiles[:]:
                if missile.update():
                    # Missile reached target, create explosion
                    self.explosions.append(Explosion(missile.target_x, missile.target_y))
                    self.player_missiles.remove(missile)

            # Update explosions
            for explosion in self.explosions[:]:
                explosion.update()
                if explosion.finished:
                    self.explosions.remove(explosion)

            # Check collisions
            self.check_collisions()

    def draw(self):
        """Draw the game state to the screen."""
        # Clear the screen
        self.screen.fill(BLACK)

        # Draw ground
        pygame.draw.rect(self.screen, GREEN,
                        (0, SCREEN_HEIGHT - GROUND_HEIGHT,
                         SCREEN_WIDTH, GROUND_HEIGHT))

        # Draw bases
        for base in self.bases:
            base.draw(self.screen)

        # Draw cities
        for city in self.cities:
            city.draw(self.screen)

        # Draw enemy missiles
        for missile in self.enemy_missiles:
            missile.draw(self.screen)

        # Draw player missiles
        for missile in self.player_missiles:
            missile.draw(self.screen)

        # Draw explosions
        for explosion in self.explosions:
            explosion.draw(self.screen)

        # Draw crosshair at mouse position
        mouse_x, mouse_y = pygame.mouse.get_pos()
        # クロスヘアを大きく、目立つようにする
        pygame.draw.line(self.screen, WHITE, (mouse_x - 15, mouse_y), (mouse_x + 15, mouse_y), 2)
        pygame.draw.line(self.screen, WHITE, (mouse_x, mouse_y - 15), (mouse_x, mouse_y + 15), 2)
        pygame.draw.circle(self.screen, WHITE, (mouse_x, mouse_y), 3, 1)

        # Draw score
        score_text = self.small_font.render(f"Score: {self.score}", True, WHITE)
        self.screen.blit(score_text, (10, 10))

        # Draw wave information
        wave_text = self.small_font.render(f"Wave: {self.wave}", True, WHITE)
        self.screen.blit(wave_text, (10, 40))

        # Draw missiles remaining in wave
        if not self.wave_complete:
            missiles_text = self.small_font.render(
                f"Missiles: {self.missiles_destroyed}/{MISSILES_PER_WAVE}", True, WHITE)
        else:
            missiles_text = self.small_font.render(
                f"Wave Complete! {self.missiles_destroyed}/{MISSILES_PER_WAVE}", True, CYAN)
        self.screen.blit(missiles_text, (10, 70))

        # Draw wave message
        if self.show_wave_message:
            # Semi-transparent overlay
            overlay = pygame.Surface((SCREEN_WIDTH, 100), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 180))
            self.screen.blit(overlay, (0, SCREEN_HEIGHT // 2 - 50))

            # Wave message
            wave_msg = self.font.render(f"WAVE {self.wave}", True, CYAN)
            msg_rect = wave_msg.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 20))
            self.screen.blit(wave_msg, msg_rect)

            # Speed message
            speed_msg = self.small_font.render(
                f"Enemy Speed: {self.enemy_missile_speed:.1f}", True, YELLOW)
            speed_rect = speed_msg.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 20))
            self.screen.blit(speed_msg, speed_rect)

        # Draw game over screen
        if self.game_over:
            # Semi-transparent overlay
            overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 128))
            self.screen.blit(overlay, (0, 0))

            # Game over text
            game_over_text = self.font.render("GAME OVER", True, RED)
            text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 70))
            self.screen.blit(game_over_text, text_rect)

            # Final score
            final_score_text = self.font.render(f"Final Score: {self.score}", True, WHITE)
            score_rect = final_score_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 20))
            self.screen.blit(final_score_text, score_rect)

            # Wave reached
            wave_text = self.font.render(f"Waves Completed: {self.wave - 1}", True, CYAN)
            wave_rect = wave_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 30))
            self.screen.blit(wave_text, wave_rect)

            # Restart instructions
            restart_text = self.small_font.render("Press 'R' to restart", True, WHITE)
            restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 80))
            self.screen.blit(restart_text, restart_rect)

        # Update the display
        pygame.display.flip()

    def run(self):
        """Main game loop."""
        running = True

        while running:
            # Handle events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

                elif event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1 and not self.game_over:  # Left mouse button
                        self.fire_player_missile(event.pos[0], event.pos[1])

                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r and self.game_over:
                        self.reset_game()
                    elif event.key == pygame.K_ESCAPE:
                        running = False

            # Update game state
            self.update()

            # Draw everything
            self.draw()

            # Cap the frame rate
            self.clock.tick(FPS)

        pygame.quit()
        sys.exit()


if __name__ == "__main__":
    game = Game()
    game.run()

実行方法

pygameをインストール

pip install pygame

コマンドラインでゲームを実行

python3 missile_command.py

スクリーンショット (1).png

感想

  • cluade codeやchatgpt codexを普段使っていますが、amazon q developperは初めてで操作に慣れるか不安でしたが、claude codeに近い感覚で使えました。
  • Bluetoothが直前で故障し、スピーカが使えなくなったためPC + Quest3 + VirtualDesktopで参加しましたが、意外と普通に作業できました
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?