├── assets ├── love-ball.png ├── Minimal5x7.ttf ├── anim-boogie.png ├── love-cursor.png ├── love-big-ball.png ├── Grundschrift-Normal.otf ├── HA-1112-M1LBuchon_flyby.ogg └── love_osx_inner.svg ├── conf.lua ├── examples ├── 007_sleeping.lua ├── 012_cursor_change.lua ├── 001_loading_image.lua ├── 015_image_rotation.lua ├── 013_cursor_image.lua ├── 008_fps_delta.lua ├── 010_key_down.lua ├── 004_mouse_setpos.lua ├── zzz_filler.lua ├── 051_callbacks_basic.lua ├── 002_mouse_getpos.lua ├── 009_timing.lua ├── 016_image_rot_scale.lua ├── 006_cursor_visibility.lua ├── 014_keyboard_move.lua ├── 005_mouse_button.lua ├── 104_display_modes.lua ├── 053_callbacks_keyboard.lua ├── 103_filesystem_lines.lua ├── video_test.lua ├── 019_physics_move_objs_.lua ├── 011_animation.lua ├── 017_font_truetype.lua ├── 150_shaders.lua ├── 100_physics_mini.lua ├── 052_callbacks_mouse.lua ├── 018_physics_fire_at.lua ├── 101_physics_mini_callbacks.lua └── 102_physics_adv.lua ├── README.md ├── viewcode.lua ├── movements.lua ├── animation.lua ├── main.lua ├── list.lua └── lexer.lua /assets/love-ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/love-ball.png -------------------------------------------------------------------------------- /assets/Minimal5x7.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/Minimal5x7.ttf -------------------------------------------------------------------------------- /assets/anim-boogie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/anim-boogie.png -------------------------------------------------------------------------------- /assets/love-cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/love-cursor.png -------------------------------------------------------------------------------- /assets/love-big-ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/love-big-ball.png -------------------------------------------------------------------------------- /assets/Grundschrift-Normal.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/Grundschrift-Normal.otf -------------------------------------------------------------------------------- /assets/HA-1112-M1LBuchon_flyby.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/love2d-community/LOVE-Example-Browser/HEAD/assets/HA-1112-M1LBuchon_flyby.ogg -------------------------------------------------------------------------------- /conf.lua: -------------------------------------------------------------------------------- 1 | function love.conf(t) 2 | --t.console = true 3 | author = "rude, and Codingale for the conversion to 0.9.0" 4 | love_version = "0.10.0" 5 | end 6 | -------------------------------------------------------------------------------- /examples/007_sleeping.lua: -------------------------------------------------------------------------------- 1 | -- Example: Sleeping 2 | 3 | function love.update(dt) 4 | -- Sleeps 10ms after each udpate. By doing this, 5 | -- CPU time is made available for other processes, 6 | -- and your OS will love you for it. 7 | love.timer.sleep(0.01) 8 | end 9 | -------------------------------------------------------------------------------- /examples/012_cursor_change.lua: -------------------------------------------------------------------------------- 1 | -- Example: Use an Image as cursor 2 | 3 | function love.load() 4 | -- Load the "cursor" (with default hot spot 0, 0) 5 | cursor = love.mouse.newCursor("assets/love-cursor.png") 6 | 7 | -- Set the cursor 8 | love.mouse.setCursor( cursor ) 9 | end 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/001_loading_image.lua: -------------------------------------------------------------------------------- 1 | -- Example: Loading an Image and displaying it 2 | --[[Description: 3 | Load an image using love.graphics.newImage(image_path) 4 | Draw it using love.graphics.draw 5 | ]] 6 | 7 | function love.load() 8 | image = love.graphics.newImage("assets/love-ball.png") 9 | end 10 | 11 | function love.draw() 12 | love.graphics.draw(image, 400, 300) 13 | end 14 | 15 | -------------------------------------------------------------------------------- /examples/015_image_rotation.lua: -------------------------------------------------------------------------------- 1 | -- Example: Rotating images 2 | 3 | angle = 0 4 | 5 | function love.load() 6 | image = love.graphics.newImage("assets/love-ball.png") 7 | end 8 | 9 | function love.update(dt) 10 | angle = (angle + dt) % (2 * math.pi) 11 | x, y = 400 + math.cos(angle)*100, 300 + math.sin(angle)*100 12 | end 13 | 14 | function love.draw() 15 | love.graphics.draw(image, x, y,angle) 16 | end 17 | -------------------------------------------------------------------------------- /examples/013_cursor_image.lua: -------------------------------------------------------------------------------- 1 | -- Example: Move an image along cursor 2 | 3 | function love.load() 4 | -- Load the "cursor" 5 | image = love.graphics.newImage("assets/love-ball.png") 6 | 7 | -- Hide the default mouse. 8 | love.mouse.setVisible(false) 9 | end 10 | 11 | function love.draw() 12 | -- Draw the "cursor" at the mouse position. 13 | love.graphics.draw(image, love.mouse.getX(), love.mouse.getY()) 14 | end 15 | 16 | -------------------------------------------------------------------------------- /examples/008_fps_delta.lua: -------------------------------------------------------------------------------- 1 | -- Example: FPS and delta-time 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | function love.draw() 8 | -- Draw the current FPS. 9 | love.graphics.print("FPS: " .. love.timer.getFPS(), 50, 50) 10 | -- Draw the current delta-time. (The same value 11 | -- is passed to update each frame). 12 | love.graphics.print("dt: " .. love.timer.getDelta(), 50, 100) 13 | end 14 | -------------------------------------------------------------------------------- /examples/010_key_down.lua: -------------------------------------------------------------------------------- 1 | -- Example: Checking if a key is down 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | function love.draw() 8 | -- Checks whether the return key is down or not. 9 | if love.keyboard.isDown("return") then 10 | love.graphics.print("The return key is down.", 50, 50) 11 | else 12 | love.graphics.print("The return key isn't down.", 50, 50) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /examples/004_mouse_setpos.lua: -------------------------------------------------------------------------------- 1 | -- Example: Setting the mouse position 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | function love.draw() 8 | love.graphics.print("Press a key to move the mouse to a random point", 50, 50) 9 | end 10 | 11 | -- Press a key to move the mouse to 12 | -- some random point. 13 | function love.keypressed(k) 14 | local x, y = math.random(0,800), math.random(0,600) 15 | love.mouse.setPosition(x, y) 16 | end 17 | -------------------------------------------------------------------------------- /examples/zzz_filler.lua: -------------------------------------------------------------------------------- 1 | -- Example: Filler 2 | 3 | angle = 0 4 | 5 | function love.load() 6 | image = love.graphics.newImage("assets/love-ball.png") 7 | end 8 | 9 | function love.update(dt) 10 | angle = angle + dt 11 | x, y = 400 + math.cos(angle)*100, 300 + math.sin(angle)*100 12 | end 13 | 14 | function love.draw() 15 | local rot = angle*180/math.pi 16 | local sx = math.cos(angle)*3 17 | local sy = math.sin(angle)*2 18 | love.graphics.draw(image, x, y, rot, sx, sy, 32, 32) 19 | end 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Löve-Example-Browser 2 | [![LOVE](https://img.shields.io/badge/L%C3%96VE-0.11.1-EA316E.svg)](http://love2d.org/) 3 | 4 | Example browser containing many helpful examples to get you started in Löve. __Check out the [online demo](http://love2d-community.github.io/LOVE-Example-Browser/).__ 5 | 6 | ![preview](http://i.imgur.com/48ARMOg.png) 7 | 8 | Ported to LÖVE [0.11.1](https://love2d.org/wiki/0.11) by slowb33. 9 | 10 | Examples for previous LÖVE versions can be found [here](https://love2d.org/wiki/examples.love). 11 | -------------------------------------------------------------------------------- /examples/051_callbacks_basic.lua: -------------------------------------------------------------------------------- 1 | -- Example: Basic callbacks 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | elapsed = 0 8 | 9 | -- Update: Called each frame. Update the 10 | -- state of your game here. 11 | function love.update(dt) 12 | elapsed = elapsed + dt 13 | end 14 | 15 | -- Draw: Called each frame. The game 16 | -- should be drawn in this functions. 17 | function love.draw() 18 | love.graphics.print("Elapsed time: " .. elapsed, 100, 100) 19 | end 20 | 21 | -------------------------------------------------------------------------------- /examples/002_mouse_getpos.lua: -------------------------------------------------------------------------------- 1 | -- Example: Getting the mouse position 2 | --[[Description: 3 | Get the mouse position with love.mouse.getPosition() 4 | Display it with love.graphics.print 5 | ]] 6 | 7 | function love.load() 8 | love.graphics.setFont(love.graphics.newFont(11)) 9 | end 10 | 11 | function love.draw() 12 | -- Gets the x- and y-position of the mouse. 13 | local x, y = love.mouse.getPosition() 14 | -- Draws the position on screen. 15 | love.graphics.print("The mouse is at (" .. x .. "," .. y .. ")", 50, 50) 16 | end 17 | -------------------------------------------------------------------------------- /examples/009_timing.lua: -------------------------------------------------------------------------------- 1 | -- Example: Timing code 2 | 3 | function love.load() 4 | -- Get time before the code to be timed. 5 | t_start = love.timer.getTime() 6 | 7 | -- Load 10 fonts. 8 | for i=13,22 do 9 | local f = love.graphics.newFont(i) 10 | love.graphics.setFont(f) 11 | end 12 | 13 | -- Get time after. 14 | t_end = love.timer.getTime() 15 | 16 | end 17 | 18 | function love.draw() 19 | love.graphics.print("Spent " .. (t_end-t_start) .. " seconds loading 10 fonts.", 50, 50) 20 | end 21 | -------------------------------------------------------------------------------- /examples/016_image_rot_scale.lua: -------------------------------------------------------------------------------- 1 | -- Example: Rotation and scaling 2 | 3 | angle = 0 4 | 5 | function love.load() 6 | image = love.graphics.newImage("assets/love-ball.png") 7 | end 8 | 9 | function love.update(dt) 10 | angle = angle + dt 11 | x, y = 400 + math.cos(angle)*100, 300 + math.sin(angle)*100 12 | end 13 | 14 | function love.draw() 15 | local rot = angle*180/math.pi 16 | local sx = math.cos(angle)*3 17 | local sy = math.sin(angle)*2 18 | love.graphics.draw(image, x, y, rot, sx, sy, 32, 32) 19 | end 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/006_cursor_visibility.lua: -------------------------------------------------------------------------------- 1 | -- Example: Cursor Visibility 2 | 3 | function love.load() 4 | -- Hide mouse on startup. 5 | love.mouse.setVisible(false) 6 | love.graphics.setFont(love.graphics.newFont(11)) 7 | end 8 | 9 | -- Toggle cursor visibility. 10 | function love.keypressed(k) 11 | if k == "v" then 12 | if love.mouse.isVisible() then 13 | love.mouse.setVisible(false) 14 | else 15 | love.mouse.setVisible(true) 16 | end 17 | end 18 | end 19 | 20 | function love.draw() 21 | love.graphics.print("Press V to toggle visibility.", 50, 50) 22 | end 23 | -------------------------------------------------------------------------------- /examples/014_keyboard_move.lua: -------------------------------------------------------------------------------- 1 | -- Example: Moving stuff with the keyboard 2 | 3 | x, y = 400, 300 4 | 5 | function love.load() 6 | image = love.graphics.newImage("assets/love-ball.png") 7 | end 8 | 9 | function love.update(dt) 10 | if love.keyboard.isDown("left") then 11 | x = x - 100 * dt 12 | end 13 | if love.keyboard.isDown("right") then 14 | x = x + 100 * dt 15 | end 16 | if love.keyboard.isDown("up") then 17 | y = y - 100 * dt 18 | end 19 | if love.keyboard.isDown("down") then 20 | y = y + 100 * dt 21 | end 22 | end 23 | 24 | function love.draw() 25 | love.graphics.draw(image, x, y) 26 | end 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/005_mouse_button.lua: -------------------------------------------------------------------------------- 1 | -- Example: Checking for pressed mouse buttons 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | function love.draw() 8 | -- Left mouse button. 9 | if love.mouse.isDown(1) then 10 | love.graphics.print("Left mouse button is down", 50, 50) 11 | end 12 | 13 | -- Right mouse button. 14 | if love.mouse.isDown(2) then 15 | love.graphics.print("Right mouse button is down", 50, 100) 16 | end 17 | 18 | -- Middle mouse button. 19 | if love.mouse.isDown(3) then 20 | love.graphics.print("Middle mouse button is down", 50, 75) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /examples/104_display_modes.lua: -------------------------------------------------------------------------------- 1 | -- Example: Display modes 2 | -- Author: surtic 3 | 4 | --[[Description: 5 | Author: surtic 6 | Displays supported fullscreen modes 7 | ]] 8 | function love.load() 9 | 10 | love.graphics.setFont(love.graphics.newFont(11)) 11 | 12 | -- Get the display modes. 13 | modes = love.window.getFullscreenModes() 14 | 15 | -- The table looks like this: 16 | -- modes = { 17 | -- { width = 800, height = 600 }, 18 | -- { width = 1024, height = 768 }, 19 | -- } 20 | 21 | end 22 | 23 | function love.draw() 24 | love.graphics.print("Supported modes: ", 50, 50) 25 | for i, mode in ipairs(modes) do 26 | local desc = string.format("mode %d: %dx%d", i, mode.width, mode.height) 27 | love.graphics.print(desc, 50, 50 + i * 20) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /examples/053_callbacks_keyboard.lua: -------------------------------------------------------------------------------- 1 | -- Example: Keyboard callbacks 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | -- Keypressed: Called whenever a key was pressed. 8 | function love.keypressed(key) 9 | -- I don't want to register spaces. 10 | if key ~= "space" then 11 | lastkey = key .. " pressed" 12 | end 13 | end 14 | 15 | -- Keyreleased: Called whenever a key was released. 16 | function love.keyreleased(key) 17 | -- I don't want to register spaces. 18 | if key ~= "space" then 19 | lastkey = key .. " released" 20 | end 21 | end 22 | 23 | 24 | -- Load a font and set the text variable. 25 | function love.load() 26 | lastkey = "nothing" 27 | end 28 | 29 | -- Output the last mouse button which was pressed/released. 30 | function love.draw() 31 | love.graphics.print("Last key: " .. lastkey, 100, 100) 32 | end 33 | -------------------------------------------------------------------------------- /examples/103_filesystem_lines.lua: -------------------------------------------------------------------------------- 1 | -- Example: Line Iterators 2 | -- Updated 0.8.0 by Bartoleo 3 | function love.load() 4 | 5 | -- Set the font. 6 | love.graphics.setFont(love.graphics.newFont(11)) 7 | 8 | -- Store the lines in this table. 9 | lines = {} 10 | 11 | --get height of the current font and reduce by 3 12 | fontheight = love.graphics.getFont():getHeight() - 3 13 | 14 | -- Open the file main.lua and loop through the first 15 | -- 50 lines. 16 | for line in love.filesystem.lines("main.lua") do 17 | table.insert(lines, line) 18 | if #lines >= 50 then break end 19 | end 20 | 21 | end 22 | 23 | function love.draw() 24 | -- Draw the loaded lines. 25 | for i = 1,#lines do 26 | --love.graphics.print(string.format("%03i: ", i) .. lines[i], 50, 50+(i*10)) 27 | -- use new colored printing in 0.10.0 instead 28 | love.graphics.print({{175,3*i,200}, string.format("%03i: ", i) , {255,3*i,175}, lines[i]}, 50, 50+(i*fontheight)) 29 | end 30 | end 31 | 32 | -------------------------------------------------------------------------------- /examples/video_test.lua: -------------------------------------------------------------------------------- 1 | -- Example: Playing a Theora video 2 | 3 | 4 | function love.load() 5 | love.graphics.setFont(love.graphics.newFont(11)) 6 | 7 | -- Load the video from a file, with audio 8 | video = love.graphics.newVideo( "assets/HA-1112-M1LBuchon_flyby.ogg", {true} ) 9 | -- Get video height 10 | videoheight = video:getHeight() 11 | --Lower the volume 12 | video:getSource():setVolume(0.15) 13 | -- Start playing it 14 | video:play() 15 | end 16 | 17 | function love.draw() 18 | 19 | -- We have to draw our video on the screen 20 | love.graphics.draw( video, 50, 100 ) 21 | 22 | -- If the video is not playing or left button is clicked 23 | if not video:isPlaying() or love.mouse.isDown(1) then 24 | -- Rewind to the start 25 | video:seek(0) 26 | -- And play 27 | video:play() 28 | end 29 | 30 | love.graphics.print(string.format("Time: %.1fs", video:tell()), 50, 100 - 12 ) 31 | love.graphics.print("Copyright (c) 2005, Kogo on Wikimedia", 50, 100 + videoheight) 32 | end 33 | 34 | function love.keypressed(k) 35 | if k == "escape" then video:pause() end 36 | end 37 | -------------------------------------------------------------------------------- /examples/019_physics_move_objs_.lua: -------------------------------------------------------------------------------- 1 | -- Example: Moving objects to a specific point 2 | --[[Description: 3 | Move an object to a target point, with acceleration, deceleration (traction) 4 | and a set top speed. 5 | ]] 6 | require ("movements") 7 | x, y = 400, 300 8 | function love.load() 9 | SPEED = 500 10 | ACCELERATION = 250 11 | DECELERATION = 0 12 | image = love.graphics.newImage("assets/love-ball.png") 13 | move=mega.movements.newMove(ACCELERATION,DECELERATION,SPEED,x,y) 14 | end 15 | 16 | function love.draw() 17 | love.graphics.draw(image, x, y) 18 | 19 | love.graphics.print("Left click to change the target.", 50, 50) 20 | love.graphics.print("Right click to stop the image from moving.", 50, 65) 21 | love.graphics.print("Middle click to make the image magically jump to your cursor.", 50, 80) 22 | 23 | if move:isFinished() == true then love.graphics.print("Have some LÖVE, will ya?", 50, 110) end 24 | end 25 | 26 | function love.update(dt) 27 | 28 | if love.mouse.isDown(1) then 29 | move:setTarget(love.mouse.getPosition()) 30 | elseif love.mouse.isDown(3) then 31 | move:setTarget(love.mouse.getPosition()) 32 | move:snapToTarget() 33 | elseif love.mouse.isDown(2) then 34 | move:setTarget(nil) 35 | end 36 | 37 | move:advance(dt) 38 | x,y=move:getPosition() 39 | end 40 | -------------------------------------------------------------------------------- /examples/011_animation.lua: -------------------------------------------------------------------------------- 1 | -- Example: Create and use an Animation 2 | require("animation") 3 | 4 | function newImagePO2(filename) 5 | local source = love.image.newImageData(filename) 6 | local w, h = source:getWidth(), source:getHeight() 7 | 8 | -- Find closest power-of-two. 9 | local wp = math.pow(2, math.ceil(math.log(w)/math.log(2))) 10 | local hp = math.pow(2, math.ceil(math.log(h)/math.log(2))) 11 | 12 | -- Only pad if needed: 13 | if wp ~= w or hp ~= h then 14 | local padded = love.image.newImageData(wp, hp) 15 | padded:paste(source, 0, 0) 16 | return love.graphics.newImage(padded) 17 | end 18 | 19 | return love.graphics.newImage(source) 20 | end 21 | 22 | function love.load() 23 | -- Set a lovely pink background color. 24 | love.graphics.setBackgroundColor(0.96, 0.77, 0.87) 25 | 26 | -- Load the source of the animation. 27 | img = newImagePO2("assets/anim-boogie.png") 28 | 29 | -- Create an animation with a frame size of 32x32 and 30 | -- 0.1s delay betwen each frame. 31 | animation1 = newAnimation(img, 32, 32, 0.1, 6) 32 | end 33 | 34 | function love.update(dt) 35 | -- The animation must be updated so it 36 | -- knows when to change frames. 37 | animation1:update(dt) 38 | end 39 | 40 | function love.draw() 41 | -- Draw the animation the center of the screen. 42 | animation1:draw(400, 300, 0, 1, 1) 43 | end 44 | -------------------------------------------------------------------------------- /examples/017_font_truetype.lua: -------------------------------------------------------------------------------- 1 | -- Example: Using a truetype font 2 | 3 | function love.load() 4 | -- Create a new font with 32pt size and set it as default. 5 | local f = love.graphics.newFont("assets/Grundschrift-Normal.otf", 24) 6 | love.graphics.setFont(f) 7 | end 8 | 9 | text = [[ 10 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, 11 | sed do eiusmod tempor incididunt ut labore et dolore magna 12 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation 13 | ullamco laboris nisi ut aliquip ex ea commodo consequat. 14 | Duis aute irure dolor in reprehenderit in voluptate velit 15 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 16 | occaecat cupidatat non proident, sunt in culpa qui officia 17 | deserunt mollit anim id est laborum. 18 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, 19 | sed do eiusmod tempor incididunt ut labore et dolore magna 20 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation 21 | ullamco laboris nisi ut aliquip ex ea commodo consequat. 22 | Duis aute irure dolor in reprehenderit in voluptate velit 23 | esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 24 | occaecat cupidatat non proident, sunt in culpa qui officia 25 | deserunt mollit anim id est laborum. 26 | ]] 27 | 28 | function love.draw() 29 | -- Print the text 30 | love.graphics.print(text, 50, 50) 31 | end 32 | 33 | -------------------------------------------------------------------------------- /viewcode.lua: -------------------------------------------------------------------------------- 1 | local lexer = require("lexer") 2 | local filename = (...) 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | parsed = {} 6 | fontheight = love.graphics.getFont():getHeight() 7 | 8 | local colors = {keyword = {0,0,1}, string = {0.5,0.5,0.5}, comment = {0,0.5,0}, 9 | number = {1,0.5,0} , iden = {0,0,0}, default = {0,0,0.5}, line={1,0,0}} 10 | 11 | local contents = love.filesystem.read(filename, 4096) 12 | if not contents then 13 | contents = "error loading file" .. filename 14 | return 15 | end 16 | 17 | maxheight=0 --this should help us in the scrolling thingy 18 | for t in contents:gfind("\n") do 19 | maxheight=maxheight+fontheight 20 | end 21 | 22 | contents = contents:gsub("\r", "") 23 | for t,v in lexer.lua(contents, {}, {}) do 24 | table.insert(parsed, colors[t] or colors["default"]) 25 | table.insert(parsed, v) 26 | end 27 | 28 | end 29 | offy=0 30 | function love.draw() 31 | love.graphics.translate(0,offy) 32 | love.graphics.setBackgroundColor({1, 1, 1}) 33 | love.graphics.print(parsed, 10, 20) 34 | end 35 | 36 | function love.wheelmoved(_,y) 37 | y=y*15 38 | height=love.graphics.getHeight() 39 | if maxheight > height then --scrolling up 40 | if y>0 and offy<0 then 41 | offy=offy+y 42 | elseif y<0 and height - offy - 40< maxheight then --scrolling down 43 | offy=offy+y 44 | end 45 | if -offy > maxheight then offy=-maxheight end 46 | if offy > 0 then offy=0 end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /examples/150_shaders.lua: -------------------------------------------------------------------------------- 1 | -- Example: Shaders 2 | -- Author: janwerder 3 | 4 | --[[Description: 5 | Author: janwerder 6 | Draw a desaturation shader with an image on a canvas 7 | Move your mouse up and down to set the strength of the shader 8 | ]] 9 | function love.load() 10 | --load a sample image 11 | image = love.graphics.newImage("assets/love-ball.png") 12 | 13 | -- Create a new canvas to draw the shader and the content on with the size of our window 14 | local sw, sh = love.graphics.getWidth(), love.graphics.getHeight() 15 | canvas = love.graphics.newCanvas(sw, sh) 16 | 17 | --Declare our shader 18 | shader = love.graphics.newShader([[ 19 | extern vec4 tint; 20 | extern number strength; 21 | vec4 effect(vec4 color, Image texture, vec2 tc, vec2 _) 22 | { 23 | color = Texel(texture, tc); 24 | number luma = dot(vec3(0.299f, 0.587f, 0.114f), color.rgb); 25 | return mix(color, tint * luma, strength); 26 | } 27 | ]]) 28 | 29 | --Send an initial value for tint to the shader in the form of a table 30 | shader:send('tint', {1.0,1.0,1.0,1.0}) 31 | end 32 | 33 | function love.update() 34 | --Update the strength of the shader with the height of the mouse y position 35 | local x,y = love.mouse.getPosition() 36 | --"strength" is a variable in the shader itself, that's why we can update it here 37 | shader:send('strength', y/love.graphics.getHeight()) 38 | end 39 | 40 | function love.draw() 41 | --Draw the image to canvas 42 | love.graphics.setCanvas(canvas) 43 | love.graphics.draw(image, 400, 300) 44 | love.graphics.setCanvas() 45 | 46 | --Now set the shader of the canvas to our shader and draw the canvas afterwars 47 | love.graphics.setShader(shader) 48 | love.graphics.draw(canvas,0,0) 49 | love.graphics.setShader() 50 | end 51 | 52 | -------------------------------------------------------------------------------- /examples/100_physics_mini.lua: -------------------------------------------------------------------------------- 1 | -- Example: Mini Physics 2 | -- Updated 0.8.0 by Bartoleo 3 | 4 | function love.load() 5 | 6 | love.graphics.setFont(love.graphics.newFont(11)) 7 | 8 | -- One meter is 32px in physics engine 9 | love.physics.setMeter( 32 ) 10 | 11 | -- Create a world with standard gravity 12 | world = love.physics.newWorld(0, 9.81*32, true) 13 | 14 | -- Create the ground body at (0, 0) static 15 | ground = love.physics.newBody(world, 0, 0, "static") 16 | 17 | -- Create the ground shape at (400,500) with size (600,10). 18 | ground_shape = love.physics.newRectangleShape( 400, 500, 600, 10) 19 | 20 | -- Create fixture between body and shape 21 | ground_fixture = love.physics.newFixture( ground, ground_shape) 22 | 23 | -- Load the image of the ball. 24 | ball = love.graphics.newImage("assets/love-ball.png") 25 | 26 | -- Create a Body for the circle 27 | body = love.physics.newBody(world, 400, 200, "dynamic") 28 | 29 | -- Attatch a shape to the body. 30 | circle_shape = love.physics.newCircleShape( 0,0,32) 31 | 32 | -- Create fixture between body and shape 33 | fixture = love.physics.newFixture( body, circle_shape) 34 | 35 | -- Calculate the mass of the body based on attatched shapes. 36 | -- This gives realistic simulations. 37 | body:setMassData(circle_shape:computeMass( 1 )) 38 | 39 | end 40 | 41 | function love.update(dt) 42 | -- Update the world. 43 | world:update(dt) 44 | end 45 | 46 | function love.draw() 47 | -- Draws the ground. 48 | love.graphics.polygon("line", ground:getWorldPoints(ground_shape:getPoints())) 49 | 50 | -- Draw the circle. 51 | love.graphics.draw(ball,body:getX(), body:getY(), body:getAngle(),1,1,32,32) 52 | 53 | -- Instructions 54 | love.graphics.print("space: Apply a random impulse",5,5) 55 | end 56 | 57 | function love.keypressed(k) 58 | if k == "space" then 59 | -- Apply a random impulse 60 | body:applyLinearImpulse(150-math.random(0, 300),-math.random(0, 1500)) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /examples/052_callbacks_mouse.lua: -------------------------------------------------------------------------------- 1 | -- Example: Mouse callbacks 2 | 3 | function love.load() 4 | love.graphics.setFont(love.graphics.newFont(11)) 5 | end 6 | 7 | -- Mousepressed: Called whenever a mouse button was pressed, 8 | -- passing the button and the x and y coordiante it was pressed at. 9 | function love.mousepressed(x, y, button, istouch) 10 | -- Checks which button was pressed. 11 | local buttonname = "" 12 | if button == 1 then 13 | buttonname = "left" 14 | elseif button == 2 then 15 | buttonname = "right" 16 | elseif button == 3 then 17 | buttonname = "middle" 18 | else 19 | -- Some mice can have more buttons 20 | buttonname = "button" .. button 21 | end 22 | 23 | last = buttonname .. " pressed @ (" .. x .. "x" .. y .. ")" 24 | end 25 | 26 | -- Mousereleased: Called whenever a mouse button was released, 27 | -- passing the button and the x and y coordiante it was released at. 28 | function love.mousereleased(x, y, button, istouch) 29 | -- Checks which button was pressed. 30 | local buttonname = "" 31 | if button == 1 then 32 | buttonname = "left" 33 | elseif button == 2 then 34 | buttonname = "right" 35 | elseif button == 3 then 36 | buttonname = "middle" 37 | else 38 | -- Some mice can have more buttons 39 | buttonname = "button" .. button 40 | end 41 | 42 | last = buttonname .. " released @ (" .. x .. "x" .. y .. ")" 43 | end 44 | 45 | 46 | -- Wheelmoved: Called whenever the mouse wheel moved, 47 | -- passing the x(horizontal) and y(vertical) wheel movement. 48 | function love.wheelmoved( x, y ) 49 | if y > 0 then 50 | lastw = "wheel moved up" 51 | elseif y < 0 then 52 | lastw = "wheel moved down" 53 | elseif x > 0 then 54 | lastw = "wheel moved right" 55 | elseif x < 0 then 56 | lastw = "wheel moved left" 57 | end 58 | end 59 | 60 | -- Load a font 61 | function love.load() 62 | last = "none" 63 | lastw = "none" 64 | end 65 | 66 | -- Output the last mouse button which was pressed/released. 67 | function love.draw() 68 | love.graphics.print("Last mouse click: " .. last, 100, 75) 69 | love.graphics.print("Last wheel move: " .. lastw, 100, 100) 70 | end 71 | -------------------------------------------------------------------------------- /examples/018_physics_fire_at.lua: -------------------------------------------------------------------------------- 1 | -- Example: Firing objects towards mouse 2 | --[[Description: 3 | Uses basic physics formulas to determine each bullet position. 4 | Auto removes off-screen bullets. 5 | ]] 6 | 7 | function love.load() 8 | SPEED = 250 9 | StartPos = {x=250, y=250, width=50, height=50} --The starting point that the bullets are fired from, acts like the shooter. 10 | bullets={} --The table that contains all bullets. 11 | end 12 | 13 | function love.draw() 14 | --Sets the color to red and draws the "bullets". 15 | love.graphics.setColor(1, 0, 0) 16 | 17 | --This loops the whole table to get every bullet. Consider v being the bullet. 18 | for i,v in pairs(bullets) do 19 | love.graphics.circle("fill", v.x, v.y, 4,4) 20 | end 21 | 22 | --Sets the color to white and draws the "player" and writes instructions. 23 | love.graphics.setColor(1, 1, 1) 24 | 25 | love.graphics.print("Left click to fire towards the mouse.", 50, 50) 26 | love.graphics.rectangle("line", StartPos.x, StartPos.y, StartPos.width, StartPos.height) 27 | end 28 | 29 | function love.update(dt) 30 | 31 | if love.mouse.isDown(1) then 32 | --Sets the starting position of the bullet, this code makes the bullets start in the middle of the player. 33 | local startX = StartPos.x + StartPos.width / 2 34 | local startY = StartPos.y + StartPos.height / 2 35 | 36 | local targetX, targetY = love.mouse.getPosition() 37 | 38 | --Basic maths and physics, calculates the angle so the code can calculate deltaX and deltaY later. 39 | local angle = math.atan2((targetY - startY), (targetX - startX)) 40 | 41 | --Creates a new bullet and appends it to the table we created earlier. 42 | newbullet={x=startX,y=startY,angle=angle} 43 | table.insert(bullets,newbullet) 44 | end 45 | 46 | for i,v in pairs(bullets) do 47 | local Dx = SPEED * math.cos(v.angle) --Physics: deltaX is the change in the x direction. 48 | local Dy = SPEED * math.sin(v.angle) 49 | v.x = v.x + (Dx * dt) 50 | v.y = v.y + (Dy * dt) 51 | 52 | --Cleanup code, removes bullets that exceeded the boundries: 53 | 54 | if v.x > love.graphics.getWidth() or 55 | v.y > love.graphics.getHeight() or 56 | v.x < 0 or 57 | v.y < 0 then 58 | table.remove(bullets,i) 59 | end 60 | end 61 | end -------------------------------------------------------------------------------- /examples/101_physics_mini_callbacks.lua: -------------------------------------------------------------------------------- 1 | -- Example: Mini Physics Callbacks 2 | -- Updated 0.8.0 by Bartoleo 3 | 4 | text = "No collision yet." 5 | 6 | function love.load() 7 | 8 | love.graphics.setFont(love.graphics.newFont(11)) 9 | 10 | -- One meter is 32px in physics engine 11 | love.physics.setMeter( 32 ) 12 | 13 | -- Create a world with standard gravity 14 | world = love.physics.newWorld(0, 9.81*32, true) 15 | 16 | -- Create the ground body at (0, 0) static 17 | ground = love.physics.newBody(world, 0, 0, "static") 18 | 19 | -- Create the ground shape at (400,500) with size (600,10). 20 | ground_shape = love.physics.newRectangleShape(400, 500, 600, 10) 21 | 22 | -- Create fixture between body and shape 23 | ground_fixture = love.physics.newFixture( ground, ground_shape) 24 | ground_fixture:setUserData("Ground") -- Set a string userdata 25 | 26 | -- Load the image of the ball. 27 | ball = love.graphics.newImage("assets/love-ball.png") 28 | 29 | -- Create a Body for the circle. 30 | body = love.physics.newBody(world, 400, 200, "dynamic") 31 | 32 | -- Attatch a shape to the body. 33 | circle_shape = love.physics.newCircleShape(0,0, 32) 34 | 35 | -- Create fixture between body and shape 36 | fixture = love.physics.newFixture( body, circle_shape) 37 | 38 | fixture:setUserData("Ball") -- Set a string userdata 39 | 40 | -- Calculate the mass of the body based on attatched shapes. 41 | -- This gives realistic simulations. 42 | body:setMassData(circle_shape:computeMass( 1 )) 43 | 44 | -- Set the collision callback. 45 | world:setCallbacks(beginContact,endContact) 46 | 47 | end 48 | 49 | function love.update(dt) 50 | -- Update the world. 51 | world:update(dt) 52 | end 53 | 54 | function love.draw() 55 | -- Draws the ground. 56 | love.graphics.polygon("line", ground_shape:getPoints()) 57 | 58 | -- Draw the circle. 59 | love.graphics.draw(ball,body:getX(), body:getY(), body:getAngle(),1,1,32,32) 60 | 61 | -- Instructions 62 | love.graphics.print("space: Apply a random impulse",5,5) 63 | 64 | -- Draw text. 65 | love.graphics.print(text, 5, 25) 66 | end 67 | 68 | function love.keypressed(k) 69 | if k == "space" then 70 | -- Apply a random impulse 71 | body:applyLinearImpulse(150-math.random(0, 300),-math.random(0, 1500)) 72 | end 73 | end 74 | 75 | -- This is called every time a collision begin. 76 | function beginContact(a, b, c) 77 | local aa=a:getUserData() 78 | local bb=b:getUserData() 79 | text = "Collided: " .. aa .. " and " .. bb 80 | end 81 | 82 | -- This is called every time a collision end. 83 | function endContact(a, b, c) 84 | local aa=a:getUserData() 85 | local bb=b:getUserData() 86 | text = "Collision ended: " .. aa .. " and " .. bb 87 | end 88 | -------------------------------------------------------------------------------- /movements.lua: -------------------------------------------------------------------------------- 1 | mega = mega or {} 2 | mega.movements={} 3 | 4 | --Defines a new move, you can then store it in a variable 5 | function mega.movements.newMove(acceleration,deceleration,maximumspeed,x1,y1,x2,y2) 6 | 7 | --Movements constansts 8 | local t = { 9 | acc = acceleration or 0, 10 | decc = deceleration or 0, 11 | topspeed = maximumspeed 12 | } 13 | 14 | --This resets the angle, you don't need to call this yourself 15 | --simply calling setPosition or setTarget will take care of this. 16 | function t:setAngle() 17 | if self.targetx == nil or self.targety == nil then return end 18 | local angle = math.atan2((self.targety - self.y), (self.targetx - self.x)) 19 | self.cosangle = math.cos(angle) 20 | self.sinangle = math.sin(angle) 21 | end 22 | 23 | --This makes the object jump and snap to the target, skipping the distance. 24 | function t:snapToTarget() 25 | self.x=self.targetx 26 | self.y=self.targety 27 | self.vel=0 28 | self.finished=true 29 | end 30 | 31 | --Call this every frame from your update function. 32 | function t:advance(dt) 33 | if self.targetx == nil or self.targety == nil then 34 | return 35 | end 36 | local distance = math.sqrt((self.targetx-self.x)^2 + (self.targety-self.y)^2) 37 | if distance < self.vel * dt or self.finished then --we almost reached it, skip the rest 38 | self:snapToTarget() 39 | return 40 | end 41 | local deccDistance --the distance we need to fully stop 42 | if self.decc > 0 then 43 | deccDistance = self.vel^2 / (2 * self.decc) 44 | else 45 | deccDistance = 0 46 | end 47 | 48 | if distance>deccDistance then 49 | self.vel=math.min(self.vel + self.acc * dt, self.topspeed) --we are still far, accelerate (if possible) 50 | else 51 | self.vel=math.max(self.vel - self.decc * dt,0) --we should be stopping 52 | end 53 | if self.vel == 0 then 54 | self:snapToTarget() 55 | return 56 | end 57 | self.x=self.x + self.vel * self.cosangle * dt 58 | self.y=self.y + self.vel * self.sinangle * dt 59 | 60 | self.finished=false 61 | end 62 | 63 | --Resets the velocity to the begining value, usually 0. 64 | function t:resetVelocity() 65 | if self.acc > 0 then self.vel=0 else self.vel=self.topspeed end 66 | end 67 | 68 | --Change the target. 69 | function t:setTarget(x,y) 70 | self.finished=false 71 | self.targetx = x 72 | self.targety = y 73 | if x == nil or y == nil then 74 | self.finished=true 75 | self.vel=0 76 | return 77 | end 78 | self:setAngle() 79 | end 80 | 81 | --A fancy way to get the current position 82 | function t:getPosition() 83 | return self.x, self.y 84 | end 85 | 86 | --If your object changes its position unexpectedly, call this function. 87 | function t:setPosition(x, y) 88 | self.x = x 89 | self.y = y 90 | self:setAngle() 91 | end 92 | 93 | --A fancy way to get if the move is done or not. 94 | function t:isFinished() 95 | return self.finished 96 | end 97 | 98 | 99 | t:setPosition(x1,y1) 100 | t:setTarget(x2,y2) 101 | t:resetVelocity() 102 | 103 | return t 104 | end 105 | -------------------------------------------------------------------------------- /animation.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright (c) 2009 Bart Bes 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | ]] 25 | 26 | local anim_mt = {} 27 | anim_mt.__index = anim_mt 28 | 29 | function newAnimation(image, fw, fh, delay, frames) 30 | local a = {} 31 | a.img = image 32 | a.frames = {} 33 | a.delays = {} 34 | a.timer = 0 35 | a.position = 1 36 | a.fw = fw 37 | a.fh = fh 38 | a.playing = true 39 | a.speed = 1 40 | a.mode = 1 41 | a.direction = 1 42 | local imgw = image:getWidth() 43 | local imgh = image:getHeight() 44 | if frames == 0 then 45 | frames = imgw / fw * imgh / fh 46 | end 47 | local rowsize = imgw/fw 48 | for i = 1, frames do 49 | local row = math.floor(i/rowsize) 50 | local column = i%rowsize 51 | local frame = love.graphics.newQuad(column*fw, row*fh, fw, fh, imgw, imgh) 52 | table.insert(a.frames, frame) 53 | table.insert(a.delays, delay) 54 | end 55 | return setmetatable(a, anim_mt) 56 | end 57 | 58 | function anim_mt:update(dt) 59 | if not self.playing then return end 60 | self.timer = self.timer + dt * self.speed 61 | if self.timer > self.delays[self.position] then 62 | self.timer = self.timer - self.delays[self.position] 63 | self.position = self.position + 1 * self.direction 64 | if self.position > #self.frames then 65 | if self.mode == 1 then 66 | self.position = 1 67 | elseif self.mode == 2 then 68 | self.position = self.position - 1 69 | self:stop() 70 | elseif self.mode == 3 then 71 | self.direction = -1 72 | self.position = self.position - 1 73 | end 74 | elseif self.position < 1 and self.mode == 3 then 75 | self.direction = 1 76 | self.position = self.position + 1 77 | end 78 | end 79 | end 80 | 81 | function anim_mt:draw(x, y, angle, sx, sy) 82 | love.graphics.draw(self.img, self.frames[self.position], x, y, angle, sx, sy) 83 | end 84 | 85 | function anim_mt:addFrame(x, y, w, h, delay) 86 | local frame = love.graphics.newQuad(x, y, w, h, a.img:getWidth(), a.img:getHeight()) 87 | table.insert(self.frames, frame) 88 | table.insert(self.delays, delay) 89 | end 90 | 91 | function anim_mt:play() 92 | self.playing = true 93 | end 94 | 95 | function anim_mt:stop() 96 | self.playing = false 97 | end 98 | 99 | function anim_mt:reset() 100 | self:seek(0) 101 | end 102 | 103 | function anim_mt:seek(frame) 104 | self.position = frame 105 | self.timer = 0 106 | end 107 | 108 | function anim_mt:getCurrentFrame() 109 | return self.position 110 | end 111 | 112 | function anim_mt:getSize() 113 | return #self.frames 114 | end 115 | 116 | function anim_mt:setDelay(frame, delay) 117 | self.delays[frame] = delay 118 | end 119 | 120 | function anim_mt:setSpeed(speed) 121 | self.speed = speed 122 | end 123 | 124 | function anim_mt:getWidth() 125 | return self.frames[self.position]:getWidth() 126 | end 127 | 128 | function anim_mt:getHeight() 129 | return self.frames[self.position]:getHeight() 130 | end 131 | 132 | function anim_mt:setMode(mode) 133 | if mode == "loop" then 134 | self.mode = 1 135 | elseif mode == "once" then 136 | self.mode = 2 137 | elseif mode == "bounce" then 138 | self.mode = 3 139 | end 140 | end 141 | 142 | if Animations_legacy_support then 143 | love.graphics.newAnimation = newAnimation 144 | local oldLGDraw = love.graphics.draw 145 | function love.graphics.draw(item, ...) 146 | if type(item) == "table" and item.draw then 147 | item:draw(...) 148 | else 149 | oldLGDraw(item, ...) 150 | end 151 | end 152 | end 153 | -------------------------------------------------------------------------------- /main.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- EXF: Example Framework 3 | -- 4 | -- This should make examples easier and more enjoyable to use. 5 | -- All examples in one application! Yaay! 6 | -- 7 | -- Updated by Dresenpai 8 | 9 | exf = {} 10 | 11 | local List = require("list") 12 | function love.load() 13 | exf.list = List:new(20, 40, 300, 450) 14 | exf.smallfont = love.graphics.newFont(11) 15 | exf.bigfont = love.graphics.newFont(16) 16 | 17 | exf.bigball = love.graphics.newImage("assets/love-big-ball.png") 18 | 19 | -- Find available demos. 20 | local files = love.filesystem.getDirectoryItems("examples") 21 | local file, contents, title, info, id 22 | local s, e 23 | for i, v in ipairs(files) do 24 | print(v) 25 | --s, e, id = string.find(v, "e(%d%d%d%d)%.lua") 26 | --if id then 27 | file = love.filesystem.newFile("examples/" .. v, love.file_read) 28 | file:open("r") 29 | contents = file:read(1000) 30 | file:close(file) 31 | 32 | s, e, title = string.find(contents, "Example: ([%a%p ]-)[\r\n]") 33 | if not title then title = "Untitled" end 34 | 35 | s, e, info = string.find(contents, "Description:\r?\n?(.-)]]") 36 | if not info then info = "" end 37 | info = info:gsub("\r", "") 38 | 39 | exf.list:add(title, v, info) 40 | --end 41 | end 42 | 43 | exf.list.onclick = function(index, b) 44 | if b==1 then exf.start(index) 45 | elseif b==2 then exf.view(index) end 46 | end 47 | exf.list:done() 48 | exf.resume() 49 | end 50 | 51 | --[[ 52 | function love.update(dt) end 53 | function love.draw() end 54 | function love.keypressed(k) end 55 | function love.keyreleased(k) end 56 | function love.mousepressed(x, y, b, it) end 57 | function love.mousereleased(x, y, b, it) end 58 | function love.mousemoved(x, y, dx, dy) end 59 | function love.wheelmoved(x, y) end 60 | ]] 61 | 62 | function exf.empty() end 63 | exf.callbacks = {"load", "update", "draw", "keypressed", "keyreleased", 64 | "mousepressed", "mousereleased", "mousemoved", "wheelmoved"} 65 | 66 | --for i, v in ipairs(exf.callbacks) do love[v] = exf.empty end 67 | 68 | function exf.update(dt) 69 | exf.list:update(dt) 70 | end 71 | 72 | function exf.draw() 73 | love.graphics.setBackgroundColor(0.21, 0.67, 0.97) 74 | 75 | love.graphics.setColor(1, 1, 1) 76 | love.graphics.setFont(exf.bigfont) 77 | love.graphics.print("Example Browser", 20, 20) 78 | love.graphics.print("Usage:", 20, 500) 79 | 80 | love.graphics.setFont(exf.smallfont) 81 | love.graphics.print("Browse and click on the example you want to run.\n" 82 | .. "Right click if you want to view its code\n" 83 | .. "Press escape to return back to the main screen.", 20, 520) 84 | 85 | 86 | local hitem = exf.list.items[exf.list.hoveritem] 87 | if hitem then 88 | love.graphics.setFont(exf.bigfont) 89 | love.graphics.print("File: " .. hitem.id, 350, 40) 90 | --love.graphics.print("Info:", 350, 60) 91 | love.graphics.setFont(exf.smallfont) 92 | love.graphics.print(hitem.tooltip, 380, 60) 93 | end 94 | 95 | love.graphics.draw(exf.bigball, 800 - 128, 600 - 128) 96 | 97 | love.graphics.setFont(exf.smallfont) 98 | exf.list:draw() 99 | end 100 | 101 | function exf.keypressed(k) 102 | end 103 | 104 | function exf.keyreleased(k) 105 | end 106 | 107 | function exf.mousepressed(x, y, b, it) 108 | exf.list:mousepressed(x, y, b, it) 109 | end 110 | 111 | function exf.mousereleased(x, y, b, it) 112 | exf.list:mousereleased(x, y, b, it) 113 | end 114 | 115 | function exf.mousemoved(x, y) 116 | exf.list:mousemoved(x, y) 117 | end 118 | 119 | function exf.wheelmoved(x, y) 120 | exf.list:wheelmoved(x, y) 121 | end 122 | 123 | function exf.intable(t, e) 124 | for k,v in ipairs(t) do 125 | if v == e then return true end 126 | end 127 | return false 128 | end 129 | 130 | function exf.run(file, title, ...) 131 | -- if not love.filesystem.exists(file) then 132 | if not love.filesystem.getInfo(file) then 133 | print("Could not load file .. " .. file) 134 | return 135 | end 136 | 137 | -- Clear all callbacks. 138 | for i, v in ipairs(exf.callbacks) do love[v] = exf.empty end 139 | 140 | love.filesystem.load(file)(...) 141 | exf.clear() 142 | 143 | love.window.setTitle(title) 144 | 145 | -- Redirect keypress 146 | local o_keypressed = love.keypressed 147 | love.keypressed = function(k) 148 | if k == "escape" then exf.resume() end 149 | o_keypressed(k) 150 | end 151 | love.load() 152 | end 153 | 154 | function exf.start(i) 155 | local item = exf.list.items[i] 156 | if item then 157 | exf.run("examples/" .. item.id, item.id .. " - " .. item.title) 158 | else 159 | print("Example ".. i .. " does not exist.") 160 | end 161 | end 162 | 163 | function exf.view(i) 164 | local item = exf.list.items[i] 165 | if item then 166 | exf.run("viewcode.lua", "Contents of " .. item.id .. " - " .. item.title, "examples/" .. item.id) 167 | else 168 | print("Example ".. i .. " does not exist.") 169 | end 170 | end 171 | 172 | 173 | function exf.clear() 174 | love.graphics.setBackgroundColor(0, 0, 0) 175 | love.graphics.setColor(1, 1, 1) 176 | love.graphics.setLineWidth(1) 177 | love.graphics.setLineStyle("smooth") 178 | love.graphics.setBlendMode("alpha") 179 | love.mouse.setVisible(true) 180 | end 181 | 182 | function exf.resume() 183 | load = nil 184 | -- Reattach callbacks 185 | for i, v in ipairs(exf.callbacks) do love[v] = exf[v] end 186 | 187 | love.mouse.setVisible(true) 188 | love.mouse.setCursor() 189 | love.window.setTitle("LOVE Example Browser") 190 | 191 | end 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /examples/102_physics_adv.lua: -------------------------------------------------------------------------------- 1 | -- Example: Physics 2 | -- Grabbity by Xcmd 3 | -- Updated by Dresenpai 4 | -- Updated 0.8.0 by Bartoleo 5 | math.randomseed( os.time() ) 6 | 7 | function love.load() 8 | 9 | love.graphics.setFont(love.graphics.newFont(11)) 10 | 11 | love.physics.setMeter( 32 ) 12 | myWorld = love.physics.newWorld(0, 9.81*32, true) -- updated Arguments for new variant of newWorld in 0.8.0 13 | gravity="down" 14 | myWorld:setCallbacks( beginContact, endContact, preSolve, postSolve ) 15 | 16 | myBallBody = love.physics.newBody( myWorld, 300, 400 ,"dynamic" ) 17 | myBallShape = love.physics.newCircleShape( 0, 0, 16 ) 18 | myBallFixture = love.physics.newFixture(myBallBody, myBallShape) 19 | myBallBody:setMassData(0,0,1,0) 20 | myBallFixture:setUserData("ball") 21 | 22 | myWinBody = love.physics.newBody( myWorld, math.floor(math.random(100, 700)), math.floor(math.random(100, 500)) ,"dynamic" ) 23 | myWinShape = love.physics.newRectangleShape( 0, 0, 16, 16, 0 ) 24 | myWinFixture = love.physics.newFixture(myWinBody, myWinShape) 25 | myWinFixture:setUserData("win") 26 | 27 | myEdgeBody1 = love.physics.newBody( myWorld, 0,0 ,"static") 28 | myEdgeShape1 = love.physics.newEdgeShape( 10,10, 790,10 ) 29 | myEdgeFixture1 = love.physics.newFixture(myEdgeBody1, myEdgeShape1) 30 | myEdgeFixture1:setUserData("edge1") 31 | 32 | myEdgeBody2 = love.physics.newBody( myWorld, 0,0 ,"static") 33 | myEdgeShape2 = love.physics.newEdgeShape( 790,10, 790,590 ) 34 | myEdgeFixture2 = love.physics.newFixture(myEdgeBody2, myEdgeShape2) 35 | myEdgeFixture2:setUserData("edge2") 36 | 37 | myEdgeBody3 = love.physics.newBody( myWorld, 0,0 ,"static") 38 | myEdgeShape3 = love.physics.newEdgeShape( 10,590, 790,590 ) 39 | myEdgeFixture3 = love.physics.newFixture(myEdgeBody3, myEdgeShape3) 40 | myEdgeFixture3:setUserData("edge3") 41 | 42 | myEdgeBody4 = love.physics.newBody( myWorld, 0,0 ,"static") 43 | myEdgeShape4 = love.physics.newEdgeShape( 10,10, 10,590 ) 44 | myEdgeFixture4 = love.physics.newFixture(myEdgeBody4, myEdgeShape4) 45 | myEdgeFixture4:setUserData("edge4") 46 | 47 | texts = {} 48 | 49 | prepostsolve = false 50 | 51 | end 52 | 53 | function love.update( dt ) 54 | myWorld:update( dt ) 55 | end 56 | 57 | function love.draw() 58 | love.graphics.line(myEdgeBody1:getWorldPoints(myEdgeShape1:getPoints())) 59 | love.graphics.line(myEdgeBody2:getWorldPoints(myEdgeShape2:getPoints())) 60 | love.graphics.line(myEdgeBody3:getWorldPoints(myEdgeShape3:getPoints())) 61 | love.graphics.line(myEdgeBody4:getWorldPoints(myEdgeShape4:getPoints())) 62 | love.graphics.circle("line", myBallBody:getX(), myBallBody:getY(), myBallShape:getRadius()) 63 | love.graphics.polygon("fill", myWinBody:getWorldPoints(myWinShape:getPoints())) 64 | love.graphics.print( "gravity:"..gravity, 25, 25 ) 65 | if prepostsolve then 66 | love.graphics.print( "space : disable preSolve/postSolve Logging", 400, 25 ) 67 | else 68 | love.graphics.print( "space : enable preSolve/postSolve Logging", 400, 25 ) 69 | end 70 | love.graphics.print( "arrows : change gravity direction", 400, 36 ) 71 | if #texts > 48 then 72 | table.remove(texts,1) 73 | end 74 | if #texts > 96 then 75 | table.remove(texts,1) 76 | end 77 | for i,v in ipairs(texts) do 78 | love.graphics.print( v, 25, 37+11*i ) 79 | end 80 | end 81 | 82 | function love.keypressed( key ) 83 | if key == "up" then 84 | myWorld:setGravity(0, -9.81*32) 85 | gravity="up" 86 | for i,v in ipairs(myWorld:getBodies( )) do 87 | v:setAwake( true ) 88 | end 89 | elseif key == "down" then 90 | myWorld:setGravity(0, 9.81*32) 91 | gravity="down" 92 | for i,v in ipairs(myWorld:getBodies( )) do 93 | v:setAwake( true ) 94 | end 95 | elseif key == "left" then 96 | myWorld:setGravity(-9.81*32, 0) 97 | gravity="left" 98 | for i,v in ipairs(myWorld:getBodies( )) do 99 | v:setAwake( true ) 100 | end 101 | elseif key == "right" then 102 | myWorld:setGravity(9.81*32, 0) 103 | gravity="right" 104 | for i,v in ipairs(myWorld:getBodies( )) do 105 | v:setAwake( true ) 106 | end 107 | end 108 | 109 | if key == "space" then 110 | prepostsolve = not prepostsolve 111 | end 112 | 113 | if key == "r" then 114 | love.load() 115 | end 116 | end 117 | 118 | function beginContact( a, b, c ) 119 | coll( a, b, c, "beginContact",true ) 120 | end 121 | 122 | function endContact( a, b, c ) 123 | coll( a, b, c, "endContact",true ) 124 | end 125 | 126 | function preSolve( a, b, c ) 127 | if prepostsolve then 128 | coll( a, b, c, "preSolve",false ) 129 | end 130 | end 131 | 132 | function postSolve( a, b, c ) 133 | if prepostsolve then 134 | coll( a, b, c, "postSolve",false ) 135 | end 136 | end 137 | 138 | local function ifnil(ptest,preturn) 139 | if p==nil then 140 | return preturn 141 | end 142 | return ptest 143 | end 144 | 145 | function coll( a, b, c, ctype,detail ) 146 | 147 | local f, r = c:getFriction(), c:getRestitution() 148 | --local s = c:getSeparation() 149 | local px1, py1, px2, py2 = c:getPositions() 150 | --local vx, vy = c:getVelocity() 151 | local nx, ny = c:getNormal() 152 | local aa = a:getUserData() 153 | local bb = b:getUserData() 154 | 155 | table.insert(texts, ctype .. " Collision : " .. aa .. " and " .. bb) 156 | if detail then 157 | table.insert(texts, "Position: " .. ifnil(px1,"nil") .. "," .. ifnil(py1,"nil") .. "," .. ifnil(px2,"nil") .. "," .. ifnil(py2,"nil") ) 158 | --table.insert(texts, "Velocity: " .. vx .. "," .. vy ) 159 | table.insert(texts, "Normal: " .. nx .. "," .. ny ) 160 | table.insert(texts, "Friction: " .. f ) 161 | table.insert(texts, "Restitution: " .. r ) 162 | --table.insert(texts, "Separation: " .. s ) 163 | end 164 | table.insert(texts, "") 165 | end 166 | 167 | -------------------------------------------------------------------------------- /list.lua: -------------------------------------------------------------------------------- 1 | ---------------------- 2 | -- List object 3 | ---------------------- 4 | 5 | local List = {} 6 | 7 | function inside(mx, my, x, y, w, h) 8 | return mx >= x and mx <= (x+w) and my >= y and my <= (y+h) 9 | end 10 | 11 | function List:new(x, y, w, h) 12 | o = {} 13 | setmetatable(o, self) 14 | self.__index = self 15 | 16 | o.items = {} 17 | o.hoveritem = 0 18 | o.onclick = nil 19 | 20 | o.x = x 21 | o.y = y 22 | 23 | o.width = w 24 | o.height = h 25 | 26 | o.item_height = 23 27 | o.sum_item_height = 0 28 | 29 | o.bar = { size = 20, pos = 0, maxpos = 0, width = 15, lock = nil} 30 | 31 | o.colors = {} 32 | o.colors.normal = {bg = {0.19, 0.61, 0.88}, fg = {0.77, 0.91, 1}} 33 | o.colors.hover = {bg = {0.28, 0.51, 0.66}, fg = {1, 1, 1}} 34 | o.windowcolor = {0.19, 0.61, 0.88} 35 | o.bordercolor = {0.28, 0.51, 0.66} 36 | return o 37 | end 38 | 39 | function List:add(title, id, tooltip) 40 | local item = {} 41 | item.title = title 42 | item.id = id 43 | if type(tooltip) == "string" then 44 | item.tooltip = tooltip 45 | else 46 | item.tooltip = "" 47 | end 48 | table.insert(self.items, item) 49 | end 50 | 51 | function List:done() 52 | 53 | self.items.n = #self.items 54 | 55 | -- Recalc bar size. 56 | self.bar.pos = 0 57 | 58 | local num_items = (self.height/self.item_height) 59 | local ratio = num_items/self.items.n 60 | self.bar.size = self.height * ratio 61 | self.bar.maxpos = self.height - self.bar.size - 3 62 | 63 | -- Calculate height of everything. 64 | self.sum_item_height = (self.item_height+1) * self.items.n + 2 65 | 66 | end 67 | 68 | function List:hasBar() 69 | return self.sum_item_height > self.height 70 | end 71 | 72 | function List:getBarRatio() 73 | return self.bar.pos / self.bar.maxpos 74 | end 75 | 76 | function List:getOffset() 77 | local ratio = self.bar.pos / self.bar.maxpos 78 | return math.floor((self.sum_item_height - self.height) * ratio + 0.5) 79 | end 80 | 81 | function List:update(dt) 82 | if self.bar.lock then 83 | local dy = math.floor(love.mouse.getY()-self.bar.lock.y+0.5) 84 | self.bar.pos = self.bar.pos + dy 85 | 86 | if self.bar.pos < 0 then 87 | self.bar.pos = 0 88 | elseif self.bar.pos > self.bar.maxpos then 89 | self.bar.pos = self.bar.maxpos 90 | end 91 | 92 | self.bar.lock.y = love.mouse.getY() 93 | 94 | end 95 | end 96 | 97 | function List:mousepressed(x, y, b, it) 98 | if b == 1 and self:hasBar() then 99 | local rx, ry, rw, rh = self:getBarRect() 100 | if inside(x, y, rx, ry, rw, rh) then 101 | self.bar.lock = { x = x, y = y } 102 | return 103 | end 104 | end 105 | 106 | if type(self.onclick) ~= "function" then return end 107 | 108 | if inside(x, y, self.x + 2, self.y + 1, self.width - 3, self.height - 3) then 109 | local tx, ty = x - self.x, y + self:getOffset() - self.y 110 | local index = math.floor((ty / self.sum_item_height) * self.items.n) 111 | local item = self.items[index + 1] 112 | if item then 113 | self.onclick(index + 1, b) 114 | end 115 | end 116 | end 117 | 118 | function List:mousereleased(x, y, b, it) 119 | if b == 1 and self:hasBar() then 120 | self.bar.lock = nil 121 | end 122 | end 123 | 124 | function List:mousemoved(x, y, dx, dy) 125 | self.hoveritem = 0 126 | 127 | if self:hasBar() then 128 | local rx, ry, rw, rh = self:getBarRect() 129 | if inside(x, y, rx, ry, rw, rh) then 130 | self.hoveritem = -1 131 | return 132 | end 133 | end 134 | 135 | if inside(x, y, self.x + 2, self.y + 1, self.width - 3, self.height - 3) then 136 | local tx, ty = x - self.x, y + self:getOffset() - self.y 137 | local index = math.floor((ty / self.sum_item_height) * self.items.n) 138 | self.hoveritem = index + 1 139 | end 140 | end 141 | 142 | function List:wheelmoved(x, y) 143 | if self:hasBar() then 144 | local per_pixel = (self.sum_item_height - self.height) / self.bar.maxpos 145 | local bar_pixel_dt = math.floor((self.item_height * 3) / per_pixel + 0.5) 146 | 147 | self.bar.pos = self.bar.pos - y * bar_pixel_dt 148 | if self.bar.pos > self.bar.maxpos then self.bar.pos = self.bar.maxpos end 149 | if self.bar.pos < 0 then self.bar.pos = 0 end 150 | end 151 | end 152 | 153 | function List:getBarRect() 154 | return self.x + self.width + 2, self.y + self.bar.pos + 1, 155 | self.bar.width - 3, self.bar.size 156 | end 157 | 158 | function List:getItemRect(i) 159 | return self.x + 2, self.y + ((self.item_height + 1) * (i - 1) + 1) - self:getOffset(), 160 | self.width - 3, self.item_height 161 | end 162 | 163 | function List:draw() 164 | love.graphics.setLineWidth(1) 165 | love.graphics.setLineStyle("rough") 166 | love.graphics.setColor(self.windowcolor) 167 | 168 | -- Get interval to display 169 | local start_i = math.floor(self:getOffset() / (self.item_height + 1)) + 1 170 | local end_i = start_i + math.floor(self.height / (self.item_height + 1)) + 1 171 | if end_i > self.items.n then end_i = self.items.n end 172 | 173 | love.graphics.setScissor(self.x, self.y, self.width, self.height) 174 | 175 | -- Items 176 | local rx, ry, rw, rh 177 | local colorset 178 | for i = start_i,end_i do 179 | if i == self.hoveritem then 180 | colorset = self.colors.hover 181 | else 182 | colorset = self.colors.normal 183 | end 184 | 185 | rx, ry, rw, rh = self:getItemRect(i) 186 | love.graphics.setColor(colorset.bg) 187 | love.graphics.rectangle("fill", rx, ry, rw, rh) 188 | 189 | love.graphics.setColor(colorset.fg) 190 | love.graphics.print(self.items[i].title, rx + 10, ry + 5) 191 | 192 | end 193 | 194 | love.graphics.setScissor() 195 | 196 | -- Bar 197 | if self:hasBar() then 198 | if self.hoveritem == -1 or self.bar.lock then 199 | colorset = self.colors.hover 200 | else 201 | colorset = self.colors.normal 202 | end 203 | 204 | rx, ry, rw, rh = self:getBarRect() 205 | love.graphics.setColor(colorset.bg) 206 | love.graphics.rectangle("fill", rx, ry, rw, rh) 207 | end 208 | 209 | -- Border 210 | love.graphics.setColor(self.bordercolor) 211 | love.graphics.rectangle("line", self.x + self.width, self.y, self.bar.width, self.height) 212 | love.graphics.rectangle("line", self.x, self.y, self.width, self.height) 213 | 214 | end 215 | 216 | 217 | return List 218 | -------------------------------------------------------------------------------- /lexer.lua: -------------------------------------------------------------------------------- 1 | --lexer.lua is part of Penlight http://stevedonovan.github.com/Penlight/ 2 | --[[ 3 | Copyright (C) 2009 Steve Donovan, David Manura. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 14 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 15 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 16 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | ]] 18 | 19 | --- Lexical scanner for creating a sequence of tokens from text. 20 | -- `lexer.scan(s)` returns an iterator over all tokens found in the 21 | -- string `s`. This iterator returns two values, a token type string 22 | -- (such as 'string' for quoted string, 'iden' for identifier) and the value of the 23 | -- token. 24 | -- 25 | -- Versions specialized for Lua and C are available; these also handle block comments 26 | -- and classify keywords as 'keyword' tokens. For example: 27 | -- 28 | -- > s = 'for i=1,n do' 29 | -- > for t,v in lexer.lua(s) do print(t,v) end 30 | -- keyword for 31 | -- iden i 32 | -- = = 33 | -- number 1 34 | -- , , 35 | -- iden n 36 | -- keyword do 37 | -- 38 | -- See the Guide for further @{06-data.md.Lexical_Scanning|discussion} 39 | -- @module pl.lexer 40 | 41 | local yield,wrap = coroutine.yield,coroutine.wrap 42 | local strfind = string.find 43 | local strsub = string.sub 44 | local append = table.insert 45 | 46 | local function assert_arg(idx,val,tp) 47 | if type(val) ~= tp then 48 | error("argument "..idx.." must be "..tp, 2) 49 | end 50 | end 51 | 52 | local lexer = {} 53 | 54 | local NUMBER1 = '^[%+%-]?%d+%.?%d*[eE][%+%-]?%d+' 55 | local NUMBER2 = '^[%+%-]?%d+%.?%d*' 56 | local NUMBER3 = '^0x[%da-fA-F]+' 57 | local NUMBER4 = '^%d+%.?%d*[eE][%+%-]?%d+' 58 | local NUMBER5 = '^%d+%.?%d*' 59 | local IDEN = '^[%a_][%w_]*' 60 | local WSPACE = '^%s+' 61 | local STRING1 = "^(['\"])%1" -- empty string 62 | local STRING2 = [[^(['"])(\*)%2%1]] 63 | local STRING3 = [[^(['"]).-[^\](\*)%2%1]] 64 | local CHAR1 = "^''" 65 | local CHAR2 = [[^'(\*)%1']] 66 | local CHAR3 = [[^'.-[^\](\*)%1']] 67 | local PREPRO = '^#.-[^\\]\n' 68 | 69 | local plain_matches,lua_matches,cpp_matches,lua_keyword,cpp_keyword 70 | 71 | local function tdump(tok) 72 | return yield(tok,tok) 73 | end 74 | 75 | local function ndump(tok,options) 76 | if options and options.number then 77 | tok = tonumber(tok) 78 | end 79 | return yield("number",tok) 80 | end 81 | 82 | -- regular strings, single or double quotes; usually we want them 83 | -- without the quotes 84 | local function sdump(tok,options) 85 | if options and options.string then 86 | tok = tok:sub(2,-2) 87 | end 88 | return yield("string",tok) 89 | end 90 | 91 | -- long Lua strings need extra work to get rid of the quotes 92 | local function sdump_l(tok,options,findres) 93 | if options and options.string then 94 | local quotelen = 3 95 | if findres[3] then 96 | quotelen = quotelen + findres[3]:len() 97 | end 98 | tok = tok:sub(quotelen, -quotelen) 99 | if tok:sub(1, 1) == "\n" then 100 | tok = tok:sub(2) 101 | end 102 | end 103 | return yield("string",tok) 104 | end 105 | 106 | local function chdump(tok,options) 107 | if options and options.string then 108 | tok = tok:sub(2,-2) 109 | end 110 | return yield("char",tok) 111 | end 112 | 113 | local function cdump(tok) 114 | return yield('comment',tok) 115 | end 116 | 117 | local function wsdump (tok) 118 | return yield("space",tok) 119 | end 120 | 121 | local function pdump (tok) 122 | return yield('prepro',tok) 123 | end 124 | 125 | local function plain_vdump(tok) 126 | return yield("iden",tok) 127 | end 128 | 129 | local function lua_vdump(tok) 130 | if lua_keyword[tok] then 131 | return yield("keyword",tok) 132 | else 133 | return yield("iden",tok) 134 | end 135 | end 136 | 137 | local function cpp_vdump(tok) 138 | if cpp_keyword[tok] then 139 | return yield("keyword",tok) 140 | else 141 | return yield("iden",tok) 142 | end 143 | end 144 | 145 | --- create a plain token iterator from a string or file-like object. 146 | -- @tparam string|file s a string or a file-like object with `:read()` method returning lines. 147 | -- @tab matches an optional match table - array of token descriptions. 148 | -- A token is described by a `{pattern, action}` pair, where `pattern` should match 149 | -- token body and `action` is a function called when a token of described type is found. 150 | -- @tab[opt] filter a table of token types to exclude, by default `{space=true}` 151 | -- @tab[opt] options a table of options; by default, `{number=true,string=true}`, 152 | -- which means convert numbers and strip string quotes. 153 | function lexer.scan(s,matches,filter,options) 154 | local file = type(s) ~= 'string' and s 155 | filter = filter or {space=true} 156 | options = options or {number=true,string=true} 157 | if filter then 158 | if filter.space then filter[wsdump] = true end 159 | if filter.comments then 160 | filter[cdump] = true 161 | end 162 | end 163 | if not matches then 164 | if not plain_matches then 165 | plain_matches = { 166 | {WSPACE,wsdump}, 167 | {NUMBER3,ndump}, 168 | {IDEN,plain_vdump}, 169 | {NUMBER1,ndump}, 170 | {NUMBER2,ndump}, 171 | {STRING1,sdump}, 172 | {STRING2,sdump}, 173 | {STRING3,sdump}, 174 | {'^.',tdump} 175 | } 176 | end 177 | matches = plain_matches 178 | end 179 | local function lex() 180 | local line_nr = 0 181 | local next_line = file and file:read() 182 | local sz = file and 0 or #s 183 | local idx = 1 184 | 185 | while true do 186 | if idx > sz then 187 | if file then 188 | if not next_line then return end 189 | s = next_line 190 | line_nr = line_nr + 1 191 | next_line = file:read() 192 | if next_line then 193 | s = s .. '\n' 194 | end 195 | idx, sz = 1, #s 196 | else 197 | return 198 | end 199 | end 200 | 201 | for _,m in ipairs(matches) do 202 | local pat = m[1] 203 | local fun = m[2] 204 | local findres = {strfind(s,pat,idx)} 205 | local i1, i2 = findres[1], findres[2] 206 | if i1 then 207 | local tok = strsub(s,i1,i2) 208 | idx = i2 + 1 209 | local res 210 | if not (filter and filter[fun]) then 211 | lexer.finished = idx > sz 212 | res = fun(tok, options, findres) 213 | end 214 | if res then 215 | local tp = type(res) 216 | -- insert a token list 217 | if tp == 'table' then 218 | yield('','') 219 | for _,t in ipairs(res) do 220 | yield(t[1],t[2]) 221 | end 222 | elseif tp == 'string' then -- or search up to some special pattern 223 | i1,i2 = strfind(s,res,idx) 224 | if i1 then 225 | tok = strsub(s,i1,i2) 226 | idx = i2 + 1 227 | yield('',tok) 228 | else 229 | yield('','') 230 | idx = sz + 1 231 | end 232 | else 233 | yield(line_nr,idx) 234 | end 235 | end 236 | 237 | break 238 | end 239 | end 240 | end 241 | end 242 | return wrap(lex) 243 | end 244 | 245 | local function isstring (s) 246 | return type(s) == 'string' 247 | end 248 | 249 | --- insert tokens into a stream. 250 | -- @param tok a token stream 251 | -- @param a1 a string is the type, a table is a token list and 252 | -- a function is assumed to be a token-like iterator (returns type & value) 253 | -- @string a2 a string is the value 254 | function lexer.insert (tok,a1,a2) 255 | if not a1 then return end 256 | local ts 257 | if isstring(a1) and isstring(a2) then 258 | ts = {{a1,a2}} 259 | elseif type(a1) == 'function' then 260 | ts = {} 261 | for t,v in a1() do 262 | append(ts,{t,v}) 263 | end 264 | else 265 | ts = a1 266 | end 267 | tok(ts) 268 | end 269 | 270 | --- get everything in a stream upto a newline. 271 | -- @param tok a token stream 272 | -- @return a string 273 | function lexer.getline (tok) 274 | local t,v = tok('.-\n') 275 | return v 276 | end 277 | 278 | --- get current line number. 279 | -- Only available if the input source is a file-like object. 280 | -- @param tok a token stream 281 | -- @return the line number and current column 282 | function lexer.lineno (tok) 283 | return tok(0) 284 | end 285 | 286 | --- get the rest of the stream. 287 | -- @param tok a token stream 288 | -- @return a string 289 | function lexer.getrest (tok) 290 | local t,v = tok('.+') 291 | return v 292 | end 293 | 294 | --- get the Lua keywords as a set-like table. 295 | -- So `res["and"]` etc would be `true`. 296 | -- @return a table 297 | function lexer.get_keywords () 298 | if not lua_keyword then 299 | lua_keyword = { 300 | ["and"] = true, ["break"] = true, ["do"] = true, 301 | ["else"] = true, ["elseif"] = true, ["end"] = true, 302 | ["false"] = true, ["for"] = true, ["function"] = true, 303 | ["if"] = true, ["in"] = true, ["local"] = true, ["nil"] = true, 304 | ["not"] = true, ["or"] = true, ["repeat"] = true, 305 | ["return"] = true, ["then"] = true, ["true"] = true, 306 | ["until"] = true, ["while"] = true 307 | } 308 | end 309 | return lua_keyword 310 | end 311 | 312 | --- create a Lua token iterator from a string or file-like object. 313 | -- Will return the token type and value. 314 | -- @string s the string 315 | -- @tab[opt] filter a table of token types to exclude, by default `{space=true,comments=true}` 316 | -- @tab[opt] options a table of options; by default, `{number=true,string=true}`, 317 | -- which means convert numbers and strip string quotes. 318 | function lexer.lua(s,filter,options) 319 | filter = filter or {space=true,comments=true} 320 | lexer.get_keywords() 321 | if not lua_matches then 322 | lua_matches = { 323 | {WSPACE,wsdump}, 324 | {NUMBER3,ndump}, 325 | {IDEN,lua_vdump}, 326 | {NUMBER4,ndump}, 327 | {NUMBER5,ndump}, 328 | {STRING1,sdump}, 329 | {STRING2,sdump}, 330 | {STRING3,sdump}, 331 | {'^%-%-%[(=*)%[.-%]%1%]',cdump}, 332 | {'^%-%-.-\n',cdump}, 333 | {'^%[(=*)%[.-%]%1%]',sdump_l}, 334 | {'^==',tdump}, 335 | {'^~=',tdump}, 336 | {'^<=',tdump}, 337 | {'^>=',tdump}, 338 | {'^%.%.%.',tdump}, 339 | {'^%.%.',tdump}, 340 | {'^.',tdump} 341 | } 342 | end 343 | return lexer.scan(s,lua_matches,filter,options) 344 | end 345 | 346 | --- create a C/C++ token iterator from a string or file-like object. 347 | -- Will return the token type type and value. 348 | -- @string s the string 349 | -- @tab[opt] filter a table of token types to exclude, by default `{space=true,comments=true}` 350 | -- @tab[opt] options a table of options; by default, `{number=true,string=true}`, 351 | -- which means convert numbers and strip string quotes. 352 | function lexer.cpp(s,filter,options) 353 | filter = filter or {space=true,comments=true} 354 | if not cpp_keyword then 355 | cpp_keyword = { 356 | ["class"] = true, ["break"] = true, ["do"] = true, ["sizeof"] = true, 357 | ["else"] = true, ["continue"] = true, ["struct"] = true, 358 | ["false"] = true, ["for"] = true, ["public"] = true, ["void"] = true, 359 | ["private"] = true, ["protected"] = true, ["goto"] = true, 360 | ["if"] = true, ["static"] = true, ["const"] = true, ["typedef"] = true, 361 | ["enum"] = true, ["char"] = true, ["int"] = true, ["bool"] = true, 362 | ["long"] = true, ["float"] = true, ["true"] = true, ["delete"] = true, 363 | ["double"] = true, ["while"] = true, ["new"] = true, 364 | ["namespace"] = true, ["try"] = true, ["catch"] = true, 365 | ["switch"] = true, ["case"] = true, ["extern"] = true, 366 | ["return"] = true,["default"] = true,['unsigned'] = true,['signed'] = true, 367 | ["union"] = true, ["volatile"] = true, ["register"] = true,["short"] = true, 368 | } 369 | end 370 | if not cpp_matches then 371 | cpp_matches = { 372 | {WSPACE,wsdump}, 373 | {PREPRO,pdump}, 374 | {NUMBER3,ndump}, 375 | {IDEN,cpp_vdump}, 376 | {NUMBER4,ndump}, 377 | {NUMBER5,ndump}, 378 | {CHAR1,chdump}, 379 | {CHAR2,chdump}, 380 | {CHAR3,chdump}, 381 | {STRING1,sdump}, 382 | {STRING2,sdump}, 383 | {STRING3,sdump}, 384 | {'^//.-\n',cdump}, 385 | {'^/%*.-%*/',cdump}, 386 | {'^==',tdump}, 387 | {'^!=',tdump}, 388 | {'^<=',tdump}, 389 | {'^>=',tdump}, 390 | {'^->',tdump}, 391 | {'^&&',tdump}, 392 | {'^||',tdump}, 393 | {'^%+%+',tdump}, 394 | {'^%-%-',tdump}, 395 | {'^%+=',tdump}, 396 | {'^%-=',tdump}, 397 | {'^%*=',tdump}, 398 | {'^/=',tdump}, 399 | {'^|=',tdump}, 400 | {'^%^=',tdump}, 401 | {'^::',tdump}, 402 | {'^.',tdump} 403 | } 404 | end 405 | return lexer.scan(s,cpp_matches,filter,options) 406 | end 407 | 408 | --- get a list of parameters separated by a delimiter from a stream. 409 | -- @param tok the token stream 410 | -- @string[opt=')'] endtoken end of list. Can be '\n' 411 | -- @string[opt=','] delim separator 412 | -- @return a list of token lists. 413 | function lexer.get_separated_list(tok,endtoken,delim) 414 | endtoken = endtoken or ')' 415 | delim = delim or ',' 416 | local parm_values = {} 417 | local level = 1 -- used to count ( and ) 418 | local tl = {} 419 | local function tappend (tl,t,val) 420 | val = val or t 421 | append(tl,{t,val}) 422 | end 423 | local is_end 424 | if endtoken == '\n' then 425 | is_end = function(t,val) 426 | return t == 'space' and val:find '\n' 427 | end 428 | else 429 | is_end = function (t) 430 | return t == endtoken 431 | end 432 | end 433 | local token,value 434 | while true do 435 | token,value=tok() 436 | if not token then return nil,'EOS' end -- end of stream is an error! 437 | if is_end(token,value) and level == 1 then 438 | append(parm_values,tl) 439 | break 440 | elseif token == '(' then 441 | level = level + 1 442 | tappend(tl,'(') 443 | elseif token == ')' then 444 | level = level - 1 445 | if level == 0 then -- finished with parm list 446 | append(parm_values,tl) 447 | break 448 | else 449 | tappend(tl,')') 450 | end 451 | elseif token == delim and level == 1 then 452 | append(parm_values,tl) -- a new parm 453 | tl = {} 454 | else 455 | tappend(tl,token,value) 456 | end 457 | end 458 | return parm_values,{token,value} 459 | end 460 | 461 | --- get the next non-space token from the stream. 462 | -- @param tok the token stream. 463 | function lexer.skipws (tok) 464 | local t,v = tok() 465 | while t == 'space' do 466 | t,v = tok() 467 | end 468 | return t,v 469 | end 470 | 471 | local skipws = lexer.skipws 472 | 473 | --- get the next token, which must be of the expected type. 474 | -- Throws an error if this type does not match! 475 | -- @param tok the token stream 476 | -- @string expected_type the token type 477 | -- @bool no_skip_ws whether we should skip whitespace 478 | function lexer.expecting (tok,expected_type,no_skip_ws) 479 | assert_arg(1,tok,'function') 480 | assert_arg(2,expected_type,'string') 481 | local t,v 482 | if no_skip_ws then 483 | t,v = tok() 484 | else 485 | t,v = skipws(tok) 486 | end 487 | if t ~= expected_type then error ("expecting "..expected_type,2) end 488 | return v 489 | end 490 | 491 | return lexer 492 | -------------------------------------------------------------------------------- /assets/love_osx_inner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 968 | 969 | 970 | 972 | 973 | 974 | 975 | --------------------------------------------------------------------------------