Compare commits

...

5 commits

Author SHA1 Message Date
Ronja
a3e2210195 correctly hide humans 2020-10-31 15:13:18 +01:00
Ronja
2f31e7a55f adventure stuff 2020-10-31 15:13:01 +01:00
Ronja
5313af2e00 more names? 2020-10-31 12:09:46 +01:00
Ronja
db34f79650 some semi-horrible string utility 2020-10-31 12:07:14 +01:00
Ronja
8cf53ab325 add event bandaid to slider and remove logging 2020-10-31 12:03:03 +01:00
8 changed files with 259 additions and 85 deletions

View file

@ -5,7 +5,11 @@
"Abyole" "Abyole"
"Afua" "Afua"
"Alisha"
"Aljoscha"
"Amelia" "Amelia"
"Ariadne"
"Ashley"
"Bertine" "Bertine"
"Bob" "Bob"
"Bug" "Bug"
@ -20,12 +24,16 @@
"Ida" "Ida"
"Innes" "Innes"
"Irene" "Irene"
"Irina"
"Isisa" "Isisa"
"Jamie"
"Jamison"
"Jess" "Jess"
"Jules" "Jules"
"Kabanga" "Kabanga"
"Karl" "Karl"
"Karo" "Karo"
"Kolja"
"Lara" "Lara"
"Laura" "Laura"
"Lauren" "Lauren"
@ -37,12 +45,16 @@
"Merryl" "Merryl"
"Mii'a" "Mii'a"
"Niels" "Niels"
"Nils"
"Nina" "Nina"
"Nova"
"Rami" "Rami"
"Ramona"
"Richard" "Richard"
"Rob" "Rob"
"Robin" "Robin"
"Ronja" "Ronja"
"Sam"
"Sandra" "Sandra"
"Simon" "Simon"
"Sironka" "Sironka"

View file

@ -2,6 +2,8 @@ import "math/observable" for Observable
import "luxe: world" for Entity, Values, Tags import "luxe: world" for Entity, Values, Tags
import "globals" for Globals import "globals" for Globals
import "blocks/resources" for Resources import "blocks/resources" for Resources
import "math/stringUtil" for StringUtil
import "blocks/human/human" for Human
class Adventures{ class Adventures{
planning{_planning} planning{_planning}
@ -12,14 +14,41 @@ class Adventures{
_in_progress = [] _in_progress = []
_archive = [] _archive = []
_max_distance = 10 _max_distance = 10
_game = Globals["Game"]
} }
plan_new(){ plan_new(){
System.print("Start planning new Adventure")
var adventure = Adventure.new() var adventure = Adventure.new()
adventure.distance = 2
_planning.value = adventure _planning.value = adventure
return adventure return adventure
} }
dispatch(){
var adventure = _planning.value
if(!adventure){
System.print("Tried to dispatch adventure, but none is planned")
return
}
System.print("Dispatching adventure \"%(adventure)\"")
adventure.setup()
adventure.adventurers.each{|human|
Human.set_active(human, false)
}
adventure.resources.list().each{|resource|
_game.resources.remove(resource["base_name"], resource["amount"])
}
_in_progress.add(adventure)
_planning.value = null
}
tick(){
//check some stuff that needs to be checked from time to time
//once per second/minute/whatever should be enough
}
new_or_current(){ new_or_current(){
if(_planning.value) return _planning.value if(_planning.value) return _planning.value
return plan_new() return plan_new()
@ -44,6 +73,12 @@ class Adventure{
distance{_distance} distance{_distance}
distance=(dist){_distance = dist} distance=(dist){_distance = dist}
toString{
return "%(adventurers.map{|id| Human.get_name(id)}.toList)"+
" travelling %(distance)km towards %(StringUtil.direction(direction))"+
" with %(resources.list().map{|resource| "%(resource["amount"]) %(resource["name"])"}.toList)"
}
construct new(){ construct new(){
_adventurers = [] _adventurers = []
_resources = Resources.new() _resources = Resources.new()
@ -53,6 +88,10 @@ class Adventure{
_distance = 0 _distance = 0
} }
setup(){
}
add_adventurer(adventurer){ add_adventurer(adventurer){
_adventurers.add(adventurer) _adventurers.add(adventurer)
} }

View file

@ -50,6 +50,18 @@ class Human {
data.adventure_count = data.adventure_count + 1 data.adventure_count = data.adventure_count + 1
} }
static get_active(entity){
if(entity == 0 || !entity) return null
var data = Modifiers.get(This, entity)
return data.active
}
static set_active(entity, active){
if(entity == 0 || !entity) return null
var data = Modifiers.get(This, entity)
data.active = active
}
} //Human } //Human
//Your modifier system implementation. //Your modifier system implementation.
@ -114,28 +126,28 @@ class HumanSystem is ModifierSystem {
game.focus.value = _hoverEnt game.focus.value = _hoverEnt
} }
} }
update() //optimisation: consider running this less often
} //tick } //tick
update(){ update(){
if(World.tag_has(_world, "edit")) return
var size = Vector.new(player_size) var size = Vector.new(player_size)
var pos = Vector.new(player_start) + size / 2 var pos = Vector.new(player_start) + size / 2
each {|entity, data| each {|entity, data|
if(!data.active){ if(!data.active){
Transform.destroy(entity) if(Transform.has(entity))Transform.destroy(entity)
Sprite.destroy(entity) if(Sprite.has(entity))Sprite.destroy(entity)
return } else {
if(!Transform.has(entity)){
Transform.create(entity)
}
if(!Sprite.has(entity)){
Sprite.create(entity, _material, 10, 12)
Sprite.set_color(entity, data.color.r, data.color.g, data.color.b, data.color.a)
}
Transform.set_pos(entity, pos.x, pos.y)
pos.x = pos.x + size.x
} }
if(!Transform.has(entity)){
Transform.create(entity)
}
if(!Sprite.has(entity)){
Sprite.create(entity, _material, 10, 12)
Sprite.set_color(entity, data.color.r, data.color.g, data.color.b, data.color.a)
}
Transform.set_pos(entity, pos.x, pos.y)
pos.x = pos.x + size.x
} }
} }
} //HumanSystem } //HumanSystem

