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.post_main = 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', '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.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.x2, self.y2 = gw/2 + 0.8*gw/2, gh/2 + 0.8*gh/2
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, self.y2, self.x2, gh + 40), color = bg[-1]}
for i, unit in ipairs(units) do
if i == 1 then
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})
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'}
if self.win_condition == 'wave' then
self.level_to_max_waves = {
@ -158,6 +160,7 @@ function Arena:on_enter(from, level)
end)
end
-- Calculate class levels
local units = {}
table.insert(units, self.player)
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.can_quit then
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
@ -235,7 +245,14 @@ function Arena:update(dt)
if #self.main:get_objects_by_classes(self.enemies) > 0 then
self.can_quit = true
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
@ -351,24 +368,3 @@ function Arena:spawn_n_enemies(p, j, n)
end}
end, n, nil, 'spawn_enemies_' .. j)
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 |
| 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.
# 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)
return self:sub(i, i)
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.
-- 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, ...)
local memo = t[1] or dv
local memo = dv or t[1]
for i = 2, #t do
memo = f(memo, t[i], i, ...)
end

View File

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

View File

@ -1,6 +1,7 @@
require 'engine'
require 'shared'
require 'arena'
require 'buy_screen'
require 'objects'
require 'player'
require 'enemies'
@ -64,12 +65,80 @@ function init()
rogue_crit1 = Sound('Dagger Stab (Flesh) 4.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 = {}
gold = 0
resource = 0
main = Main()
main:add(Arena'arena')
main:go_to('arena', {first_run = true})
main:add(BuyScreen'buy_screen')
main:go_to('buy_screen', 0)
end

View File

@ -7,10 +7,10 @@ function Player:init(args)
self:init_unit()
if self.character == 'vagrant' then
self.color = fg[0]
self.color = character_colors.vagrant
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = {'ranger', 'warrior', 'psy'}
self.classes = character_classes.vagrant
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()
@ -21,10 +21,10 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'swordsman' then
self.color = yellow[0]
self.color = character_colors.swordsman
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = {'warrior'}
self.classes = character_classes.swordsman
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()
@ -32,10 +32,10 @@ function Player:init(args)
end, nil, nil, 'attack')
elseif self.character == 'wizard' then
self.color = blue[0]
self.color = character_colors.wizard
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = {'mage'}
self.classes = character_classes.wizard
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()
@ -46,10 +46,10 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'archer' then
self.color = green[0]
self.color = character_colors.archer
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = {'ranger'}
self.classes = character_classes.archer
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()
@ -60,10 +60,10 @@ function Player:init(args)
end, nil, nil, 'shoot')
elseif self.character == 'scout' then
self.color = red[0]
self.color = character_colors.scout
self:set_as_rectangle(9, 9, 'dynamic', 'player')
self.visual_shape = 'rectangle'
self.classes = {'rogue'}
self.classes = character_classes.scout
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()

View File

@ -393,7 +393,11 @@ function TransitionEffect:init(args)
self.t:after(0.5, function()
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: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)