aboutsummaryrefslogtreecommitdiff
path: root/src/char.moon
diff options
context:
space:
mode:
authorAlexander M Pickering <alex@cogarr.net>2024-01-29 16:20:10 -0600
committerAlexander M Pickering <alex@cogarr.net>2024-01-29 16:20:10 -0600
commitc2926c5ec74d7e37da395c8c32a7ff2b4cae7d06 (patch)
treeac2bb208dab1274cdc5e9059ffe014ae19181a4c /src/char.moon
downloadfools_rush_in-c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06.tar.gz
fools_rush_in-c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06.tar.bz2
fools_rush_in-c2926c5ec74d7e37da395c8c32a7ff2b4cae7d06.zip
All the files
Diffstat (limited to 'src/char.moon')
-rw-r--r--src/char.moon307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/char.moon b/src/char.moon
new file mode 100644
index 0000000..5e1a35c
--- /dev/null
+++ b/src/char.moon
@@ -0,0 +1,307 @@
+
+util = require "util"
+broadphase = require "broadphase"
+main = require "main"
+constrain = require "constrain"
+color = require "color"
+room = require "room"
+import LobbyRoom from room
+ability_reg = require "ability_reg"
+
+
+mod = ...
+mod.characters = {}
+mod.classes = {}
+require "char_tank"
+require "char_mage"
+require "char_theif"
+require "char_fool"
+require "char_jugg"
+mod.class_order = {
+ "Tumbler",
+ "Fire Breather",
+ "Juggler",
+ "Troubador",
+ "Juggernaut"
+}
+mod.class_order_rev = {}
+for k,v in ipairs(mod.class_order)
+ mod.class_order_rev[v] = k
+print("After requireing characters, mod.classes was",mod.classes)
+mod.enemies = {}
+--require "e_rat"
+require "e_bethany"
+require "e_ruminating_randy"
+require "e_mopey_marvin"
+require "e_sullen_salley"
+require "e_child"
+print("After requireing rat, mod.enemies was",mod.enemies)
+--print("test")
+--[[Stores a single input, and the time it was inputed]]
+class KeyInput
+ new:(key = "<input>") =>
+ @time = 0
+ @key = key
+ @value = false
+
+--print "test"
+
+class AnimFrame
+ new:(anim,interupt,mode) =>
+ @anim = anim
+ @interupt = interupt
+ @mode = mode
+
+class ActionInput
+ new:(action = "<input>") =>
+ @time = 0
+ @action = action
+
+mod.sprite_direction_co = () =>
+ return () ->
+ while true
+ @stop_anim(@sprites.right)
+ @stop_anim(@sprites.left)
+ @stop_anim(@sprites.stop_right)
+ @stop_anim(@sprites.stop_left)
+ @stop_anim(@sprites.falling_left)
+ @stop_anim(@sprites.falling_right)
+ for input in *@inputs
+ if @velocity.x > 0.01
+ @set_anim(@sprites.right,1,"loop")
+ break
+ elseif @velocity.x < -0.01
+ @set_anim(@sprites.left,1,"loop")
+ break
+ coroutine.yield!
+
+mod.can_die_co = () =>
+ return () ->
+ while not @dead
+ coroutine.yield!
+
+ for k,v in pairs @sprites
+ if k ~= "idle"
+ @stop_anim(v)
+ if @sprites.die
+ @set_anim(@sprites.die,5)
+ coroutine.yield(true)
+
+mod.make_animate = (c) ->
+ assertf(c.sprites ~= nil, "Tried to animate something that had no .sprites: %q", c.__class.__name)
+ assertf(c.sprites.idle ~= nil and #c.sprites.idle > 0, "Tried to animate something without a .idle animation: %q", c.__class.__name)
+ c.anim_stack = {AnimFrame(c.sprites.idle,0,"loop")}
+ c.anim = c.sprites.idle
+ c.keyframe = 0
+ c.animrate = c.animrate or 1
+ c.anim_interupt = 0
+ c.set_anim = (self,tbl,interupt,mode) ->
+ if type(tbl) ~= "table"
+ error("Tried to set anim to something that was not a table!",2)
+ if #tbl == 0
+ error("Tried to set anim to an empty table",2)
+ if interupt > @anim_interupt
+ table.insert(@anim_stack,AnimFrame(tbl,interupt,mode))
+ @anim = @anim_stack[#@anim_stack].anim
+ @anim_interupt = interupt
+
+ c.stop_anim = (self,tbl,err_if_unable=false) ->
+ anim_found = false
+ for k,v in pairs @anim_stack
+ if v.anim == tbl
+ --print("Found anim to remove")
+ anim_found = true
+ table.remove(@anim_stack,k)
+ break
+ if err_if_unable
+ assertf(anim_found, "Could not find animation to remove")
+ @anim = @anim_stack[#@anim_stack].anim
+ @anim_interupt = @anim_stack[#@anim_stack].interupt
+
+ c.node\action(coroutine.create(() ->
+ while not c.dead
+ c.keyframe = math.floor(am.current_time()*c.animrate) % #c.anim
+ spritename = c.anim[c.keyframe + 1]
+ assert(spritename, "Failed to find an appropriate image to draw.")
+ --print("Setting:",spritename)
+ c.node("sprite").source = spritename
+ coroutine.yield!
+ --we are dead
+ keyframe_0 = am.current_time()
+ while c.keyframe < #c.anim - 1
+ c.keyframe = math.floor((am.current_time! - keyframe_0)*c.animrate)
+ assert(c.anim[c.keyframe + 1], "Failed to find an appropriate image to draw.")
+ c.node("sprite").source = c.anim[c.keyframe + 1]
+ coroutine.yield!
+ c\remove()
+ coroutine.yield(true)
+ ))
+
+mod.inherited = {}
+hp_bar_width = 20
+--[[The character, extended to make both players and ai]]
+class Character
+ @classes = {}
+ @players = {} -- players singleton, [peerid] = Character
+ new:(uname, data, charclass) =>
+ assert(charclass, "Charclass may not be nil")
+ @uname = uname or false
+ @data = data or {
+ status: "active",
+ location: -1,
+ position: charclass.default_position
+ }
+ @class = charclass
+ assert(@class.name, "Character classes must have a name")
+ @calc_class_values!
+ @node = am.group!
+
+ --print("Creating character!",uname,data,charclass)
+ @node\append(am.translate(0,0)\tag("char_translate")^ am.sprite(@class.sprite,color.white,"center","bottom")\tag("char_sprite"))
+ print("A character has been created!")
+ print(debug.traceback!)
+ --Draw healthbar
+ healthbar_trans = am.translate(0,60)
+ healthbar_left = am.sprite("data/bar_left.png", color.white,"left","center")\tag("hp_l")
+ healthbar_right = am.sprite("data/bar_right.png", color.white, "right","center")\tag("hp_r")
+ healthbar_bar = am.sprite("data/bar_mid.png", color.white,"left","center")\tag("hp_b")
+ healthbar_fill = am.sprite("data/bar_fill.png", color.white,"left","center")\tag("hp_f")
+ healthbar_scale = am.scale(hp_bar_width,1)
+ healthbar_fill_scale = am.scale(hp_bar_width + 1,1)\tag("hp_fill_scale")
+ healthbar_trans\append(am.translate(-hp_bar_width,0)^ healthbar_left)
+ healthbar_trans\append(am.translate(hp_bar_width,0)^ healthbar_right)
+ healthbar_trans\append(am.translate(-hp_bar_width/2,0)^ healthbar_scale^ healthbar_bar)
+ healthbar_trans\append(am.translate((-hp_bar_width/2) - 1,0)^ healthbar_fill_scale^ healthbar_fill)
+ @.node("char_sprite")\append(healthbar_trans)
+ --End draw healthbar
+ assert(@.__class.draw,"Characters must have a draw() method")
+ table.insert(mod.characters,@)
+ constrain(@,"set anim", (self,value) ->
+ assertf(type(value) == "table", "Tried to set anim on %q to something other than a table (%q)",@, type(value))
+ assert(#value > 0, "Tried to set animation for char to something with 0 frames!")
+ )
+ assert(@.__class != Character,"Character class must be subclassed")
+ --main.root("world_characters")\append(@node)
+
+ __tostring: () =>
+ return string.format(
+ "<%s, %s> at (%d)",
+ @.__class.__name,
+ (@class and @class.name or "no class"),
+ ( @data and @data.position or -1)
+ )
+
+ @__inherited: (c) =>
+ assert(c, "Inheritance must exist")
+ assert(c.__name, "Inherited class must have a .__name")
+ @@.classes[c.__name] = c
+ mod.inherited[c.__name] = c
+
+ calc_class_values: () =>
+ for k,v in pairs(@class)
+ if k\match("^default")
+ field = k\match("^default_(.*)")
+ if type(v) == "function"
+ @data[field] = v!
+ else
+ @data[field] = v
+
+ set_field: (name, value) =>
+ assert(@data[name], "Field must exist to be set")
+ @data[name] = value
+ print("my data table is:",@data)
+ if name == "hp"
+ perc = (@data.hp / @data.maxhp) * 20
+ @.node("hp_fill_scale").x = perc
+
+ serialize: () =>
+ print("Serializing char:",@)
+ print("Name:", @@__name)
+ print("uname:",@uname)
+ print("data:",@data)
+ data_abilities = {}
+ for i,ability in pairs(@data.abilities)
+ data_abilities[i] = ability.__name
+ data_copy = table.shallow_copy(@data)
+ data_copy.abilities = data_abilities
+ print("class.name:",@class.name)
+ ret = am.to_json({name:@@__name, uname:@uname, data:data_copy, class:@class.name})
+ print("Ret is:",ret)
+ ret
+
+ deserialize: (data) ->
+ print("Deserializing character")
+ tbl = am.parse_json(data)
+ if mod.classes[tbl.class]
+ data_abilities = {}
+ for i, ability_name in pairs(tbl.data.abilities)
+ data_abilities[i] = ability_reg[ability_name]
+ tbl.data.abilities = data_abilities
+ return mod.inherited[tbl.name](tbl.uname, tbl.data, mod.classes[tbl.class])
+ elseif mod.enemies[tbl.class]
+ e = mod.Enemy(tbl.data, mod.enemies[tbl.class])
+ e.uname = tbl.uname
+ return e
+
+
+ draw:(screenpos) =>
+ print("draw")
+ remove: () =>
+ @node\remove_all!
+ die: () =>
+ @dead = true
+ print(@,"is dieing, node is",@.node,"and color is",color)
+ @.node("char_sprite")\append(am.line(vec2(-10,-10),vec2(10,10),5,color.bright))
+ @.node("char_sprite")\append(am.line(vec2(10,-10),vec2(-10,10),5,color.bright))
+ enter_room: (room) =>
+ @room = room
+ print("Character",@,"entered room",room)
+ @.node("char_translate").y = room.floor_y
+ if room.__class == LobbyRoom
+ print("Class was lobbyRoom")
+ rng_x = math.random(-(main.width/2), (main.width/2))
+ print("RNG x:",rng_x)
+ @.node("char_translate").x = rng_x
+ else
+ print("Class was not LobbyRoom")
+ x_pos = @room\player_location_of(@data.position)
+ print("Got x pos for",@,x_pos)
+ @.node("char_translate").x = x_pos + math.random(-15,15) --some random variance to stop stacking
+ set_class: (newclass) =>
+ assert(newclass, "Cannot set a class to nil")
+ @class = newclass
+ @calc_class_values!
+ @.node("char_sprite").source = newclass.sprite
+
+ set_position: (pos) =>
+ @data.position = pos
+
+ set_location: (loc) =>
+ @data.location = loc
+
+mod.enemy_counter = 0
+class Enemy extends Character
+ new: (data, eclass) =>
+ super(eclass.name .. ":" .. tostring(mod.enemy_counter), data, eclass)
+ mod.enemy_counter += 1
+ nwuname: (uname, data, eclass) ->
+ @(data, eclass)
+
+ mod.enemy_counter += 1
+ __tostring: () =>
+ return string.format("<%s> at (%d)",@uname, @data.position or 0)
+
+ enter_room: (room) => --overload character's to get enemy locations
+ print("Character",@,"entered room",room)
+ @room = room
+ @.node("char_translate").y = @room.floor_y
+ @.node("char_translate").x = @room\enemy_location_of(@data.position)
+
+ select_action: () =>
+ return @class.select_action(@)
+
+mod["Character"] = Character
+mod["KeyInput"] = KeyInput
+mod["Enemy"] = Enemy
+--Things that extend the character class
+mod