master
a327ex 2021-04-25 01:09:43 -03:00
parent b1862400e8
commit 5ee9cdf2ec
9 changed files with 282 additions and 140 deletions

View File

@ -147,38 +147,6 @@ function Arena:on_enter(from, level, units, passives)
self.t:every(function() return #self.main:get_objects_by_classes(self.enemies) <= 0 and self.wave > self.max_waves end, function() self.can_quit = true end)
end)
elseif self.win_condition == 'enemy_kill' then
self.level_to_enemies_to_kill = {
8, 12, random:int(14, 16),
16, 16, 18, random:int(18, 20),
20, 20, 20, 20, random:int(20, 22),
22, 22, 22, 22, 22, random:int(22, 24),
24, 26, 28, 30, 30, 32, 40
}
self.enemies_killed = 0
self.enemies_to_kill = self.level_to_enemies_to_kill[self.level]
self.enemy_spawn_delay = 8
self.enemies_spawned = 0
self.start_time = 3
self.t:after(1, function()
self.t:every(1, function()
if self.start_time > 1 then alert1:play{volume = 0.5} end
self.start_time = self.start_time - 1
self.hfx:use('condition1', 0.25, 200, 10)
end, 3, function()
alert1:play{pitch = 1.2, volume = 0.5}
camera:shake(4, 0.25)
SpawnEffect{group = self.effects, x = gw/2, y = gh/2 - 48}
self:spawn_distributed_enemies()
self.t:every(2, function()
if love.timer.getTime() - self.last_spawn_enemy_time >= self.enemy_spawn_delay and #self.main:get_objects_by_class(self.enemies) < self.enemies_to_kill and not self.transitioning then
self:spawn_distributed_enemies()
end
end, nil, nil, 'spawn_enemies')
end)
end)
self.t:every(function() return #self.main:get_objects_by_classes(self.enemies) <= 0 and self.enemies_killed >= self.enemies_to_kill end, function() self.can_quit = true end)
elseif self.win_condition == 'time' then
self.level_to_time_left = {
20, 20, random:int(20, 25),
@ -313,18 +281,22 @@ function Arena:update(dt)
end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)}
end
--[[
if input.w.pressed then
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url'https://store.steampowered.com/app/915310/SNKRX/'
end
]]--
end
--[[
if input.w.pressed and self.won then
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url'https://store.steampowered.com/app/915310/SNKRX/'
end
]]--
self:update_game_object(dt*slow_amount)
cascade_instance.pitch = math.clamp(slow_amount*self.main_slow_amount, 0.05, 1)
@ -342,15 +314,18 @@ function Arena:update(dt)
if not self.win_text and not self.win_text2 then
self.won = true
camera.x, camera.y = gw/2, gh/2
self.win_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 64, lines = {{text = '[wavy_mid, cbyc2]congratulations!', font = fat_font, alignment = 'center'}}}
self.win_text = Text2{group = self.ui, x = gw/2, y = gh/2 - 66, lines = {{text = '[wavy_mid, cbyc2]congratulations!', font = fat_font, alignment = 'center'}}}
self.t:after(2.5, function()
self.win_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 16, lines = {
{text = "[fg]you've beaten the demo!", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = "[fg]the game's full version is coming in a few weeks,", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = "[fg]so if you liked the game, make sure to wishlist it!", font = pixul_font, alignment = 'center', height_multiplier = 5},
{text = "[wavy_mid, fg]thanks for playing!", font = pixul_font, alignment = 'center'},
self.win_text2 = Text2{group = self.ui, x = gw/2, y = gh/2 + 20, lines = {
{text = "[fg]you've beaten the game!", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = "[fg]i made this game in 2 months as a dev challenge", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = "[fg]and i'm happy with how it turned out!", font = pixul_font, alignment = 'center', height_multiplier = 1.2},
{text = "[fg]if you liked it too and want to play more games like this:", font = pixul_font, alignment = 'center', height_multiplier = 5},
{text = "[fg]i will release more games this year, so stay tuned!", font = pixul_font, alignment = 'center', height_multiplier = 1.4},
{text = "[wavy_mid, yellow]thanks for playing!", font = pixul_font, alignment = 'center'},
}}
WishlistButton{group = self.ui, x = gw/2, y = gh/2 + 30, w_to_wishlist = true}
SteamFollowButton{group = self.ui, x = gw/2, y = gh/2 + 37}
RestartButton{group = self.ui, x = gw - 40, y = gh - 20}
end)
end
@ -387,7 +362,7 @@ function Arena:draw()
self.post_main:draw()
self.effects:draw()
if self.level == 18 and self.trailer then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end
if self.choosing_passives then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end
if self.choosing_passives or self.won or self.paused then graphics.rectangle(gw/2, gh/2, 2*gw, 2*gh, nil, nil, modal_transparent) end
self.ui:draw()
graphics.draw_with_mask(function()
@ -431,20 +406,10 @@ function Arena:draw()
graphics.print(self.wave .. '/' .. self.max_waves, fat_font, self.x2 - 25, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
graphics.pop()
end
elseif self.win_condition == 'enemy_kill' then
if self.start_time <= 0 then
graphics.push(self.x2 - 106, self.y1 - 10, 0, self.hfx.condition2.x, self.hfx.condition2.x)
graphics.print_centered('enemies killed:', fat_font, self.x2 - 106, self.y1 - 10, 0, 0.6, 0.6, nil, nil, fg[0])
graphics.pop()
graphics.push(self.x2 - 41 + fat_font:get_text_width(self.enemies_killed .. '/' .. self.enemies_to_kill)/2, self.y1 - 8, 0, self.hfx.condition1.x, self.hfx.condition1.x)
graphics.print(self.enemies_killed .. '/' .. self.enemies_to_kill, fat_font, self.x2 - 41, self.y1 - 8, 0, 0.75, 0.75, nil, fat_font.h/2, self.hfx.condition1.f and fg[0] or yellow[0])
graphics.pop()
end
end
end
end
camera:detach()
end
@ -459,7 +424,6 @@ function Arena:die()
self.death_info_text = Text2{group = self.ui, x = gw/2, y = gh/2 + 24, sx = 0.7, sy = 0.7, lines = {
{text = '[wavy_mid, light_bg]level reached: [wavy_mid, yellow]' .. self.level, font = fat_font, alignment = 'center'},
{text = '[wavy_mid, light_bg]r - start new run', font = fat_font, alignment = 'center'},
{text = '[wavy_mid, light_bg]w - wishlist on steam', font = fat_font, alignment = 'center'},
}}
end)
end
@ -506,20 +470,6 @@ function Arena:transition()
end
function Arena:enemy_killed()
if self.win_condition == 'enemy_kill' then
self.enemies_killed = self.enemies_killed + 1
self.hfx:use('condition1', 0.25, 200, 10)
self.hfx:pull('condition2', 0.0625)
self.enemy_spawn_delay = self.enemy_spawn_delay*0.95
if self.enemies_killed >= self.enemies_to_kill then
self.can_quit = true
self.t:cancel'spawn_enemies'
end
end
end
function Arena:spawn_distributed_enemies()
local t = {'4', '4+4', '4+4+4', '2x4', '3x4', '4x2'}
local spawn_type = t[random:weighted_pick(40, 20, 5, 15, 5, 15)]
@ -589,10 +539,6 @@ function Arena:spawn_n_enemies(p, j, n)
n = n or 4
self.last_spawn_enemy_time = love.timer.getTime()
self.t:every(0.1, function()
if self.win_condition == 'enemy_kill' then
if self.enemies_spawned >= math.floor(1.4*self.enemies_to_kill) then return end
self.enemies_spawned = self.enemies_spawned + 1
end
local o = self.spawn_offsets[(self.t:get_every_iteration('spawn_enemies_' .. j) % 5) + 1]
SpawnEffect{group = self.effects, x = p.x + o.x, y = p.y + o.y, action = function(x, y)
spawn1:play{pitch = random:float(0.8, 1.2), volume = 0.15}

View File

@ -200,6 +200,56 @@ end
SteamFollowButton = Object:extend()
SteamFollowButton:implement(GameObject)
function SteamFollowButton:init(args)
self:init_game_object(args)
self.interact_with_mouse = true
self.shape = Rectangle(self.x, self.y, fat_font:get_text_width('follow me on steam!'), fat_font.h)
self.text = Text({{text = '[blue]follow me on steam!', font = fat_font, alignment = 'center'}}, global_text_tags)
end
function SteamFollowButton:update(dt)
self:update_game_object(dt)
if self.selected and input.m1.pressed then
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.spring:pull(0.2, 200, 10)
self.selected = true
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
system.open_url'https://store.steampowered.com/dev/a327ex/'
end
end
function SteamFollowButton:draw()
graphics.push(self.x, self.y, 0, self.spring.x, self.spring.y)
self.text:draw(self.x, self.y)
graphics.rectangle(self.x, self.y + self.text.h/5, self.text.w, 2, 2, 2, self.selected and blue[5] or blue[0])
graphics.pop()
end
function SteamFollowButton:on_mouse_enter()
love.mouse.setCursor(love.mouse.getSystemCursor'hand')
ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5}
pop2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.selected = true
self.text:set_text{{text = '[blue5]follow me on steam!', font = fat_font, alignment = 'center'}}
self.spring:pull(0.05, 200, 10)
end
function SteamFollowButton:on_mouse_exit()
love.mouse.setCursor()
self.text:set_text{{text = '[blue]follow me on steam!', font = fat_font, alignment = 'center'}}
self.selected = false
end
WishlistButton = Object:extend()
WishlistButton:implement(GameObject)
function WishlistButton:init(args)
@ -261,6 +311,61 @@ end
RestartButton = Object:extend()
RestartButton:implement(GameObject)
function RestartButton:init(args)
self:init_game_object(args)
self.shape = Rectangle(self.x, self.y, pixul_font:get_text_width('restart') + 4, pixul_font.h + 4)
self.interact_with_mouse = true
self.text = Text({{text = '[bg10]restart', font = pixul_font, alignment = 'center'}}, global_text_tags)
end
function RestartButton:update(dt)
self:update_game_object(dt)
if self.selected and input.m1.pressed then
main.current.transitioning = true
ui_transition2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
ui_switch1:play{pitch = random:float(0.95, 1.05), volume = 0.5}
TransitionEffect{group = main.transitions, x = gw/2, y = gh/2, color = fg[0], transition_action = function()
slow_amount = 1
gold = 2
passives = {}
cascade_instance:stop()
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', 0, {}, passives)
end, text = Text({{text = '[wavy, bg]restarting...', font = pixul_font, alignment = 'center'}}, global_text_tags)}
end
end
function RestartButton:draw()
graphics.push(self.x, self.y, 0, self.spring.x, self.spring.y)
graphics.rectangle(self.x, self.y, self.shape.w, self.shape.h, 4, 4, self.selected and fg[0] or bg[1])
self.text:draw(self.x, self.y + 1, 0, 1, 1)
graphics.pop()
end
function RestartButton:on_mouse_enter()
ui_hover1:play{pitch = random:float(1.3, 1.5), volume = 0.5}
pop2:play{pitch = random:float(0.95, 1.05), volume = 0.5}
self.selected = true
self.text:set_text{{text = '[fgm5]restart', font = pixul_font, alignment = 'center'}}
self.spring:pull(0.2, 200, 10)
end
function RestartButton:on_mouse_exit()
self.text:set_text{{text = '[bg10]restart', font = pixul_font, alignment = 'center'}}
self.selected = false
end
GoButton = Object:extend()
GoButton:implement(GameObject)
function GoButton:init(args)

View File

@ -1051,3 +1051,7 @@ I also made some small graphical improvements to the game that I think will help
* Achievements
* Come up with a few new ones as I play the game more and balance the numbers
* Implement all the ones I already uploaded to Steam
# Day 67 - 24/04/21
Added an end game screen and started work on making elites spawn throughout the levels.

View File

@ -404,7 +404,6 @@ function Seeker:hit(damage, projectile)
self.dead = true
for i = 1, random:int(4, 6) do HitParticle{group = main.current.effects, x = self.x, y = self.y, color = self.color} end
HitCircle{group = main.current.effects, x = self.x, y = self.y, rs = 12}:scale_down(0.3):change_color(0.5, self.color)
main.current:enemy_killed()
_G[random:table{'enemy_die1', 'enemy_die2'}]:play{pitch = random:float(0.9, 1.1), volume = 0.5}
if self.speed_booster then

View File

@ -118,6 +118,8 @@ function Text:format_text()
c.y = y
c.sx = line.sx or c.sx or 1
c.sy = line.sy or c.sy or 1
c.w = line.font:get_text_width(c.character)
c.h = line.font.h
x = x + line.font:get_text_width(c.character)
end
y = y + h

View File

@ -113,6 +113,7 @@ function engine_run(config)
for name, a, b, c, d, e, f in love.event.poll() do
if name == "quit" then
if not love.quit or not love.quit() then
system.save_state()
steam.shutdown()
return a or 0
end

186
main.lua
View File

@ -827,70 +827,6 @@ function init()
['voider'] = function(units) return 2, 4, get_number_of_units_per_class(units).voider end,
}
level_to_tier_weights = {
[1] = {90, 10, 0, 0},
[2] = {80, 15, 5, 0},
[3] = {75, 20, 5, 0},
[4] = {70, 20, 10, 0},
[5] = {70, 20, 10, 0},
[6] = {65, 25, 10, 0},
[7] = {60, 25, 15, 0},
[8] = {55, 25, 15, 5},
[9] = {50, 30, 15, 5},
[10] = {50, 30, 15, 5},
[11] = {45, 30, 20, 5},
[12] = {45, 30, 20, 5},
[13] = {40, 30, 20, 10},
[14] = {40, 30, 20, 10},
[15] = {35, 35, 20, 10},
[16] = {30, 40, 20, 10},
[17] = {20, 40, 25, 15},
[18] = {20, 40, 25, 15},
[19] = {15, 40, 30, 15},
[20] = {10, 40, 30, 20},
[21] = {5, 40, 35, 20},
[22] = {5, 35, 35, 25},
[23] = {5, 35, 35, 25},
[24] = {0, 30, 40, 30},
[25] = {0, 25, 40, 35},
}
level_to_gold_gained = {
[1] = {2, 2},
[2] = {2, 2},
[3] = {4, 6},
[4] = {2, 3},
[5] = {3, 5},
[6] = {6, 10},
[7] = {4, 7},
[8] = {4, 7},
[9] = {10, 16},
[10] = {5, 8},
[11] = {5, 8},
[12] = {12, 20},
[13] = {6, 10},
[14] = {6, 10},
[15] = {14, 22},
[16] = {8, 12},
[17] = {8, 12},
[18] = {16, 24},
[19] = {8, 12},
[20] = {10, 14},
[21] = {20, 28},
[22] = {11, 15},
[23] = {11, 15},
[24] = {24, 36},
[25] = {100, 100},
}
level_to_boss = {
[6] = 'speed_booster',
[12] = 'exploder',
[18] = 'swarmer',
[24] = 'forcer',
[25] = 'randomizer',
}
passive_names = {
['ouroboros_technique_r'] = 'Ouroboros Technique R',
['ouroboros_technique_l'] = 'Ouroboros Technique L',
@ -1034,6 +970,62 @@ function init()
[3] = {'divine_machine_arrow', 'divine_punishment', 'flying_daggers', 'crucio', 'hive', 'void_rift'},
}
level_to_tier_weights = {
[1] = {90, 10, 0, 0},
[2] = {80, 15, 5, 0},
[3] = {75, 20, 5, 0},
[4] = {70, 20, 10, 0},
[5] = {70, 20, 10, 0},
[6] = {65, 25, 10, 0},
[7] = {60, 25, 15, 0},
[8] = {55, 25, 15, 5},
[9] = {50, 30, 15, 5},
[10] = {50, 30, 15, 5},
[11] = {45, 30, 20, 5},
[12] = {45, 30, 20, 5},
[13] = {40, 30, 20, 10},
[14] = {40, 30, 20, 10},
[15] = {35, 35, 20, 10},
[16] = {30, 40, 20, 10},
[17] = {20, 40, 25, 15},
[18] = {20, 40, 25, 15},
[19] = {15, 40, 30, 15},
[20] = {10, 40, 30, 20},
[21] = {5, 40, 35, 20},
[22] = {5, 35, 35, 25},
[23] = {5, 35, 35, 25},
[24] = {0, 30, 40, 30},
[25] = {0, 25, 40, 35},
}
level_to_gold_gained = {
[1] = {2, 2},
[2] = {2, 2},
[3] = {4, 6},
[4] = {2, 3},
[5] = {3, 5},
[6] = {6, 10},
[7] = {4, 7},
[8] = {4, 7},
[9] = {10, 16},
[10] = {5, 8},
[11] = {5, 8},
[12] = {12, 20},
[13] = {6, 10},
[14] = {6, 10},
[15] = {14, 22},
[16] = {8, 12},
[17] = {8, 12},
[18] = {16, 24},
[19] = {8, 12},
[20] = {10, 14},
[21] = {20, 28},
[22] = {11, 15},
[23] = {11, 15},
[24] = {24, 36},
[25] = {100, 100},
}
level_to_passive_tier_weights = {
[3] = {70, 20, 10},
[6] = {60, 25, 15},
@ -1045,13 +1037,77 @@ function init()
[24] = {20, 30, 50},
}
level_to_elite_spawn_weights = {
[1] = {0},
[2] = {4, 2},
[3] = {10},
[4] = {4, 4},
[5] = {4, 3, 2},
[6] = {14},
[7] = {5, 3, 2},
[8] = {6, 3, 3, 3},
[9] = {18},
[10] = {8, 4},
[11] = {8, 6, 2},
[12] = {18},
[13] = {8, 8},
[14] = {12, 6},
[15] = {18},
[16] = {10, 6, 4},
[17] = {6, 5, 4, 3},
[18] = {18},
[19] = {10, 6},
[20] = {10, 6, 2},
[21] = {28},
[22] = {10, 10, 5},
[23] = {20, 5, 5},
[24] = {35},
[25] = {5, 5, 5, 5, 5, 5},
}
level_to_boss = {
[6] = 'speed_booster',
[12] = 'exploder',
[18] = 'swarmer',
[24] = 'forcer',
[25] = 'randomizer',
}
level_to_elite_spawn_types = {
[1] = {'speed_booster'},
[2] = {'speed_booster', 'shooter'},
[3] = {'speed_booster'},
[4] = {'speed_booster', 'exploder'},
[5] = {'speed_booster', 'exploder', 'shooter'},
[6] = {'speed_booster'},
[7] = {'speed_booster', 'exploder', 'headbutter'},
[8] = {'speed_booster', 'exploder', 'headbutter', 'shooter'},
[9] = {'shooter'},
[10] = {'exploder', 'headbutter'},
[11] = {'exploder', 'headbutter', 'tank'},
[12] = {'exploder'},
[13] = {'speed_booster', 'shooter'},
[14] = {'speed_booster', 'spawner'},
[15] = {'shooter'},
[16] = {'speed_booster', 'exploder', 'spawner'},
[17] = {'speed_booster', 'exploder', 'spawner', 'shooter'},
[18] = {'spawner'},
[19] = {'headbutter', 'tank'},
[20] = {'speed_booster', 'tank', 'spawner'},
[21] = {'headbutter'},
[22] = {'speed_booster', 'headbutter', 'tank'},
[23] = {'headbutter', 'tank', 'shooter'},
[24] = {'tank'},
[25] = {'speed_booster', 'exploder', 'headbutter', 'tank', 'shooter', 'spawner'},
}
gold = 2
passives = {}
system.load_state()
main = Main()
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', 0, {{character = 'cryomancer', level = 1}, {character = 'pyromancer', level = 1}}, passives)
main:go_to('buy_screen', 0, {}, passives)
--[[
main:add(Media'media')
main:go_to('media')

View File

@ -499,11 +499,24 @@ global_text_tags = {
fgm5 = TextTag{draw = function(c, i, text) graphics.set_color(fg[-5]) end},
fgm10 = TextTag{draw = function(c, i, text) graphics.set_color(fg[-10]) end},
greenm5 = TextTag{draw = function(c, i, text) graphics.set_color(green[-5]) end},
blue5 = TextTag{draw = function(c, i, text) graphics.set_color(blue[5]) end},
bluem5 = TextTag{draw = function(c, i, text) graphics.set_color(blue[-5]) end},
wavy = TextTag{update = function(c, dt, i, text) c.oy = 2*math.sin(4*time + i) end},
wavy_mid = TextTag{update = function(c, dt, i, text) c.oy = 0.75*math.sin(3*time + i) end},
wavy_mid2 = TextTag{update = function(c, dt, i, text) c.oy = 0.5*math.sin(3*time + i) end},
wavy_lower = TextTag{update = function(c, dt, i, text) c.oy = 0.25*math.sin(2*time + i) end},
steam_link = TextTag{
init = function(c, i, text)
c.color = blue[0]
end,
draw = function(c, i, text)
graphics.set_color(c.color)
graphics.line(c.x - c.w/2, c.y + c.h/2 + c.h/10, c.x + c.w/2, c.y + c.h/2 + c.h/10)
end
},
cbyc = TextTag{init = function(c, i, text)
c.color = invisible
text.t:after((i-1)*0.15, function()

26
todo
View File

@ -1,9 +1,25 @@
Achievements
Hover class highlight
DPS list
Remove enemies killed mode
Make bosses have only wave mode
General balance
Enemies should have a chance to be spawned with a modifier as levels increase
Every 3rd level should be wave only
* Remove "enemies killed" mode
Balance playthroughs (record all balance playthroughs as they can be used for trailers; do this after graphical improvements done)
UI improvements
Hover class highlight
DPS list (right)
HP list (bottom)
Item list (left)
Graphical improvements
Further graphical improvements if there's time
Trailers
3-4 pure gameplay playthroughs showcasing different builds
Misc
Better pause screen
* End screen
Ascension mode (difficulty ramps up faster and goes higher than normal at the end)
Music for bosses and shop
Achievements
Come up with a few new ones as I play the game more and balance the numbers
Implement all the ones I already uploaded to Steam
Engine improvements for after SNKRX release