Download
63 lines 2.4 KiBTomoModified 2025-04-07 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
# A satellite sits on the map and beams controls to the player

use ./raylib.tm
use ./box.tm
use ./player.tm

struct Satellite(pos:Vector2, beam_end=Vector2(0,0), facing=Vector2(1,0))
    SIZE := Vector2(32,32)

    func draw_beam(s:Satellite)
        DrawLineEx(s.pos, s.beam_end, 5, Color(0x80,0x80,0xff,0xcc))

    func draw(s:Satellite)
        texture := Texture.load((./assets/Satellite.png))
        texture.draw(s.pos, Satellite.SIZE, angle=s.facing.angle() + Num32.TAU/8)

    func update(s:&Satellite, boxes:[@Box], player:&Player)
        if player.dead
            s.beam_end = s.pos
        else
            s.facing = (player.pos - s.pos).norm()
            s.beam_end = s.raycast(boxes, player.pos)
            if s.beam_end.dist(player.pos).near(0)
                player.has_signal = yes

    func vertical_edge_hit(pos,dir:Vector2, edge_x:Num32, y_min,y_max:Num32 -> Vector2?)
        t := (edge_x - pos.x)/dir.x
        return none if t < 0
        y := pos.y + (t*dir.y)
        return none if y < y_min or y > y_max
        return Vector2(edge_x, y)

    func horizontal_edge_hit(pos,dir:Vector2, edge_y:Num32, x_min,x_max:Num32 -> Vector2?)
        t := (edge_y - pos.y)/dir.y
        return none if t < 0
        x := pos.x + (t*dir.x)
        return none if x < x_min or x > x_max
        return Vector2(x, edge_y)

    func raycast(s:Satellite, boxes:[@Box], end:Vector2, epsilon=Num32(0.1) -> Vector2)
        return end if s.pos == end
        dist := s.pos.dist(end)
        forward := (end - s.pos).norm()

        for b in boxes
            skip if b.color.a < 0xff
            x_min := b.pos.x - b.size.x/2
            x_max := b.pos.x + b.size.x/2
            y_min := b.pos.y - b.size.y/2
            y_max := b.pos.y + b.size.y/2
            hit : Vector2? = none
            if forward.y != 0
                hit = Satellite.horizontal_edge_hit(s.pos, forward, y_min, x_min, x_max)
                if hit then end = end _min_.dist(s.pos) hit
                hit = Satellite.horizontal_edge_hit(s.pos, forward, y_max, x_min, x_max)
                if hit then end = end _min_.dist(s.pos) hit
            if forward.x != 0
                hit = Satellite.vertical_edge_hit(s.pos, forward, x_min, y_min, y_max)
                if hit then end = end _min_.dist(s.pos) hit
                hit = Satellite.vertical_edge_hit(s.pos, forward, x_max, y_min, y_max)
                if hit then end = end _min_.dist(s.pos) hit

        return end