import "CoreLibs/graphics" import "CoreLibs/ui" local function clamp(value, min, max) return math.max(math.min(value, max), min) end local function clamp_angle(value) if value < 0 then value = value + 360 end if value > 360 then value = value - 360 end return value end local function make_projectile(position) local projectile = { position=table.deepcopy(position), speed=3 } projectile.draw = function(self, id) local current_width = playdate.graphics.getLineWidth() playdate.graphics.setLineWidth(2) local angle_rad = math.rad(self.position.theta) local dx, dy = self.speed * math.cos(angle_rad), self.speed * math.sin(angle_rad) local new_x, new_y = self.position.x + dx, self.position.y + dy playdate.graphics.drawLine(self.position.x,self.position.y, new_x,new_y) playdate.graphics.setLineWidth(current_width) self.position.x, self.position.y = new_x, new_y end return projectile end local function make_player(x, y, width, height, screen) local crankPosition = playdate.getCrankPosition() local player = { position={ x=x, y=y, theta=crankPosition}, width=width, height=height, screen=screen, projectiles={} } player.draw = function(self) local w, h, transform = self.width / 2, self.height / 2, playdate.geometry.affineTransform.new() local polygon = playdate.geometry.polygon.new(-w,-0.5*h, -w,0.5*h, w,0, -w,-0.5*h) transform:translate(self.position.x, self.position.y) transform:rotate(self.position.theta, self.position.x, self.position.y) local transformedPolygon = transform:transformedPolygon(polygon) playdate.graphics.drawPolygon(transformedPolygon) for i, projectile in ipairs(self.projectiles) do projectile:draw(i) end end player.translate = function(self, offset_theta, amount) local w, h, theta = self.width / 2, self.height / 2, self.position.theta local angle_rad = math.rad(clamp_angle(theta + offset_theta)) local new_x = self.position.x + (amount * math.cos(angle_rad)) local new_y = self.position.y + (amount * math.sin(angle_rad)) self.position.x = clamp(new_x, w, self.screen.width - w) self.position.y = clamp(new_y, h, self.screen.height - h) end player.rotate = function(self, degrees) self.position.theta = clamp_angle(self.position.theta + degrees) end player.handle_crank = function(self) local change, _acceleratedChange = playdate.getCrankChange() self:rotate(change) end player.shoot_projectile = function(self) local projectile = make_projectile(self.position) table.insert(self.projectiles, projectile) end return player end local screen = { width=400, height=240 } local player = make_player(screen.width / 2, screen.height / 2, 20, 30, screen) function playdate.update() playdate.graphics.clear() if playdate.isCrankDocked() then playdate.ui.crankIndicator:draw() end if playdate.buttonIsPressed(playdate.kButtonUp) then player:translate(0, 10) end if playdate.buttonIsPressed(playdate.kButtonDown) then player:translate(180, 10) end if playdate.buttonIsPressed(playdate.kButtonLeft) then player:translate(270, 1) end if playdate.buttonIsPressed(playdate.kButtonRight) then player:translate(90, 1) end if playdate.buttonJustPressed(playdate.kButtonA) then player:shoot_projectile() end player:handle_crank() player:draw() end