master
a327ex 2021-03-05 04:29:19 -03:00
parent d92f846836
commit cd651bb2c3
19 changed files with 257 additions and 46 deletions

View File

@ -15,7 +15,7 @@ function Arena:on_enter(from, level)
self.main = Group():set_as_physics_world(32, 0, 0, {'player', 'enemy', 'projectile', 'enemy_projectile'}) self.main = Group():set_as_physics_world(32, 0, 0, {'player', 'enemy', 'projectile', 'enemy_projectile'})
self.post_main = Group() self.post_main = Group()
self.effects = Group() self.effects = Group()
self.ui = Group():no_camera() self.ui = Group()
self.main:disable_collision_between('player', 'player') self.main:disable_collision_between('player', 'player')
self.main:disable_collision_between('player', 'projectile') self.main:disable_collision_between('player', 'projectile')
self.main:disable_collision_between('player', 'enemy_projectile') self.main:disable_collision_between('player', 'enemy_projectile')
@ -28,7 +28,10 @@ function Arena:on_enter(from, level)
self.main:enable_trigger_between('enemy_projectile', 'player') self.main:enable_trigger_between('enemy_projectile', 'player')
self.enemies = {Seeker} self.enemies = {Seeker}
self.resources_gained = 0
self.color = self.color or fg[0]
-- Spawn solids and player
self.x1, self.y1 = gw/2 - 0.8*gw/2, gh/2 - 0.8*gh/2 self.x1, self.y1 = gw/2 - 0.8*gw/2, gh/2 - 0.8*gh/2
self.x2, self.y2 = gw/2 + 0.8*gw/2, gh/2 + 0.8*gh/2 self.x2, self.y2 = gw/2 + 0.8*gw/2, gh/2 + 0.8*gh/2
self.spawn_points = { self.spawn_points = {
@ -50,7 +53,6 @@ function Arena:on_enter(from, level)
WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x1, -40, self.x2, self.y1), color = bg[-1]} WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x1, -40, self.x2, self.y1), color = bg[-1]}
WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x1, self.y2, self.x2, gh + 40), color = bg[-1]} WallCover{group = self.post_main, vertices = math.to_rectangle_vertices(self.x1, self.y2, self.x2, gh + 40), color = bg[-1]}
for i, unit in ipairs(units) do for i, unit in ipairs(units) do
if i == 1 then if i == 1 then
self.player = Player{group = self.main, x = gw/2, y = gh/2, leader = true, character = unit.character, level = unit.level} self.player = Player{group = self.main, x = gw/2, y = gh/2, leader = true, character = unit.character, level = unit.level}
@ -58,8 +60,8 @@ function Arena:on_enter(from, level)
self.player:add_follower(Player{group = self.main, character = unit.character, level = unit.level}) self.player:add_follower(Player{group = self.main, character = unit.character, level = unit.level})
end end
end end
-- self.player:add_follower(Player{group = self.main, character = 'elementor'})
-- Set win condition and enemy spawns
self.win_condition = random:table{'time', 'enemy_kill', 'wave'} self.win_condition = random:table{'time', 'enemy_kill', 'wave'}
if self.win_condition == 'wave' then if self.win_condition == 'wave' then
self.level_to_max_waves = { self.level_to_max_waves = {
@ -158,6 +160,7 @@ function Arena:on_enter(from, level)
end) end)
end end
-- Calculate class levels
local units = {} local units = {}
table.insert(units, self.player) table.insert(units, self.player)
for _, f in ipairs(self.player.followers) do table.insert(units, f) end for _, f in ipairs(self.player.followers) do table.insert(units, f) end
@ -224,7 +227,14 @@ function Arena:update(dt)
if self.win_condition == 'enemy_kill' then if self.win_condition == 'enemy_kill' then
if self.can_quit then if self.can_quit then
self.t:after(2, function() self.t:after(2, function()
PostArenaScreen{group = self.ui, x = gw/2, y = gh/2} TransitionEffect{group = main.transition, x = self.player.x, y = self.player.y, dont_tween_out = true, color = self.color, transition_action = function()
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', self, self.level, self.color)
end, text = Text({
{text = '[wavy, bg]resources gained: +' .. tostring(self.resources_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy, bg]interest: +' .. tostring(math.floor(resource/10)), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy, bg]total: +' .. tostring(self.resources_gained + math.floor(resource/10)), font = pixul_font, alignment = 'center'}
}, global_text_tags)}
end) end)
end end
@ -235,7 +245,14 @@ function Arena:update(dt)
if #self.main:get_objects_by_classes(self.enemies) > 0 then if #self.main:get_objects_by_classes(self.enemies) > 0 then
self.can_quit = true self.can_quit = true
else else
PostArenaScreen{group = self.ui, x = gw/2, y = gh/2} TransitionEffect{group = main.transition, x = self.player.x, y = self.player.y, dont_tween_out = true, color = self.color, transition_action = function()
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', self, self.level, self.color)
end, text = Text({
{text = '[wavy, bg]resources gained: +' .. tostring(self.resources_gained), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy, bg]interest: +' .. tostring(math.floor(resource/10)), font = pixul_font, alignment = 'center', height_multiplier = 1.5},
{text = '[wavy, bg]total: +' .. tostring(self.resources_gained + math.floor(resource/10)), font = pixul_font, alignment = 'center'}
}, global_text_tags)}
end end
end) end)
end end
@ -351,24 +368,3 @@ function Arena:spawn_n_enemies(p, j, n)
end} end}
end, n, nil, 'spawn_enemies_' .. j) end, n, nil, 'spawn_enemies_' .. j)
end end
PostArenaScreen = Object:extend()
PostArenaScreen:implement(GameObject)
function PostArenaScreen:init(args)
self:init_game_object(args)
self.transparent = Color(0.1, 0.1, 0.1, 0.5)
end
function PostArenaScreen:update(dt)
self:update_game_object(dt)
end
function PostArenaScreen:draw()
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

