pdadv 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +87 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +46 -0
- data/LICENSE.txt +21 -0
- data/README.md +71 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/pdadv +5 -0
- data/lib/pdadv.rb +40 -0
- data/lib/pdadv/cli.rb +31 -0
- data/lib/pdadv/entities/image_entity.rb +16 -0
- data/lib/pdadv/environment.rb +29 -0
- data/lib/pdadv/renderer.rb +142 -0
- data/lib/pdadv/scenario.rb +76 -0
- data/lib/pdadv/scenario_parser.rb +61 -0
- data/lib/pdadv/screen.rb +57 -0
- data/lib/pdadv/version.rb +5 -0
- data/pdadv.gemspec +29 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: db1b45f1233e3944fc6198d0424f1ae18a02e94fa0a7184285bbf2451b4d3601
|
4
|
+
data.tar.gz: 10cd89134f983a62c0452a7c0e22a349810217cbc52fe551bdea6143e3af5413
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b01f155f45e826804ca74fe71dc41a0a7d81f3b56e6a8d92b7e3a4a11ed485b8e21b54f2e48bdb739e1fabf6ae9a9bfa77d657d780d253e039528d426d772208
|
7
|
+
data.tar.gz: a68ef65fd34b466cfc4c570773b3f3545e470e6f63478d8aab86b3613fd5aae74a9bbc804488477a351679e17a08b28fadb5a5197703526d5b324ca0aaec3238
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- tmp/**/*
|
4
|
+
- vendor/**/*
|
5
|
+
TargetRubyVersion: 2.5
|
6
|
+
DisplayCopNames: true
|
7
|
+
|
8
|
+
# use japanese :)
|
9
|
+
Style/AsciiComments:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
# use method chain ( avoid use `end.compact` )
|
13
|
+
#
|
14
|
+
# hoge.map { |item|
|
15
|
+
# item.piyo
|
16
|
+
# }.compact
|
17
|
+
Style/BlockDelimiters:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
# rubocop v.0.51.0 is bugging...
|
21
|
+
#
|
22
|
+
# def tweet(hash_tag: '#twitter')`
|
23
|
+
# ...
|
24
|
+
# end
|
25
|
+
Style/CommentedKeyword:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
# no document
|
29
|
+
Style/Documentation:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
# use `!!hoge`
|
33
|
+
Style/DoubleNegation:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
# empty case is useful
|
37
|
+
#
|
38
|
+
# case
|
39
|
+
# when user.admin?
|
40
|
+
# ...
|
41
|
+
# when user.active?
|
42
|
+
# ...
|
43
|
+
# else
|
44
|
+
# ...
|
45
|
+
# end
|
46
|
+
Style/EmptyCaseCondition:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
# my preference :)
|
50
|
+
Style/EmptyMethod:
|
51
|
+
EnforcedStyle: expanded
|
52
|
+
|
53
|
+
# use `-> {}` syntax
|
54
|
+
Style/Lambda:
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
# see Style/BlockDelimiters
|
58
|
+
Style/MultilineBlockChain:
|
59
|
+
Enabled: false
|
60
|
+
|
61
|
+
# I feel `.zero?` difficult to understand...
|
62
|
+
Style/NumericPredicate:
|
63
|
+
Enabled: false
|
64
|
+
|
65
|
+
# %w[a b c] or %i[a b c] ?
|
66
|
+
Style/SymbolArray:
|
67
|
+
Enabled: false
|
68
|
+
|
69
|
+
# incompatible DSL
|
70
|
+
Layout/EmptyLinesAroundArguments:
|
71
|
+
Enabled: false
|
72
|
+
|
73
|
+
# incompatible DSL
|
74
|
+
Metrics/BlockLength:
|
75
|
+
Enabled: false
|
76
|
+
|
77
|
+
# :)
|
78
|
+
Metrics/ClassLength:
|
79
|
+
Enabled: false
|
80
|
+
|
81
|
+
# :)
|
82
|
+
Metrics/LineLength:
|
83
|
+
Max: 120
|
84
|
+
|
85
|
+
# :)
|
86
|
+
Metrics/MethodLength:
|
87
|
+
Max: 25
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pdadv (0.1.0)
|
5
|
+
fastimage
|
6
|
+
prawn
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
ast (2.4.0)
|
12
|
+
fastimage (2.1.3)
|
13
|
+
jaro_winkler (1.5.1)
|
14
|
+
parallel (1.12.1)
|
15
|
+
parser (2.5.1.2)
|
16
|
+
ast (~> 2.4.0)
|
17
|
+
pdf-core (0.7.0)
|
18
|
+
powerpack (0.1.2)
|
19
|
+
prawn (2.2.2)
|
20
|
+
pdf-core (~> 0.7.0)
|
21
|
+
ttfunk (~> 1.5)
|
22
|
+
rainbow (3.0.0)
|
23
|
+
rake (10.5.0)
|
24
|
+
rubocop (0.58.2)
|
25
|
+
jaro_winkler (~> 1.5.1)
|
26
|
+
parallel (~> 1.10)
|
27
|
+
parser (>= 2.5, != 2.5.1.1)
|
28
|
+
powerpack (~> 0.1)
|
29
|
+
rainbow (>= 2.2.2, < 4.0)
|
30
|
+
ruby-progressbar (~> 1.7)
|
31
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
32
|
+
ruby-progressbar (1.10.0)
|
33
|
+
ttfunk (1.5.1)
|
34
|
+
unicode-display_width (1.4.0)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
bundler (~> 1.16)
|
41
|
+
pdadv!
|
42
|
+
rake (~> 10.0)
|
43
|
+
rubocop
|
44
|
+
|
45
|
+
BUNDLED WITH
|
46
|
+
1.16.1
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 ru_shalm
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Pdadv
|
2
|
+
|
3
|
+
> PDF Adventure game framework
|
4
|
+
|
5
|
+
*It's a joke framework :)*
|
6
|
+
|
7
|
+
## demo
|
8
|
+
|
9
|
+
- play on browser
|
10
|
+
- https://niconare.nicovideo.jp/watch/kn3335
|
11
|
+
- scenario file
|
12
|
+
- https://github.com/rutan/pdadv_demo_quest
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
```bash
|
17
|
+
$ gem install pdadv
|
18
|
+
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
(1) make scenario file
|
23
|
+
|
24
|
+
```
|
25
|
+
%setGlobal Size, 1280, 960
|
26
|
+
%setGlobal Frame, ./assets/frame.png
|
27
|
+
%setGlobal Font, ./assets/myFont.ttf
|
28
|
+
%setGlobal TextColor, #ffffff
|
29
|
+
%setGlobal TextSize, 40
|
30
|
+
%setGlobal MessageArea, 360, 570, 570, 350
|
31
|
+
%setGlobal MessageWindow, ./assets/message_window.png
|
32
|
+
|
33
|
+
%register back, ./assets/back.jpg
|
34
|
+
%register myCharacter, ./assets/myCharacter.png
|
35
|
+
|
36
|
+
%back title
|
37
|
+
|
38
|
+
## start
|
39
|
+
|
40
|
+
%back back
|
41
|
+
%show 1, myCharacter
|
42
|
+
|
43
|
+
Hello, Pdadv!
|
44
|
+
|
45
|
+
- [Hello!](hello)
|
46
|
+
- [Good Bye!](end)
|
47
|
+
|
48
|
+
## hello
|
49
|
+
|
50
|
+
%back back
|
51
|
+
%show 1, myCharacter
|
52
|
+
|
53
|
+
Game Clear!
|
54
|
+
|
55
|
+
## end
|
56
|
+
%back back
|
57
|
+
|
58
|
+
Game Over...
|
59
|
+
|
60
|
+
- [Retry!](start)
|
61
|
+
```
|
62
|
+
|
63
|
+
(2) convert scenario to PDF
|
64
|
+
|
65
|
+
```bash
|
66
|
+
pdadv -o output.pdf scenario.txt
|
67
|
+
```
|
68
|
+
|
69
|
+
## License
|
70
|
+
|
71
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'pdadv'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/pdadv
ADDED
data/lib/pdadv.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prawn'
|
4
|
+
|
5
|
+
require 'pdadv/version'
|
6
|
+
require 'pdadv/entities/image_entity'
|
7
|
+
require 'pdadv/cli'
|
8
|
+
require 'pdadv/environment'
|
9
|
+
require 'pdadv/renderer'
|
10
|
+
require 'pdadv/scenario'
|
11
|
+
require 'pdadv/scenario_parser'
|
12
|
+
require 'pdadv/screen'
|
13
|
+
|
14
|
+
module Prawn
|
15
|
+
module Text
|
16
|
+
module Formatted
|
17
|
+
class Box
|
18
|
+
alias upstream_draw_fragment_overlay_anchor draw_fragment_overlay_anchor
|
19
|
+
def draw_fragment_overlay_anchor(fragment)
|
20
|
+
return unless fragment.anchor
|
21
|
+
|
22
|
+
if /\A#\d+\z/.match?(fragment.anchor.to_s)
|
23
|
+
i = fragment.anchor.sub('#', '').to_i
|
24
|
+
box = fragment.absolute_bounding_box
|
25
|
+
page = @document.state.pages[i]
|
26
|
+
if page
|
27
|
+
@document.link_annotation(
|
28
|
+
box,
|
29
|
+
Border: [0, 0, 0],
|
30
|
+
Dest: @document.dest_xyz(0, 0, nil, page)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
upstream_draw_fragment_overlay_anchor(fragment)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/pdadv/cli.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
module Pdadv
|
6
|
+
class CLI
|
7
|
+
def initialize(argv)
|
8
|
+
@options = {
|
9
|
+
output: 'output.pdf'
|
10
|
+
}
|
11
|
+
|
12
|
+
opt = OptionParser.new
|
13
|
+
opt.on('-o VAL') { |n| @options[:output] = n }
|
14
|
+
@scenario_name, = opt.parse(argv)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
scenario = Pdadv::ScenarioParser.new(@scenario_name).parse
|
19
|
+
|
20
|
+
renderer = Pdadv::Renderer.new(scenario)
|
21
|
+
renderer.render
|
22
|
+
renderer.save_as(@options[:output])
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def run!(argv)
|
27
|
+
new(argv).run
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pdadv
|
4
|
+
module Entities
|
5
|
+
class ImageEntity
|
6
|
+
def initialize(params = {})
|
7
|
+
@path = params[:path].to_s
|
8
|
+
@x = params[:x].to_i
|
9
|
+
@y = params[:y].to_i
|
10
|
+
@width = params[:width].to_i
|
11
|
+
@height = params[:height].to_i
|
12
|
+
end
|
13
|
+
attr_reader :path, :x, :y, :width, :height
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pdadv
|
4
|
+
class Environment
|
5
|
+
def initialize
|
6
|
+
@base_path = ''
|
7
|
+
@settings = {
|
8
|
+
'Font' => '',
|
9
|
+
'TextColor' => '#ffffff',
|
10
|
+
'TextSize' => '40',
|
11
|
+
'Size' => [1280, 960],
|
12
|
+
'MessageWindow' => nil,
|
13
|
+
'MessageArea' => [0, 0, 1280, 960],
|
14
|
+
'Frame' => nil
|
15
|
+
}
|
16
|
+
end
|
17
|
+
attr_accessor :base_path
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
@settings[key.to_s]
|
21
|
+
end
|
22
|
+
|
23
|
+
def []=(key, value)
|
24
|
+
key = key.to_s
|
25
|
+
raise "unknown global env: #{key}" unless @settings.key?(key)
|
26
|
+
@settings[key] = value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'prawn'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
module Pdadv
|
7
|
+
class Renderer
|
8
|
+
include Prawn::View
|
9
|
+
|
10
|
+
def initialize(scenario)
|
11
|
+
@scenario = scenario
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :scenario
|
15
|
+
|
16
|
+
def document
|
17
|
+
@document ||= Prawn::Document.new(
|
18
|
+
page_size: scenario.env['Size'].map(&:to_i),
|
19
|
+
margin: 0
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render
|
24
|
+
font(scenario.asset_path(scenario.env['Font']))
|
25
|
+
create_pages
|
26
|
+
scenario.screens.each.with_index do |screen, i|
|
27
|
+
go_to_page(i + 1)
|
28
|
+
render_page(screen)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def create_pages
|
35
|
+
scenario.screens.each.with_index do |_, i|
|
36
|
+
start_new_page if i > 0
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_page(screen)
|
41
|
+
add_dest(screen.name, dest_xyz(0, 0))
|
42
|
+
|
43
|
+
draw_back(screen)
|
44
|
+
draw_characters(screen)
|
45
|
+
draw_message_window(screen)
|
46
|
+
draw_frame
|
47
|
+
draw_message_body(screen)
|
48
|
+
end
|
49
|
+
|
50
|
+
def draw_back(screen)
|
51
|
+
return unless screen.back
|
52
|
+
float do
|
53
|
+
image(
|
54
|
+
scenario.asset_path(screen.back.path),
|
55
|
+
position: :center,
|
56
|
+
vposition: :center,
|
57
|
+
fit: scenario.env['Size']
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def draw_characters(screen)
|
63
|
+
screen.actors.each.with_index do |actor, i|
|
64
|
+
next unless actor
|
65
|
+
|
66
|
+
float do
|
67
|
+
x = (i + 1) * scenario.env['Size'][0] / 7
|
68
|
+
draw_character_image(actor, x)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def draw_character_image(actor, base_x)
|
74
|
+
image(
|
75
|
+
scenario.asset_path(actor.path),
|
76
|
+
at: [base_x + actor.x - actor.width / 2, -(actor.y - actor.height)]
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def draw_message_window(screen)
|
81
|
+
return if scenario.env['MessageWindow'].empty?
|
82
|
+
return if screen.message.empty?
|
83
|
+
|
84
|
+
float do
|
85
|
+
image(
|
86
|
+
scenario.asset_path(scenario.env['MessageWindow']),
|
87
|
+
position: :center,
|
88
|
+
vposition: :bottom
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def draw_message_body(screen)
|
94
|
+
return create_large_next_link if screen.message.empty?
|
95
|
+
|
96
|
+
float do
|
97
|
+
message_window_box do
|
98
|
+
text screen.format_message(scenario), draw_message_options
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_large_next_link
|
104
|
+
target_page = state.pages[page_number]
|
105
|
+
return unless target_page
|
106
|
+
@document.link_annotation(
|
107
|
+
[bounds.absolute_left, bounds.absolute_bottom, bounds.absolute_right, bounds.absolute_top],
|
108
|
+
Border: [0, 0, 0],
|
109
|
+
Dest: @document.dest_xyz(0, 0, nil, target_page)
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
def message_window_box
|
114
|
+
x, y, w, h = scenario.env['MessageArea']
|
115
|
+
y = scenario.env['Size'][1] - y
|
116
|
+
bounding_box([x, y], width: w, height: h) do
|
117
|
+
yield
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def draw_message_options
|
122
|
+
{
|
123
|
+
color: scenario.env['TextColor'].delete('#'),
|
124
|
+
size: scenario.env['TextSize'],
|
125
|
+
leading: (scenario.env['TextSize'] * 0.5),
|
126
|
+
inline_format: true
|
127
|
+
}
|
128
|
+
end
|
129
|
+
|
130
|
+
def draw_frame
|
131
|
+
return if scenario.env['Frame'].empty?
|
132
|
+
|
133
|
+
float do
|
134
|
+
image(
|
135
|
+
scenario.asset_path(scenario.env['Frame']),
|
136
|
+
position: :center,
|
137
|
+
vposition: :center
|
138
|
+
)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fastimage'
|
4
|
+
|
5
|
+
module Pdadv
|
6
|
+
class Scenario
|
7
|
+
def initialize
|
8
|
+
@env = Pdadv::Environment.new
|
9
|
+
@screens = []
|
10
|
+
@registered_images = {}
|
11
|
+
end
|
12
|
+
attr_reader :env, :screens
|
13
|
+
|
14
|
+
def asset_path(path)
|
15
|
+
File.expand_path(path, @env.base_path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def last_screen
|
19
|
+
enter_page if screens.empty?
|
20
|
+
@screens.last
|
21
|
+
end
|
22
|
+
|
23
|
+
def enter_page(name = nil)
|
24
|
+
@screens.push(Pdadv::Screen.new(name))
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_message(message)
|
28
|
+
return if message.strip.empty?
|
29
|
+
last_screen.message = message.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_command(name, argv = [])
|
33
|
+
case name.downcase
|
34
|
+
when 'setglobal'
|
35
|
+
add_set_global_command(argv)
|
36
|
+
when 'register'
|
37
|
+
add_register_command(argv)
|
38
|
+
when 'back'
|
39
|
+
add_back_command(argv)
|
40
|
+
when 'show'
|
41
|
+
add_show_command(argv)
|
42
|
+
else
|
43
|
+
puts "[unknown command]\t#{name}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def add_set_global_command(argv)
|
50
|
+
key, *values = argv
|
51
|
+
values = values.map(&:to_i) if values.all? { |n| n.match(/\A\d+\z/) }
|
52
|
+
@env[key] = values.size > 1 ? values : values.first
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_register_command(argv)
|
56
|
+
name, path, x, y = argv
|
57
|
+
w, h = FastImage.size(asset_path(path))
|
58
|
+
@registered_images[name] = Pdadv::Entities::ImageEntity.new(
|
59
|
+
path: path,
|
60
|
+
x: x || 0,
|
61
|
+
y: y || 0,
|
62
|
+
width: w,
|
63
|
+
height: h
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_back_command(argv)
|
68
|
+
last_screen.back = @registered_images[argv.first]
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_show_command(argv)
|
72
|
+
i, name = argv
|
73
|
+
last_screen.actors[i.to_i] = @registered_images[name]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pdadv
|
4
|
+
class ScenarioParser
|
5
|
+
def initialize(file_path)
|
6
|
+
@file_path = file_path
|
7
|
+
@lines = File.read(@file_path).split(/\r?\n/)
|
8
|
+
reset
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset
|
12
|
+
@messages = []
|
13
|
+
@result = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse
|
17
|
+
return @result if @result
|
18
|
+
|
19
|
+
reset
|
20
|
+
scenario = Scenario.new
|
21
|
+
parse_meta(scenario)
|
22
|
+
parse_commands(scenario)
|
23
|
+
|
24
|
+
@result = scenario
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_meta(scenario)
|
28
|
+
scenario.env.base_path = File.expand_path('..', @file_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_commands(scenario)
|
32
|
+
@lines.each do |line|
|
33
|
+
case line
|
34
|
+
when %r{^//}
|
35
|
+
nil # comment
|
36
|
+
when /^%(?<name>[^\s]+)\s*(?<argv>.+)$/
|
37
|
+
name = Regexp.last_match(1)
|
38
|
+
argv = Regexp.last_match(2).to_s.split(/\s*,\s*/)
|
39
|
+
scenario.add_command(name, argv)
|
40
|
+
when /^#+\s(?<flag_name>.+)$/
|
41
|
+
name = Regexp.last_match(1)
|
42
|
+
add_message(scenario)
|
43
|
+
scenario.enter_page(name)
|
44
|
+
when /^-{3,}$/
|
45
|
+
add_message(scenario)
|
46
|
+
scenario.enter_page
|
47
|
+
else
|
48
|
+
@messages.push line
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
add_message(scenario)
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_message(scenario)
|
56
|
+
return if @messages.empty?
|
57
|
+
scenario.add_message(@messages.join("\n"))
|
58
|
+
@messages = []
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/pdadv/screen.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Pdadv
|
6
|
+
class Screen
|
7
|
+
def initialize(name = nil)
|
8
|
+
@name = name || "id-#{rand(999_999_999)}"
|
9
|
+
@back = nil
|
10
|
+
@actors = []
|
11
|
+
@message = ''
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :name, :back, :message
|
15
|
+
attr_reader :actors
|
16
|
+
|
17
|
+
def format_message(scenario)
|
18
|
+
return '' if message.empty?
|
19
|
+
|
20
|
+
text = CGI.escape_html(message)
|
21
|
+
text = create_link(scenario, text)
|
22
|
+
|
23
|
+
text
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def create_link(scenario, text)
|
29
|
+
text.gsub(/\[(?<name>[^\]]+)\](\((?<to>[^\)]+)\))?/) do
|
30
|
+
text = Regexp.last_match(1)
|
31
|
+
to = Regexp.last_match(2)
|
32
|
+
case to
|
33
|
+
when nil
|
34
|
+
create_next_page_link(scenario, text)
|
35
|
+
when /^https?:/
|
36
|
+
create_web_link(text, to)
|
37
|
+
else
|
38
|
+
create_page_link(scenario, text, to)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_next_page_link(scenario, text)
|
44
|
+
i = scenario.screens.find_index { |s| s.name == name } || 0
|
45
|
+
"<u><link anchor=\"##{i + 1}\">#{text}</link></u>"
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_web_link(text, url)
|
49
|
+
"<u><link href=\"##{url}\">#{text}</link></u>"
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_page_link(scenario, text, dest_name)
|
53
|
+
i = scenario.screens.find_index { |s| s.name == dest_name } || 0
|
54
|
+
"<u><link anchor=\"##{i}\">#{text}</link></u>"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/pdadv.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'pdadv/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'pdadv'
|
9
|
+
spec.version = Pdadv::VERSION
|
10
|
+
spec.authors = ['ru_shalm']
|
11
|
+
spec.email = ['ru_shalm@hazimu.com']
|
12
|
+
|
13
|
+
spec.summary = 'PDF Adventure game framework'
|
14
|
+
spec.homepage = 'https://github.com/rutan/pdadv'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'fastimage'
|
25
|
+
spec.add_dependency 'prawn'
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
27
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
spec.add_development_dependency 'rubocop'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pdadv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ru_shalm
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-08-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fastimage
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: prawn
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.16'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.16'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- ru_shalm@hazimu.com
|
86
|
+
executables:
|
87
|
+
- pdadv
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rubocop.yml"
|
93
|
+
- Gemfile
|
94
|
+
- Gemfile.lock
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bin/console
|
99
|
+
- bin/setup
|
100
|
+
- exe/pdadv
|
101
|
+
- lib/pdadv.rb
|
102
|
+
- lib/pdadv/cli.rb
|
103
|
+
- lib/pdadv/entities/image_entity.rb
|
104
|
+
- lib/pdadv/environment.rb
|
105
|
+
- lib/pdadv/renderer.rb
|
106
|
+
- lib/pdadv/scenario.rb
|
107
|
+
- lib/pdadv/scenario_parser.rb
|
108
|
+
- lib/pdadv/screen.rb
|
109
|
+
- lib/pdadv/version.rb
|
110
|
+
- pdadv.gemspec
|
111
|
+
homepage: https://github.com/rutan/pdadv
|
112
|
+
licenses:
|
113
|
+
- MIT
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.7.6
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: PDF Adventure game framework
|
135
|
+
test_files: []
|