Skip to content

3. Hello World

Hyrdaboo edited this page Jul 6, 2023 · 1 revision

Creating a window

All Dwarf applications need to derive from the Application class. Here's an example of the most basic Dwarf app

import DwarfEngine.Core.Application;

class HelloWorld extends Application {

	// Start is called at the start of the application
	@Override
	public void OnStart() {
		// the title of the window
		title = "Hello World";
	}

	// Update is called every frame
	@Override
	public void OnUpdate() {
		
	}
	
}


public class Main {

	public static void main(String[] args) {
		HelloWorld app = new HelloWorld();
		// specify the resolution in this case 1280x720 (720p)
		// the third parameter is pixel scale which tells the application
		// how many device pixels does every pixel of the application correspond to
		app.Initialize(1280, 720, 1);
	}	
}

After running this code we get an empty window with 1280x720 resolution:

Drawing things

Let's draw a circle where mouse is. Our updated code will look like this:

import DwarfEngine.Core.Application;
import DwarfEngine.Core.Input;
import DwarfEngine.MathTypes.Vector2;

// import everything inside the DisplayRenderer class
import static DwarfEngine.Core.DisplayRenderer.*;

import java.awt.Color;

class HelloWorld extends Application {

	// Start is called at the start of the application
	@Override
	public void OnStart() {
		// the title of the window
		title = "Hello World";
	}

	// Update is called every frame
	@Override
	public void OnUpdate() {
		//Clear the screen. Without this we would see the old frames on top of each other
		clear(Color.black);
		Vector2 mousePos = Input.getMousePosition();
		// Draws a red circle with a radius of 10 at the position of mouse cursor
		FillCircle(mousePos, 10, Color.red);
	}
	
}


public class Main {

	public static void main(String[] args) {
		HelloWorld app = new HelloWorld();
		// specify the resolution in this case 1280x720 (720p)
		// the third parameter is pixel scale which tells the application
		// how many device pixels does every pixel of the application correspond to
		app.Initialize(1280, 720, 1);
	}	
}

Run this and you will have a small red circle following your cursor. Not very impressive? Well let's get some 3D stuff going!

Creating a 3D scene

First of all every scene needs to derive from Scene class and implement its methods. We'll see it in a minute now. I will now recreate the first scene from the demos.

package Demos;

import java.io.File;

import DwarfEngine.Texture;
import DwarfEngine.Core.Application;
import DwarfEngine.MathTypes.Vector3;
import Renderer3D.Camera;
import Renderer3D.Light;
import Renderer3D.Light.LightType;
import Renderer3D.ObjLoader;
import Renderer3D.Prop;
import Renderer3D.Scene;
import Renderer3D.BuiltInShaders.Phong;
import Renderer3D.BuiltInShaders.Unlit;

// Loading a simple 3D scene with a model. Every scene needs to derive from Scene class
public class SuzanneDemo extends Scene {

	// Store a reference to the application so that we may use its methods later
	Application app;
	public SuzanneDemo(Application application) {
		super(application);
		// set a reference to application to access its functions
		app = application;
		app.title = "Simple Scene with 1 object";
	}

	// This function is called when the scene is loaded
	@Override
	protected void OnSceneLoad() {
		// load a texture
		Texture uvchecker = new Texture();
		uvchecker.Load("DemoResources/uvgrid.png");

		// create a phong shader from unlit texture shader
		Unlit unlit = new Unlit();
		unlit.setTexture(uvchecker);
		Phong phong = new Phong(unlit);
		phong.shininess = 50;

		File suzanneFile = new File("DemoResources/suzanne.obj");
		// every object in a scene that gets rendered is a prop
		// a prop has a mesh that describes its shape and a shader that describes the surface appearance
		suzanne = new Prop(ObjLoader.Load(suzanneFile));
		//set the shader to the phong shader that we have created and add this prop to the list of objects
		suzanne.setShader(phong);
		objects.add(suzanne);

		// load a skybox object which is actually a giant sphere turned inside out (flipped normals) with an hdri
		Texture skyTexture = new Texture();
		skyTexture.Load("DemoResources/skyImage.png");

		Unlit skyShader = new Unlit();
		skyShader.setTexture(skyTexture);
		File skyFile = new File("DemoResources/sky.obj");
		Prop sky = new Prop(ObjLoader.Load(skyFile));
		sky.setShader(skyShader);
		sky.transform.scale = Vector3.mulVecFloat(Vector3.one(), 1000);
		objects.add(sky);

		// add a sun and rotate it
		Light sun = new Light();
		sun.transform.rotation = new Vector3(40, 25, 0);
		sun.setColor(new Vector3(1, 1, 0.6f));
		// every light source needs to be added to the list of lights
		lights.add(sun);

		// add ambient light so that it isn't so dark where light doesn't shine directly
		Light ambient = new Light();
		ambient.setColor(new Vector3(0.3f, 0.37f, 0.43f));
		ambient.type = LightType.Ambient;
		lights.add(ambient);

		// add camera so that we can see and move it back 3 units
		camera = new Camera();
		camera.transform.position.z = -3;
		setCamera(camera);
	}

	Prop suzanne;
	Camera camera;

	@Override
	protected void OnSceneUpdate() {
		// simple fps control. Check out the demos if you wanna see more
		FpsControls.GetInput((float) app.getDeltaTime(), camera.transform);
		suzanne.transform.rotation.y += app.getDeltaTime() * 10;
	}
}

Now back in our HelloWorld class let's initialize and render this scene. Modifying our code like so:

import DwarfEngine.Core.Application;
import DwarfEngine.Core.Input;
import DwarfEngine.Core.Keycode;
import Renderer3D.SceneManager;

import Demos.SuzanneDemo;

class HelloWorld extends Application {

	@Override
	public void OnStart() {
		// Add the Suzannedemo.class with the name `demo` to the scene manager 
		//so that it knows which class to instantiate when the scene with this name is loaded
		SceneManager.AddScene(SuzanneDemo.class, "demo");
		// actually load the scene which will instantiate new SuzanneDemo object
		SceneManager.LoadScene("demo");
	}

	@Override
	public void OnUpdate() {
		// render currently loaded scene
		SceneManager.renderActiveScene();
		
		// Switch fullscreen when 'F' key is pressed
		if (Input.OnKeyPressed(Keycode.F)) {
			switchFullscreen();
		}
	}
}


public class Main {

	public static void main(String[] args) {
		HelloWorld app = new HelloWorld();
		// I'll lower the resolution by half to get better performace :(
		// If you are wondering why check out the readme of this project where
		// it is explained
		app.Initialize(1280/2, 720/2, 1);
	}	
}

After modifying the code you should see this result:

Which looks pretty darn cool if I do say so myself (Except for performance which is a shame😔).
This wraps up our wiki tutorials. I would honestly want to make more tutorials but I don't think anybody is ever gonna use this and I was running out of time for this project. It already took much longer than it should have. If you have gotten up to this point you are a legend and this belongs to you 👑

Clone this wiki locally