127
buy_screen.lua 100644
View File

@ -0,0 +1,127 @@
BuyScreen = Object:extend()
BuyScreen:implement(State)
BuyScreen:implement(GameObject)
function BuyScreen:init(name)
self:init_state(name)
self:init_game_object()
end
function BuyScreen:on_enter(from, level)
self.level = level
self.main = Group()
self.effects = Group()
self.ui = Group()
if self.level == 0 then
local units = {'vagrant', 'swordsman', 'wizard', 'archer', 'scout', 'cleric'}
PairCard{group = self.main, x = gw/2, y = 85, w = gw, h = gh/4, unit_1 = random:table_remove(units), unit_2 = random:table_remove(units), i = 1}
local units = {'vagrant', 'swordsman', 'wizard', 'archer', 'scout', 'cleric'}
PairCard{group = self.main, x = gw/2, y = 155, w = gw, h = gh/4, unit_1 = random:table_remove(units), unit_2 = random:table_remove(units), i = 2}
local units = {'vagrant', 'swordsman', 'wizard', 'archer', 'scout', 'cleric'}
PairCard{group = self.main, x = gw/2, y = 225, w = gw, h = gh/4, unit_1 = random:table_remove(units), unit_2 = random:table_remove(units), i = 3}
self.title = Text({{text = '[fg]choose your initial party', font = pixul_font, alignment = 'center'}}, global_text_tags)
end
end
function BuyScreen:update(dt)
self:update_game_object(dt*slow_amount)
self.main:update(dt*slow_amount)
self.effects:update(dt*slow_amount)
self.ui:update(dt*slow_amount)
if self.level == 0 then
self.title:update(dt)
end
end
function BuyScreen:draw()
self.main:draw()
self.effects:draw()
self.ui:draw()
if self.level == 0 then
self.title:draw(3.25*gw/4, 25)
end
end
PairCard = Object:extend()
PairCard:implement(GameObject)
function PairCard:init(args)
self:init_game_object(args)
self.plus_r = 0
if self.i == 1 then
self:select()
end
end
function PairCard:update(dt)
self:update_game_object(dt)
end
function PairCard:select()
self.selected = true
self.spring:pull(0.05, 200, 10)
self.t:every_immediate(1.4, function()
if self.selected then
self.t:tween(0.7, self, {sx = 0.97, sy = 0.97, plus_r = -math.pi/32}, math.linear, function()
self.t:tween(0.7, self, {sx = 1.03, sy = 1.03, plus_r = math.pi/32}, math.linear, nil, 'pulse_1')
end, 'pulse_2')
end
end, nil, nil, 'pulse')
end
function PairCard:draw()
local x = self.x - self.w/3
if self.selected then
graphics.push(x + (fat_font:get_text_width(self.i) + 20)/2, self.y - 25 + 37/2, 0, self.spring.x*self.sx, self.spring.x*self.sy)
graphics.rectangle2(x - 52, self.y - 25, fat_font:get_text_width(self.i) + 20, 37, nil, nil, bg[2])
graphics.pop()
end
-- 1, 2, 3
graphics.push(x - 40 + fat_font:get_text_width(self.i)/2, self.y - fat_font.h/8, 0, self.spring.x*self.sx, self.spring.x*self.sy)
graphics.print(self.i, fat_font, x - 40, self.y, 0, self.sx, self.sy, nil, fat_font.h/2, fg[0])
graphics.pop()
-- Unit 1 + class symbols
graphics.push(x + (fat_font:get_text_width(self.unit_1:capitalize() .. 'w') + table.reduce(character_classes[self.unit_1], function(memo, v) return memo + 0.5*_G[v].w end, 0))/2, self.y - fat_font.h/8, 0,
self.spring.x*self.sx, self.spring.x*self.sy)
graphics.print(self.unit_1:capitalize(), fat_font, x, self.y, 0, 1, 1, nil, fat_font.h/2, character_colors[self.unit_1])
x = x + fat_font:get_text_width(self.unit_1 .. 'w')
for i, class in ipairs(character_classes[self.unit_1]) do
_G[class]:draw(x, self.y, 0, 0.4, 0.4, nil, 20, class_colors[class])
x = x + 0.5*_G[class].w
end
graphics.pop()
-- +
graphics.push(x + fat_font:get_text_width('+')/2, self.y, self.plus_r, self.spring.x*self.sx, self.spring.x*self.sy)
graphics.print('+', fat_font, x, self.y, 0, 1, 1, nil, fat_font.h/2, fg[0])
graphics.pop()
-- Unit 2 + class symbols
x = x + fat_font:get_text_width('+l')
graphics.push(x + (fat_font:get_text_width(self.unit_2:capitalize() .. 'w') + table.reduce(character_classes[self.unit_2], function(memo, v) return memo + 0.5*_G[v].w end, 0))/2, self.y - fat_font.h/8, 0,
self.spring.x*self.sx, self.spring.x*self.sy)
graphics.print(self.unit_2:capitalize(), fat_font, x, self.y, 0, 1, 1, nil, fat_font.h/2, character_colors[self.unit_2])
x = x + fat_font:get_text_width(self.unit_2 .. 'w')
for i, class in ipairs(character_classes[self.unit_2]) do
_G[class]:draw(x, self.y, 0, 0.4, 0.4, nil, 20, class_colors[class])
x = x + 0.5*_G[class].w
end
graphics.pop()
end

