aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2023-04-16 18:06:53 +0100
committerFederico Igne <git@federicoigne.com>2023-04-16 18:06:53 +0100
commit2e6882c1843374b00942e964604302772476a4e8 (patch)
tree475c580be87b15df37ec2e416ee7b909e383304b
parentcd3d19443e80ed1d328dd0cb466906bb90e3baae (diff)
downloadraccoon-master.tar.gz
raccoon-master.zip
feat: add dialog functionalityHEADmaster
-rw-r--r--raccoon.lua185
1 files changed, 171 insertions, 14 deletions
diff --git a/raccoon.lua b/raccoon.lua
index fac2f03..750c890 100644
--- a/raccoon.lua
+++ b/raccoon.lua
@@ -8,6 +8,7 @@
8-- Add width/height to Pos component 8-- Add width/height to Pos component
9-- Extend to 4 action buttons 9-- Extend to 4 action buttons
10-- Call math.randomseed (x) in an init function 10-- Call math.randomseed (x) in an init function
11-- Screen shake on hit
11 12
12--- Utility functions 13--- Utility functions
13-- @section Utility functions 14-- @section Utility functions
@@ -413,6 +414,76 @@ function Metadata:init(name)
413 return self 414 return self
414end 415end
415 416
417-- Dialog width is 61 cols and 6 rows
418Dialog = Component("Dialog")
419function Dialog:init(content)
420 self.content_id = 1
421 self.content = content
422 self.display = ""
423 return self
424end
425function Dialog.step(self)
426 if self.content[self.content_id] then
427 local cont = self.content[self.content_id]
428 if not cont.type or cont.type == "text" then
429 if not self.line_id then
430 self.line_id = 1
431 self.char_id = 0
432 self.display = ""
433 end
434 self.char_id = self.char_id + 1
435 if self.char_id <= #cont[self.line_id] then
436 local c = string.sub(cont[self.line_id], self.char_id, self.char_id)
437 self.display = self.display .. c
438 else
439 self.line_id = self.line_id + 1
440 if self.line_id <= #cont then
441 self.display = self.display .. "\n"
442 self.char_id = 0
443 else
444 self.content_id = self.content_id + 1
445 self.line_id = nil
446 end
447 end
448 elseif cont.type == "confirm" then
449 -- wait for user input
450 else
451 -- other types of content
452 end
453 return true
454 else
455 return false
456 end
457end
458function Dialog:yes()
459 if self.content[self.content_id] then
460 local cont = self.content[self.content_id]
461 if not cont.type or cont.type == "text" then
462 self.display = ""
463 for l = 1,#cont do
464 self.display = self.display .. cont[l] .. "\n"
465 end
466 self.content_id = self.content_id + 1
467 self.line_id = nil
468 elseif cont.type == "confirm" then
469 self.content_id = self.content_id + 1
470 else
471 -- other types of content
472 end
473 return true
474 else
475 return false
476 end
477end
478function Dialog:no()
479 -- Not implemented
480 return true
481end
482function Dialog:is_confirm()
483 return self.content[self.content_id] and
484 self.content[self.content_id].type == "confirm"
485end
486
416Action = Component("Action") 487Action = Component("Action")
417function Action:init(a,b) 488function Action:init(a,b)
418 self.a = a 489 self.a = a
@@ -428,6 +499,30 @@ function Action.forcefield(entity,game)
428 ForceField(2,10,ForceField.by_id(entity.id),true), 499 ForceField(2,10,ForceField.by_id(entity.id),true),
429 CircleEffect(20)})) 500 CircleEffect(20)}))
430end 501end
502function Action.dialog(entity,game)
503 if game.status ~= 3 then
504 game.status = 3
505 game.dialog =
506 Entity():with(
507 Dialog(
508 {
509 {
510 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed",
511 "do eiusmod tempor incididunt ut labore et dolore magna",
512 "aliqua. Ut enim ad minim veniam, quis nostrud exercitation",
513 "ullamco laboris nisi ut aliquip ex ea commodo consequat.",
514 "Duis aute irure dolor in reprehenderit in voluptate velit",
515 "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint"
516 },
517 { type = "confirm" },
518 {
519 "occaecat cupidatat non proident, sunt in culpa qui officia",
520 "deserunt mollit anim id est laborum."
521 },
522 { type = "confirm" }
523 }))
524 end
525end
431 526
432Target = Component("Target") 527Target = Component("Target")
433function Target:init(pos, prox, sticky) 528function Target:init(pos, prox, sticky)
@@ -632,12 +727,43 @@ function DrawingSystem:exec(entity,level)
632 end 727 end
633 end 728 end
634end 729end
730function DrawingSystem:dialog(d)
731 local origin = {1,9}
732 local size = {27,6}
733 -- Top/bottom
734 for i = origin[1]+1,origin[1]+size[1]-1 do
735 spr(18, i*8, origin[2]*8, 0)
736 spr(18, i*8, (origin[2]+size[2])*8, 0, 1, 2)
737 end
738 -- Left/right
739 for i = origin[2]+1,origin[2]+size[2]-1 do
740 spr(19, origin[1]*8, i*8, 0)
741 spr(19, (origin[1]+size[1])*8, i*8, 0, 1, 1)
742 end
743 -- Corners (NW,NE,SW,SE)
744 spr(16, origin[1]*8, origin[2]*8, 0)
745 spr(16, (origin[1]+size[1])*8, origin[2]*8, 0, 1, 1)
746 spr(16, origin[1]*8, (origin[2]+size[2])*8, 0, 1, 2)
747 spr(16, (origin[1]+size[1])*8, (origin[2]+size[2])*8, 0, 1, 3)
748 -- Filling
749 rect((origin[1]+1)*8, (origin[2]+1)*8,
750 (size[1]-1)*8, (size[2]-1)*8, 11)
751 -- Dialog
752 local dialog = d:get_dialog()
753 print(dialog.display, 2*8, 10*8, 15, false, 1, true)
754 if dialog:is_confirm() then
755 spr(20, (origin[1]+size[1]-1)*8, (origin[2]+size[2])*8-4, 0)
756 end
757end
635function DrawingSystem:draw(game) 758function DrawingSystem:draw(game)
636 local level = game.levels[game.level] 759 local level = game.levels[game.level]
637 local info = level:get_level() 760 local info = level:get_level()
638 local pos = level:get_pos() 761 local pos = level:get_pos()
639 map(pos.x//8,pos.y//8,31,18,-(pos.x%8),-(pos.y%8),-1) 762 map(pos.x//8,pos.y//8,31,18,-(pos.x%8),-(pos.y%8),-1)
640 DrawingSystem:run(game.entities,pos) 763 self:run(game.entities,pos)
764 if game.status == 3 then
765 self:dialog(game.dialog)
766 end
641end 767end
642 768
643local LevelSystem = System(Level) 769local LevelSystem = System(Level)
@@ -675,6 +801,19 @@ function ActionSystem:exec(entity,game)
675 end 801 end
676end 802end
677 803
804-- Not a System per se but it should be
805local DialogSystem = util.new_class()
806function DialogSystem:run(entity,input,game)
807 local dialog = entity:get_dialog()
808 if not dialog:step() then
809 game.status = 1
810 elseif input.rawp[5] and not dialog:yes() then
811 game.status = 1
812 elseif input.rawp[6] and not dialog:no() then
813 game.status = 1
814 end
815end
816
678local EffectSystem = System() 817local EffectSystem = System()
679function EffectSystem:exec(entity) 818function EffectSystem:exec(entity)
680 if entity:has_circleeffect() then 819 if entity:has_circleeffect() then
@@ -722,7 +861,7 @@ local player = Entity():with({
722 Metadata("Giulia"), Sprite(256), 861 Metadata("Giulia"), Sprite(256),
723 Pos(100,10), Health(100), Status(), 862 Pos(100,10), Health(100), Status(),
724 Movement(), Jump(10), 863 Movement(), Jump(10),
725 Input(0,1,2,3,4,5), Action(Action.forcefield,nil) 864 Input(0,1,2,3,4,5), Action(Action.forcefield,Action.dialog)
726}) 865})
727 866
728local level1_entities = { 867local level1_entities = {
@@ -738,9 +877,14 @@ local level1_entities = {
738 :with(PosAnim(function(t,p) p.y = p.y - math.sin(t/6)/3 end)), 877 :with(PosAnim(function(t,p) p.y = p.y - math.sin(t/6)/3 end)),
739} 878}
740 879
741-- TODO turn this into something more structured, containing everything related 880--- Wrapper description of the running game
742-- to the game 881--
882-- A table containing all the information about the game.
883-- @field status The status of the game (1 = running, 2 = pause, 3 = dialog)
884-- @field player Reference to the main player
885-- TODO turn `game` into a component
743local game = { 886local game = {
887 status = 1,
744 player = player, 888 player = player,
745 entities = { player }, 889 entities = { player },
746 level = 1, 890 level = 1,
@@ -764,20 +908,28 @@ function TIC()
764 cls(0) 908 cls(0)
765 909
766 InputSystem:run(game.entities) 910 InputSystem:run(game.entities)
767 TargetSystem:run(game.entities)
768 911
769 StatusSystem:run(game.entities) 912 if game.status == 1 then
913 -- Running game
914 ActionSystem:run(game.entities, game)
915 TargetSystem:run(game.entities)
916
917 StatusSystem:run(game.entities)
770 918
771 MovementSystem:run(game.entities) 919 MovementSystem:run(game.entities)
772 ActionSystem:run(game.entities, game) 920 ForceFieldSystem:run(game.entities, game.entities)
773 ForceFieldSystem:run(game.entities, game.entities)
774 921
775 PosAnimSystem:run(game.entities) 922 PosAnimSystem:run(game.entities)
776 EffectSystem:run(game.entities) 923 EffectSystem:run(game.entities)
777 ParticlesSystem:run(game.entities, game) 924 ParticlesSystem:run(game.entities, game)
778 925
779 LevelSystem:run(game.levels, game) 926 LevelSystem:run(game.levels, game)
780 BoundarySystem:run(game.entities, game.levels[game.level]:get_pos()) 927 BoundarySystem:run(game.entities, game.levels[game.level]:get_pos())
928
929 elseif game.status == 3 then
930 -- Dialog/Menu
931 DialogSystem:run(game.dialog, game.player:get_input(), game)
932 end
781 933
782 DrawingSystem:draw(game) 934 DrawingSystem:draw(game)
783 935
@@ -794,6 +946,11 @@ end
794-- 002:6666666666666666666666666666666666666666666666666666666666666666 946-- 002:6666666666666666666666666666666666666666666666666666666666666666
795-- 003:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 947-- 003:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
796-- 004:9999999999999999999999999999999999999999999999999999999999999999 948-- 004:9999999999999999999999999999999999999999999999999999999999999999
949-- 016:8888000089988888899899998888aaaa089abbbb089abbbb089abbbb089abbbb
950-- 017:089abbbb089abbbb089abbbb089abbbb8888aaaa899899998998888888880000
951-- 018:000000008888888899999999aaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
952-- 019:089abbbb089abbbb089abbbb089abbbb089abbbb089abbbb089abbbb089abbbb
953-- 020:0000000000000000cccccccd0cccccd000cccd00000cd0000000000000000000
797-- </TILES> 954-- </TILES>
798 955
799-- <SPRITES> 956-- <SPRITES>