from st3m.application import Application, ApplicationContext from st3m.run import run_view import os.path UP = 0 LEFT = 1 DOWN = 2 RIGHT = 3 def dir_str(dir): if dir == UP: return 'back' elif dir == LEFT: return 'left' elif dir == DOWN: return 'front' elif dir == RIGHT: return 'right' def image_path(direction, step): dir = os.path.dirname(__file__) return f"{dir}/sprites/{dir_str(direction)}{str(step + 1)}.png" class Random: def __init__(self): self._state = 0x9ec5_9ec5 # (two gecs) # idk its fine its just for choosing delay and direction def next(self): self._state *= 37 self._state &= 0xffff_ffff return self._state >> 24 def direction(self): return self.next() & 3 def delay(self): return Quox.TURN_DELAY_BASE + self.next() # screen coords range ±120 each side class Quox(Application): STEP_DELAY = 250 TURN_DELAY_BASE = 1400 MOVE_DELAY = 100 TOP = -90 BOTTOM = 70 # so its always a bit visible LEFT = -90 RIGHT = 70 def __init__(self, app_ctx): super().__init__(app_ctx) self.random = Random() self.choose_direction() self.choose_turn_delay() self.step = 0 self.step_delay = Quox.STEP_DELAY self.move_delay = Quox.MOVE_DELAY self.x = -10 self.y = -10 def draw(self, ctx): self.clear(ctx) # self.text(ctx) self.image(ctx) def clear(self, ctx): ctx.rgb(0, 0, 0) \ .rectangle(-120, -120, 240, 240) \ .fill() def image(self, ctx): path = image_path(self.direction, self.step) ctx.image(path, self.x, self.y, -1, -1) @staticmethod def coord(d): if d == UP: return (-20, -100) elif d == LEFT: return (-100, -20) elif d == RIGHT: return (100, 20) elif d == DOWN: return (20, 100) def rect(self, ctx): if self.step: ctx = ctx.rgb(.1, .6, .3) else: ctx = ctx.rgb(.1, .3, .6) ctx.rectangle(0, 0, *Quox.coord(self.direction)).fill() def text(self, ctx): msg = f"{self.x}, {self.y}" ctx.font_size = 16.0 ctx.text_align = ctx.CENTER ctx.rgb(1, 1, 1).move_to(0, -100).text(msg) def think(self, state, Δ): super().think(state, Δ) self.update_delay(Δ) def update_delay(self, Δ): self.turn_delay -= Δ self.step_delay -= Δ self.move_delay -= Δ if self.turn_delay <= 0: old_delay = self.turn_delay self.choose_direction() self.choose_turn_delay(old_delay) if self.step_delay <= 0: self.step_delay = Quox.STEP_DELAY self.step = (self.step + 1) & 3 if self.move_delay <= 0: self.move_delay += Quox.MOVE_DELAY self.move() def choose_direction(self): self.direction = self.random.direction() def choose_turn_delay(self, subtract=0): self.turn_delay = self.random.delay() + subtract def at_edge(self): return ((self.direction == UP and self.y <= Quox.TOP) or (self.direction == DOWN and self.y >= Quox.BOTTOM) or (self.direction == LEFT and self.x <= Quox.LEFT) or (self.direction == RIGHT and self.x >= Quox.RIGHT)) def flip_direction(self): if self.direction == UP: self.direction = DOWN elif self.direction == LEFT: self.direction = RIGHT elif self.direction == DOWN: self.direction = UP elif self.direction == RIGHT: self.direction = LEFT def move(self): if self.at_edge(): self.flip_direction() if self.direction == UP: self.y -= 5 elif self.direction == LEFT: self.x -= 5 elif self.direction == DOWN: self.y += 5 elif self.direction == RIGHT: self.x += 5 if __name__ == '__main__': run_view(Quox(ApplicationContext()))