View File

@ -314,6 +314,13 @@ based on what's actually in the code:
| Enchanter | 1.2 | 1 | 1 | 1 | 1 | 1.2 | 1.2 | | Enchanter | 1.2 | 1 | 1 | 1 | 1 | 1.2 | 1.2 |
| Psy | 1.5 | 1 | 1 | 1 | 1 | 0.5 | 1 | | Psy | 1.5 | 1 | 1 | 1 | 1 | 0.5 | 1 |
# Day 12-13 - 28/02/21 & 01/03/21 # Day 12-15 - 28/02/21-03/03/21
I didn't work on anything. I didn't work on anything.
# Day 16 - 04/03/21
UI work on the game's first screen. These days that I ended up not doing nothing happened because of a mix of me not knowing what to do next, fixing my sleep schedule (failed, so I give up on this already), and trying
to think up how exactly I want the game's UI to be like. I ended up thinking too much and paralyzed myself into not doing anything.
Right now I'm just doing the most basic thing I can that still looks reasonably OK and conveys all the info needed.

View File

@ -43,3 +43,11 @@ end
function string:index(i) function string:index(i)
return self:sub(i, i) return self:sub(i, i)
end end
-- Returns the capitalized string
-- a = 'engine'
-- a:capitalize() -> 'Engine'
function string:capitalize()
return self:gsub("^%l", string.upper)
end