View file

@ -14,19 +14,24 @@ class Resources is Observable{
value_no_update = this value_no_update = this
} }
toString{
return list().map{|resource| "%(resource["amount"]) %(resource["name"])"}.toList.toString
}
list(){ list(){
//construct map from name and amount //construct map from name and amount
var list = _nameList.map{ |res| {"name": res, "amount": _resources[res["name"]]}}.//<-- butt dot! var list = _nameList.map{ |res| {"name": res, "amount": _resources[res["name"]]}}.
//filter out the ones without an amount //filter out the ones without an amount
where{ |res| res["amount"] }. where{ |res| res["amount"] }.
toList //toList makes the each work ^^ otherwise the result sequence runs map twice toList //toList makes the each work ^^ otherwise the result sequence runs map twice
//get correct name and respect plural rules //also this is its own line because each returns void >.> //get correct name and respect plural rules //also this is its own line because each returns void >.>
list.each{ |res| list.each{ |res|
var name = res["name"]["name"] var name = res["name"]["name"]
var singular = res["amount"] == 1 || res["name"]["alwaysSingular"] var singular = res["amount"] == 1 || res["name"]["alwaysSingular"]
res["name"] = singular ? name : StringUtil.plural(name) res["name"] = singular ? name : StringUtil.plural(name)
} res["base_name"] = name
}
return list return list
} }

View file

