Toggle Navigation
TiDAL Hatchery
Eggs
Lunar Lander
__init__.py
Users
Badges
Login
Register
__init__.py
raw
Content
import math import random import tidal from app import TextApp from scheduler import get_scheduler import vga2_8x8 as default_font class LunarLander(TextApp): def on_start(self): super().on_start() def on_activate(self): super().on_activate() self.restart() self.update() # Need this or else the game sleeps and resets after ~1800 frames get_scheduler().set_sleep_enabled(False) def on_deactivate(self): super().on_deactivate() self.update_task.cancel() # Turn light sleep back on get_scheduler().set_sleep_enabled(True) def restart(self): tidal.display.fill(tidal.BLACK) self.lander_poly = [(0, -11), (-5, 2), (5, 2)] self.explosion_cols = [tidal.RED, tidal.BRAND_ORANGE, tidal.YELLOW, tidal.color565(40, 40, 40)] self.time = 0 self.alive = True self.won = False self.rotation = (random.uniform(0, math.pi) - (math.pi*0.25)) % (2 * math.pi) self.pos_x = 64.0 self.pos_x_int = int(self.pos_x) self.pos_y = 15.0 self.pos_y_int = 5 self.thruster_offset = (0,6) start_speed = random.uniform(0, 0.5) self.speed_x = math.cos(self.rotation + math.pi) * start_speed self.speed_y = -math.sin(self.rotation + math.pi) * start_speed self.gravity = 0.001 self.rotation_speed = 0.1 self.thrust = 2 self.thrust_changed = False self.thrust_enabled = False self.update_time = 10 self.level_height = [] self.f0 = 0 self.o0 = 0 self.f1 = 0 self.o1 = 0 self.f2 = 0 self.o2 = 0 self.create_level() self.explode_step = 0 self.update_task = None def update(self): self.draw_ship(True) self.time += 1 if self.alive: self.speed_y += self.gravity if tidal.JOY_LEFT.value() == 0: self.rotation -= self.rotation_speed if self.rotation < 0: self.rotation += 2*math.pi if tidal.JOY_RIGHT.value() == 0: self.rotation += self.rotation_speed if self.rotation >= 2 * math.pi: self.rotation -= 2*math.pi if tidal.JOY_DOWN.value() == 0: if not self.thrust_changed: self.thrust -= 1 self.thrust_changed = True if self.thrust < 1: self.thrust = 3 elif tidal.JOY_UP.value() == 0: if not self.thrust_changed: self.thrust += 1 self.thrust_changed = True if self.thrust > 3: self.thrust = 1 else: self.thrust_changed = False if tidal.BUTTON_A.value() == 0 or tidal.JOY_CENTRE.value() == 0: self.speed_x += math.sin(self.rotation) * self.thrust * 0.002 self.speed_y -= math.cos(self.rotation) * self.thrust * 0.002 self.thrust_enabled = True else: self.thrust_enabled = False self.pos_x += self.speed_x self.pos_y += self.speed_y self.pos_x_int = int(self.pos_x) self.pos_y_int = int(self.pos_y) if self.pos_x_int < 0 or self.pos_x_int >= tidal.display.width() or self.pos_y_int < 0: tidal.display.text(default_font, " CRASH LANDING ", 0, 100) tidal.display.text(default_font, " lost to space ", 0, 116) self.die() elif self.pos_y_int >= self.level_height[self.pos_x_int]-1: if self.check_win(): self.win() else: self.die() if self.alive: self.draw_ship() else: if self.explode_step <= 6: self.draw_explosion(self.pos_x_int, self.pos_y_int, self.explode_step) self.explode_step += 1 elif self.explode_step == 7: tidal.display.fill_circle(self.pos_x_int, self.pos_y_int, 6, tidal.BLACK) self.draw_level() self.explode_step += 1 if tidal.BUTTON_A.value() == 0 or tidal.JOY_CENTRE.value() == 0: if not self.thrust_changed: self.restart() self.thrust_changed = True else: self.thrust_changed = False self.draw_ingame_text() self.update_task = self.after(self.update_time, self.update) def check_win(self): x = self.pos_x_int rot = self.get_slope(x) speed = (self.speed_x * self.speed_x) + (self.speed_y * self.speed_y) if speed >= 0.025: tidal.display.text(default_font, " CRASH LANDING ", 0, 100) tidal.display.text(default_font, " too fast ", 0, 116) return False if speed >= 0.01: tidal.display.text(default_font, " hard landing ", 0, 116) return True delta_angle = math.atan2(math.sin(self.rotation - rot), math.cos(self.rotation - rot)) safe_landing = abs(delta_angle) < math.pi / 8 if not safe_landing: tidal.display.text(default_font, " CRASH LANDING ", 0, 100) tidal.display.text(default_font, " bad angle ", 0, 116) return safe_landing # derivative of the wave of the level shape. yes i know i could clean this up, no i am not going to def get_slope(self, x): aterm = (50 * math.cos(x/self.f0 + self.o0) * math.sin((x / self.f1) + self.o1) * math.sin((x / self.f2) + self.o2)) / self.f0 bterm = (50 * math.sin(x/self.f0 + self.o0) * math.cos((x / self.f1) + self.o1) * math.sin((x / self.f2) + self.o2)) / self.f1 cterm = (50 * math.sin(x/self.f0 + self.o0) * math.sin((x / self.f1) + self.o1) * math.cos((x / self.f2) + self.o2)) / self.f2 return aterm + bterm + cterm def die(self): self.explode_step = 0 self.alive = False def win(self): self.explode_step = 7 self.alive = False self.draw_ship() tidal.display.text(default_font, " good job! ", 0, 100) def draw_ingame_text(self): speed = (self.speed_x * self.speed_x) + (self.speed_y * self.speed_y) tidal.display.text(default_font, "Thrust {}".format(self.thrust), 0, 216) tidal.display.text(default_font, "Speed {}".format(speed), 0, 232) def draw_explosion(self, x, y, step): for i in range(3): if i+step >= len(self.explosion_cols): break tidal.display.fill_circle(x, y, 6-(2*i), self.explosion_cols[i+step]) def draw_ship(self, clear=False): if self.thrust_enabled: # thank god for matrix mutiplication offset_x = self.pos_x offset_x += math.cos(self.rotation) * self.thruster_offset[0] + -math.sin(self.rotation) * self.thruster_offset[1] offset_y = self.pos_y offset_y += math.sin(self.rotation) * self.thruster_offset[0] + math.cos(self.rotation) * self.thruster_offset[1] tidal.display.fill_circle(int(offset_x), int(offset_y), 1+self.thrust+self.time%2, self.explosion_cols[self.time % 3] if not clear else tidal.BLACK) if self.alive: tidal.display.fill_polygon(self.lander_poly, self.pos_x_int, self.pos_y_int, tidal.WHITE if not clear else tidal.BLACK, self.rotation) def create_level(self): w = tidal.display.width() h = tidal.display.height() self.level_height = [] self.f0 = random.randint(40, 120) * math.pi self.o0 = random.randint(0, 80) * math.pi self.f1 = random.randint(20, 40) * math.pi self.o1 = random.randint(0, 20) self.f2 = random.randint(5, 15) self.o2 = random.randint(0, 10) for x in range(w): y = int(h - 8 - (((math.sin((x / self.f0) + self.o0) * math.sin((x / self.f1) + self.o1) * math.sin((x / self.f2) + self.o2))) * 50 + 50)) self.level_height.append(y) self.draw_level() def draw_level(self): for x in range(1, tidal.display.width()): x0 = x-1 y0 = self.level_height[x0] tidal.display.line(x0, y0, x, self.level_height[x], tidal.WHITE) main = LunarLander