diff --git a/GameEngine/src/main/java/Main.java b/GameEngine/src/main/java/Main.java index 9fa6e95..c309caf 100644 --- a/GameEngine/src/main/java/Main.java +++ b/GameEngine/src/main/java/Main.java @@ -1,4 +1,3 @@ -import gameEngine.GameEditor; import gameEngine.views.Window; public class Main { diff --git a/GameEngine/src/main/java/gameEngine/GameEditor.java b/GameEngine/src/main/java/gameEngine/GameEditor.java index b19bdd1..7d2f92d 100644 --- a/GameEngine/src/main/java/gameEngine/GameEditor.java +++ b/GameEngine/src/main/java/gameEngine/GameEditor.java @@ -1,368 +1,61 @@ package gameEngine; -import gameEngine.entites.Entity; -import gameEngine.entites.GameObject; -import gameEngine.entites.gameComponents.GameComponent; -import gameEngine.entites.gameComponents.*; -import gameEngine.scenes.*; +import gameEngine.views.Button; +import gameEngine.scenes.Scene; +import gameEngine.views.Sprite; +import gameEngine.views.Text; import gameEngine.views.Window; -import org.joml.Vector3f; -import javax.swing.*; -import java.awt.*; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.util.List; -import java.util.Map; +public class GameEditor { + private Scene scene; + private final String frameImagePath = "GameEngine/resources/EditorFrame.png"; -public class GameEditor extends JFrame { + private Sprite[] EditorFrameSprite = new Sprite[4]; - private JList objectList; - private DefaultListModel listModel; - private DefaultListModel componentListModel; - private JList componentList; - private JLabel entityLabel, nameLabel, posLabel, rotLabel, scaLabel; - private JTextField posXField, posYField, posZField; - private JTextField rotXField, rotYField, rotZField; - private JTextField scaleXField, scaleYField, scaleZField; - private JTextField nameField; - private Scene gameScene; - private Timer updateTimer; - private JComboBox componentDropdown; + private Button playButton; + private Text playButtonText; - private String lastLoadedName; - private Vector3f lastLoadedPos, lastLoadedRot, lastLoadedScale; + private Button createObjectButton; + private Text createObjectButtonText; - public GameEditor() - { - setTitle("Game Object Editor"); - setSize(500, 400); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 閉じられないようにする - setLayout(null); // レイアウトを絶対座標に設定 - initializeUIComponents();// 各UI要素の初期化 - initializeUpdateTimer(); // 定期的にリスト更新を行うタイマーを初期化 - setVisible(true); // フレームを表示} + public GameEditor(Scene scene) { + this.scene = scene; + initializeEditorComponents(); } - // UI要素を初期化し、配置関数を呼び出す - private void initializeUIComponents() { - listModel = new DefaultListModel<>(); - objectList = new JList<>(listModel); - JScrollPane scrollPane = new JScrollPane(objectList); + private void initializeEditorComponents() { + EditorFrameSprite[0] = new Sprite(frameImagePath, 0, 0, 20, 0.5f); + EditorFrameSprite[1] = new Sprite(frameImagePath, 0, 0, 0.25f, 20); + EditorFrameSprite[2] = new Sprite(frameImagePath, Window.get().width-16, 0, 0.25f, 20); + EditorFrameSprite[3] = new Sprite(frameImagePath, 0, Window.get().height-16, 20, 0.5f); - objectList.setCellRenderer(createEntityRenderer()); - componentListModel = new DefaultListModel<>(); - componentList = new JList<>(componentListModel); - JScrollPane componentScrollPane = new JScrollPane(componentList); - componentList.setCellRenderer(createComponentRenderer()); + playButton = new Button(Window.get().width/ 2 -16 , 3, 1, 0.4f); + playButtonText = new Text(Window.get().width/ 2 - 11.25f, 1, "Play", 24); - // 各UIコンポーネントの作成と配置 - entityLabel = new JLabel("Entity:"); - nameField = new JTextField(20); - nameLabel = new JLabel("Name:"); - posLabel = new JLabel("Position:"); - rotLabel = new JLabel("Rotation:"); - scaLabel = new JLabel("Scale:"); - posXField = new JTextField(5); - posYField = new JTextField(5); - posZField = new JTextField(5); - rotXField = new JTextField(5); - rotYField = new JTextField(5); - rotZField = new JTextField(5); - scaleXField = new JTextField(5); - scaleYField = new JTextField(5); - scaleZField = new JTextField(5); - componentDropdown = new JComboBox<>(new String[]{"ColorController", "CopyEntity", "MoveImage", "Physics"}); + createObjectButton = new Button(50, 3, 0.4f, 0.4f); + createObjectButtonText = new Text(50 +5.25f, 0.4f, "+", 24); - addChangeListener(posXField, posYField, posZField, rotXField, rotYField, rotZField, scaleXField, scaleYField, scaleZField, nameField); - - JButton newGameObjectButton = new JButton("Add Entity"); - newGameObjectButton.addActionListener(e -> createNewGameObject()); - - JButton addComponentButton = new JButton("+ Component"); - addComponentButton.addActionListener(e -> addComponentToGameObject()); - - JButton removeComponentButton = new JButton("- Component"); - removeComponentButton.addActionListener(e -> removeComponentFromGameObject()); - - - int pos = 170; - // 各要素の位置とサイズを設定 - setComponentBounds(entityLabel, 10, 5, 100, 30); - setComponentBounds(scrollPane, 10, 30, 150, 300); - setComponentBounds(componentScrollPane, 350, 170, 130, 165); - setComponentBounds(nameLabel, pos, 10, 100, 30); - setComponentBounds(nameField, pos+50, 10, 170, 25); - setComponentBounds(posLabel, pos, 50, 100, 30); - setComponentBounds(posXField, pos + 50, 50, 50, 30); - setComponentBounds(posYField, pos + 110, 50, 50, 30); - setComponentBounds(posZField, pos + 170, 50, 50, 30); - setComponentBounds(rotLabel, pos, 90, 100, 30); - setComponentBounds(rotXField, pos + 50, 90, 50, 30); - setComponentBounds(rotYField, pos + 110, 90, 50, 30); - setComponentBounds(rotZField, pos + 170, 90, 50, 30); - setComponentBounds(scaLabel, pos, 130, 100, 30); - setComponentBounds(scaleXField, pos + 50, 130, 50, 30); - setComponentBounds(scaleYField, pos + 110, 130, 50, 30); - setComponentBounds(scaleZField, pos + 170, 130, 50, 30); - setComponentBounds(newGameObjectButton, 200, 170, 110, 20); - setComponentBounds(addComponentButton, 200, 260, 130, 20); - setComponentBounds(removeComponentButton, 200, 290, 130, 20); - setComponentBounds(componentDropdown, 200, 225, 130, 20); // ドロップダウンの位置とサイズを設定 - - objectList.addListSelectionListener(e -> { - if (!e.getValueIsAdjusting()) { // ユーザーが調整中でない場合のみ - loadSelectedGameObject(); // オブジェクトのプロパティをロード - } - }); - } - private void addChangeListener(JTextField... fields) { - for (JTextField field : fields) { - field.addActionListener(e -> applyGameObjectChanges()); - - field.addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - updateTimer.stop(); - } - - @Override - public void focusLost(FocusEvent e) { - applyGameObjectChanges(); - updateTimer.start(); - } - }); - } + setButtonListeners(); } - private void initializeUpdateTimer() { - updateTimer = new Timer(750, e -> { - String selectedObject = objectList.getSelectedValue(); - GameComponent selectedComponent = componentList.getSelectedValue(); + private void setButtonListeners() { + playButton.clearListeners(); + playButton.addListener(scene::changeSceneStart); - updateGameObjectList(gameScene); - - if (selectedObject != null) { - objectList.setSelectedValue(selectedObject, true); - Entity selectedEntity = gameScene.getEntity(selectedObject); - if (selectedEntity instanceof GameObject) { - updateComponentList((GameObject) selectedEntity); - } - } - - if (selectedComponent != null) { - componentList.setSelectedValue(selectedComponent, true); - } - }); - updateTimer.start(); + createObjectButton.clearListeners(); + createObjectButton.addListener(scene::addNewObject); } - private ListCellRenderer createEntityRenderer() { - return (list, value, index, isSelected, cellHasFocus) -> { - JLabel label = new JLabel(); - Entity entity = gameScene.getEntity(value); - label.setText(entity.getName()); - label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); - label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground()); - label.setOpaque(true); - return label; - }; - } - private ListCellRenderer createComponentRenderer() { - return (list, value, index, isSelected, cellHasFocus) -> { - JLabel label = new JLabel(value.getClass().getSimpleName()); - label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); - label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground()); - label.setOpaque(true); - return label; - }; + public void setScene(Scene newScene) { + this.scene = newScene; + setButtonListeners(); } - private void setComponentBounds(Component component, int x, int y, int width, int height) { - component.setBounds(x, y, width, height); - add(component); //フレームに追加 + public void update() { + for(Sprite editorFrameSprites : EditorFrameSprite) editorFrameSprites.update(); + playButton.update(); + playButtonText.update(); + createObjectButton.update(); + createObjectButtonText.update(); } - - private void createNewGameObject() { - gameScene.addNewObject(); // 新しいGameObjectを作成 - updateGameObjectList(gameScene); // オブジェクトリストの更新 - objectList.setSelectedIndex(listModel.getSize() - 1); // 新規作成したオブジェクトを選択 - applyGameObjectChanges(); // 作成直後に即座にプロパティを反映させる - } - - private void addComponentToGameObject() { - // 現在の選択状態を保存 - String selectedObject = objectList.getSelectedValue(); - GameComponent selectedComponent = componentList.getSelectedValue(); - - // コンポーネントの追加処理 - if (selectedObject != null) { - Entity selectedEntity = gameScene.getEntity(selectedObject); - if (selectedEntity instanceof GameObject) { - GameObject gameObject = (GameObject) selectedEntity; - - String component = (String) componentDropdown.getSelectedItem(); - switch (component) { - case "ColorController": - gameScene.addComponentToGameObject(gameObject, new ColorController()); - break; - case "CopyEntity": - gameScene.addComponentToGameObject(gameObject, new CopyEntity(gameObject)); - break; - case "MoveImage": - gameScene.addComponentToGameObject(gameObject, new MoveImage(gameObject)); - break; - case "Physics": - gameScene.addComponentToGameObject(gameObject, new Physics(gameObject)); - break; - default: - JOptionPane.showMessageDialog(this, "Unknown Component Selected"); - break; - } - - // リストの更新 - updateComponentList(gameObject); - updateGameObjectList(gameScene); // オブジェクトリストの更新 - - //ダイアログ - JOptionPane.showMessageDialog(this, "Component Added to " + selectedEntity.name); - } - } - - // 選択状態を復元 - if (selectedObject != null) { - objectList.setSelectedValue(selectedObject, true); - } - if (selectedComponent != null) { - componentList.setSelectedValue(selectedComponent, true); - } - } - - private void removeComponentFromGameObject() { - String selectedIdStr = objectList.getSelectedValue(); - if (selectedIdStr != null) { - Entity selectedEntity = gameScene.getEntity(selectedIdStr); - if (selectedEntity instanceof GameObject) { - GameObject gameObject = (GameObject) selectedEntity; - GameComponent selectedComponent = componentList.getSelectedValue(); // GameComponentとして取得 - if (selectedComponent != null) { - gameScene.removeComponentFromGameObject(gameObject, selectedComponent); - updateComponentList(gameObject); // コンポーネントリストの更新 - JOptionPane.showMessageDialog(this, "Component Removed from " + selectedEntity.name); - } - } - } - } - - private void updateGameObjectList(Scene gameScene) { - listModel.clear(); - for (Map.Entry entry : gameScene.entities.entrySet()) { - Entity entity = entry.getValue(); - listModel.addElement(entity.getId()); - } - objectList.repaint(); - } - - - private void updateComponentList(GameObject gameObject) { - componentListModel.clear(); // リストをクリア - List components = gameObject.gameComponents; - for (GameComponent component : components) { - componentListModel.addElement(component); // コンポーネントを追加 - } - componentList.repaint(); - } - - private void loadSelectedGameObject() { - String selectedIdStr = objectList.getSelectedValue(); - if (selectedIdStr != null) { - Entity selectedEntity = gameScene.getEntity(selectedIdStr); - if (selectedEntity != null) { - loadObjectProperties(selectedEntity); - if (selectedEntity instanceof GameObject) { - updateComponentList((GameObject) selectedEntity); - } - } - } - } - - private void applyGameObjectChanges() { - String selectedIdStr = objectList.getSelectedValue(); - if (selectedIdStr != null) { - Entity selectedEntity = gameScene.getEntity(selectedIdStr); - if (selectedEntity != null) { - try { - String newName = nameField.getText(); - if (!newName.equals(lastLoadedName)) { - selectedEntity.setName(newName); - } - - Vector3f newPos = new Vector3f( - Float.parseFloat(posXField.getText()), - Float.parseFloat(posYField.getText()), - Float.parseFloat(posZField.getText()) - ); - if (!newPos.equals(lastLoadedPos)) { - selectedEntity.transform.setPosition(newPos); - } - - Vector3f newRot = new Vector3f( - Float.parseFloat(rotXField.getText()), - Float.parseFloat(rotYField.getText()), - Float.parseFloat(rotZField.getText()) - ); - if (!newRot.equals(lastLoadedRot)) { - selectedEntity.transform.setRotation(newRot); - } - - Vector3f newScale = new Vector3f( - Float.parseFloat(scaleXField.getText()), - Float.parseFloat(scaleYField.getText()), - Float.parseFloat(scaleZField.getText()) - ); - if (!newScale.equals(lastLoadedScale)) { - selectedEntity.transform.setScale(newScale); - } - - updateGameObjectList(gameScene); - - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(this, "Invalid input. Please enter valid numbers.", "Error", JOptionPane.ERROR_MESSAGE); - } - } - } - } - - - public void updateListByScene(Scene gameScene) { - this.gameScene = gameScene; - updateGameObjectList(gameScene); - componentListModel.clear(); - componentList.repaint(); - } - - //entityの情報を取得 - private void loadObjectProperties(Entity entity) { - nameField.setText(entity.getName()); - Vector3f pos = entity.transform.position; - posXField.setText(String.valueOf(pos.x)); - posYField.setText(String.valueOf(pos.y)); - posZField.setText(String.valueOf(pos.z)); - - Vector3f rot = entity.transform.rotation; - rotXField.setText(String.valueOf(rot.x)); - rotYField.setText(String.valueOf(rot.y)); - rotZField.setText(String.valueOf(rot.z)); - - Vector3f scale = entity.transform.scale; - scaleXField.setText(String.valueOf(scale.x)); - scaleYField.setText(String.valueOf(scale.y)); - scaleZField.setText(String.valueOf(scale.z)); - - lastLoadedName = entity.getName(); - lastLoadedPos = pos; - lastLoadedRot = rot; - lastLoadedScale = scale; - } - } diff --git a/GameEngine/src/main/java/gameEngine/SwingGameEditor.java b/GameEngine/src/main/java/gameEngine/SwingGameEditor.java new file mode 100644 index 0000000..e43fa9e --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/SwingGameEditor.java @@ -0,0 +1,367 @@ +package gameEngine; + +import gameEngine.entites.Entity; +import gameEngine.entites.GameObject; +import gameEngine.entites.gameComponents.GameComponent; +import gameEngine.entites.gameComponents.*; +import gameEngine.scenes.*; +import org.joml.Vector3f; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.util.List; +import java.util.Map; + +public class SwingGameEditor extends JFrame { + + private JList objectList; + private DefaultListModel listModel; + private DefaultListModel componentListModel; + private JList componentList; + private JLabel entityLabel, nameLabel, posLabel, rotLabel, scaLabel; + private JTextField posXField, posYField, posZField; + private JTextField rotXField, rotYField, rotZField; + private JTextField scaleXField, scaleYField, scaleZField; + private JTextField nameField; + private Scene gameScene; + private Timer updateTimer; + private JComboBox componentDropdown; + + private String lastLoadedName; + private Vector3f lastLoadedPos, lastLoadedRot, lastLoadedScale; + + public SwingGameEditor() + { + setTitle("Game Object Editor"); + setSize(500, 400); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 閉じられないようにする + setLayout(null); // レイアウトを絶対座標に設定 + initializeUIComponents();// 各UI要素の初期化 + initializeUpdateTimer(); // 定期的にリスト更新を行うタイマーを初期化 + setVisible(true); // フレームを表示} + } + + // UI要素を初期化し、配置関数を呼び出す + private void initializeUIComponents() { + listModel = new DefaultListModel<>(); + objectList = new JList<>(listModel); + JScrollPane scrollPane = new JScrollPane(objectList); + + objectList.setCellRenderer(createEntityRenderer()); + componentListModel = new DefaultListModel<>(); + componentList = new JList<>(componentListModel); + JScrollPane componentScrollPane = new JScrollPane(componentList); + componentList.setCellRenderer(createComponentRenderer()); + + // 各UIコンポーネントの作成と配置 + entityLabel = new JLabel("Entity:"); + nameField = new JTextField(20); + nameLabel = new JLabel("Name:"); + posLabel = new JLabel("Position:"); + rotLabel = new JLabel("Rotation:"); + scaLabel = new JLabel("Scale:"); + posXField = new JTextField(5); + posYField = new JTextField(5); + posZField = new JTextField(5); + rotXField = new JTextField(5); + rotYField = new JTextField(5); + rotZField = new JTextField(5); + scaleXField = new JTextField(5); + scaleYField = new JTextField(5); + scaleZField = new JTextField(5); + componentDropdown = new JComboBox<>(new String[]{"ColorController", "CopyEntity", "MoveImage", "Physics"}); + + addChangeListener(posXField, posYField, posZField, rotXField, rotYField, rotZField, scaleXField, scaleYField, scaleZField, nameField); + + JButton newGameObjectButton = new JButton("Add Entity"); + newGameObjectButton.addActionListener(e -> createNewGameObject()); + + JButton addComponentButton = new JButton("+ Component"); + addComponentButton.addActionListener(e -> addComponentToGameObject()); + + JButton removeComponentButton = new JButton("- Component"); + removeComponentButton.addActionListener(e -> removeComponentFromGameObject()); + + + int pos = 170; + // 各要素の位置とサイズを設定 + setComponentBounds(entityLabel, 10, 5, 100, 30); + setComponentBounds(scrollPane, 10, 30, 150, 300); + setComponentBounds(componentScrollPane, 350, 170, 130, 165); + setComponentBounds(nameLabel, pos, 10, 100, 30); + setComponentBounds(nameField, pos+50, 10, 170, 25); + setComponentBounds(posLabel, pos, 50, 100, 30); + setComponentBounds(posXField, pos + 50, 50, 50, 30); + setComponentBounds(posYField, pos + 110, 50, 50, 30); + setComponentBounds(posZField, pos + 170, 50, 50, 30); + setComponentBounds(rotLabel, pos, 90, 100, 30); + setComponentBounds(rotXField, pos + 50, 90, 50, 30); + setComponentBounds(rotYField, pos + 110, 90, 50, 30); + setComponentBounds(rotZField, pos + 170, 90, 50, 30); + setComponentBounds(scaLabel, pos, 130, 100, 30); + setComponentBounds(scaleXField, pos + 50, 130, 50, 30); + setComponentBounds(scaleYField, pos + 110, 130, 50, 30); + setComponentBounds(scaleZField, pos + 170, 130, 50, 30); + setComponentBounds(newGameObjectButton, 200, 170, 110, 20); + setComponentBounds(addComponentButton, 200, 260, 130, 20); + setComponentBounds(removeComponentButton, 200, 290, 130, 20); + setComponentBounds(componentDropdown, 200, 225, 130, 20); // ドロップダウンの位置とサイズを設定 + + objectList.addListSelectionListener(e -> { + if (!e.getValueIsAdjusting()) { // ユーザーが調整中でない場合のみ + loadSelectedGameObject(); // オブジェクトのプロパティをロード + } + }); + } + private void addChangeListener(JTextField... fields) { + for (JTextField field : fields) { + field.addActionListener(e -> applyGameObjectChanges()); + + field.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + updateTimer.stop(); + } + + @Override + public void focusLost(FocusEvent e) { + applyGameObjectChanges(); + updateTimer.start(); + } + }); + } + } + + private void initializeUpdateTimer() { + updateTimer = new Timer(750, e -> { + String selectedObject = objectList.getSelectedValue(); + GameComponent selectedComponent = componentList.getSelectedValue(); + + updateGameObjectList(gameScene); + + if (selectedObject != null) { + objectList.setSelectedValue(selectedObject, true); + Entity selectedEntity = gameScene.getEntity(selectedObject); + if (selectedEntity instanceof GameObject) { + updateComponentList((GameObject) selectedEntity); + } + } + + if (selectedComponent != null) { + componentList.setSelectedValue(selectedComponent, true); + } + }); + updateTimer.start(); + } + + private ListCellRenderer createEntityRenderer() { + return (list, value, index, isSelected, cellHasFocus) -> { + JLabel label = new JLabel(); + Entity entity = gameScene.getEntity(value); + label.setText(entity.getName()); + label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); + label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground()); + label.setOpaque(true); + return label; + }; + } + private ListCellRenderer createComponentRenderer() { + return (list, value, index, isSelected, cellHasFocus) -> { + JLabel label = new JLabel(value.getClass().getSimpleName()); + label.setBackground(isSelected ? list.getSelectionBackground() : list.getBackground()); + label.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground()); + label.setOpaque(true); + return label; + }; + } + + private void setComponentBounds(Component component, int x, int y, int width, int height) { + component.setBounds(x, y, width, height); + add(component); //フレームに追加 + } + + private void createNewGameObject() { + gameScene.addNewObject(); // 新しいGameObjectを作成 + updateGameObjectList(gameScene); // オブジェクトリストの更新 + objectList.setSelectedIndex(listModel.getSize() - 1); // 新規作成したオブジェクトを選択 + applyGameObjectChanges(); // 作成直後に即座にプロパティを反映させる + } + + private void addComponentToGameObject() { + // 現在の選択状態を保存 + String selectedObject = objectList.getSelectedValue(); + GameComponent selectedComponent = componentList.getSelectedValue(); + + // コンポーネントの追加処理 + if (selectedObject != null) { + Entity selectedEntity = gameScene.getEntity(selectedObject); + if (selectedEntity instanceof GameObject) { + GameObject gameObject = (GameObject) selectedEntity; + + String component = (String) componentDropdown.getSelectedItem(); + switch (component) { + case "ColorController": + gameScene.addComponentToGameObject(gameObject, new ColorController()); + break; + case "CopyEntity": + gameScene.addComponentToGameObject(gameObject, new CopyEntity(gameObject)); + break; + case "MoveImage": + gameScene.addComponentToGameObject(gameObject, new MoveImage(gameObject)); + break; + case "Physics": + gameScene.addComponentToGameObject(gameObject, new Physics(gameObject)); + break; + default: + JOptionPane.showMessageDialog(this, "Unknown Component Selected"); + break; + } + + // リストの更新 + updateComponentList(gameObject); + updateGameObjectList(gameScene); // オブジェクトリストの更新 + + //ダイアログ + JOptionPane.showMessageDialog(this, "Component Added to " + selectedEntity.name); + } + } + + // 選択状態を復元 + if (selectedObject != null) { + objectList.setSelectedValue(selectedObject, true); + } + if (selectedComponent != null) { + componentList.setSelectedValue(selectedComponent, true); + } + } + + private void removeComponentFromGameObject() { + String selectedIdStr = objectList.getSelectedValue(); + if (selectedIdStr != null) { + Entity selectedEntity = gameScene.getEntity(selectedIdStr); + if (selectedEntity instanceof GameObject) { + GameObject gameObject = (GameObject) selectedEntity; + GameComponent selectedComponent = componentList.getSelectedValue(); // GameComponentとして取得 + if (selectedComponent != null) { + gameScene.removeComponentFromGameObject(gameObject, selectedComponent); + updateComponentList(gameObject); // コンポーネントリストの更新 + JOptionPane.showMessageDialog(this, "Component Removed from " + selectedEntity.name); + } + } + } + } + + private void updateGameObjectList(Scene gameScene) { + listModel.clear(); + for (Map.Entry entry : gameScene.entities.entrySet()) { + Entity entity = entry.getValue(); + listModel.addElement(entity.getId()); + } + objectList.repaint(); + } + + + private void updateComponentList(GameObject gameObject) { + componentListModel.clear(); // リストをクリア + List components = gameObject.gameComponents; + for (GameComponent component : components) { + componentListModel.addElement(component); // コンポーネントを追加 + } + componentList.repaint(); + } + + private void loadSelectedGameObject() { + String selectedIdStr = objectList.getSelectedValue(); + if (selectedIdStr != null) { + Entity selectedEntity = gameScene.getEntity(selectedIdStr); + if (selectedEntity != null) { + loadObjectProperties(selectedEntity); + if (selectedEntity instanceof GameObject) { + updateComponentList((GameObject) selectedEntity); + } + } + } + } + + private void applyGameObjectChanges() { + String selectedIdStr = objectList.getSelectedValue(); + if (selectedIdStr != null) { + Entity selectedEntity = gameScene.getEntity(selectedIdStr); + if (selectedEntity != null) { + try { + String newName = nameField.getText(); + if (!newName.equals(lastLoadedName)) { + selectedEntity.setName(newName); + } + + Vector3f newPos = new Vector3f( + Float.parseFloat(posXField.getText()), + Float.parseFloat(posYField.getText()), + Float.parseFloat(posZField.getText()) + ); + if (!newPos.equals(lastLoadedPos)) { + selectedEntity.transform.setPosition(newPos); + } + + Vector3f newRot = new Vector3f( + Float.parseFloat(rotXField.getText()), + Float.parseFloat(rotYField.getText()), + Float.parseFloat(rotZField.getText()) + ); + if (!newRot.equals(lastLoadedRot)) { + selectedEntity.transform.setRotation(newRot); + } + + Vector3f newScale = new Vector3f( + Float.parseFloat(scaleXField.getText()), + Float.parseFloat(scaleYField.getText()), + Float.parseFloat(scaleZField.getText()) + ); + if (!newScale.equals(lastLoadedScale)) { + selectedEntity.transform.setScale(newScale); + } + + updateGameObjectList(gameScene); + + } catch (NumberFormatException e) { + JOptionPane.showMessageDialog(this, "Invalid input. Please enter valid numbers.", "Error", JOptionPane.ERROR_MESSAGE); + } + } + } + } + + + public void updateListByScene(Scene gameScene) { + this.gameScene = gameScene; + updateGameObjectList(gameScene); + componentListModel.clear(); + componentList.repaint(); + } + + //entityの情報を取得 + private void loadObjectProperties(Entity entity) { + nameField.setText(entity.getName()); + Vector3f pos = entity.transform.position; + posXField.setText(String.valueOf(pos.x)); + posYField.setText(String.valueOf(pos.y)); + posZField.setText(String.valueOf(pos.z)); + + Vector3f rot = entity.transform.rotation; + rotXField.setText(String.valueOf(rot.x)); + rotYField.setText(String.valueOf(rot.y)); + rotZField.setText(String.valueOf(rot.z)); + + Vector3f scale = entity.transform.scale; + scaleXField.setText(String.valueOf(scale.x)); + scaleYField.setText(String.valueOf(scale.y)); + scaleZField.setText(String.valueOf(scale.z)); + + lastLoadedName = entity.getName(); + lastLoadedPos = pos; + lastLoadedRot = rot; + lastLoadedScale = scale; + } + +} diff --git a/GameEngine/src/main/java/gameEngine/entites/GameObject.java b/GameEngine/src/main/java/gameEngine/entites/GameObject.java index 6f1f3ff..3325805 100644 --- a/GameEngine/src/main/java/gameEngine/entites/GameObject.java +++ b/GameEngine/src/main/java/gameEngine/entites/GameObject.java @@ -1,6 +1,5 @@ package gameEngine.entites; -import gameEngine.entites.gameComponents.EditorButton; import gameEngine.entites.gameComponents.GameComponent; import gameEngine.entites.gameComponents.Mesh; import gameEngine.entites.gameComponents.TextMesh; @@ -55,9 +54,6 @@ else if (component instanceof TextMesh) { component.update(); } - else if(component instanceof EditorButton){ - component.update(); - } } else { component.update(); } diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Button.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Button.java deleted file mode 100644 index 55b1702..0000000 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Button.java +++ /dev/null @@ -1,71 +0,0 @@ -package gameEngine.entites.gameComponents; - -import gameEngine.entites.Entity; -import gameEngine.entites.GameObject; -import gameEngine.input.Input; -import gameEngine.input.MouseInput; -import gameEngine.views.Color; - -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.List; - -public class Button extends GameComponent { - - private Entity entity; - private Mesh mesh; - private List onClickListeners = new ArrayList<>(); - private boolean isPressed = false; - - public Color normalColor = new Color(1f,1f,1f,1f); - public Color pressedColor = new Color(0.5f, 0.5f, 0.5f, 1f); - - public Button(Entity entity, Mesh mesh) { - this.entity = entity; - this.mesh = mesh; - } - - @Override - public GameComponent copy() { - return null; - } - - public void init() { - } - - public void update() { - - GameObject gameObject = (GameObject) entity; - float mouseX = MouseInput.getX(); - float mouseY = MouseInput.getY(); - - float x = entity.transform.position.x; - float y = entity.transform.position.y; - float width = mesh.getDisplayedWidth(); - float height = mesh.getDisplayedHeight(); - - if (Input.GetMouseButtonDown(0) && mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { - isPressed = true; // ボタン上でMouseDownした場合のみ押下状態にする - gameObject.getComponent(Mesh.class).setColor(pressedColor); - - } - - if (Input.GetMouseButtonUp(0)) { - gameObject.getComponent(Mesh.class).setColor(normalColor); - if (isPressed && mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height) { - System.out.println("Button pressed! Mouse X: " + mouseX + ", Mouse Y: " + mouseY); - for (Runnable listener : onClickListeners) { - listener.run(); - System.out.println(listener); - } - } - isPressed = false; - } - - } - - public void addListener(Runnable listener) { - onClickListeners.add(listener); - } -} diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/ButtonComponent.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/ButtonComponent.java new file mode 100644 index 0000000..a54ac69 --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/entites/gameComponents/ButtonComponent.java @@ -0,0 +1,43 @@ +package gameEngine.entites.gameComponents; + +import gameEngine.entites.Entity; +import gameEngine.views.Button; +import gameEngine.views.Color; + +public class ButtonComponent extends GameComponent { + private Button button; + + public ButtonComponent(Entity entity) { + this.button = new Button(entity.transform.position.x, entity.transform.position.y, + entity.transform.scale.x, entity.transform.scale.y); + } + + @Override + public GameComponent copy() { + return this; // Deep copy if needed + } + + public void init() { + button.update(); + } + + public void update() { + button.update(); + } + + public void addListener(Runnable listener) { + button.addListener(listener); + } + + public void clearListeners() { + button.clearListeners(); + } + + public void setNormalColor(Color color) { + button.setNormalColor(color); + } + + public void setPressedColor(Color color) { + button.setPressedColor(color); + } +} diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/EditorButton.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/EditorButton.java deleted file mode 100644 index 792ca2e..0000000 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/EditorButton.java +++ /dev/null @@ -1,15 +0,0 @@ -package gameEngine.entites.gameComponents; - -import gameEngine.entites.Entity; - -// -// Editor時に動くButton(通常ButtonはGame実行時のみ動く) -// - -public class EditorButton extends Button{ - - public EditorButton(Entity entity, Mesh mesh) { - super(entity, mesh); - } - -} diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java index 59bc2b5..1c55d6a 100644 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java +++ b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Mesh.java @@ -3,6 +3,7 @@ import gameEngine.entites.Entity; import gameEngine.entites.GameObject; import gameEngine.views.Color; +import gameEngine.views.Sprite; import gameEngine.views.Texture; import gameEngine.views.Window; import static org.lwjgl.opengl.GL11.*; @@ -14,26 +15,22 @@ } private final MeshType type; - private Texture texture; // スプライトのテクスチャを保持 + private Sprite sprite; private final Entity parent; // 親のオブジェクトを持つ - private Color color = new Color(1f, 1f, 1f, 1f); - - private int spriteWidth = 64; // スプライト幅(今後指定可能にする) - private int spriteHeight = 64; // スプライト高さ(今後指定可能にする) public Mesh(Entity parent, MeshType type, String texturePath) { this.parent = parent; this.type = type; if (type == MeshType.SPRITE) { - this.texture = new Texture(texturePath); // Load the image - updateSpriteDimensions(); + this.sprite = new Sprite(texturePath); + sprite.updateSpriteDimensions(); } } public Mesh(Mesh original, Entity newParent) { this.type = original.type; - this.texture = original.texture; // Textureをそのまま参照 - this.parent = newParent; // 新しい親オブジェクトに設定 - updateSpriteDimensions(); + this.sprite = original.sprite; + this.parent = newParent; + sprite.updateSpriteDimensions(); } @Override @@ -44,131 +41,35 @@ @Override public void init() { if (type == MeshType.SPRITE) { - renderSprite(); // スプライトの描画 - updateSpriteDimensions(); + sprite.update(); + sprite.updateSpriteDimensions(); } } @Override public void update() { if (type == MeshType.SPRITE) { - Integer id = texture.getId(); - if(id == null){ - texture.init(); - } - renderSprite(); // スプライトの描画 + sprite.setPosition(parent.transform.position); + sprite.setRotation(parent.transform.rotation); + sprite.setScale(parent.transform.scale); + sprite.update(); } } - /** - * メッシュのカラーを変更 - * - */ + public void setSprite(String texturePath){ + sprite.setTexturePath(texturePath); + } + public void setColor(Color color){ - this.color = color; - renderSprite(); + sprite.setColor(color); + sprite.update(); } - /** - * スプライトの最終的な表示幅を取得 - * @return 表示幅(スケールとZスケールを考慮したサイズ) - */ public float getDisplayedWidth() { - float zScale = calculateZScale(); - return spriteWidth * parent.transform.scale.x * zScale; + return sprite != null ? sprite.getDisplayedWidth() : 0; } - /** - * スプライトの最終的な表示高さを取得 - * @return 表示高さ(スケールとZスケールを考慮したサイズ) - */ public float getDisplayedHeight() { - float zScale = calculateZScale(); - return spriteHeight * parent.transform.scale.y * zScale; - } - - /** - * Z軸スケールを計算する - * @return 計算されたZ軸スケール - */ - private float calculateZScale() { - float z = parent.transform.position.z; - if (z >= 0) { - return 1.0f + (z * 0.1f); - } else { - return 1.0f / (1.0f + Math.abs(z) * 0.1f); - } - } - - private void updateSpriteDimensions() { - if (texture != null) { - this.spriteWidth = texture.getWidth(); - this.spriteHeight = texture.getHeight(); - } - } - - public void setTexturePath(String texturePath){ - this.texture = new Texture(texturePath); - updateSpriteDimensions(); - } - - private void renderSprite() { - // 2Dの描画モードに切り替え - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - // ピクセル単位の座標系に設定 - glOrtho(0, Window.get().width, Window.get().height, 0, -1000, 1000); - - // モデルビュー行列に切り替えて描画する位置を決める - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - // テクスチャをバインド - glBindTexture(GL_TEXTURE_2D, texture.getId()); - - // 親のGameObjectの座標と回転を取得 - float x = parent.transform.position.x; - float y = parent.transform.position.y; - float z = parent.transform.position.z; - float rotationZ = parent.transform.rotation.z; - float scaleX = parent.transform.scale.x; - float scaleY = parent.transform.scale.y; - float zScale; - if (z >= 0) { - zScale = 1.0f + (z * 0.1f); - } else { - zScale = 1.0f / (1.0f + Math.abs(z) * 0.1f); - } - - // 左上基準でスケーリング - glTranslatef(x, y, z); - glScalef(scaleX * zScale, scaleY * zScale, 1.0f); // スケールを適用 - glRotatef(rotationZ, 0, 0, 1); // Z軸周りの回転 - - // テクスチャの描画設定 - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(color.r, color.g, color.b, color.a); - - // 四角形を描画 - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex3f(0, 0, 0); // 左上の頂点 - glTexCoord2f(1, 0); glVertex3f(spriteWidth, 0, 0); // 右上の頂点 - glTexCoord2f(1, 1); glVertex3f(spriteWidth, spriteHeight, 0); // 右下の頂点 - glTexCoord2f(0, 1); glVertex3f(0, spriteHeight, 0); // 左下の頂点 - glEnd(); - - // テクスチャの使用を終了 - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - // 行列を元に戻す - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); + return sprite != null ? sprite.getDisplayedHeight() : 0; } } \ No newline at end of file diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/MoveImage.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/MoveImage.java index 8503ae8..21fdd09 100644 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/MoveImage.java +++ b/GameEngine/src/main/java/gameEngine/entites/gameComponents/MoveImage.java @@ -26,12 +26,12 @@ if(Input.GetKey(GLFW_KEY_O)){ GameObject gameObject = (GameObject) entity; TextMesh textmesh = gameObject.getComponent(TextMesh.class); - textmesh.setTextSize(textmesh.textSize+1); + textmesh.setTextSize(textmesh.getTextSize() + 1); } if(Input.GetKey(GLFW_KEY_P)){ GameObject gameObject = (GameObject) entity; TextMesh textmesh = gameObject.getComponent(TextMesh.class); - textmesh.setTextSize(textmesh.textSize-1); + textmesh.setTextSize(textmesh.getTextSize() - 1); } if(Input.GetKeyDown(GLFW_KEY_I)){ GameObject gameObject = (GameObject) entity; diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Physics.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Physics.java index 67f0a8f..84be1d9 100644 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/Physics.java +++ b/GameEngine/src/main/java/gameEngine/entites/gameComponents/Physics.java @@ -8,7 +8,7 @@ private Entity entity; public boolean useGravity = true; private float gravity = 9.8f; // 地球の重力加速度を使用 - private float velocityY = 0; // Y軸方向の速度 + private float velocityY = 0; // Y軸方向の速度 Resetしなければ速度が引き継がれる public Physics(Entity entity){ this.entity = entity; diff --git a/GameEngine/src/main/java/gameEngine/entites/gameComponents/TextMesh.java b/GameEngine/src/main/java/gameEngine/entites/gameComponents/TextMesh.java index ae5d244..cdba938 100644 --- a/GameEngine/src/main/java/gameEngine/entites/gameComponents/TextMesh.java +++ b/GameEngine/src/main/java/gameEngine/entites/gameComponents/TextMesh.java @@ -2,45 +2,27 @@ import gameEngine.entites.Entity; import gameEngine.views.*; -import java.util.Map; - -import static java.awt.Font.*; -import static org.lwjgl.opengl.GL11.*; public class TextMesh extends GameComponent{ - private Texture fontTexture; // スプライトのテクスチャを保持 - private Map fontGlyphs; - private int fontHeight; - private Entity parent; // 親のオブジェクトを持つ - public String text; - public int textSize; - private Color color = new Color(0f,0f,0f,1f); + private Entity parent; + private Text textRenderer; - private int spriteWidth = 1; // サイズとは無関係 - private int spriteHeight = 1; // サイズとは無関係 - - // コンストラクタ public TextMesh(Entity parent, String text, int textSize) { this.parent = parent; - this.text = text; - this.textSize = textSize; - Font font = new Font(new java.awt.Font(SANS_SERIF, PLAIN, textSize),true); - fontTexture = font.getTexture(); - fontGlyphs = font.getGlyphs(); - fontHeight = font.getFontHeight(); + this.textRenderer = new Text(parent.transform.position.x, parent.transform.position.y, text, textSize); } public TextMesh(TextMesh original, Entity newParent) { this.parent = newParent; - this.text = original.text; - this.textSize = original.textSize; - this.fontGlyphs = original.fontGlyphs; - this.fontTexture = original.fontTexture; - this.fontHeight = original.fontHeight; + this.textRenderer = new Text( + newParent.transform.position.x, + newParent.transform.position.y, + original.textRenderer.text, + original.textRenderer.textSize + ); } - @Override public GameComponent copy() { return this; @@ -48,156 +30,31 @@ @Override public void init() { - renderText(); + textRenderer.update(); } @Override public void update() { - Integer id = fontTexture.getId(); - if (id == null) { - fontTexture.init(); - } - renderText(); // テキストの描画 + textRenderer.setPosition(parent.transform.position); + textRenderer.setRotation(parent.transform.rotation); + textRenderer.setScale(parent.transform.scale); + textRenderer.update(); } public void setText(String newText){ - this.text = newText; - renderText(); + textRenderer.setText(newText); } public void setTextSize(int newTextSize) { - if(newTextSize < 3 || newTextSize > 127) return; - - this.textSize = newTextSize; - Font font = new Font(new java.awt.Font(SANS_SERIF, PLAIN, textSize), true); - this.fontTexture = font.getTexture(); - this.fontGlyphs = font.getGlyphs(); - this.fontHeight = font.getFontHeight(); - renderText(); + textRenderer.setTextSize(newTextSize); } public void setColor(Color color){ - this.color = color; - renderText(); + textRenderer.setColor(color); } - public void renderText() { - // Switch to 2D rendering mode - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, Window.get().width, Window.get().height, 0, -1000, 1000); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - // Bind the font texture for text rendering - glBindTexture(GL_TEXTURE_2D, fontTexture.getId()); - - // Retrieve parent GameObject's transform data - float x = parent.transform.position.x; - float y = parent.transform.position.y; - float z = parent.transform.position.z; - float rotationX = parent.transform.rotation.x; - float rotationY = parent.transform.rotation.y; - float rotationZ = parent.transform.rotation.z; - float scaleX = parent.transform.scale.x; - float scaleY = parent.transform.scale.y; - float scaleZ = parent.transform.scale.z; - - float zScale = z >= 0 ? 1.0f + (z * 0.1f) : 1.0f / (1.0f + Math.abs(z) * 0.1f); - - glTranslatef(x + spriteWidth / 2.0f, y + spriteHeight / 2.0f, z); - glRotatef(rotationX, 1, 0, 0); - glRotatef(rotationY, 0, 1, 0); - glRotatef(rotationZ, 0, 0, 1); - glScalef(scaleX * zScale, scaleY * zScale, scaleZ); - glTranslatef(-(x + spriteWidth / 2.0f), -(y + spriteHeight / 2.0f), z); - - glEnable(GL_TEXTURE_2D); - //ここで文字の背景の透明化 - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //ここまで文字の背景の透明化 - glColor4f(color.r, color.g, color.b, color.a); - - // Text drawing logic - float drawX = x; - float drawY = y; - int textHeight = getHeight(text); - if (textHeight > fontHeight) { - drawY += textHeight - fontHeight; - } - - for (int i = 0; i < text.length(); i++) { - char ch = text.charAt(i); - if (ch == '\n') { - // Handle new line - drawY -= fontHeight; - drawX = x; - continue; - } - if (ch == '\r') { - continue; - } - - Glyph g = fontGlyphs.get(ch); - if (g != null) { - // Render each character as a textured quad - glBegin(GL_QUADS); - glTexCoord2f(g.x / (float) fontTexture.getWidth(), g.y / (float) fontTexture.getHeight()); - glVertex3f(drawX, drawY, z); - - glTexCoord2f((g.x + g.width) / (float) fontTexture.getWidth(), g.y / (float) fontTexture.getHeight()); - glVertex3f(drawX + g.width, drawY, z); - - glTexCoord2f((g.x + g.width) / (float) fontTexture.getWidth(), (g.y + g.height) / (float) fontTexture.getHeight()); - glVertex3f(drawX + g.width, drawY + g.height, z); - - glTexCoord2f(g.x / (float) fontTexture.getWidth(), (g.y + g.height) / (float) fontTexture.getHeight()); - glVertex3f(drawX, drawY + g.height, z); - glEnd(); - - drawX += g.width; - } - } - - // Reset OpenGL states - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - // Restore the previous matrix state - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); + public int getTextSize(){ + return textRenderer.textSize; } - /** - * Gets the height of the specified text. - * - * @param text The text - * @return Height of text - */ - public int getHeight(CharSequence text) { - int height = 0; - int lineHeight = 0; - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - if (c == '\n') { - /* Line end, add line height to stored height */ - height += lineHeight; - lineHeight = 0; - continue; - } - if (c == '\r') { - /* Carriage return, just skip it */ - continue; - } - Glyph g = fontGlyphs.get(c); - lineHeight = Math.max(lineHeight, g.height); - } - height += lineHeight; - return height; - } } diff --git a/GameEngine/src/main/java/gameEngine/input/KeyInput.java b/GameEngine/src/main/java/gameEngine/input/KeyInput.java index 47b4aa4..9da6c25 100644 --- a/GameEngine/src/main/java/gameEngine/input/KeyInput.java +++ b/GameEngine/src/main/java/gameEngine/input/KeyInput.java @@ -33,6 +33,14 @@ } } + // フレームの終わりでリセットするメソッド + public static void endFrame() { + for (int i = 0; i < get().keyDown.length; i++) { + get().keyDown[i] = false; + get().keyUp[i] = false; + } + } + protected static boolean isKeyDown(int keyCode) { if (keyCode <= GLFW_KEY_LAST && keyCode >= 0) { boolean result = get().keyDown[keyCode]; diff --git a/GameEngine/src/main/java/gameEngine/input/MouseInput.java b/GameEngine/src/main/java/gameEngine/input/MouseInput.java index ab1a2b7..19e1481 100644 --- a/GameEngine/src/main/java/gameEngine/input/MouseInput.java +++ b/GameEngine/src/main/java/gameEngine/input/MouseInput.java @@ -56,11 +56,17 @@ get().scrollY = yOffset; } - public static void endFrame(){ + public static void endFrame() { get().scrollX = 0; get().scrollY = 0; get().lastX = get().xPos; get().lastY = get().yPos; + + // フレームの終わりでリセット + for (int i = 0; i < get().mouseButtonDown.length; i++) { + get().mouseButtonDown[i] = false; + get().mouseButtonUp[i] = false; + } } public static float getX(){ @@ -88,12 +94,11 @@ } protected static boolean isMouseButtonDown(int button) { - if (button < get().mouseButtonDown.length) { - boolean result = get().mouseButtonDown[button]; - get().mouseButtonDown[button] = false; // 一度だけ検知するためにリセット - return result; - } - return false; + return button < get().mouseButtonDown.length && get().mouseButtonDown[button]; + } + + protected static boolean isMouseButtonUp(int button) { + return button < get().mouseButtonUp.length && get().mouseButtonUp[button]; } protected static boolean isMouseButtonPressed(int button) { @@ -103,12 +108,4 @@ return false; } - protected static boolean isMouseButtonUp(int button) { - if (button < get().mouseButtonUp.length) { - boolean result = get().mouseButtonUp[button]; - get().mouseButtonUp[button] = false; // 一度だけ検知するためにリセット - return result; - } - return false; - } } diff --git a/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java b/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java index 4af24ef..f615f02 100644 --- a/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java +++ b/GameEngine/src/main/java/gameEngine/scenes/EditorScene.java @@ -10,7 +10,6 @@ public EditorScene(){ System.out.println("Active Editor scene"); glClearColor(1, 1, 1, 0); - addEditor(); } public EditorScene(HashMap entities){ this.entities = entities; diff --git a/GameEngine/src/main/java/gameEngine/scenes/Scene.java b/GameEngine/src/main/java/gameEngine/scenes/Scene.java index 620fb67..6dd2bb0 100644 --- a/GameEngine/src/main/java/gameEngine/scenes/Scene.java +++ b/GameEngine/src/main/java/gameEngine/scenes/Scene.java @@ -48,18 +48,9 @@ entities.remove(eid); } - public void addNewObject() { - enqueueTask(() -> { - addNewGameObject(); - }); - } - - public void addEditor(){ - enqueueTask(() -> { - addEditorFrameObject(); - addNewButtonObject(); - addNewTextObject(); - }); + public Runnable addNewObject() { + enqueueTask(this::addNewGameObject); + return null; } private GameObject createGameObject(){ @@ -70,39 +61,14 @@ return gameObject; } - private void addEditorFrameObject(){ - GameObject editorFrame = createGameObject(); - editorFrame.addComponent(new Mesh(editorFrame, Mesh.MeshType.SPRITE, "GameEngine/resources/EditorFrame.png")); - editorFrame.transform.setPosition(0, 0, 0); - editorFrame.transform.setScale(Window.get().width,0.8f,1); - editorFrame.setName("EditorFrame"); - } - - - private void addNewButtonObject(){ - GameObject button = createGameObject(); - button.addComponent(new Mesh(button, Mesh.MeshType.SPRITE, "GameEngine/resources/button.png")); - button.addComponent(new EditorButton(button, button.getComponent(Mesh.class))); - button.transform.setPosition((float) Window.get().width / 2 - button.getComponent(Mesh.class).getDisplayedWidth()/2 , 5f, 0); - button.transform.setScale(1.4f,0.6f,1); - button.setName("NewEntity" + button.getId()); - - button.getComponent(Button.class).addListener(this::changeSceneStart); - } - - private void addNewTextObject(){ - GameObject text = createGameObject(); - text.addComponent(new TextMesh(text, "Play",32)); - text.transform.setPosition(580, 3f, 0); - text.setName("NewEntity" + text.getId()); - } - private void addNewGameObject(){ GameObject object = createGameObject(); object.addComponent(new Mesh(object, Mesh.MeshType.SPRITE, "GameEngine/resources/0.png")); object.transform.setPosition((float) Window.get().width / 2 - object.getComponent(Mesh.class).getDisplayedWidth()/2 , (float) Window.get().height / 2 - object.getComponent(Mesh.class).getDisplayedHeight()/2, 0); object.addComponent(new MoveImage(object)); + object.addComponent(new TextMesh(object, "Test", 30)); + object.addComponent(new ButtonComponent(object)); } /** @@ -174,12 +140,12 @@ }); } - private void changeSceneStart(){ + public void changeSceneStart(){ if(!changingScene) changingScene = true; } //シーン切り替え時の演出 - void changeScene(int scene, float dt){ + public void changeScene(int scene, float dt){ if(!changingScene && Input.GetKeyDown(KeyEvent.VK_SPACE)){ changingScene = true; } diff --git a/GameEngine/src/main/java/gameEngine/views/Button.java b/GameEngine/src/main/java/gameEngine/views/Button.java new file mode 100644 index 0000000..8714392 --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/views/Button.java @@ -0,0 +1,84 @@ +package gameEngine.views; + +import gameEngine.input.Input; +import gameEngine.input.MouseInput; + +import java.util.ArrayList; +import java.util.List; + +public class Button { + private Sprite buttonSprite; + private List onClickListeners = new ArrayList<>(); + private boolean isPressed = false; + + private Color normalColor = new Color(1f, 1f, 1f, 1f); + private Color pressedColor = new Color(0.5f, 0.5f, 0.5f, 1f); + + public Button(float x, float y, Sprite sprite) { + buttonSprite = sprite; + buttonSprite.setPosition(x, y); + } + + public Button(float posX, float posY, float scaleX, float scaleY){ + this(posX, posY, new Sprite("GameEngine/resources/button.png")); + buttonSprite.setScale(scaleX, scaleY); + } + + public Button(){ + this(0,0, new Sprite("GameEngine/resources/button.png")); + } + + public void update() { + buttonSprite.update(); + float mouseX = MouseInput.getX(); + float mouseY = MouseInput.getY(); + + float width = buttonSprite.getDisplayedWidth(); + float height = buttonSprite.getDisplayedHeight(); + + if (Input.GetMouseButtonDown(0) && isMouseOver(mouseX, mouseY, width, height)) { + isPressed = true; // ボタン上でMouseDownした場合のみ押下状態にする + buttonSprite.setColor(pressedColor); + } + + if (Input.GetMouseButtonUp(0)) { + buttonSprite.setColor(normalColor); + if (isPressed && isMouseOver(mouseX, mouseY, width, height)) { + System.out.println("Editor Button clicked at Mouse X: " + mouseX + ", Mouse Y: " + mouseY); + for (Runnable listener : onClickListeners) { + listener.run(); + } + } + isPressed = false; + } + } + + private boolean isMouseOver(float mouseX, float mouseY, float width, float height) { + return mouseX >= buttonSprite.position.x && mouseX <= buttonSprite.position.x + + width && mouseY >= buttonSprite.position.y && mouseY <= buttonSprite.position.y + height; + } + + public void addListener(Runnable listener) { + onClickListeners.add(listener); + } + + public void clearListeners() { + onClickListeners.clear(); + } + + public void setNormalColor(Color normalColor) { + this.normalColor = normalColor; + } + + public void setPressedColor(Color pressedColor) { + this.pressedColor = pressedColor; + } + + public void setPosition(float x, float y) { + buttonSprite.setPosition(x,y); + } + + public void setScale(float x, float y){ + buttonSprite.setScale(x,y); + } +} \ No newline at end of file diff --git a/GameEngine/src/main/java/gameEngine/views/Renderer.java b/GameEngine/src/main/java/gameEngine/views/Renderer.java new file mode 100644 index 0000000..fa11129 --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/views/Renderer.java @@ -0,0 +1,80 @@ +package gameEngine.views; + +import org.joml.Vector3f; + +import static org.lwjgl.opengl.GL11.*; + +public abstract class Renderer { + protected Vector3f position = new Vector3f(0, 0, 0); + protected Vector3f rotation = new Vector3f(0, 0, 0); + protected Vector3f scale = new Vector3f(1, 1, 1); + protected Color color = new Color(1f, 1f, 1f, 1f); + + public void setPosition(float x, float y){ + this.position.x = x; + this.position.y = y; + } + + public void setPosition(float x, float y, float z){ + this.position = new Vector3f(x,y,z); + } + + public void setPosition(Vector3f pos){ + this.position = pos; + } + + public void setRotation(float x, float y, float z){ + this.rotation = new Vector3f(x,y,z); + } + + public void setRotation(Vector3f rot){ + this.rotation = rot; + } + + public void setScale(float x, float y){ + this.scale.x = x; + this.scale.y = y; + } + + public void setScale(float x, float y, float z){ + this.scale = new Vector3f(x,y,z); + } + + public void setScale(Vector3f scale){ + this.scale = scale; + } + + protected void prepareRendering() { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, Window.get().width, Window.get().height, 0, -1000, 1000); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + float zScale = (position.z >= 0) ? 1.0f + (position.z * 0.1f) : 1.0f / (1.0f + Math.abs(position.z) * 0.1f); + glTranslatef(position.x, position.y, position.z); + glRotatef(rotation.x, 1, 0, 0); + glRotatef(rotation.y, 0, 1, 0); + glRotatef(rotation.z, 0, 0, 1); + glScalef(scale.x * zScale, scale.y * zScale, scale.z); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(color.r, color.g, color.b, color.a); + } + + protected void endRendering() { + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + } + + public abstract void render(); +} \ No newline at end of file diff --git a/GameEngine/src/main/java/gameEngine/views/Sprite.java b/GameEngine/src/main/java/gameEngine/views/Sprite.java new file mode 100644 index 0000000..e7c2280 --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/views/Sprite.java @@ -0,0 +1,77 @@ +package gameEngine.views; + +import org.joml.Vector3f; + +import static org.lwjgl.opengl.GL11.*; + +public class Sprite extends Renderer { + + private Texture texture; + + private int spriteWidth = 1; + private int spriteHeight = 1; + + public Sprite(String texturePath, Vector3f pos, Vector3f scale) { + this.texture = new Texture(texturePath); // テクスチャの読み込み + this.position = pos; + this.rotation = new Vector3f(0,0,0); + this.scale = scale; + updateSpriteDimensions(); + } + + public Sprite(String texturePath, float posX, float posY, float scaleX, float scaleY) { + this(texturePath, new Vector3f(posX, posY,0), new Vector3f(scaleX, scaleY ,1.0f)); + updateSpriteDimensions(); + } + + public Sprite(String texturePath) { + this(texturePath, new Vector3f(0, 0,0), new Vector3f(1.0f, 1.0f, 1.0f)); + } + + public void update(){ + Integer id = texture.getId(); + if(id == null) { + texture.init(); + } + render(); + } + + public void setColor(Color color) { + this.color = color; + } + + public void setTexturePath(String texturePath) { + this.texture = new Texture(texturePath); + updateSpriteDimensions(); + } + + public float getDisplayedWidth() { + return spriteWidth * scale.x; + } + + public float getDisplayedHeight() { + return spriteHeight * scale.y; + } + + public void updateSpriteDimensions() { + if (texture != null) { + this.spriteWidth = texture.getWidth(); + this.spriteHeight = texture.getHeight(); + } + } + + @Override + public void render() { + prepareRendering(); + glBindTexture(GL_TEXTURE_2D, texture.getId()); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex3f(0, 0, 0); // 左上の頂点 + glTexCoord2f(1, 0); glVertex3f(spriteWidth, 0, 0); // 右上の頂点 + glTexCoord2f(1, 1); glVertex3f(spriteWidth, spriteHeight, 0); // 右下の頂点 + glTexCoord2f(0, 1); glVertex3f(0, spriteHeight, 0); // 左下の頂点 + glEnd(); + + endRendering(); + } +} \ No newline at end of file diff --git a/GameEngine/src/main/java/gameEngine/views/Text.java b/GameEngine/src/main/java/gameEngine/views/Text.java new file mode 100644 index 0000000..41025b3 --- /dev/null +++ b/GameEngine/src/main/java/gameEngine/views/Text.java @@ -0,0 +1,121 @@ +package gameEngine.views; +import org.joml.Vector3f; + +import java.util.Map; + +import static java.awt.Font.PLAIN; +import static java.awt.Font.SANS_SERIF; +import static org.lwjgl.opengl.GL11.*; + +public class Text extends Renderer { + + private Texture fontTexture; + private Map fontGlyphs; + private int fontHeight; + public String text; + public int textSize; + + public Text(float posX, float posY, String text, int textSize) { + this.position = new Vector3f(posX,posY,0); + this.rotation = new Vector3f(0,0,0); + this.scale = new Vector3f(1,1,1); + this.text = text; + this.textSize = textSize; + this.color = new Color(0,0,0,1); + + Font font = new Font(new java.awt.Font(SANS_SERIF, PLAIN, textSize), true); + fontTexture = font.getTexture(); + fontGlyphs = font.getGlyphs(); + fontHeight = font.getFontHeight(); + } + + public void update(){ + Integer id = fontTexture.getId(); + if(id == null) { + fontTexture.init(); + } + render(); + } + + public void setText(String newText) { + this.text = newText; + render(); + } + + public void setTextSize(int newTextSize) { + if (newTextSize < 3 || newTextSize > 127) return; + + this.textSize = newTextSize; + Font font = new Font(new java.awt.Font(SANS_SERIF, PLAIN, textSize), true); + this.fontTexture = font.getTexture(); + this.fontGlyphs = font.getGlyphs(); + this.fontHeight = font.getFontHeight(); + render(); + } + + public void setColor(Color color) { + this.color = color; + render(); + } + + @Override + public void render() { + prepareRendering(); + glBindTexture(GL_TEXTURE_2D, fontTexture.getId()); + + float drawX = 0; // Render relative to the transformed position + float drawY = 0; + + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (ch == '\n') { + drawY += fontHeight; + drawX = 0; // Move back to the start of the line + continue; + } + + Glyph g = fontGlyphs.get(ch); + if (g != null) { + glBegin(GL_QUADS); + glTexCoord2f(g.x / (float) fontTexture.getWidth(), g.y / (float) fontTexture.getHeight()); + glVertex3f(drawX, drawY, 0); + + glTexCoord2f((g.x + g.width) / (float) fontTexture.getWidth(), g.y / (float) fontTexture.getHeight()); + glVertex3f(drawX + g.width, drawY, 0); + + glTexCoord2f((g.x + g.width) / (float) fontTexture.getWidth(), (g.y + g.height) / (float) fontTexture.getHeight()); + glVertex3f(drawX + g.width, drawY + g.height, 0); + + glTexCoord2f(g.x / (float) fontTexture.getWidth(), (g.y + g.height) / (float) fontTexture.getHeight()); + glVertex3f(drawX, drawY + g.height, 0); + glEnd(); + + drawX += g.width; // Advance x position by character width + } + } + + endRendering(); + } + + public int getHeight(CharSequence text) { + int height = 0; + int lineHeight = 0; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (c == '\n') { + height += lineHeight; + lineHeight = 0; + continue; + } + if (c == '\r') { + continue; + } + Glyph g = fontGlyphs.get(c); + lineHeight = Math.max(lineHeight, g.height); + } + height += lineHeight; + return height; + } + + +} diff --git a/GameEngine/src/main/java/gameEngine/views/Window.java b/GameEngine/src/main/java/gameEngine/views/Window.java index d442522..54fa1f6 100644 --- a/GameEngine/src/main/java/gameEngine/views/Window.java +++ b/GameEngine/src/main/java/gameEngine/views/Window.java @@ -1,5 +1,6 @@ package gameEngine.views; import gameEngine.GameEditor; +import gameEngine.SwingGameEditor; import gameEngine.Time; import gameEngine.entites.Entity; import gameEngine.entites.GameObject; @@ -28,6 +29,7 @@ public int height; private String title; private long glfwWindow; + private static SwingGameEditor swingGameEditor; private static GameEditor gameEditor; private static HashMap sceneEntities; @@ -43,22 +45,18 @@ switch (newScene) { case 0: // EditorScene if (sceneEntities == null) { + //起動時、エディターシーン作成 currentScene = new EditorScene(); System.out.println("new"); } else { + //エンティティ情報を復元 currentScene = new EditorScene(sceneEntities); System.out.println(sceneEntities); // オリジナルのTransformを復元 for (Entity entity : currentScene.entities.values()) { entity.restoreOriginalTransform(); } - // ゲームシーンのコンポーネントを削除 - for (Entity entity : currentScene.entities.values()) { - if (entity instanceof GameObject) { - GameObject gameObject = (GameObject) entity; - gameObject.gameComponents.removeIf(GameComponent::isGameSceneComponent); - } - } + gameEditor.setScene(currentScene); } initializeSceneEntities(); break; @@ -69,8 +67,6 @@ } sceneEntities = currentScene.entities; HashMap gameSceneEntities = new HashMap<>(sceneEntities); - - // コピーした entities を使って GameScene を作成 currentScene = new GameScene(gameSceneEntities); initializeSceneEntities(); break; @@ -87,7 +83,8 @@ gameObject.initComponents(); // コンポーネントの初期化 } } - if(gameEditor != null) gameEditor.updateListByScene(currentScene); // ゲームエディタ側にシーン情報を渡す + if(swingGameEditor != null) swingGameEditor.updateListByScene(currentScene); // ゲームエディタ側にシーン情報を渡す + } public static Window get() { @@ -99,13 +96,14 @@ } public void runWithEditor() { - gameEditor = new GameEditor(); + swingGameEditor = new SwingGameEditor(); run(); } public void run() { System.out.println("Hello LWJGL " + Version.getVersion() + "!"); Window.changeScene(0); + gameEditor = new GameEditor(currentScene); loop(); glfwFreeCallbacks(glfwWindow); glfwDestroyWindow(glfwWindow); @@ -122,7 +120,7 @@ //Configure GLFW glfwDefaultWindowHints(); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE); glfwWindow = glfwCreateWindow(this.width, this.height, this.title, NULL, NULL); @@ -157,18 +155,13 @@ glfwMakeContextCurrent(glfwWindow); glfwSwapInterval(1); glfwShowWindow(glfwWindow); - GL.createCapabilities(); } private void loop() { - Time.update(); - while (!glfwWindowShouldClose(glfwWindow)) { - - glfwPollEvents(); // ウィンドウイベントをポーリング - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // フレームバッファをクリア - + glfwPollEvents(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); float dt = Time.deltaTime; if (dt >= 0) { @@ -186,10 +179,15 @@ // シーン全体の update を呼び出す currentScene.update(dt); currentScene.processTasks(); + + if(currentScene instanceof EditorScene) gameEditor.update(); + + MouseInput.endFrame(); + KeyInput.endFrame(); + } - glfwSwapBuffers(glfwWindow); // カラーバッファを交換 - + glfwSwapBuffers(glfwWindow); Time.update(); } @@ -201,7 +199,6 @@ boolean isGameScene = currentScene instanceof GameScene; if (isGameScene && !startGameScene) { Time.reset(); - startGameScene = true; } if (!isGameScene) startGameScene = false;