@ -1,32 +1,33 @@
import "luxe: assets" for Assets, Strings
import "luxe: color" for Color
import "luxe: containers" for Lists
import "luxe: draw" for Draw, PathStyle import "luxe: draw" for Draw, PathStyle
import "luxe: game" for Frame
import "luxe: math" for Math
import "luxe: render" for Material, TextAlign
import "luxe: ui/control" for Control
import "luxe: ui/image" for UIImage
import "luxe: ui/label" for UILabel
import "luxe: world" for Entity, Transform, UI, UIRenderMode, UIEvent import "luxe: world" for Entity, Transform, UI, UIRenderMode, UIEvent
import "luxe: world" for UILayout, UILayoutBehave, UILayoutContain import "luxe: world" for UILayout, UILayoutBehave, UILayoutContain
import "luxe: ui/control" for Control
import "luxe: ui/label" for UILabel
import "luxe: ui/image" for UIImage
import "luxe: assets" for Assets, Strings
import "luxe: render" for Material, TextAlign
import "luxe: color" for Color
import "luxe: game" for Frame
import "luxe: containers" for Lists
import "luxe: math" for Math
import "globals" for Globals import "blocks/human/human" for Human
import "blocks/ui/clickable" for Clickable
import "blocks/ui/image_util" for UiImageUtil
import "math/observable" for Observable
import "blocks/ui/simple_text" for UISimpleText
import "blocks/ui/ui" for Ui
import "blocks/ui/slider" for UiSlider
import "blocks/ui/box" for UIBox import "blocks/ui/box" for UIBox
import "blocks/ui/scroll_box" for UiScrollBox import "blocks/ui/clickable" for Clickable
import "blocks/ui/compass" for UiCompass import "blocks/ui/compass" for UiCompass
import "blocks/ui/image_util" for UiImageUtil
import "blocks/ui/info" for UiInfo //this is a cyclic dependency waiting to happen... import "blocks/ui/info" for UiInfo //this is a cyclic dependency waiting to happen...
import "blocks/ui/number_field" for NumberField import "blocks/ui/number_field" for NumberField
import "math/math" for M import "blocks/ui/scroll_box" for UiScrollBox
import "math/util" for Util import "blocks/ui/simple_text" for UISimpleText
import "blocks/ui/slider" for UiSlider
import "blocks/ui/ui" for Ui
import "globals" for Globals
import "math/event" for MultiListenerToken import "math/event" for MultiListenerToken
import "blocks/human/human" for Human import "math/math" for M
import "math/observable" for Observable
import "math/stringUtil" for StringUtil
import "math/util" for Util
class UiAdventure{ class UiAdventure{
root{_root} root{_root}
@ -35,6 +36,7 @@ class UiAdventure{
static people{"people"} static people{"people"}
static resources{"resources"} static resources{"resources"}
static depart{"depart"} static depart{"depart"}
static abort{"abort"}
adventure{_game.adventures.planning} //shortcut to get currently planning adventure (observable) adventure{_game.adventures.planning} //shortcut to get currently planning adventure (observable)
@ -50,17 +52,25 @@ class UiAdventure{
setup(){ setup(){
var ui_rect = Globals["UiRect"] var ui_rect = Globals["UiRect"]
var game = Globals["Game"]
_root = Control.create(_ent) _root = Control.create(_ent)
Control.set_allow_input(_root, true) Control.set_allow_input(_root, true)
Control.set_size(_root, ui_rect.width, ui_rect.height) Control.set_size(_root, ui_rect.width, ui_rect.height)
//if no adventure is planned anymore, leave adventure planning ui
_game.adventures.planning.on_change{|adventure|
if(!adventure){
_ui.ui_mode = Ui.Info
_page.value = UiAdventure.direction
}
}
toolbar() toolbar()
direction() direction()
people() people()
resources() resources()
depart() depart()
abort()
} }
toolbar(){ toolbar(){
@ -78,11 +88,7 @@ class UiAdventure{
_ui.list_button(list, [2, 0], "People") {_page.value = UiAdventure.people} _ui.list_button(list, [2, 0], "People") {_page.value = UiAdventure.people}
_ui.list_button(list, [4, 0], "Stuff") {_page.value = UiAdventure.resources} _ui.list_button(list, [4, 0], "Stuff") {_page.value = UiAdventure.resources}
_ui.list_button(list, [5, 0], "Depart") {_page.value = UiAdventure.depart} _ui.list_button(list, [5, 0], "Depart") {_page.value = UiAdventure.depart}
_ui.list_button(list, [0, 0], "Abort") { _ui.list_button(list, [0, 0], "Abort") {_page.value = UiAdventure.abort}
_ui.ui_mode = Ui.Info
_game.adventures.discard()
_page.value = UiAdventure.direction
}
} }
direction(){ direction(){
@ -102,21 +108,6 @@ class UiAdventure{
Control.set_size(compass, 32, 32) Control.set_size(compass, 32, 32)
UILayout.set_margin(_ent, compass, 8, 0, 0, 0) UILayout.set_margin(_ent, compass, 8, 0, 0, 0)
var steps = 16 //compass steps var steps = 16 //compass steps
var step_names = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"]
var full_step_names = step_names.map{|short|
var shorts = "NESW"
var base_directions = ["north","east","south","west"]
if(short.count == 1){
return base_directions[shorts.indexOf(short)]
} else if(short.count == 2) {
return base_directions[shorts.indexOf(short[0])] +
base_directions[shorts.indexOf(short[1])]
} else { //assume 3
return base_directions[shorts.indexOf(short[0])] + "-" +
base_directions[shorts.indexOf(short[1])] +
base_directions[shorts.indexOf(short[2])]
}
}.toList
adventure.on_change(true){|val| adventure.on_change(true){|val|
if(val == null) return if(val == null) return
@ -176,7 +167,7 @@ class UiAdventure{
adventure.on_change(true) { |val| adventure.on_change(true) { |val|
if(val == null) return if(val == null) return
//this stuff does bad things //this stuff does bad things
var dir = full_step_names[val.direction] var dir = StringUtil.direction(val.direction)
var dist = val.distance var dist = val.distance
UILabel.set_text(text, "%(dist)km\n%(dir)") UILabel.set_text(text, "%(dist)km\n%(dir)")
} }
@ -333,13 +324,13 @@ class UiAdventure{
//change resource data //change resource data
Control.set_events(amount){|event| Control.set_events(amount){|event|
if(event.type == UIEvent.change){ if(event.type == UIEvent.change){
var value = event.change.round var value = Math.clamp(event.change.round, 0, resource["amount"])
adventure.resources.set(resource["name"], value) adventure.resources.set(resource["base_name"], value)
} }
} }
//change ui on resource data change //change ui on resource data change
var token = adventure.resources.on_change{|value| var token = adventure.resources.on_change{|value|
NumberField.set_value(amount, Math.clamp(value.get(resource["name"]), 0, resource["amount"])) NumberField.set_value(amount, value.get(resource["base_name"]))
} }
_itemEvents.add(token) _itemEvents.add(token)
_itemListItems.add(item) _itemListItems.add(item)
@ -354,6 +345,9 @@ class UiAdventure{
Control.child_add(_root, page) Control.child_add(_root, page)
UILayout.set_behave(_ent, page, UILayoutBehave.fill) UILayout.set_behave(_ent, page, UILayoutBehave.fill)
UILayout.set_margin(_ent, page, 0, 0, 0, 16) UILayout.set_margin(_ent, page, 0, 0, 0, 16)
_page.on_change(true){|val|
Control.set_visible(page, val == UiAdventure.depart)
}
var ready = UILabel.create(_ent) var ready = UILabel.create(_ent)
Control.child_add(page, ready) Control.child_add(page, ready)
@ -372,6 +366,8 @@ class UiAdventure{
UILabel.set_font(go, _ui.font) UILabel.set_font(go, _ui.font)
UILabel.set_text_size(go, 16) UILabel.set_text_size(go, 16)
UILabel.set_text(go, "GO") UILabel.set_text(go, "GO")
UILabel.set_color(go, [1,1,1,1])
UILabel.set_color_hover(go, [1,1,1,1])
UILayout.set_behave(_ent, go, UILayoutBehave.left | UILayoutBehave.top) //| UILayout.set_behave(_ent, go, UILayoutBehave.left | UILayoutBehave.top) //|
UILayout.set_margin(_ent, go, 56, 24, 0, 0) UILayout.set_margin(_ent, go, 56, 24, 0, 0)
Clickable.make_clickable(go) Clickable.make_clickable(go)
@ -379,14 +375,48 @@ class UiAdventure{
UILabel.set_text(go, data["hover"]?"GO!":"GO") UILabel.set_text(go, data["hover"]?"GO!":"GO")
} }
Clickable.set_on_click(go){ Clickable.set_on_click(go){
//todo, start adventure, not discard!! _game.adventures.dispatch()
_ui.ui_mode = Ui.Info }
_game.adventures.discard() }
_page.value = UiAdventure.direction
abort(){
var page = Control.create(_ent)
Control.child_add(_root, page)
UILayout.set_behave(_ent, page, UILayoutBehave.fill)
UILayout.set_margin(_ent, page, 0, 0, 0, 16)
_page.on_change(true){|val|
Control.set_visible(page, val == UiAdventure.abort)
} }
_page.on_change(true){|val| var ready = UILabel.create(_ent)
Control.set_visible(page, val == UiAdventure.depart) Control.child_add(page, ready)
Control.set_size(ready, 100, 10)
UILabel.set_align_vertical(ready, TextAlign.bottom)
UILabel.set_font(ready, _ui.font)
UILabel.set_text_size(ready, 8)
UILabel.set_text(ready, "This will discard the adventure")
UILayout.set_behave(_ent, ready, UILayoutBehave.left | UILayoutBehave.top) //|
UILayout.set_margin(_ent, ready, 12, 0, 0, 0)
UILabel.set_color(ready, [0.7, 0.7, 0.7, 1])
var abort = UILabel.create(_ent)
Control.child_add(page, abort)
Control.set_size(abort, 100, 20)
UILabel.set_align_vertical(abort, TextAlign.bottom)
UILabel.set_align(abort, TextAlign.right)
UILabel.set_font(abort, _ui.font)
UILabel.set_text_size(abort, 16)
UILabel.set_text(abort, "ABORT")
UILabel.set_color(abort, [1,1,1,1])
UILabel.set_color_hover(abort, [1,1,1,1])
UILayout.set_behave(_ent, abort, UILayoutBehave.left | UILayoutBehave.top) //|
UILayout.set_margin(_ent, abort, 25, 8, 0, 0)
Clickable.make_clickable(abort)
Clickable.set_state_change(abort){ |data, button|
UILabel.set_text(abort, data["hover"]?"ABORT!":"ABORT")
}
Clickable.set_on_click(abort){
_game.adventures.discard()
} }
} }
} }

View file

@ -36,21 +36,17 @@ class UiCompass{
Control.set_process(compass){|control, state, event, x,y,w,h| Control.set_process(compass){|control, state, event, x,y,w,h|
if(event.control != control) return if(event.control != control) return
System.print("event: %(event) - currently captured: %(UI.get_captured(ent))")
if(event.type == UIEvent.press){ if(event.type == UIEvent.press){
var relative_pos = AABB.new(x, y, w, h).relative_pos([event.x, event.y]) var relative_pos = AABB.new(x, y, w, h).relative_pos([event.x, event.y])
var inside = M.length(relative_pos.map{|comp| comp - 0.5}) < 0.5 var inside = M.length(relative_pos.map{|comp| comp - 0.5}) < 0.5
if(inside) { if(inside) {
state["pressed"] = true state["pressed"] = true
UI.capture(control) UI.capture(control)
System.print("CAPTURE COMPASS")
} }
} }
if(event.type == UIEvent.release){ if(event.type == UIEvent.release){
state["pressed"] = false state["pressed"] = false
UI.uncapture(control) UI.uncapture(control)
System.print("UNCAPTURE COMPASS")
} }
if((event.type == UIEvent.move || event.type == UIEvent.press) && state["pressed"]){ if((event.type == UIEvent.move || event.type == UIEvent.press) && state["pressed"]){
var center = [x + w/2, y + h/2] var center = [x + w/2, y + h/2]

View file

@ -9,6 +9,7 @@ import "globals" for Globals
import "math/rect" for AABB import "math/rect" for AABB
import "math/math" for M import "math/math" for M
import "blocks/debug" for DrawDebug import "blocks/debug" for DrawDebug
import "math/util" for Util
class UiSlider{ class UiSlider{
static horizontal{"horiz"} static horizontal{"horiz"}
@ -50,6 +51,7 @@ class UiSlider{
} }
Control.set_process(slider){|control, state, event, x,y,w,h| Control.set_process(slider){|control, state, event, x,y,w,h|
if(event.control != control) return if(event.control != control) return
if(!Util.valid_event(event)) return
if(event.type == UIEvent.press){ if(event.type == UIEvent.press){
state["pressed"] = true state["pressed"] = true
UI.capture(control) UI.capture(control)

View file

@ -1,6 +1,28 @@
//a lot of this is bad and can only handle ASCII
//too bad ¯\_(ツ)_/¯
class StringUtil{ class StringUtil{
static directions{
if(!__directions){
var step_names = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"]
__directions= step_names.map{|short|
var shorts = "NESW"
var base_directions = ["north","east","south","west"]
if(short.count == 1){
return base_directions[shorts.indexOf(short)]
} else if(short.count == 2) {
return base_directions[shorts.indexOf(short[0])] +
base_directions[shorts.indexOf(short[1])]
} else { //assume 3
return base_directions[shorts.indexOf(short[0])] + "-" +
base_directions[shorts.indexOf(short[1])] +
base_directions[shorts.indexOf(short[2])]
}
}.toList
}
return __directions
}
static possesive(string){ static possesive(string){
if(string.endsWith("s")){ if(string.endsWith("s")){
return "%(string)'" return "%(string)'"
@ -20,26 +42,82 @@ class StringUtil{
//todo: this doesnt cover all cases perfectly, add more //todo: this doesnt cover all cases perfectly, add more
static a(string){ static a(string){
var firstChar = string[0] var firstChar = string[0]
if(isVowel(firstChar)){ if(is_vowel(firstChar)){
return "an %(string)" return "an %(string)"
} else { } else {
return "a %(string)" return "a %(string)"
} }
} }
static isVowel(char){ static is_vowel(char){
return "aeiou".contains(char) return "aeiou".contains(char)
} }
//todo: do static direction(index){
static capitalize(string){ return directions[index]
return string
} }
//todo: ths ignores words that arent preceeded by a space like (this) or "this". maybe fix that? //checks if a character (as codepoint is lowercase)
static is_lower(char){
return char >= 97 && char <= 122
}
//checks if a character (as codepoint is uppercase)
static is_upper(char){
return char >= 65 && char <= 90
}
static is_letter(char){
return is_lower(char) || is_upper(char)
}
static to_upper(string){
return string.codePoints.map{|c|is_lower(c)?c-32:c}.map{|c|String.fromCodePoint(c)}.join()
}
static to_lower(string){
return string.codePoints.map{|c|is_upper(c)?c+32:c}.map{|c|String.fromCodePoint(c)}.join()
}
static capitalize(string){
return to_upper(string[0]) + string[1..-1]
}
//todo: this ignores words that arent preceeded by a space like (this) or "this". maybe fix that?
static capitalize_all(string){ static capitalize_all(string){
var words = string.split(" ") //split by words/stuff between words and capitalize everything,
words = words.map{|word| capitalize(word)} //capitalize function doesnt know what to do with separators so it wont touch them
return words.join(" ") return WordSequence.new(string).map{|word| capitalize(word)}.join()
}
}
class WordSequence is Sequence{
static new(string){
return new(string) {|c|
return StringUtil.is_letter(c)
}
}
construct new(string, letterCheck){
_string = string
_check = letterCheck
}
iterate(iterator){
if(!iterator) iterator = [-1, -1, false] //fake value from -1 to -1
if(iterator[1] >= _string.count-1) return false //abort when at end
var start = iterator[1]+1
var is_word = StringUtil.is_letter(_string.codePointAt_(start))
var end = start + 1
//count up until you find something thats not a word/separator depending on what the first letter was
while(end < _string.count && StringUtil.is_letter(_string.codePointAt_(end)) == is_word){
end = end + 1
}
end = end - 1
return [start, end, is_word]
}
iteratorValue(iterator){
return _string[iterator[0]..iterator[1]]
} }
} }