diff --git a/Luxe/.gitignore b/Luxe/.gitignore new file mode 100644 index 0000000..d9dc9db --- /dev/null +++ b/Luxe/.gitignore @@ -0,0 +1,10 @@ +*/.DS_Store +.DS_Store +.DS_Store? +*/thumbs.db +thumbs.db +.thumbs.db? +.luxe/ +_luxe.data/ +_luxe.deploy/ +log.txt \ No newline at end of file diff --git a/Luxe/blocks/debug.wren b/Luxe/blocks/debug.wren new file mode 100644 index 0000000..642bd90 --- /dev/null +++ b/Luxe/blocks/debug.wren @@ -0,0 +1,41 @@ +import "luxe: world" for World +import "luxe: draw" for Draw, PathStyle +import "luxe: io" for IO + +class DrawDebug{ + static Context{ __context } + + static setup(world){ + __context = Draw.create(World.render_set(world)) + } + + static commit(){ + Draw.commit(__context) + } + + static rect(x, y, w, h){ + rect(x, y, w, h, [1, 0, 0, 1]) + } + + static rect_centered(x, y, w, h, col){ + rect(x - w/2, y - h/2, w, h, col) + } + + static rect(x, y, w, h, col){ + var style = PathStyle.new() + style.color = col + Draw.quad(__context, x, y, 0, w, h, 0, col) + } +} + + +class Holder{ + static x{ + System.print("%(__value) was taken from me") + return __value + } + static x=(val){ + System.print("I was given %(val)") + __value = val + } +} \ No newline at end of file diff --git a/Luxe/blocks/ui.wren b/Luxe/blocks/ui.wren new file mode 100644 index 0000000..b5bc9a0 --- /dev/null +++ b/Luxe/blocks/ui.wren @@ -0,0 +1,28 @@ +import "luxe: draw" for Draw, PathStyle +import "luxe: world" for Entity, Transform, UI, UIRenderMode +import "luxe: ui/control" for Control +import "luxe: ui/panel" for UIPanel + +class Ui{ + + static setup(app){ + __ui = Entity.create(app.ui, "UI Root") + + var x = 0 + var y = app.width + var w = app.width + var h = app.height - app.width + + + UI.create(__ui, x, y, w, h, 0, app.ui_camera) + UI.set_render_mode(__ui, UIRenderMode.world) + + + var panel = UIPanel.create(__ui) + UIPanel.set_color(panel, [1, 0, 0, 1]) + Control.set_size(panel, w, h) + + //UI.commit(__ui) + + } +} \ No newline at end of file diff --git a/Luxe/game.wren b/Luxe/game.wren new file mode 100644 index 0000000..13cc305 --- /dev/null +++ b/Luxe/game.wren @@ -0,0 +1,63 @@ +import "luxe: game" for Game +import "luxe: assets" for Assets +import "luxe: input" for Input, Key +import "luxe: world" for World, Entity, Transform, Sprite, Values, Tags, Camera +import "luxe: math" for Math +import "luxe: draw" for Draw +import "luxe: io" for IO + +import "outline/app" for App +import "blocks/ui" for Ui +import "blocks/debug" for DrawDebug, Holder +import "globals" for ActiveRenderer +import "math/vector" for Vector + +class game is Game { + + construct ready() { + + System.print("ready!") + + app = App.new() + Ui.setup(app) + + System.print("render size: %(app.width) x %(app.height) @ %(app.scale)x") + + DrawDebug.setup(app.world) + + _logo = Entity.create(app.world, "sprite") + Transform.create(_logo) + Transform.set_pos(_logo, app.width/2, app.height/2, 0) + Sprite.create(_logo, Assets.material("luxe: material/logo"), 16, 16) + + } //ready + + tick(delta) { + var mouse_pos = Vector.new(Input.mouse_x(), Input.mouse_y()) + mouse_pos = ActiveRenderer.x.game_mouse(mouse_pos) + var pos = Camera.screen_point_to_world(app.camera, mouse_pos.x, mouse_pos.y) + + Transform.set_pos(_logo, pos.x + 5, pos.y-8, 0) + + if(Input.key_state_released(Key.escape)) { + IO.shutdown() + } + + app.tick(delta) + + + DrawDebug.commit() + + } //tick + + destroy() { + + System.print("unready!") + app.destroy() + + } //destroy + + app { _app } + app=(v) { _app=v } + +} //Game diff --git a/Luxe/globals.wren b/Luxe/globals.wren new file mode 100644 index 0000000..23d88b6 --- /dev/null +++ b/Luxe/globals.wren @@ -0,0 +1,3 @@ + + +var ActiveRenderer = [null] diff --git a/Luxe/math/math.wren b/Luxe/math/math.wren new file mode 100644 index 0000000..192cb46 --- /dev/null +++ b/Luxe/math/math.wren @@ -0,0 +1,17 @@ + + + +class M{ + static inv_lerp(from, to, inter){ + return (inter - from) / (to - from) + } + + static lerp(from, to, value){ + return from + value * (to - from) + } + + static remap(min_in, max_in, min_out, max_out, value){ + var inter = inv_lerp(min_in, max_in, value) + return lerp(min_out, max_out, inter) + } +} \ No newline at end of file diff --git a/Luxe/math/rect.wren b/Luxe/math/rect.wren new file mode 100644 index 0000000..5e5376d --- /dev/null +++ b/Luxe/math/rect.wren @@ -0,0 +1,63 @@ +import "math/vector" for Vector + +class AABB{ + x{_x} + y{_y} + + x=(val){_x = val} + y=(val){_y = val} + + width {_width} + height {_height} + + width=(val){_width = val} + height=(val){_height = val} + + min_x{_x} + min_y{_y} + max_x{_x + _width} + max_y{_y + _height} + + + min{Vector.new(min_x, min_y)} + max{Vector.new(max_x, max_y)} + + center{(min + max) / 2} + pos{min} + pos=(val){ + _x = val.x + _y = val.y + } + size{Vector.new(_width, _height)} + + pos_size_list{[x, y, width, height]} + min_max_list{[min_x, min_y, max_x, max_y]} + + construct new(){} + + construct new(x, y, width, height){ + _x = x + _y = y + _width = width + _height = height + } + + construct min_max(min, max){ + min_max(min.x, min.y, max.x, max.y) + } + + construct min_max(min_x, min_y, max_x, max_y){ + _x = min_x + _y = min_y + _width = max_x - min_x + _height = max_y - min_y + } + + static intersects(one, other){ + return one.max > other.min && one.min < other.max + } + + static contains(one, other){ + return one.max > other.max && one.min < other.min + } +} \ No newline at end of file diff --git a/Luxe/math/vector.wren b/Luxe/math/vector.wren new file mode 100644 index 0000000..14a3594 --- /dev/null +++ b/Luxe/math/vector.wren @@ -0,0 +1,81 @@ + + +class Vector { + x{_x} + x=(val){_x = val} + + y{_y} + y=(val){_y = val} + + list{[x, y]} + + construct new(x, y){ + _x = x + _y = y + } + + construct new(list){ + _x = list.x + _y = list.x + } + + construct new(){ + _x = 0 + _y = 0 + } + + + invert_x(){ + _x = -_x + return this + } + + invert_y(){ + _y = -_y + return this + } + + or_lt(one, other){ + return one.x < other.x || one.y < other.y + } + + or_gt(one, other){ + return one.x > other.x || one.y > other.y + } + + +(other){ + if(other is Vector) { + return Vector.new(x + other.x, y + other.y) + } + } + + -(other){ + return Vector.new(x - other.x, y - other.y) + } + + *(other){ + if(other is Vector){ + return Vector.new(x * other.x, y * other.y) + } + if(other is Num) { + return Vector.new(x * other, y * other) + } + } + + /(other){ + if(other is Vector) { + return Vector.new(x / other.x, y / other.y) + } + if(other is Num) { + return Vector.new(x / other, y / other) + } + } + + <(other){ + return x < other.x && y < other.y + } + + >(other){ + return x > other.x && y > other.y + } +} \ No newline at end of file diff --git a/Luxe/outline/app.wren b/Luxe/outline/app.wren new file mode 100644 index 0000000..2863d19 --- /dev/null +++ b/Luxe/outline/app.wren @@ -0,0 +1,78 @@ +import "luxe: world" for World, Camera, Entity, Transform +import "luxe: render" for Render +import "outline/Renderer" for Renderer + +class App { + + world { _world } + ui { _ui_world } + + camera { _camera } + ui_camera { _ui_camera } + + color { _color } + color=(v) { _color = v } + + width { Render.window_w() } + height { Render.window_h() } + scale { Render.drawable_ratio() } + + construct new() { + + _color = [0,0,0.2,1] + + //create worlds + + _world = World.create("game") + _ui_world = World.create("ui") + + //create cameras + + _camera = Entity.create(_world, "app.camera") + Transform.create(_camera) + Camera.create(_camera) + Camera.set_default(_world, _camera) + Camera.ortho(_camera, 0, Renderer.pixel_width, Renderer.pixel_width, 0, -20, 20) + + _ui_camera = Entity.create(_ui_world, "app.ui_camera") + Transform.create(_ui_camera) + Camera.create(_ui_camera) + Camera.set_default(_ui_world, _ui_camera) + + } //new + + destroy() { + + //destroy cameras + + Camera.destroy(_camera) + Camera.destroy(_ui_camera) + + Entity.destroy(_camera) + Entity.destroy(_ui_camera) + + //destroy worlds + + World.destroy(_ui_world) + World.destroy(_world) + + } //destroy + + tick(delta) { + + //update worlds + + World.tick_systems(_world, delta) + World.tick_systems(_ui_world, delta) + + World.tick_world(_world, delta) + World.tick_world(_ui_world, delta) + + //render worlds + + World.render(_world, _camera, "game", {"clear_color":_color}) + World.render(_ui_world, _ui_camera, "ui") + + } //tick + +} // diff --git a/Luxe/outline/inputs.input.lx b/Luxe/outline/inputs.input.lx new file mode 100644 index 0000000..e5b5f9d --- /dev/null +++ b/Luxe/outline/inputs.input.lx @@ -0,0 +1,6 @@ +input = { + nodes = [ + { name = "ui" where = "front" channels = ["c01"] } + { name = "game" where = "after: ui" channels = ["c02"] } + ] +} diff --git a/Luxe/outline/renderer.wren b/Luxe/outline/renderer.wren new file mode 100644 index 0000000..05e2fa9 --- /dev/null +++ b/Luxe/outline/renderer.wren @@ -0,0 +1,107 @@ +import "luxe: render" for Render, RenderLayerDesc, PassLayerDesc, LoadAction +import "luxe: render" for SortType, ImageDesc, ImageType, PixelFormat, Image +import "luxe: math" for Math +import "luxe: io" for IO +import "globals" for ActiveRenderer +import "math/vector" for Vector +import "math/rect" for AABB +import "blocks/debug" for Holder +import "math/math" for M + +class Renderer { + + target{ "scene" } + + static pixel_width{128} + pixel_width{Renderer.pixel_width} + + pixelSize{_pixelSize} + + construct new() { + ActiveRenderer.x = this + + System.print("game / render / init / ok") + } //new + + update_targets(){ + _pixelSize = (Render.window_w() / pixel_width).floor + var x_offset = ((Render.window_w() - pixel_width * _pixelSize) / 2).round + var y_offset = Render.window_h() - pixel_width * _pixelSize + _gameRect = AABB.new(x_offset, y_offset, pixel_width * _pixelSize, pixel_width * _pixelSize) + } + + game_mouse(mouse_pos){ + var window = AABB.new(0, 0, Render.window_w(), Render.window_h()) + var screen = AABB.new(_gameRect.min_x, Render.window_h() - _gameRect.max_y, _gameRect.width, _gameRect.height) //Y- mouse positions are the bane of my existance + return M.remap(screen.min, screen.max, window.min, window.max, mouse_pos) + } + + ready() { + + _desc = ImageDesc.new() + _desc.type = ImageType.image2D + _desc.pixel_format = PixelFormat.rgba8Unorm + _desc.width = pixel_width + _desc.height = pixel_width + + Render.define_resource(target, Image.create(_desc)) + + + update_targets() + IO.on("engine.runtime.window.size_changed") {|type, data| + update_targets() + } + } + + tick(delta) { + + } + + render_path(ctx) { + + if(ctx.path == "game") { + game_render_path(ctx) + } else if(ctx.path == "ui") { + ui_render_path(ctx) + } + + } //render_path + + game_render_path(ctx) { + + var layer = RenderLayerDesc.new() + layer.dest.color[0].render_target = target + layer.dest.color[0].clear_color = ctx.get("clear_color", [1,1,1,1]) + layer.dest.color[0].load_action = LoadAction.clear + layer.dest.depth.load_action = LoadAction.clear + + ctx.layer_render("default", layer) + + var out_pass = PassLayerDesc.new() + out_pass.library = "shaders/upscale" + out_pass.function = "upscale_top_center" + out_pass.targets = ["screen"] + out_pass.inputs = { + "pass.flipy" : true, + "pass.rect" : _gameRect.pos_size_list, + "pass.image" : { + "image": target, //image resource name + "sampler": "nearest_clamp" //sampler state + }, + } + + ctx.layer_pass(out_pass) + + } //game_render_path + + ui_render_path(ctx) { + + var layer = RenderLayerDesc.new() + layer.dest.color[0].load_action = LoadAction.dont_care + layer.dest.depth.load_action = LoadAction.clear + + ctx.layer_render("default", layer) + + } //ui_render_path + +} //Renderer diff --git a/Luxe/outline/settings.settings.lx b/Luxe/outline/settings.settings.lx new file mode 100644 index 0000000..f92c7cf --- /dev/null +++ b/Luxe/outline/settings.settings.lx @@ -0,0 +1,16 @@ +engine = { + runtime = { + window = { + width = 540 + height = 960 + resizable = true + fullscreen = false + } + } + + render = { + antialiasing = 2 + stencil = 8 + depth = 24 + } +} \ No newline at end of file diff --git a/Luxe/project.luxe b/Luxe/project.luxe new file mode 100644 index 0000000..e98c98e --- /dev/null +++ b/Luxe/project.luxe @@ -0,0 +1,14 @@ +import "luxe: project" for Project + +class project is Project { + + construct new(target) { + + name = "Cabin Game" + version = "0.0.0" + renderer = "outline/renderer" + settings = "outline/settings" + + } //new + +} //Project \ No newline at end of file diff --git a/Luxe/project.modules.lx b/Luxe/project.modules.lx new file mode 100644 index 0000000..d493c0b --- /dev/null +++ b/Luxe/project.modules.lx @@ -0,0 +1,3 @@ +modules = { + luxe = "2020.2.0" +} //modules diff --git a/Luxe/shaders/upscale.emsl b/Luxe/shaders/upscale.emsl new file mode 100644 index 0000000..b7d8cbb --- /dev/null +++ b/Luxe/shaders/upscale.emsl @@ -0,0 +1,50 @@ +input View { + mat4 mvp, + mat4 proj, + mat4 proj_inverse, + mat4 view, + mat4 world, //geometry.world atm + float2 fov, //fov.x, fov.y + float2 resolution, + float4 target_region, + float4 target_region_size +} + +input UniformShaderData { + #0 image2D image, + float4 rect, + bool flipy +} + +stage vertex vert_layer_pass( + input {}, + vertex in { + #0 float2 pos, + #1 float2 uv + }, + fragment out { float2 uv } +) { + out.uv = in.uv; + stage.pos = float4(in.pos, 0.0, 1.0); +} + +stage fragment upscale_top_center( + input { View view, UniformShaderData pass }, + fragment in { float2 uv } +) { + + //this is the uv in the full screen area + float y = in.uv.y; + if(input.pass.flipy) { y = 1.0 - y; } + float2 uv = float2(in.uv.x, y); + + float2 dest_size = floor(input.view.target_region_size.zw); + float4 local_rect = float4(input.pass.rect.xy / dest_size, input.pass.rect.zw / dest_size); + float2 local_uv = (uv - local_rect.xy) / local_rect.zw; + stage.color[0] = texture(input.pass.image, local_uv); + + if(local_uv.x < 0.0 || local_uv.y < 0.0 || local_uv.x > 1.0 || local_uv.y > 1.0){ + stage.color[0] = float4(0, 0, 0, 1); + } + return; +} \ No newline at end of file diff --git a/official/gameplay.gif b/official/gameplay.gif new file mode 100644 index 0000000..f2e6a2a Binary files /dev/null and b/official/gameplay.gif differ diff --git a/official/gameplay.mp4 b/official/gameplay.mp4 new file mode 100644 index 0000000..324f55c Binary files /dev/null and b/official/gameplay.mp4 differ diff --git a/official/pixelspace.mp4 b/official/pixelspace.mp4 new file mode 100644 index 0000000..4bde013 Binary files /dev/null and b/official/pixelspace.mp4 differ diff --git a/official/resume.odt b/official/resume.odt new file mode 100644 index 0000000..0dae9ad Binary files /dev/null and b/official/resume.odt differ diff --git a/official/resume.pdf b/official/resume.pdf new file mode 100644 index 0000000..2066853 Binary files /dev/null and b/official/resume.pdf differ