local paddle_x = nil local paddle_y = nil local paddle_width = 0.1 local paddle_height = 0.02 local wall_thickness = 0.01 local missiles = {} local missile_radius = 0.005 local window_width = nil local window_height = nil local viewport_x_offset = nil local viewport_y_offset = nil local scale = nil function setScreenDimensions(width, height) window_width = width window_height = height viewport_x_offset = 0 viewport_y_offset = 0 scale = math.min(width, height) viewport_x_offset = (window_width - scale) / 2 viewport_y_offset = (window_height - scale) / 2 end function toScreenCoordinates(x, y) local screen_x = x * scale + viewport_x_offset local screen_y = y * scale + viewport_y_offset return screen_x, screen_y end function toScreenSize(size) return size * scale end function fromScreenCoordinate(x, y) local logical_x = (x - viewport_x_offset) / scale local logical_y = (y - viewport_y_offset) / scale return logical_x, logical_y end function love.load() love.mouse.setVisible(false) local width, height = love.graphics.getDimensions() setScreenDimensions(width, height) movePaddle(0) spawnMissile(0.5, 0.1, -0.1, -0.2) spawnMissile(0.5, 0.1, 0.1, 0.1) end function spawnMissile(x, y, dx, dy) table.insert(missiles, { x = x, y = y, dx = dx, dy = dy, reflected = false, }) end function updateMissiles(dt) for i, missile in ipairs(missiles) do missile.x = missile.x + missile.dx * dt missile.y = missile.y + missile.dy * dt if missile.y < wall_thickness + missile_radius then -- Collision with top wall missile.y = wall_thickness + missile_radius missile.dy = -missile.dy end if missile.x < wall_thickness + missile_radius then -- Collision with left wall missile.x = wall_thickness + missile_radius missile.dx = -missile.dx elseif missile.x > 1 - (wall_thickness + missile_radius) then -- Collision with right wall missile.x = 1 - (wall_thickness + missile_radius) missile.dx = -missile.dx end local paddle_left = paddle_x - paddle_width/2 local paddle_right = paddle_x + paddle_width/2 local paddle_top = paddle_y - paddle_height/2 if paddle_left <= missile.x and missile.x <= paddle_right and paddle_top <= missile.y and missile.y <= paddle_y then -- Collision with the paddle missile.y = paddle_top missile.dy = -missile.dy missile.reflected = true end end local i = 1 while i <= #missiles do if missiles[i].y > 1 + missile_radius then -- Went off the bottom of the screen, delete table.remove(missiles, i) else i = i +1 end end end function love.update(dt) updateMissiles(dt) end function movePaddle(screen_x) paddle_x = fromScreenCoordinate(screen_x, 0) paddle_x = math.max(paddle_x, paddle_width/2 + wall_thickness) paddle_x = math.min(paddle_x, 1 - (paddle_width/2 + wall_thickness)) paddle_y = 0.9 end love.mousemoved = movePaddle love.resize = setScreenDimensions function drawWalls() love.graphics.setColor(0, 0, 1) local x, y = toScreenCoordinates(0, 0) local width = toScreenSize(1) local height =toScreenSize(wall_thickness) love.graphics.rectangle('fill', x, y, width, height) local width = toScreenSize(wall_thickness) local height = toScreenSize(1) love.graphics.rectangle('fill', x, y, width, height) local x, y = toScreenCoordinates(1 - wall_thickness, 0) love.graphics.rectangle('fill', x, y, width, height) end function drawMissiles() for _, missile in ipairs(missiles) do local style = 'fill' if missile.reflected then love.graphics.setColor(1, 0.5, 0) style = 'line' else love.graphics.setColor(1, 0.5, 0.5) end local x, y = toScreenCoordinates(missile.x, missile.y) local radius = toScreenSize(missile_radius) love.graphics.circle(style, x, y, radius) end end function drawPaddle() love.graphics.setColor(1, 1, 1) local x, y = toScreenCoordinates(paddle_x - paddle_width / 2, paddle_y - paddle_height / 2) local width = toScreenSize(paddle_width) local height = toScreenSize(paddle_height) love.graphics.rectangle('fill', x, y, width, height) end function love.draw() drawWalls() drawMissiles() drawPaddle() end