-
Notifications
You must be signed in to change notification settings - Fork 10
/
main.lua
175 lines (139 loc) · 5.2 KB
/
main.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
--[[
GD50 2018
Flappy Bird Remake James was here 2018
Author: Colton Ogden
A mobile game by Dong Nguyen that went viral in 2013, utilizing a very simple
but effective gameplay mechanic of avoiding pipes indefinitely by just tapping
the screen, making the player's bird avatar flap its wings and move upwards slightly.
A variant of popular games like "Helicopter Game" that floated around the internet
for years prior. Illustrates some of the most basic procedural generation of game
levels possible as by having pipes stick out of the ground by varying amounts, acting
as an infinitely generated obstacle course for the player.
]]
-- push is a library that will allow us to draw our game at a virtual
-- resolution, instead of however large our window is; used to provide
-- a more retro aesthetic
--
-- https://github.com/Ulydev/push
push = require 'push'
-- the "Class" library we're using will allow us to represent anything in
-- our game as code, rather than keeping track of many disparate variables and
-- methods
--
-- https://github.com/vrld/hump/blob/master/class.lua
Class = require 'class'
-- a basic StateMachine class which will allow us to transition to and from
-- game states smoothly and avoid monolithic code in one file
require 'StateMachine'
-- all states our StateMachine can transition between
require 'states/BaseState'
require 'states/CountdownState'
require 'states/PlayState'
require 'states/ScoreState'
require 'states/TitleScreenState'
require 'Bird'
require 'Pipe'
require 'PipePair'
-- physical screen dimensions
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720
-- virtual resolution dimensions
VIRTUAL_WIDTH = 512
VIRTUAL_HEIGHT = 288
local background = love.graphics.newImage('background.png')
local backgroundScroll = 0
local ground = love.graphics.newImage('ground.png')
local groundScroll = 0
local BACKGROUND_SCROLL_SPEED = 30
local GROUND_SCROLL_SPEED = 60
local BACKGROUND_LOOPING_POINT = 413
function love.load()
-- initialize our nearest-neighbor filter
love.graphics.setDefaultFilter('nearest', 'nearest')
-- seed the RNG
math.randomseed(os.time())
-- app window title
love.window.setTitle('Fifty Bird')
-- initialize our nice-looking retro text fonts
smallFont = love.graphics.newFont('font.ttf', 8)
mediumFont = love.graphics.newFont('flappy.ttf', 14)
flappyFont = love.graphics.newFont('flappy.ttf', 28)
hugeFont = love.graphics.newFont('flappy.ttf', 56)
love.graphics.setFont(flappyFont)
-- initialize our table of sounds
sounds = {
['jump'] = love.audio.newSource('jump.wav', 'static'),
['explosion'] = love.audio.newSource('explosion.wav', 'static'),
['hurt'] = love.audio.newSource('hurt.wav', 'static'),
['score'] = love.audio.newSource('score.wav', 'static'),
-- https://freesound.org/people/xsgianni/sounds/388079/
['music'] = love.audio.newSource('marios_way.mp3', 'static')
}
-- kick off music
sounds['music']:setLooping(true)
sounds['music']:play()
-- initialize our virtual resolution
push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
vsync = true,
fullscreen = false,
resizable = true
})
-- initialize state machine with all state-returning functions
gStateMachine = StateMachine {
['title'] = function() return TitleScreenState() end,
['countdown'] = function() return CountdownState() end,
['play'] = function() return PlayState() end,
['score'] = function() return ScoreState() end
}
gStateMachine:change('title')
-- initialize input table
love.keyboard.keysPressed = {}
-- initialize mouse input table
love.mouse.buttonsPressed = {}
end
function love.resize(w, h)
push:resize(w, h)
end
function love.keypressed(key)
-- add to our table of keys pressed this frame
love.keyboard.keysPressed[key] = true
if key == 'escape' then
love.event.quit()
end
end
--[[
LÖVE2D callback fired each time a mouse button is pressed; gives us the
X and Y of the mouse, as well as the button in question.
]]
function love.mousepressed(x, y, button)
love.mouse.buttonsPressed[button] = true
end
--[[
Custom function to extend LÖVE's input handling; returns whether a given
key was set to true in our input table this frame.
]]
function love.keyboard.wasPressed(key)
return love.keyboard.keysPressed[key]
end
--[[
Equivalent to our keyboard function from before, but for the mouse buttons.
]]
function love.mouse.wasPressed(button)
return love.mouse.buttonsPressed[button]
end
function love.update(dt)
-- scroll our background and ground, looping back to 0 after a certain amount
backgroundScroll = (backgroundScroll + BACKGROUND_SCROLL_SPEED * dt) % BACKGROUND_LOOPING_POINT
groundScroll = (groundScroll + GROUND_SCROLL_SPEED * dt) % VIRTUAL_WIDTH
gStateMachine:update(dt)
love.keyboard.keysPressed = {}
love.mouse.buttonsPressed = {}
end
function love.draw()
push:start()
love.graphics.draw(background, -backgroundScroll, 0)
gStateMachine:render()
love.graphics.draw(ground, -groundScroll, VIRTUAL_HEIGHT - 16)
push:finish()
end