View File

@ -254,7 +254,7 @@ end
-- The memo variable starts as the first argument in the array, but sometimes, as in the last example, that's not the desired functionality. -- The memo variable starts as the first argument in the array, but sometimes, as in the last example, that's not the desired functionality.
-- For those cases the third argument comes in handy and can be used to set the initial value of memo directly. -- For those cases the third argument comes in handy and can be used to set the initial value of memo directly.
function table.reduce(t, f, dv, ...) function table.reduce(t, f, dv, ...)
local memo = t[1] or dv local memo = dv or t[1]
for i = 2, #t do for i = 2, #t do
memo = f(memo, t[i], i, ...) memo = f(memo, t[i], i, ...)
end end

View File

@ -40,15 +40,15 @@ function State:init_state(name)
end end
function State:enter(from) function State:enter(from, ...)
self.active = true self.active = true
if self.on_enter then self:on_enter(from) end if self.on_enter then self:on_enter(from, ...) end
end end
function State:exit(to) function State:exit(to, ...)
self.active = false self.active = false
if self.on_exit then self:on_exit(to) end if self.on_exit then self:on_exit(to, ...) end
end end

View File

@ -1,6 +1,7 @@
require 'engine' require 'engine'
require 'shared' require 'shared'
require 'arena' require 'arena'
require 'buy_screen'
require 'objects' require 'objects'
require 'player' require 'player'
require 'enemies' require 'enemies'
@ -64,12 +65,80 @@ function init()
rogue_crit1 = Sound('Dagger Stab (Flesh) 4.ogg', s) rogue_crit1 = Sound('Dagger Stab (Flesh) 4.ogg', s)
rogue_crit2 = Sound('Sword hits another sword 6.ogg', s) rogue_crit2 = Sound('Sword hits another sword 6.ogg', s)
warrior = Image('warrior')
ranger = Image('ranger')
healer = Image('healer')
mage = Image('mage')
rogue = Image('rogue')
nuker = Image('nuker')
conjurer = Image('conjurer')
enchanter = Image('enchanter')
psy = Image('psy')
class_colors = {
['warrior'] = yellow[0],
['ranger'] = green[0],
['healer'] = green[0],
['conjurer'] = yellow[0],
['mage'] = blue[0],
['nuker'] = blue[0],
['rogue'] = red[0],
['enchanter'] = red[0],
['psy'] = fg[0],
}
character_colors = {
['vagrant'] = fg[0],
['swordsman'] = yellow[0],
['wizard'] = blue[0],
['archer'] = green[0],
['scout'] = red[0],
['cleric'] = green[0],
['outlaw'] = red[0],
['blade'] = yellow[0],
['elementor'] = blue[0],
['saboteur'] = red[0],
['stormweaver'] = red[0],
['sage'] = blue[0],
['squire'] = yellow[0],
['cannoneer'] = green[0],
['dual_gunner'] = green[0],
['hunter'] = green[0],
['chronomancer'] = blue[0],
['spellblade'] = blue[0],
['psykeeper'] = fg[0],
['engineer'] = yellow[0],
}
character_classes = {
['vagrant'] = {'ranger', 'warrior', 'psy'},
['swordsman'] = {'warrior'},
['wizard'] = {'mage'},
['archer'] = {'ranger'},
['scout'] = {'rogue'},
['cleric'] = {'healer'},
['outlaw'] = {'warrior', 'rogue'},
['blade'] = {'warrior', 'nuker'},
['elementor'] = {'mage', 'nuker'},
['saboteur'] = {'rogue', 'conjurer', 'nuker'},
['stormweaver'] = {'enchanter'},
['sage'] = {'mage', 'nuker'},
['squire'] = {'warrior', 'healer', 'enchanter'},
['cannoneer'] = {'ranger', 'nuker'},
['dual_gunner'] = {'ranger', 'rogue'},
['hunter'] = {'ranger', 'conjurer'},
['chronomancer'] = {'mage', 'enchanter'},
['spellblade'] = {'mage', 'rogue'},
['psykeeper'] = {'healer', 'psy'},
['engineer'] = {'conjurer'},
}
units = {} units = {}
gold = 0 resource = 0
main = Main() main = Main()
main:add(Arena'arena') main:add(BuyScreen'buy_screen')
main:go_to('arena', {first_run = true}) main:go_to('buy_screen', 0)
end end

