├── Episode 1 ├── README.md ├── conf.lua ├── main.lua ├── player.lua └── run.bat ├── Episode 2 ├── README.md ├── ball.lua ├── conf.lua ├── main.lua ├── player.lua └── run.bat ├── Episode 3 ├── README.md ├── ai.lua ├── ball.lua ├── conf.lua ├── main.lua ├── player.lua └── run.bat ├── Episode 4 ├── README.md └── assets │ ├── 1.png │ ├── 2.png │ ├── ball.png │ ├── planets.png │ └── universe.png └── README.md /Episode 1/README.md: -------------------------------------------------------------------------------- 1 | Full source code and assets from the tutorial series. 2 | Note: The code and assets have different licences 3 | 4 | Code: WTFPL (Do whatever you want, no restrictions) 5 | Art: BY-NC-ND (https://creativecommons.org/licenses/by-nc-nd/4.0/) More restricted. 6 | -------------------------------------------------------------------------------- /Episode 1/conf.lua: -------------------------------------------------------------------------------- 1 | 2 | function love.conf(t) 3 | t.title = "Pong" -- The title of the window the game is in (string) 4 | t.version = "11.3" -- The LÖVE version this game was made for (string) 5 | t.console = true -- Attach a console (boolean, Windows only) 6 | t.window.width = 1280 -- The window width (number) 7 | t.window.height = 720 -- The window height (number) 8 | end 9 | -------------------------------------------------------------------------------- /Episode 1/main.lua: -------------------------------------------------------------------------------- 1 | require("player") --Lets our game know that we have created a new file named "player.lua" 2 | 3 | function love.load() --Base Löve function, all the code inside is called 1 time when the game starts. 4 | Player:load() -- Calls the "Player:load"-function that loads all the players variables. 5 | end 6 | 7 | 8 | function love.update(dt) -- Base Löve function, all the code inside is called every frame. DT stands for Delta time and is the time it took to produce the frame. 9 | Player:update(dt) --Calls the "Player:update"-function that loads all the players variables. 10 | end 11 | 12 | 13 | function love.draw() -- Base Löve function, all the code inside is called every frame. Used to draw graphics to the screen. 14 | Player:draw() -- Calls the "Player:draw"-function that draws the players paddle. 15 | end 16 | -------------------------------------------------------------------------------- /Episode 1/player.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | Player = {} -- Table for the player 4 | 5 | function Player:load() 6 | self.x = 50 -- Variable that stores the player paddles X-position. Set to 50 pixels (from the left side of the window) 7 | self.y = love.graphics.getHeight() / 2 -- Variable that stores the player paddles Y-position. Set to half of the windows width (1280 / 2) 8 | self.width = 20 --Variable that stores the player paddles width. Set to 20 pixels wide. 9 | self.height = 100 --Variable that stores the player paddles height. Set to 100 pixels tall. 10 | self.speed = 500 -- Variable that stores the player paddles speed. Set to 500 pixels per second (since we multiply by DT in the update function.) 11 | end 12 | 13 | 14 | function Player:update(dt) 15 | self:move(dt) -- Calls the "move"-function 16 | self:checkBoundaries() -- Calls the "checkBoundaries"-function 17 | end 18 | 19 | 20 | function Player:move(dt) 21 | if love.keyboard.isDown("w") then -- If the "W"-key is pressed then 22 | self.y = self.y - self.speed * dt -- decrease the Y position by the speed * Delta time 23 | elseif love.keyboard.isDown("s") then -- Else if the "S"-key is pressed then 24 | self.y = self.y + self.speed * dt -- increase the Y position by the speed * Delta time 25 | end 26 | end 27 | 28 | function Player:checkBoundaries() 29 | if self.y < 0 then -- If the Y position is smaller than 0 () 30 | self.y = 0 -- Set the Y position to be 0 31 | elseif self.y + self.height > love.graphics.getHeight() then -- Else if the bottom side of the player paddle is greater than the window height then 32 | self.y = love.graphics.getHeight() - self.height -- Set the Y position to be equal to the window height - the paddles height 33 | end 34 | end 35 | 36 | 37 | function Player:draw() 38 | love.graphics.rectangle("fill", self.x, self.y, self.width, self.height) -- Draws a rectangle at the X and Y position of the player. 39 | end 40 | -------------------------------------------------------------------------------- /Episode 1/run.bat: -------------------------------------------------------------------------------- 1 | @ECHO 2 | 3 | start "" "C:\Program Files\LOVE\lovec" . -------------------------------------------------------------------------------- /Episode 2/README.md: -------------------------------------------------------------------------------- 1 | Full source code and assets from the tutorial series. 2 | Note: The code and assets have different licences 3 | 4 | Code: WTFPL (Do whatever you want, no restrictions) 5 | Art: BY-NC-ND (https://creativecommons.org/licenses/by-nc-nd/4.0/) More restricted. 6 | -------------------------------------------------------------------------------- /Episode 2/ball.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ball = {} 4 | 5 | 6 | function Ball:load() 7 | self.x = love.graphics.getWidth() / 2 -- Sets the balls X position to be equal to half of the screens width. 8 | self.y = love.graphics.getHeight() / 2 -- Sets the balls Y position to be equal to half of the screens height. 9 | self.width = 20 -- Sets the balls width to be equal to 20 pixels. 10 | self.height = 20 -- Sets the balls height to be equal to 20 pixels. 11 | self.speed = 200 -- Sets the balls speed to be equal to 200 pixels per second. 12 | self.xVel = -self.speed -- Sets the balls starting X-velocity to be equal to negative speed (-200). Meaning the ball will travel to the left. 13 | self.yVel = 0 -- Sets the balls starting Y-velocity to be equal to 0. 14 | end 15 | 16 | 17 | function Ball:update(dt) 18 | self:move(dt) 19 | self:collide() 20 | end 21 | 22 | 23 | function Ball:collide() 24 | if checkCollision(self, Player) then -- Checks if the ball (self) and Player rectangles are intersecting. 25 | self.xVel = self.speed --sets the balls X-velocity to the speed variable (200), meaning it will now travel towards the right. 26 | local middleBall = self.y + self.height / 2 --Stores the middle point of the ball in a local variable. 27 | local middlePlayer = Player.y + Player.height / 2 --Stores the middle point of the player in a local variable 28 | local collisionPosition = middleBall - middlePlayer --Stores the collision position (basically if the ball hit the top or bottom part of the player paddle), in a local variable. 29 | self.yVel = collisionPosition * 5 -- Sets the Y-velocity to be equal to the collision position * 5, this changes the angle of the balls trajectory. 30 | end 31 | 32 | if self.y < 0 then -- Checks if the top of the ball is above the top of the screen. 33 | self.y = 0 -- Sets the ball back inside the screen. 34 | self.yVel = -self.yVel -- Flips the y-velocity 35 | elseif self.y + self.height > love.graphics.getHeight() then -- Checks if the bottom of the ball is below the bottom of the screen. 36 | self.y = love.graphics.getHeight() - self.height -- Sets the ball back inside the screen. 37 | self.yVel = -self.yVel -- Flips the y-velocity. 38 | end 39 | end 40 | 41 | function Ball:move(dt) 42 | self.x = self.x + self.xVel * dt -- Updates the balls X-position based on the X-velocity. 43 | self.y = self.y + self.yVel * dt -- Updates the balls Y-position based on the Y-velocity. 44 | end 45 | 46 | 47 | function Ball:draw() 48 | love.graphics.rectangle("fill", self.x, self.y, self.width, self.height) -- Draws the ball 49 | end 50 | -------------------------------------------------------------------------------- /Episode 2/conf.lua: -------------------------------------------------------------------------------- 1 | 2 | function love.conf(t) 3 | t.title = "Pong" -- The title of the window the game is in (string) 4 | t.version = "11.3" -- The LÖVE version this game was made for (string) 5 | t.console = true -- Attach a console (boolean, Windows only) 6 | t.window.width = 1280 -- The window width (number) 7 | t.window.height = 720 -- The window height (number) 8 | end 9 | -------------------------------------------------------------------------------- /Episode 2/main.lua: -------------------------------------------------------------------------------- 1 | require("player") --Lets our game know that we have created a new file named "player.lua" 2 | require("ball") 3 | 4 | function love.load() --Base Löve function, all the code inside is called 1 time when the game starts. 5 | Player:load() -- Calls the "Player:load"-function that loads all the players variables. 6 | Ball:load() 7 | end 8 | 9 | 10 | function love.update(dt) -- Base Löve function, all the code inside is called every frame. DT stands for Delta time and is the time it took to produce the frame. 11 | Player:update(dt) --Calls the "Player:update"-function that handles all of the players functionallity. 12 | Ball:update(dt) --Calls the "Ball:update"-function that handles all of the balls functionallity. 13 | end 14 | 15 | 16 | function love.draw() -- Base Löve function, all the code inside is called every frame. Used to draw graphics to the screen. 17 | Player:draw() -- Calls the "Player:draw"-function that draws the players paddle. 18 | Ball:draw() -- Calls the "Ball:draw"-function that draws the ball. 19 | end 20 | 21 | 22 | function checkCollision(a, b) --Takes two arguments, the rectangles we want to check for collision. 23 | if a.x + a.width > b.x and a.x < b.x + b.width and a.y + a.height > b.y and a.y < b.y + b.height then -- Is A, intersecting B 24 | return true -- Returns the boolean value true, indicating that A and B are colliding. 25 | else 26 | return false -- Returns the boolean value false, indicating that A and B are not colliding. 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /Episode 2/player.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | Player = {} -- Table for the player 4 | 5 | function Player:load() 6 | self.x = 50 -- Variable that stores the player paddles X-position. Set to 50 pixels (from the left side of the window) 7 | self.y = love.graphics.getHeight() / 2 -- Variable that stores the player paddles Y-position. Set to half of the windows width (1280 / 2) 8 | self.width = 20 --Variable that stores the player paddles width. Set to 20 pixels wide. 9 | self.height = 100 --Variable that stores the player paddles height. Set to 100 pixels tall. 10 | self.speed = 500 -- Variable that stores the player paddles speed. Set to 500 pixels per second (since we multiply by DT in the update function.) 11 | end 12 | 13 | 14 | function Player:update(dt) 15 | self:move(dt) -- Calls the "move"-function 16 | self:checkBoundaries() -- Calls the "checkBoundaries"-function 17 | end 18 | 19 | 20 | function Player:move(dt) 21 | if love.keyboard.isDown("w") then -- If the "W"-key is pressed then 22 | self.y = self.y - self.speed * dt -- decrease the Y position by the speed * Delta time 23 | elseif love.keyboard.isDown("s") then -- Else if the "S"-key is pressed then 24 | self.y = self.y + self.speed * dt -- increase the Y position by the speed * Delta time 25 | end 26 | end 27 | 28 | function Player:checkBoundaries() 29 | if self.y < 0 then -- If the Y position is smaller than 0 () 30 | self.y = 0 -- Set the Y position to be 0 31 | elseif self.y + self.height > love.graphics.getHeight() then -- Else if the bottom side of the player paddle is greater than the window height then 32 | self.y = love.graphics.getHeight() - self.height -- Set the Y position to be equal to the window height - the paddles height 33 | end 34 | end 35 | 36 | 37 | function Player:draw() 38 | love.graphics.rectangle("fill", self.x, self.y, self.width, self.height) -- Draws a rectangle at the X and Y position of the player. 39 | end 40 | -------------------------------------------------------------------------------- /Episode 2/run.bat: -------------------------------------------------------------------------------- 1 | @ECHO 2 | 3 | start "" "C:\Program Files\LOVE\lovec" . -------------------------------------------------------------------------------- /Episode 3/README.md: -------------------------------------------------------------------------------- 1 | Full source code and assets from the tutorial series. 2 | Note: The code and assets have different licences 3 | 4 | Code: WTFPL (Do whatever you want, no restrictions) 5 | Art: BY-NC-ND (https://creativecommons.org/licenses/by-nc-nd/4.0/) More restricted. 6 | -------------------------------------------------------------------------------- /Episode 3/ai.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | AI = {} 4 | 5 | 6 | function AI:load() 7 | self.width = 20 8 | self.height = 100 9 | self.x = love.graphics.getWidth() - self.width - 50 10 | self.y = love.graphics.getHeight() / 2 11 | self.yVel = 0 12 | self.speed = 500 13 | 14 | self.timer = 0 15 | self.rate = 0.5 16 | end 17 | 18 | 19 | function AI:update(dt) 20 | self:move(dt) 21 | self.timer = self.timer + dt 22 | if self.timer > self.rate then 23 | self.timer = 0 24 | self:acquireTarget() 25 | end 26 | end 27 | 28 | 29 | function AI:move(dt) 30 | self.y = self.y + self.yVel * dt 31 | end 32 | 33 | 34 | function AI:acquireTarget() 35 | if Ball.y + Ball.height < self.y then 36 | self.yVel = -self.speed 37 | elseif Ball.y > self.y + self.height then 38 | self.yVel = self.speed 39 | else 40 | self.yVel = 0 41 | end 42 | end 43 | 44 | 45 | function AI:draw() 46 | love.graphics.rectangle("fill", self.x, self.y, self.width, self.height) 47 | end 48 | -------------------------------------------------------------------------------- /Episode 3/ball.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ball = {} 4 | 5 | 6 | function Ball:load() 7 | self.x = love.graphics.getWidth() / 2 8 | self.y = love.graphics.getHeight() / 2 9 | self.width = 20 10 | self.height = 20 11 | self.speed = 200 12 | self.xVel = -self.speed 13 | self.yVel = 0 14 | end 15 | 16 | 17 | function Ball:update(dt) 18 | self:move(dt) 19 | self:collide() 20 | end 21 | 22 | 23 | function Ball:collide() 24 | if checkCollision(self, Player) then 25 | self.xVel = self.speed 26 | local middleBall = self.y + self.height / 2 27 | local middlePlayer = Player.y + Player.height / 2 28 | local collisionPosition = middleBall - middlePlayer 29 | self.yVel = collisionPosition * 5 30 | end 31 | 32 | if checkCollision(self, AI) then 33 | self.xVel = -self.speed 34 | local middleBall = self.y + self.height / 2 35 | local middleAI = AI.y + AI.height / 2 36 | local collisionPosition = middleBall - middleAI 37 | self.yVel = collisionPosition * 5 38 | end 39 | 40 | if self.y < 0 then 41 | self.y = 0 42 | self.yVel = -self.yVel 43 | elseif self.y + self.height > love.graphics.getHeight() then 44 | self.y = love.graphics.getHeight() - self.height 45 | self.yVel = -self.yVel 46 | end 47 | 48 | if self.x < 0 then 49 | self.x = love.graphics.getWidth() / 2 - self.width / 2 50 | self.y = love.graphics.getHeight() / 2 - self.height / 2 51 | self.yVel = 0 52 | self.xVel = self.speed 53 | end 54 | 55 | if self.x + self.width > love.graphics.getWidth() then 56 | self.x = love.graphics.getWidth() / 2 - self.width / 2 57 | self.y = love.graphics.getHeight() / 2 - self.height / 2 58 | self.yVel = 0 59 | self.xVel = -self.speed 60 | end 61 | end 62 | 63 | 64 | function Ball:move(dt) 65 | self.x = self.x + self.xVel * dt 66 | self.y = self.y + self.yVel * dt 67 | end 68 | 69 | 70 | function Ball:draw() 71 | love.graphics.rectangle("fill", self.x, self.y, self.width, self.height) 72 | end 73 | -------------------------------------------------------------------------------- /Episode 3/conf.lua: -------------------------------------------------------------------------------- 1 | 2 | function love.conf(t) 3 | t.title = "Pong" -- The title of the window the game is in (string) 4 | t.version = "11.3" -- The LÖVE version this game was made for (string) 5 | t.console = true -- Attach a console (boolean, Windows only) 6 | t.window.width = 1280 -- The window width (number) 7 | t.window.height = 720 -- The window height (number) 8 | end 9 | -------------------------------------------------------------------------------- /Episode 3/main.lua: -------------------------------------------------------------------------------- 1 | require("player") 2 | require("ball") 3 | require("ai") 4 | 5 | 6 | function love.load() 7 | Player:load() 8 | Ball:load() 9 | AI:load() 10 | end 11 | 12 | 13 | function love.update(dt) 14 | Player:update(dt) 15 | Ball:update(dt) 16 | AI:update(dt) 17 | end 18 | 19 | 20 | function love.draw() 21 | Player:draw() 22 | Ball:draw() 23 | AI:draw() 24 | end 25 | 26 | 27 | function checkCollision(a, b) 28 | if a.x + a.width > b.x and a.x < b.x + b.width and a.y + a.height > b.y and a.y < b.y + b.height then 29 | return true 30 | else 31 | return false 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /Episode 3/player.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | Player = {} 4 | 5 | function Player:load() 6 | self.x = 50 7 | self.y = love.graphics.getHeight() / 2 8 | self.width = 20 9 | self.height = 100 10 | self.speed = 500 11 | end 12 | 13 | 14 | function Player:update(dt) 15 | self:move(dt) 16 | self:checkBoundaries() 17 | end 18 | 19 | 20 | function Player:move(dt) 21 | if love.keyboard.isDown("w") then 22 | self.y = self.y - self.speed * dt 23 | elseif love.keyboard.isDown("s") then 24 | self.y = self.y + self.speed * dt 25 | end 26 | end 27 | 28 | function Player:checkBoundaries() 29 | if self.y < 0 then 30 | self.y = 0 31 | elseif self.y + self.height > love.graphics.getHeight() then 32 | self.y = love.graphics.getHeight() - self.height 33 | end 34 | end 35 | 36 | 37 | function Player:draw() 38 | love.graphics.rectangle("fill", self.x, self.y, self.width, self.height) 39 | end 40 | -------------------------------------------------------------------------------- /Episode 3/run.bat: -------------------------------------------------------------------------------- 1 | @ECHO 2 | 3 | start "" "C:\Program Files\LOVE\lovec" . -------------------------------------------------------------------------------- /Episode 4/README.md: -------------------------------------------------------------------------------- 1 | Full source code and assets from the tutorial series. 2 | Note: The code and assets have different licences 3 | 4 | Code: WTFPL (Do whatever you want, no restrictions) 5 | Art: BY-NC-ND (https://creativecommons.org/licenses/by-nc-nd/4.0/) More restricted. 6 | -------------------------------------------------------------------------------- /Episode 4/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jeepzor/Pong-tutorial/bcf4e25159a780704940daf26f530f3b9f2463ec/Episode 4/assets/1.png -------------------------------------------------------------------------------- /Episode 4/assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jeepzor/Pong-tutorial/bcf4e25159a780704940daf26f530f3b9f2463ec/Episode 4/assets/2.png -------------------------------------------------------------------------------- /Episode 4/assets/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jeepzor/Pong-tutorial/bcf4e25159a780704940daf26f530f3b9f2463ec/Episode 4/assets/ball.png -------------------------------------------------------------------------------- /Episode 4/assets/planets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jeepzor/Pong-tutorial/bcf4e25159a780704940daf26f530f3b9f2463ec/Episode 4/assets/planets.png -------------------------------------------------------------------------------- /Episode 4/assets/universe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jeepzor/Pong-tutorial/bcf4e25159a780704940daf26f530f3b9f2463ec/Episode 4/assets/universe.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Full source code and assets from the tutorial series. 2 | Note: The code and assets have different licences 3 | 4 | Code: WTFPL (Do whatever you want, no restrictions) 5 | Art: BY-NC-ND (https://creativecommons.org/licenses/by-nc-nd/4.0/) More restricted. 6 | --------------------------------------------------------------------------------