2 Batto! A clicking arcade game
3 Copyright 2018 Pajo <xpio at tut dot by>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
22 love
.window
.setMode(1000, 600)
24 w
= love
.graphics
.getWidth(),
25 h
= love
.graphics
.getHeight()
33 love
.graphics
.setColor(.5, .5, .8)
34 love
.graphics
.circle("fill", self
.x
, self
.y
, self
.size
/ 2)
36 move
= function(self
, x
, y
)
37 if trails
[1] then return end
38 trails
:make(x
, y
, self
.x
, self
.y
)
42 destroy
= function(self
)
43 game
.score
= game
.score
- 10
44 explosions
:make(self
.x
, self
.y
, self
.size
)
52 make
= function(self
, x
, y
, sx
, sy
)
54 for a
= 1, self
.max do
55 fall
= 1 - a
/ self
.max
58 x
= sx
- (sx
- x
) * fall
,
59 y
= sy
- (sy
- y
) * fall
64 love
.graphics
.setColor(1, .5, 0)
66 love
.graphics
.circle("line", self
[a
].x
, self
[a
].y
, self
[a
].size
/ 2)
69 expire
= function(self
, dt
)
70 self
.timer
= self
.timer
+ dt
71 if self
.timer
> self
.duration
and #self
> 0 then
73 self
.timer
= self
.timer
- self
.duration
76 check
= function(self
)
77 for a
= 1, #self
do for b
= 1, #enemies
do
78 if not enemies
[b
].dying
and collides(trails
[a
], enemies
[b
]) then
88 self
.x
= self
.x
+ self
.speedx
89 self
.y
= self
.y
+ self
.speedy
90 self
.dying
= self
.dying
or
91 (self
.x
< 1 or self
.x
> screen
.w
or self
.y
< 1 or self
.y
> screen
.h
)
94 wander
= function(self
)
95 self
.x
= self
.x
+ self
.speedx
96 self
.y
= self
.y
+ self
.speedy
97 if self
.x
< 1 or self
.x
> screen
.w
then
98 self
.speedx
= - self
.speedx
100 if self
.y
< 1 or self
.y
> screen
.h
then
101 self
.speedy
= - self
.speedy
105 chase
= function(self
)
106 self
.speedx
= self
.speedx
* 199/200 + (player
.x
- self
.x
) / 2000
107 self
.speedy
= self
.speedy
* 199/200 + (player
.y
- self
.y
) / 2000
108 self
.speedx
= self
.speedx
/ math
.abs(self
.speedx
) * math
.min(3, math
.abs(self
.speedx
))
109 self
.speedy
= self
.speedy
/ math
.abs(self
.speedy
) * math
.min(3, math
.abs(self
.speedy
))
110 self
.x
= self
.x
+ self
.speedx
111 self
.y
= self
.y
+ self
.speedy
115 draw
= function(self
)
117 love
.graphics
.setColor(self
[a
].kind
.color
)
118 love
.graphics
.rectangle("fill", self
[a
].x
- self
[a
].size
/ 2, self
[a
].y
- self
[a
].size
/ 2, self
[a
].size
, self
[a
].size
)
121 make
= function(self
, kind
, x
, y
, speedx
, speedy
)
123 --kind = enemies.kinds.wanderer,
124 --x = math.random(size, screen.w - size),
125 --y = math.random(size, screen.h - size),
126 --speedx = math.random(-3, 3),
127 --speedy = math.random(-3, 3),
130 kind
= kind
, x
= x
, y
= y
, speedx
= speedx
, speedy
= speedy
,
134 explosions
:make(self
.x
, self
.y
, self
.size
)
135 game
.score
= game
.score
+ 1
137 -- will be disposed of in cleanup
141 if #self % 5 == 0 then
142 self[#self].kind = enemies.kinds.chaser
144 if #self % 2 == 0 then
145 self[#self].kind = enemies.kinds.passer
149 move
= function(self
)
151 self
[a
] = self
[a
].kind
.movement(self
[a
])
154 check
= function(self
)
156 if not self
[a
].dying
and collides(player
, self
[a
]) then
162 cleanup
= function(self
)
163 for a
= #self
, 1, -1 do if self
[a
].dying
then
164 self
[a
] = self
[#self
]
173 movement
= enemies
.movements
.wander
,
178 movement
= enemies
.movements
.chase
,
183 movement
= enemies
.movements
.pass
,
190 make
= function(self
, x
, y
, size
)
198 grow
= function(self
)
199 -- must go backwards not to disrupt the loop
200 for a
= #self
, 1, -1 do
201 self
[a
].step
= self
[a
].step
+ 1
202 if self
[a
].step
> self
.maxsteps
then
207 destroy
= function(self
, a
)
208 self
[a
] = self
[#self
]
211 draw
= function(self
)
212 love
.graphics
.setColor(1,1,0)
214 love
.graphics
.rectangle("line", self
[a
].x
- self
[a
].size
/ 2 - self
[a
].step
* 2, self
[a
].y
- self
[a
].size
/ 2 - self
[a
].step
* 2, self
[a
].size
+ self
[a
].step
* 4, self
[a
].size
+ self
[a
].step
* 4)
220 ul
= { x
= 0, y
= 0 },
221 u
= { x
= screen
.w
/ 2, y
= 0 },
222 ur
= { x
= screen
.w
, y
= 0 },
223 l
= { x
= 0, y
= screen
.h
/ 2 },
224 c
= { x
= screen
.w
/ 2, y
= screen
.h
/ 2 },
225 r
= { x
= screen
.w
, y
= screen
.h
/ 2 },
226 dl
= { x
= 0, y
= screen
.h
},
227 d
= { x
= screen
.w
/ 2, y
= screen
.h
},
228 dr
= { x
= screen
.w
, y
= screen
.h
},
235 player_origin
= origins
.c
,
237 { time
= 0, origin
= origins
.ul
, speed
= { 1, 1 }, kind
= enemies
.kinds
.passer
},
239 { time
= 2, origin
= origins
.l
, speed
= { 1, 0 }, kind
= enemies
.kinds
.passer
},
241 { time
= 4, origin
= origins
.dl
, speed
= { 1, -1 }, kind
= enemies
.kinds
.passer
},
243 { time
= 6, origin
= origins
.d
, speed
= { 0, -1 }, kind
= enemies
.kinds
.passer
},
248 player_origin
= origins
.d
,
250 { time
= 0, origin
= origins
.ul
, speed
= { 1, 1 }, kind
= enemies
.kinds
.wanderer
},
252 { time
= 2, origin
= origins
.l
, speed
= { 1, 0 }, kind
= enemies
.kinds
.wanderer
},
266 function collides(obj1
, obj2
)
267 local o1x
, o1y
, o2x
, o2y
, d
268 o1x
= obj1
.x
+ obj1
.size
/ 2
269 o1y
= obj1
.y
+ obj1
.size
/ 2
270 o2x
= obj2
.x
+ obj2
.size
/ 2
271 o2y
= obj2
.y
+ obj2
.size
/ 2
272 d
= obj1
.size
/ 2 + obj2
.size
/ 2
273 return (o1x
- o2x
) ^
2 + (o1y
- o2y
) ^
2 < d ^
2
277 function beginlevel()
281 player
.x
= scenario
[game
.level
].player_origin
.x
282 player
.y
= scenario
[game
.level
].player_origin
.y
286 function happen(number)
287 game
.happened
= number
288 print(number, ' happened')
292 function love
.update(dt
)
294 love
.timer
.sleep(1/30 - dt
)
296 game
.timer
= game
.timer
+ dt
297 if game
.mode
== "play" then
303 for a
= game
.happened
+ 1, #scenario
[game
.level
] do
304 if game
.timer
> scenario
[game
.level
][a
].time
then
308 elseif game
.mode
== "title" then
309 if game
.timer
> 3 then
317 love
.graphics
.setColor(1,1,1)
318 love
.graphics
.print(math
.floor(game
.timer
) .. ':' .. game
.score
, 1, 2)
319 love
.graphics
.print('game.mode = ' .. game
.mode
, 1, 20)
324 if game
.mode
== "play" then
329 elseif game
.mode
== "title" then
330 love
.graphics
.setColor(1,1,1)
331 love
.graphics
.print(scenario
[game
.level
].title
, 100, 100)
337 function love
.mousepressed(x
, y
, button
)
338 if game
.mode
== "title" then
340 elseif game
.mode
== "play" then
344 enemies
.kinds
.wanderer
, -- kind
345 math
.random(enemies
.kinds
.wanderer
.size
, screen
.w
- enemies
.kinds
.wanderer
.size
), -- x
346 math
.random(enemies
.kinds
.wanderer
.size
, screen
.h
- enemies
.kinds
.wanderer
.size
), -- y
347 math
.random(-3, 3), math
.random(-3, 3) -- speedx, speedy
353 function love
.keypressed(k
)
354 if k
== "escape" then
355 love
.event
.push("quit")