Skip to content

Commit

Permalink
ecs and assets.
Browse files Browse the repository at this point in the history
  • Loading branch information
codescapade committed Sep 15, 2024
1 parent f345497 commit ff2dc1a
Show file tree
Hide file tree
Showing 24 changed files with 1,420 additions and 3 deletions.
68 changes: 67 additions & 1 deletion src/jume/Jume.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
package jume;

import jume.events.SceneEvent;
import jume.math.Random;
import jume.audio.Audio;
import jume.graphics.RenderTarget;
import jume.view.View;
import jume.utils.TimeStep;
import jume.input.Input;
import jume.graphics.Graphics;
import jume.graphics.gl.Context;
import jume.ecs.Scene;

import haxe.Timer;

import jume.events.FocusEvent;
Expand Down Expand Up @@ -40,6 +51,20 @@ class Jume {
*/
final events: Events;

final context: Context;

final graphics: Graphics;

final input: Input;

final timeStep: TimeStep;

final view: View;

var target: RenderTarget;

var scene: Scene;

/**
* Create a new Jume instance.
* @param options The game options.
Expand Down Expand Up @@ -77,6 +102,31 @@ class Jume {
events = new Events();
Services.add(events);

context = new Context(options.canvasId, options.forceWebGL1);
Services.add(context);

view = new View({
width: options.designSize.widthi,
height: options.designSize.heighti,
pixelRatio: pixelRatio,
pixelFilter: options.pixelFilter,
isFullScreen: isFullScreen,
targetFps: options.targetFps,
canvasId: options.canvasId
});
Services.add(view);

input = new Input(options.canvasId);
Services.add(input);

timeStep = new TimeStep();
Services.add(timeStep);

Services.add(new Audio());
Services.add(new Random());

graphics = new Graphics(context, view);

#if !headless
canvas.focus();
canvas.addEventListener('blur', () -> lostFocus());
Expand All @@ -85,7 +135,10 @@ class Jume {
#end
}

public function launch() {
public function launch(sceneType: Class<Scene>) {
events.addListener({ type: SceneEvent.CHANGE, callback: onSceneChange });
changeScene(sceneType);

#if headless
prevTime = Timer.stamp();
Timer.delay(headlessLoop, Std.int(1.0 / 60.0 * 1000));
Expand Down Expand Up @@ -138,4 +191,17 @@ class Jume {
}

function render() {}

function onSceneChange(event: SceneEvent) {
changeScene(event.sceneType);
event.canceled = true;
}

function changeScene(sceneType: Class<Scene>) {
if (scene != null) {
scene.destroy();
}

scene = Type.createInstance(sceneType, []);
}
}
40 changes: 40 additions & 0 deletions src/jume/assets/AssetLoader.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package jume.assets;

import jume.di.Injectable;

import haxe.Exception;

class AssetLoader<T> implements Injectable {
public final assetType: Class<T>;

final loadedAssets: Map<String, T>;

public function new(assetType: Class<T>) {
this.assetType = assetType;
loadedAssets = new Map<String, T>();
}

public function load(id: String, path: String, callback: (asset: T)->Void, ?props: Dynamic, ?keep: Bool) {}

public function add(id: String, instance: T) {
this.loadedAssets[id] = instance;
}

public function get(id: String): T {
if (loadedAssets.exists(id)) {
return loadedAssets[id];
}

throw new Exception('Asset with id ${id} not loaded.');
}

public function unload(id: String): Bool {
if (loadedAssets.exists(id)) {
loadedAssets.remove(id);

return true;
}

return false;
}
}
86 changes: 86 additions & 0 deletions src/jume/assets/Assets.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package jume.assets;

import haxe.Exception;

typedef AssetItem = {
var type: Class<Dynamic>;
var id: String;
var path: String;
var ?props: Dynamic;
}

typedef LoadParams<T> = {
var assetType: Class<T>;
var id: String;
var path: String;
var callback: (asset: T)->Void;
var ?props: Dynamic;
var ?keep: Bool;
}

class Assets {
final loaders: Map<String, AssetLoader<Dynamic>>;

public function new() {
loaders = new Map<String, AssetLoader<Dynamic>>();
}

public function registerLoader<T>(loader: AssetLoader<T>) {
final name = Type.getClassName(loader.assetType);
loaders[name] = loader;
}

public function load<T>(params: LoadParams<T>) {
final name = Type.getClassName(params.assetType);
if (loaders.exists(name)) {
loaders[name].load(params.id, params.path, params.callback, params.props, params.keep);
} else {
throw new Exception('Loader is not registered for type ${name}');
}
}

public function loadAll(items: Array<AssetItem>, callback: ()->Void) {
var loaded = 0;
for (item in items) {
load({
assetType: item.type,
id: item.id,
path: item.path,
props: item.props,
callback: (asset) -> {
loaded++;
if (loaded == items.length) {
callback();
}
}
});
}
}

public function add<T>(assetType: Class<T>, id: String, instance: T) {
final name = Type.getClassName(assetType);
if (loaders.exists(name)) {
loaders[name].add(id, instance);
} else {
throw new Exception('Loader is not registered for type ${name}');
}
}

public function get<T>(assetType: Class<T>, id): T {
final name = Type.getClassName(assetType);
if (loaders.exists(name)) {
return loaders[name].get(id);
} else {
throw new Exception('Loader is not registered for type ${name}');
}
}

public function unload<T>(assetType: Class<T>, id: String) {
final name = Type.getClassName(assetType);
if (loaders.exists(name)) {
loaders[name].unload(id);
} else {
throw new Exception('Loader is not registered for type ${name}');
}
}
}
54 changes: 54 additions & 0 deletions src/jume/assets/AtlasLoader.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package jume.assets;

import jume.graphics.Image;
import jume.graphics.atlas.Atlas;

class AtlasLoader extends AssetLoader<Atlas> {
@:inject
var assets: Assets;

public function new() {
super(Atlas);
}

public override function load(id: String, path: String, callback: (asset: Atlas)->Void, ?props: Dynamic,
?keep: Bool) {
keep ??= true;
assets.load({
assetType: Image,
id: 'jume_atlas_${id}',
path: '${path}.png',
keep: keep,
callback: (image) -> {
assets.load({
assetType: String,
id: 'jume_atlas_${id}',
path: '${path}.json',
keep: keep,
callback: (text) -> {
if (image == null || text == null) {
callback(null);
} else {
final atlas = new Atlas(image, text);
if (keep) {
loadedAssets[id] = atlas;
}
callback(atlas);
}
}
});
}
});
}

public override function unload(id: String): Bool {
if (loadedAssets.exists(id)) {
assets.unload(Image, 'jume_atlas_${id}');
assets.unload(String, 'jume_atlas_${id}');

return super.unload(id);
}

return false;
}
}
53 changes: 53 additions & 0 deletions src/jume/assets/BitmapFontLoader.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package jume.assets;

import jume.graphics.Image;
import jume.graphics.bitmapFont.BitmapFont;

class BitmapFontLoader extends AssetLoader<BitmapFont> {
@:inject
var assets: Assets;

public function new() {
super(BitmapFont);
}

public override function load(id: String, path: String, callback: (asset: BitmapFont)->Void, ?props: Dynamic,
?keep: Bool) {
keep ??= true;
assets.load({
assetType: Image,
id: 'jume_bitmap_font_${id}',
path: '${path}.png',
keep: keep,
callback: (image) -> {
assets.load({
assetType: String,
id: 'jume_bitmap_font_${id}',
path: '${path}.fnt',
keep: keep,
callback: (text) -> {
if (image == null && text == null) {
callback(null);
} else {
final font = new BitmapFont(image, text);
if (keep) {
loadedAssets[id] = font;
}

callback(font);
}
}
});
}
});
}

public override function unload(id: String): Bool {
if (loadedAssets.exists(id)) {
assets.unload(Image, 'jume_bitmap_font_${id}');
assets.unload(String, 'jume_bitmap_font_${id}');
}

return super.unload(id);
}
}
53 changes: 53 additions & 0 deletions src/jume/assets/ImageLoader.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package jume.assets;

import js.html.CanvasElement;
import js.Browser;
import js.lib.Uint8ClampedArray;

import jume.graphics.Image;

class ImageLoader extends AssetLoader<Image> {
public function new() {
super(Image);
}

public override function load(id: String, path: String, callback: (asset: Image)->Void, ?props: Dynamic,
?keep: Bool) {
keep ??= true;
final element = Browser.document.createImageElement();
element.onload = () -> {
element.onload = null;
final canvas: CanvasElement = cast Browser.document.createElement('canvas');
canvas.width = element.width;
canvas.height = element.height;

final canvasContext = canvas.getContext2d();
canvasContext.drawImage(element, 0, 0);

final data: Uint8ClampedArray = cast canvasContext.getImageData(0, 0, element.width, element.height).data;
final image = new Image(element.width, element.height, data);
if (keep) {
loadedAssets[id] = image;
}

callback(image);
}

element.onerror = () -> {
trace('Unable to load image ${id}.');
callback(null);
}

element.src = path;
}

public override function unload(id: String): Bool {
final image = loadedAssets[id];
if (image != null) {
image.destroy();
return super.unload(id);
}

return false;
}
}
Loading

0 comments on commit ff2dc1a

Please sign in to comment.