router = require("router") ecs = require("ecs") world = require("world") win = require("window") sprites = require("world.sprites") class FishGraphicComponent extends world.GraphicsComponent @fish_size = 0.5 @static = false @loctbl = { {-1,-1} {-1,1} {1,1} {1,1} {1,-1} {-1,-1} } buf_size: () => 6 populate_buf: (geom_view, normal_view, offset) => @buf = geom_view h = @@fish_size / 2 --@lamp_offset = vec4(2.5,1.4,0,0) aspect = win.width / win.height --@lamp = world.level.add_lamp(vec4(0,0,0,0.1 * aspect) + @lamp_offset) for i = 1,6 loctbl = @@loctbl[i] geom_view[i] = vec3(@@loctbl[i][1] * h, @@loctbl[i][2] * h, -1.5) uv = sprites.player_normal normal_view[1] = vec2(uv.s1,uv.t1) normal_view[2] = vec2(uv.s1,uv.t2) normal_view[3] = vec2(uv.s2,uv.t2) normal_view[4] = vec2(uv.s2,uv.t2) normal_view[5] = vec2(uv.s2,uv.t1) normal_view[6] = vec2(uv.s1,uv.t1) join: (entity) => super(entity) aspect = win.width / win.height program = @.node("use_program") @pred = entity\get("pred") graphic = entity\get("graphic") assert(@pred, "Fish graphic must have a predicted component") @node\remove(program) @node\append(am.blend("alpha")\append(program)) @ent = entity comp = @ move: (pos) => h = @@fish_size / 2 --print("Calling move with", pos) --if @ent.state ~= "swimming" -- error("called move while not swimming") for i = 1,6 @buf[i] = vec3(@@loctbl[i][1] * h, @@loctbl[i][2] * h, -0.13) + vec3(pos.x, pos.y, 0) friction = 0.1 class FishPredictedComponent extends ecs.PredictedComponent new: (id) => fish_speed = 0.00001 super(id, {accel: vec2(0,0), vel: vec2(0,0), pos: vec2(0,0)}, "netc", { accel: () => --print("ent state:", @cc.state) if @cc.state ~= "swimming" return vec2(0,0) localized = @net.properties.next_loc - @properties.pos --direction = math.atan(localized.y / localized.x) math.normalize(localized + @properties.vel) * fish_speed vel: () => --print("Before calculating vel, properties was ", @properties) delta = world.sync_time! - @net.properties.next_loc_time --print("Delta time:", delta) (@properties.accel / friction) + ((@properties.vel - (@properties.accel / friction)) * math.exp(-friction * delta)) pos: () => if @properties.pos.x > 20 error("Very far, stopping") delta = world.sync_time! - @net.properties.next_loc_time friction_loss = @properties.accel / friction (friction_loss * delta) - ((1/friction) * (@properties.vel - friction_loss) * (math.exp(-friction * delta))) + @properties.pos }) @node = am.group! join: (entity) => @net = entity\get("net") @gc = entity\get("graphic") @properties.pos = @net.properties.pos @cc = entity\get("control") @ent = entity --print("Got graphic component:",@gc, @gc.node) --print("And my node is", @node) @gc.node\append(@node) s = @ @node\action(() => s\forward! ) forward: () => super! if @ent.state == "catching" @gc.node.hidden=true else @gc\move(@properties.pos) class Fish extends ecs.Entity new: (id, pos) => @width = 40 -- TODO: randomize fish width components = { pred: FishPredictedComponent("pred") net: ecs.NetworkedComponent("net",{pos: pos, next_loc: pos, next_loc_time: am.current_time!}) graphic: FishGraphicComponent("graphic") control: require("controllers.fish").FishControllerComponent() phys: world.PhysicsComponent("phys",{},"circle",{pos.x, pos.y, @width / 256}) } super(id, components) destroy: (...) => super(...) error("Where did fish go") class SpawnFishComponent extends ecs.Component new: (id, properties, spawnrect) => super(id, properties) join: (entity) => graphic = entity\get("graphic") router = router.r! set_spawnable = () -> if router.state == "elected" graphic\action(() -> error("Spawn fish callback") ) set_spawnable! router\onchange(set_spawnable) {:Fish, :SpawnFishComponent}