View File

@ -7,10 +7,10 @@ function Player:init(args)
self:init_unit() self:init_unit()
if self.character == 'vagrant' then if self.character == 'vagrant' then
self.color = fg[0] self.color = character_colors.vagrant
self:set_as_rectangle(9, 9, 'dynamic', 'player') self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle' self.visual_shape = 'rectangle'
self.classes = {'ranger', 'warrior', 'psy'} self.classes = character_classes.vagrant
self.attack_sensor = Circle(self.x, self.y, 96) self.attack_sensor = Circle(self.x, self.y, 96)
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
@ -21,10 +21,10 @@ function Player:init(args)
end, nil, nil, 'shoot') end, nil, nil, 'shoot')
elseif self.character == 'swordsman' then elseif self.character == 'swordsman' then
self.color = yellow[0] self.color = character_colors.swordsman
self:set_as_rectangle(9, 9, 'dynamic', 'player') self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle' self.visual_shape = 'rectangle'
self.classes = {'warrior'} self.classes = character_classes.swordsman
self.attack_sensor = Circle(self.x, self.y, 64) self.attack_sensor = Circle(self.x, self.y, 64)
self.t:cooldown(3, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() self.t:cooldown(3, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
@ -32,10 +32,10 @@ function Player:init(args)
end, nil, nil, 'attack') end, nil, nil, 'attack')
elseif self.character == 'wizard' then elseif self.character == 'wizard' then
self.color = blue[0] self.color = character_colors.wizard
self:set_as_rectangle(9, 9, 'dynamic', 'player') self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle' self.visual_shape = 'rectangle'
self.classes = {'mage'} self.classes = character_classes.wizard
self.attack_sensor = Circle(self.x, self.y, 128) self.attack_sensor = Circle(self.x, self.y, 128)
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
@ -46,10 +46,10 @@ function Player:init(args)
end, nil, nil, 'shoot') end, nil, nil, 'shoot')
elseif self.character == 'archer' then elseif self.character == 'archer' then
self.color = green[0] self.color = character_colors.archer
self:set_as_rectangle(9, 9, 'dynamic', 'player') self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle' self.visual_shape = 'rectangle'
self.classes = {'ranger'} self.classes = character_classes.archer
self.attack_sensor = Circle(self.x, self.y, 160) self.attack_sensor = Circle(self.x, self.y, 160)
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()
@ -60,10 +60,10 @@ function Player:init(args)
end, nil, nil, 'shoot') end, nil, nil, 'shoot')
elseif self.character == 'scout' then elseif self.character == 'scout' then
self.color = red[0] self.color = character_colors.scout
self:set_as_rectangle(9, 9, 'dynamic', 'player') self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle' self.visual_shape = 'rectangle'
self.classes = {'rogue'} self.classes = character_classes.scout
self.attack_sensor = Circle(self.x, self.y, 64) self.attack_sensor = Circle(self.x, self.y, 64)
self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function() self.t:cooldown(2, function() local enemies = self:get_objects_in_shape(self.attack_sensor, main.current.enemies); return enemies and #enemies > 0 end, function()

View File

@ -393,7 +393,11 @@ function TransitionEffect:init(args)
self.t:after(0.5, function() self.t:after(0.5, function()
self.x, self.y = gw/2, gh/2 self.x, self.y = gw/2, gh/2
self.t:after(0.7, function() self.t:tween(0.05, self, {text_sx = 0, text_sy = 0}, math.cubic_in_out) end) self.t:after(0.7, function() self.t:tween(0.05, self, {text_sx = 0, text_sy = 0}, math.cubic_in_out) end)
self.t:tween(0.75, self, {rs = 0}, math.linear, function() self.text = nil; self.dead = true end) if not args.dont_tween_out then
self.t:tween(0.75, self, {rs = 0}, math.linear, function() self.text = nil; self.dead = true end)
else
self.t:after(0.75, function() self.text = nil; self.dead = true end)
end
end) end)
end) end)
end) end)