202 lines
5.6 KiB
Java
202 lines
5.6 KiB
Java
package com.danitheskunk.skunkworks;
|
|
|
|
import com.danitheskunk.skunkworks.audio.AudioEngine;
|
|
import com.danitheskunk.skunkworks.audio.ISample;
|
|
import com.danitheskunk.skunkworks.audio.nodes.Mixer;
|
|
import com.danitheskunk.skunkworks.audio.nodes.Node;
|
|
import com.danitheskunk.skunkworks.audio.nodes.SamplePlayer;
|
|
import com.danitheskunk.skunkworks.audio.nodes.TTS;
|
|
import com.danitheskunk.skunkworks.backends.gl.Gamepad;
|
|
import com.danitheskunk.skunkworks.gfx.Color;
|
|
import com.danitheskunk.skunkworks.gfx.IRenderContext;
|
|
import com.danitheskunk.skunkworks.gfx.ITexture;
|
|
import com.danitheskunk.skunkworks.gfx.font.IFont;
|
|
import com.danitheskunk.skunkworks.gfx.threedee.IRenderContext3D;
|
|
import com.danitheskunk.skunkworks.nodes.NodeRoot;
|
|
import org.lwjgl.glfw.GLFW;
|
|
|
|
/**
|
|
* Main class to extend to write a game in Skunkworks
|
|
* <p>
|
|
* Extend this class and override {@link BaseGame#update update},
|
|
* {@link BaseGame#render render}, {@link BaseGame#renderPre renderPre},
|
|
* and/or {@link BaseGame#render3D render3D} to add functionality. Then instance
|
|
* and call {@link BaseGame#run run}.
|
|
* <p>
|
|
* Automatic timing (by default 60fps), resizing(with various scalers), 2d
|
|
* and 3d rendering, and audio playback.
|
|
*/
|
|
@SuppressWarnings("SameParameterValue")
|
|
public abstract class BaseGame {
|
|
protected final AudioEngine audioEngine;
|
|
protected final IFont debugFont;
|
|
protected final Engine engine;
|
|
protected final Mixer mixer;
|
|
protected final NodeRoot rootNode;
|
|
protected final SamplePlayer samplePlayer;
|
|
protected final TTS tts;
|
|
protected final IWindow window;
|
|
protected final BaseGamepad gamepad;
|
|
|
|
/**
|
|
* Create with given window size and title
|
|
*
|
|
* @param windowSize the size of the game's window
|
|
* @param windowTitle the title of the game's window
|
|
*/
|
|
public BaseGame(Vec2i windowSize, String windowTitle) {
|
|
audioEngine = new AudioEngine(48000, 256, 8);
|
|
mixer = new Mixer(audioEngine, 2);
|
|
samplePlayer = new SamplePlayer(audioEngine);
|
|
tts = new TTS(audioEngine);
|
|
Node.connect(samplePlayer, 0, mixer, 0);
|
|
Node.connect(tts, 0, mixer, 1);
|
|
audioEngine.setNode(mixer);
|
|
|
|
engine = new Engine();
|
|
window = engine.openWindow(windowSize, windowTitle);
|
|
gamepad = window.getGamepad(0);
|
|
//todo: load from .jar
|
|
debugFont = window.loadFontTileset("fonts/ega-8x14.png");
|
|
rootNode = new NodeRoot();
|
|
}
|
|
|
|
/**
|
|
* Load sample from path
|
|
*
|
|
* @param path file path to the sample
|
|
* @return the loaded sample
|
|
*/
|
|
protected ISample loadSample(String path) {
|
|
return audioEngine.loadSample(path);
|
|
}
|
|
|
|
/**
|
|
* Load image from path and prepare as gpu texture
|
|
*
|
|
* @param path file path to the image file
|
|
* @return the loaded texture
|
|
*/
|
|
protected ITexture loadTexture(String path) {
|
|
return window.loadTexture(path);
|
|
}
|
|
|
|
/**
|
|
* Play sample once
|
|
*
|
|
* @param sample the sample to be played
|
|
*/
|
|
protected void playSample(ISample sample) {
|
|
samplePlayer.play(sample);
|
|
}
|
|
|
|
/**
|
|
* Play sample once or looped
|
|
*
|
|
* @param sample the sample to be played
|
|
* @param looping loops forever if true, otherwise play once
|
|
*/
|
|
protected void playSample(ISample sample, boolean looping) {
|
|
samplePlayer.play(sample, looping);
|
|
}
|
|
|
|
/**
|
|
* Render Callback
|
|
* <p>
|
|
* This method will be called after {@link BaseGame#render3D render3D},
|
|
* when the engine is ready for 2d rendering. Override this method to
|
|
* render 2d things on screen.
|
|
*
|
|
* @param rc the render context with all the render functions
|
|
*/
|
|
protected void render(IRenderContext rc) {
|
|
//to be overriden by child class
|
|
}
|
|
|
|
/**
|
|
* 3D Render Callback
|
|
* <p>
|
|
* This method will be called when the engine is ready for 3d rendering.
|
|
* Override this method to render 3d things on screen.
|
|
*
|
|
* @param rc3d the render context with all the render functions
|
|
*/
|
|
protected void render3D(IRenderContext3D rc3d) {
|
|
//to be overriden by child class
|
|
}
|
|
|
|
/**
|
|
* Early Render Callback
|
|
* <p>
|
|
* This method will be called before {@link BaseGame#render3D render3D},
|
|
* when the engine is ready for 2d rendering. Override this method to
|
|
* render 2d things on screen underneath 3d content.
|
|
*
|
|
* @param rc the render context with all the render functions
|
|
*/
|
|
protected void renderPre(IRenderContext rc) {
|
|
//to be overriden by child class
|
|
}
|
|
|
|
/**
|
|
* Runs the game
|
|
* <p>
|
|
* This will transfer the control to Skunkworks until the game window
|
|
* closes.
|
|
*/
|
|
public void run() {
|
|
double lastTime, currentTime, delta, currentFrameTime;
|
|
|
|
currentFrameTime = 0;
|
|
|
|
lastTime = GLFW.glfwGetTime();
|
|
while(!window.shouldClose()) {
|
|
currentTime = GLFW.glfwGetTime();
|
|
delta = currentTime - lastTime;
|
|
lastTime = currentTime;
|
|
currentFrameTime += delta;
|
|
engine.tick();
|
|
window.tick();
|
|
gamepad.tick();
|
|
//todo: frame rate control
|
|
if(currentFrameTime >= 1.0 / 60.0) {
|
|
rootNode.tick();
|
|
update(1.0 / 60.0);
|
|
var p3d = window.getPipeline3D();
|
|
var p2d = window.getPipeline2D();
|
|
window.startFrame();
|
|
p3d.startFrame();
|
|
//todo: should be transparent but bugged
|
|
p3d.getRenderContext().clear(Color.BLACK);
|
|
render3D(p3d.getRenderContext());
|
|
p3d.finishFrame();
|
|
p2d.startFrame();
|
|
render(p2d.getRenderContext());
|
|
rootNode.render(p2d.getRenderContext());
|
|
p2d.finishFrame();
|
|
window.finishFrame();
|
|
currentFrameTime -= 1.0 / 60.0;
|
|
} else {
|
|
try {
|
|
Thread.sleep(1);
|
|
} catch(InterruptedException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
audioEngine.refill();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update Callback
|
|
* <p>
|
|
* This method will be called periodically, either in a fixed(by default)
|
|
* or variable period. Can be changed by setting {@link Timestep}
|
|
*
|
|
* @param delta time that passed since last update in seconds
|
|
*/
|
|
protected void update(double delta) {
|
|
|
|
}
|
|
}
|