luxe is a thing now

This commit is contained in:
Ronja 2020-08-16 15:59:43 +02:00
parent 3a9ac811f0
commit 08a9d38043
20 changed files with 580 additions and 0 deletions

10
Luxe/.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
var ActiveRenderer = [null]

17
Luxe/math/math.wren Normal file
View 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
View 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
View 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
View 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
} //

View 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
View 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

View 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
View 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
View file

@ -0,0 +1,3 @@
modules = {
luxe = "2020.2.0"
} //modules

50
Luxe/shaders/upscale.emsl Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

BIN
official/gameplay.mp4 Normal file

Binary file not shown.

BIN
official/pixelspace.mp4 Normal file

Binary file not shown.

BIN
official/resume.odt Normal file

Binary file not shown.

BIN
official/resume.pdf Normal file

Binary file not shown.