luxe is a thing now
This commit is contained in:
parent
3a9ac811f0
commit
08a9d38043
20 changed files with 580 additions and 0 deletions
10
Luxe/.gitignore
vendored
Normal file
10
Luxe/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
*/.DS_Store
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
*/thumbs.db
|
||||
thumbs.db
|
||||
.thumbs.db?
|
||||
.luxe/
|
||||
_luxe.data/
|
||||
_luxe.deploy/
|
||||
log.txt
|
||||
41
Luxe/blocks/debug.wren
Normal file
41
Luxe/blocks/debug.wren
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
28
Luxe/blocks/ui.wren
Normal file
28
Luxe/blocks/ui.wren
Normal file
|
|
@ -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)
|
||||
|
||||
}
|
||||
}
|
||||
63
Luxe/game.wren
Normal file
63
Luxe/game.wren
Normal file
|
|
@ -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
|
||||
3
Luxe/globals.wren
Normal file
3
Luxe/globals.wren
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
var ActiveRenderer = [null]
|
||||
17
Luxe/math/math.wren
Normal file
17
Luxe/math/math.wren
Normal file
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
63
Luxe/math/rect.wren
Normal file
63
Luxe/math/rect.wren
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
81
Luxe/math/vector.wren
Normal file
81
Luxe/math/vector.wren
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
78
Luxe/outline/app.wren
Normal file
78
Luxe/outline/app.wren
Normal file
|
|
@ -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
|
||||
|
||||
} //
|
||||
6
Luxe/outline/inputs.input.lx
Normal file
6
Luxe/outline/inputs.input.lx
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
input = {
|
||||
nodes = [
|
||||
{ name = "ui" where = "front" channels = ["c01"] }
|
||||
{ name = "game" where = "after: ui" channels = ["c02"] }
|
||||
]
|
||||
}
|
||||
107
Luxe/outline/renderer.wren
Normal file
107
Luxe/outline/renderer.wren
Normal file
|
|
@ -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
|
||||
16
Luxe/outline/settings.settings.lx
Normal file
16
Luxe/outline/settings.settings.lx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
engine = {
|
||||
runtime = {
|
||||
window = {
|
||||
width = 540
|
||||
height = 960
|
||||
resizable = true
|
||||
fullscreen = false
|
||||
}
|
||||
}
|
||||
|
||||
render = {
|
||||
antialiasing = 2
|
||||
stencil = 8
|
||||
depth = 24
|
||||
}
|
||||
}
|
||||
14
Luxe/project.luxe
Normal file
14
Luxe/project.luxe
Normal file
|
|
@ -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
|
||||
3
Luxe/project.modules.lx
Normal file
3
Luxe/project.modules.lx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
modules = {
|
||||
luxe = "2020.2.0"
|
||||
} //modules
|
||||
50
Luxe/shaders/upscale.emsl
Normal file
50
Luxe/shaders/upscale.emsl
Normal file
|
|
@ -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;
|
||||
}
|
||||
BIN
official/gameplay.gif
Normal file
BIN
official/gameplay.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 351 KiB |
BIN
official/gameplay.mp4
Normal file
BIN
official/gameplay.mp4
Normal file
Binary file not shown.
BIN
official/pixelspace.mp4
Normal file
BIN
official/pixelspace.mp4
Normal file
Binary file not shown.
BIN
official/resume.odt
Normal file
BIN
official/resume.odt
Normal file
Binary file not shown.
BIN
official/resume.pdf
Normal file
BIN
official/resume.pdf
Normal file
Binary file not shown.
Loading…
Reference in a new issue