package gameEngine.scenes;
import gameEngine.entites.Camera;
import gameEngine.entites.Entity;
import gameEngine.entites.GameObject;
import gameEngine.entites.gameComponents.*;
import gameEngine.geometry.Transform;
import gameEngine.input.Input;
import gameEngine.views.Color;
import gameEngine.views.Window;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import static org.lwjgl.opengl.GL11.glClearColor;
public abstract class Scene {
private Camera camera;
public HashMap<String, Entity> entities = new HashMap<>();
private final Queue<Runnable> taskQueue = new LinkedList<>();
private boolean changingScene = false;
private float timeToChangeScene = 2.0f;
private final Color editorBackColor = new Color(1,1,1,0);
public Scene(){
}
public abstract void update(float dt);
public Camera getCamera() {
return camera;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
public Entity getEntity(String eid) {
return entities.get(eid);
}
public void addEntity(String eid, Entity entity) {
entities.put(eid, entity);
}
public void removeEntity(String eid) {
entities.remove(eid);
}
public void addNewObject() {
enqueueTask(() -> {
addNewGameObject();
});
}
public void addEditor(){
enqueueTask(() -> {
addEditorFrameObject();
addNewButtonObject();
addNewTextObject();
});
}
private GameObject createGameObject(){
int entitiesLength = entities.size();
String newId = Integer.toString(entitiesLength);
GameObject gameObject = new GameObject(newId);
addEntity(newId, gameObject);
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));
}
/**
* Adds a component to the specified GameObject.
* This method enqueues a task to add the given GameComponent to the GameObject's component list.
*
* @param gameObject The GameObject to which the component will be added.
* @param component The GameComponent to be added to the GameObject.
*/
public void addComponentToGameObject(GameObject gameObject, GameComponent component) {
enqueueTask(() -> gameObject.addComponent(component));
}
/**
* Removes a component from the specified GameObject.
* This method enqueues a task to remove the given GameComponent from the GameObject's component list.
*
* @param gameObject The GameObject from which the component will be removed.
* @param component The GameComponent to be removed from the GameObject.
*/
public void removeComponentFromGameObject(GameObject gameObject, GameComponent component) {
enqueueTask(() -> gameObject.removeComponent(component));
}
// タスクを登録
private synchronized void enqueueTask(Runnable task) {
taskQueue.add(task);
}
// タスクの実行
public synchronized void processTasks() {
while (!taskQueue.isEmpty()) {
taskQueue.poll().run();
}
}
//現状一つのEntityからしか呼び出せない
public void Instantiate(GameObject original)
{
enqueueTask(() -> {
String newId = Integer.toString(entities.size());
GameObject newGameObject = new GameObject(newId);
newGameObject.setName(original.getName() + "_copy");
newGameObject.transform = new Transform(original.transform);
if (original.getComponent(Mesh.class) != null) {
newGameObject.addComponent(new Mesh((Mesh)original.getComponent(Mesh.class).copy(), newGameObject));
}
if (original.getComponent(TextMesh.class) != null) {
newGameObject.addComponent(new TextMesh((TextMesh)original.getComponent(TextMesh.class).copy(), newGameObject));
}
if (original.getComponent(ColorController.class) != null) {
newGameObject.addComponent(new ColorController());
}
if (original.getComponent(CopyEntity.class) != null) {
newGameObject.addComponent(new CopyEntity(newGameObject));
}
if (original.getComponent(MoveImage.class) != null) {
newGameObject.addComponent(new MoveImage(newGameObject));
}
if (original.getComponent(Physics.class) != null) {
newGameObject.addComponent(new Physics(newGameObject));
}
addEntity(newId, newGameObject);
});
}
private void changeSceneStart(){
if(!changingScene) changingScene = true;
}
//シーン切り替え時の演出
void changeScene(int scene, float dt){
if(!changingScene && Input.GetKeyDown(KeyEvent.VK_SPACE)){
changingScene = true;
}
if(changingScene && timeToChangeScene > 0){
timeToChangeScene -= dt * 1.5f;
editorBackColor.r -= dt * 5.0f;
editorBackColor.g -= dt * 5.0f;
editorBackColor.b -= dt * 5.0f;
glClearColor(editorBackColor.r, editorBackColor.g, editorBackColor.b, editorBackColor.a);
}
else if(changingScene){
Window.changeScene(scene);
}
}
}