GithubHelp home page GithubHelp logo

andymeneely / squib Goto Github PK

View Code? Open in Web Editor NEW
904.0 23.0 68.0 20.17 MB

A Ruby DSL for prototyping card games.

Home Page: http://squib.rocks

License: MIT License

Ruby 99.12% HTML 0.68% Dockerfile 0.21%
ruby squib game card prototyping dsl tabletop pngs svg sublime-text

squib's Introduction

Squib Gem Version Build Status Build status Coverage Status ReadTheDocs BoardGameGeek

Squib is a Ruby DSL for prototyping card and board games. Write a little bit of Ruby, define your deck's stats, then compile your game into a series of images ready for print-and-play or even print-on-demand. Squib is very data-driven and built on the principle of Don't Repeat Yourself. Think of it like nanDeck done "the Ruby way". Squib supports:

  • A concise set of rules for laying out your cards
  • Loading PNGs and SVGs
  • Complex text rendering using Pango
  • Reading xlsx and csv files
  • Rendering to PNGs, PDFs, and SVGs (sheets or individual files)
  • Flexible, data-driven layouts in Yaml
  • Basic shape drawing, blending operators, gradients, etc.
  • Unit conversion
  • The full power of Ruby!

Squib is based on the Cairo graphics rendering engine, the library of choice for WebKit, Gecko, Inkscape and many, many others.

Check this out.

require 'squib'

Squib::Deck.new(cards: 2) do
  text str: %w(Hello World!)
  save_png
end

We just created a 2-card deck with "Hello" on the first card, and "World" on the second, and saved them out to PNGs.

Wanna see more? Check out the website: http://andymeneely.github.io/squib/

Installation

Squib requires Ruby 3.0 or later.

Install it yourself with:

$ gem install squib

If you're using Bundler, add this line to your application's Gemfile:

gem 'squib'

And then execute:

$ bundle

More info: http://squib.readthedocs.org/en/latest/install.html

Getting Started

After installing Squib, you can create a project and run your first build like this:

$ squib new my-cool-game
$ cd my-cool-game
$ ruby deck.rb

The squib new command will generate files and folders like this:

├── .gitignore
├── ABOUT.md
├── Gemfile
├── IDEAS.md
├── PLAYTESTING.md
├── PNP NOTES.md
├── RULES.md
├── Rakefile
├── _output
│   └── gitkeep.txt
├── config.yml
├── deck.rb
└── layout.yml

12 files

Learning Squib

Go read the docs!

Also:

  • The samples directory in the source repository has lots of examples.
  • Masters of the Heist is my own creation, and it was made with Squib. Go through the repository and watch how it evolved!
  • Junk Land is my own creation that's uses Squib for full-color rendering, and makes use of Ruby in a lot of interesting ways. The port is still in process.
  • Project Spider Monkey is another of my own creations. This one was started from scratch with Squib, but it's still in its early stages.

Staying DRY

Squib tries to keep you DRY (Don't Repeat Yourself) with the following features:

  • Custom layouts allow you to specify various arguments in a separate file. This is great for x-y coordinates and alignment properties that would otherwise clutter up perfectly readable code. Squib goes even further and has a special "extends" that works especially well for grouped-together styles.
  • Flexible ranges and array handling: the range parameter in Squib is very flexible, meaning that one text command can specify different text in different fonts, styles, colors, etc. for each card. If you find yourself doing multiple text command for the same field across different ranges of cards, there's probably a better way to condense.
  • Custom colors keep you from hardcoding magic color strings everywhere. Custom colors go into config.yml file.
  • Plus, you know, Ruby.

Docker

Want to run in a controlled environment? We've got a Docker image on DockerHub

Here's one way to run it. On the command line, go to the root of your repository. With these commands, we'll map the current directory to the /usr/src/app directory in the Docker image. When squib-in-docker read & writes files from there, it'll write it back out to your current directory.

Assuming you have a script called hello.rb:

On Windows:

docker run --rm -v "%cd%":/usr/src/app andymeneely/squib ruby hello.rb

On Macs:

docker run --rm -v "$PWD":/usr/src/app andymeneely/squib ruby hello.rb

This will create a folder called _output in your current directory and write the output of the script there.

We're still working on ways to customize your own Docker build (e.g. document building, custom fonts, etc.) with your own Dockerfile. Pull requests and ideas welcome!

Get Help and Give Help

See this page

What's up the with the name?

Truthfully, I just thought it was a cool, simple word that was not used much in the Ruby community nor the board game community. But, now that I've committed to the name, I've realized that:

  • Squibs are small explosive devices, much like Squib "explodes" your rules into a playable game
  • Squibs are often used in heist movies, leading to a sudden plot twist that often resembles the twists of good tabletop game
  • Squibs are also part of the Harry Potter world - they are people who are non-magical but wizard-born. Squib is aware of wizarding magic and comes from that heritage, but it's not magical itself.

squib's People

Contributors

alexgorski avatar andymeneely avatar cixelyn avatar daveschaefer avatar davidmfinol avatar felixleong avatar fwolfst avatar karneades avatar kocsenc avatar meltheadorable avatar ncallaway avatar novalis avatar olivierkes avatar qgel avatar sparr avatar spilth avatar stochaztic avatar vador avatar vtbassmatt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

squib's Issues

SVG Backend

Currently we just support Cairo::ImageSurface (raster) back ends. This is nice and fast, but it does have some disadvantages. For one, the PDFs generated are rasterized, which is (a) huge, and (b) may not be printed as well as they could be. Then again, SVG is slower and requires an XML file to be written out every time a command is run. Plus you have to configure a tmp directory, which gets messy.

We CAN theoretically have most of our commands be compatible with an SVG back end. The hardest part is PDF, but for that we can load the images from the tmp directory and render them that way.

Regression testing is key here. We'll need to make sure that a pdf with lots of stuff gets rendered vector and not raster.

Create a color deficiency vision test

Given the prevalence of various forms of color-blindness and it's significant impact on gaming, I think it would be cool to have a command that shows what your cards look like to someone of various types of color blindness.

Cairo doesn't support this natively, but there are plenty of implementations out there to work from for our own implementation. Here are a few notable ones:

https://www.npmjs.com/package/color-blind
http://docs.gimp.org/en/gimp-display-filter-dialog.html#gimp-deficient-vision
http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=5645874&tag=1
http://www.vischeck.com/
http://newmanservices.com/colorblind/default.asp

This is a neat overview, although light on details
http://www.ijrrr.com/papers6/paper4.pdf

The daltonize method is best laid out here:
http://link.springer.com/chapter/10.1007%2F978-3-642-23187-2_29

Assuming we can get the math right (perhaps that should become a separate gem altogether like the Node.js package), the Squib implementation would be something like:

color_deficiency range: 0,2, output: "color_deficiency.png"

The output would be a PNG showing a table of your cards along with filtered versions of the cards that simulate what the card would look like to a person with color blindness. We can also put statistics on each form of color blindness about what's more prevalent (some of the rarer forms of colorblindness are extremely hard to design with). The PNG that is automatically sized based on the card dimensions, so there's no need to size it.

Text hints are broken on rotated text

For some reason this won't put the text hint in the proper place:

text str: "Rotated",
        x: 565, y: 675, angle: 0.1,
        font: 'Arial 18', hint: :red

The box also changes places depending on the angle. Doing a 2*pi degree rotation does put it in the right place, so it has to do with translation or something.

Smart Quotes: convert to curly quotes at word boundaries

See Wikipedia article that mentions smart quoting.

Basically, use the curly quotes according to word boundaries so that quotes curl inward. As opposed to being perfectly vertical.

Not sure if smart quotes are handled by Pango or not, but these would be nice to have. Might be as simple as doing a string-replace (assuming UTF-8 strings). Shouldn't vary from font-to-font. Pango does handle word boundaries, so I could use that.

What if the font doesn't have curly quotes? Is there a way of checking that? Or just fail gracefully?

Allow for units and percentages in strings

Allow for some arguments like x,y, width, and height to allow for unit conversion and percentage of width and height. For example,

title:
  width: 50% #computes to 50% of the width of the card
  height: 50% #computes to 50% of the width of the card
  x: 1in # goes to 300 pixels if @dpi is set to 300.

More basic shapes

Adding new shapes are really easy to implement, so this is low hanging fruit. It's just a matter of looking up how to draw them with lines and arcs.

  • Star
  • Polygon (e.g. hex)
  • Ellipse
  • Grid
  • Hex grid

Markup for embedding icons in text

It would be very useful to be able to embed images via tags or some similar inline approach.

As a reference, nandeck provides this functionality with statements like:

HTMLIMAGE=,"(S)","art/icon.png",1,1,P
HTMLTEXT=,"some text with the (S) icon embedded",0,0,6,1,#ffffff,0,T

If there was markup available to embed images, then a string transform could be used to convert - whatever arbitrary markup the designer chooses - into the appropriate tag with src/size data.

Customize PDF support

Currently PDF support is pretty hard-coded - introduce more flexibility, more paper sizes, etc.

Text embedding doesn't work for first icon in right and center aligned text

Sadly, it looks like we've got a bug with Pango's index_to_pos for right-aligned text. For some reason, the first icon doesn't locate properly from index_to_pos when the text is right-aligned or center-aligned. The rest of the icons do embed just fine, so I don't think it's a problem in Squib's logic.

  embed_text = 'Embedded icons! Take 1 :tool: and gain 2:health:. If Level 2, take 2 :tool:'
  text(str: embed_text, font: 'Sans 18', x: '1.8in', y: '2.5in', width: '0.85in',
       align: :right, ellipsize: false) do |embed|
    embed.svg key: ':tool:',   width: 28, height: 28, file: 'spanner.svg'
    embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg'
  end

For now, if you try to do it, Squib will throw a warning that it's a known issue.

There is a workaround. Since this only happens to the first icon, just embed an empty icon at 1x1 pixels first, then carry on as normal. Create an SVG file that has absolutely nothing in it, and then do something like this:

  embed_text = ':empty:Embedded icons! Take 1 :tool: and gain 2:health:. If Level 2, take 2 :tool:'
  text(str: embed_text, font: 'Sans 18', x: '1.8in', y: '2.5in', width: '0.85in',
       align: :right, ellipsize: false) do |embed|
    embed.svg key: ':tool:',   width: 28, height: 28, file: 'spanner.svg'
    embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg'
    embed.svg key: ':empty:', width: 1, height: 1, file: 'empty.svg'
  end

This is probably a bug in Pango. I'll try to create a minimal example and send it their way.

Release v0.1.0

Here's the todo-list:

  • CHANGELOG is written for all new changes
  • README is updated
  • Samples are updated
  • Check that sample regression tests are all enabled
  • Bump version.rb
  • Do a full rake locally
  • Travis is passing on dev branch
  • gem push pkg/squib-x.y.z.gem
  • rake doc
  • Push rake doc to website
  • Bump version.rb to the next alpha

Add a mask argument to png and svg

It'll takes in a color for the svg and png commands and use the image as a mask instead of a paint. That way you can do different colors for the same icon if you like.

Add a showcase feature

Make a command that generates something that looks like what I did in Gimp here: http://www.playconfidencegames.com/masters-of-the-heist/

So the Cairo people have said over and over again that they won't support the 3x3 matrices that would handle perspective transforms. Ok, so since our perspective transform is a bit simpler, we can use a "striping method" that does the job for us. It's a little bit involved, but it works well enough with some magic numbers. I've got a prototype that I'll put in the comments

Needed for this:

  • Define the API call for it, and some warnings
  • New unit tests for the front end stuff
  • Add new sample
  • Add new regression test
  • Add Sublime snippet
  • Update README

Work on this is in the showcase_idea branch; https://github.com/andymeneely/squib/tree/showcase_idea

Add a `sheet` command

Like the PDF sheet, stitch together decks on a sheet. Allow for file prefix, trimming, margins, columns, and either set rows or infinite rows.

Circle drawing stroke from current x,y to circle origin?

Whenever I use a circle command in my decks, a stroke is drawn from the closing coordinates of the prior command to the origin coordinates of the circle, then the circle itself is drawn. The only way I have found to work around it is to draw a circle with no stroke, then re-draw the same circle with a stroke at the same coordinates.

I'm not sure if this is an issue with Squib or an upstream Cairo issue, but looking in lib/squib/graphics/shapes.rb, and with the context that I have absolutely no idea how cairo works, it looks like a simple

cc.move_to(x,y)

at the start of the circle function would probably address it, though it might also need a stroke width set to 0 first (depending on how move_to works)

Thanks!

Create a scoring track example

Showing an example of how to do a scoring track would be nice to see. If there's anything that Squib can do to ease that (e.g. a custom iterator), go ahead and do it.

Add a bezier curve command

This basically comes down to providing an interface to Cairo's arc command. Need to hammer out what the syntax and behavior of this command looks like.

Make nearly every argument allow an array or singleton, as in str in text

To allow for some pretty basic flexibility, we need to allow for, say, different colors for different bonus texts depending on their content. For example, this should be able to work for text string colors:

text str: %w(a b), color: %w(color_a color_b)

We'll need a flexible way to expand (expandify?) our arguments across the range.

Invalid progress bar error

On this command:

save_sheet prefix: 'sheet_', columns: 16, margin: 75, gap: 5, trim: 37

I'm getting tons of warnings about invalid progress bars.

WARNING: Your progress bar is currently at 108 out of 108 and cannot be incremented. In v2.0.0 this will become a ProgressBar::InvalidProgressError

Run layout.yml through ERB

It would be neat if we could allow for some coding in layout.yml via ERB, much like how Rails does with its fixtures. This allows for things like subtracting from the width of the card for right-aligned things.

title:
  x: <%=@width-75%>

But, is this too complicated? Would this allow for really messy layout.yml between yml, erb, and the extends key? Definitely document it's usage, but does it violate principle of least surprise?

Add support for linear and radial gradients

Would be nice if we could do gradients instead of fill colors for background and the various shapes. Cairo supports multiple stops, which makes them quite variable

Here are the examples/ideas:

background gradient: { x1: 0, y1:0, 
                       x2: 500, y2: 500, 
                       colors: {0.0: :red, 
                                1.0: :blue }
                     }

It would be the first time we would have the inputs be hashes within hashes (within hashes). Is that too complex? Is there another way?

Or... do we just say "use SVG". Perhaps that would keep things simpler.

Release v0.3.0

  • CHANGELOG is written for all new changes
  • README is updated
  • Samples are updated
  • rake doc
  • Check that sample regression tests are all enabled
  • Bump version.rb
  • Do a full rake locally
  • Travis is passing on dev branch
  • Merge master branch
  • Create GitHub release tag
  • gem push pkg/squib-x.y.z.gem
  • Github milestone closed
  • Push rake doc to website
  • Bump version.rb to the next alpha

Layout support on all relevant commands

Layouts, at this point, are just ways of supplying x, y, width, and height to a given command. The feature branch for text is coming along - follow that into everything else that uses those inputs.

Maybe with #2 we can easily add valign and align, since we can now essentially supply useless parameters and they just get ignored.

Add a chroma_key option for png command that treates one color as transparent

With the mask option in the png command, it would be nice if we could take, say, all white pixels and make them transparent. This would make converting to black-and-white a nearly automated process. Syntax would look like this:

png file: 'hammer.png', mask: :black, chroma_key: :white

Possibly also add a tolerance to it for antialiasing, too? Depends on how I would do this with Cairo.

png file: 'hammer.png', mask: :black, chroma_key: :white, chroma_tolerance: 2 # white and white +/- 2

Allow config.yml to define custom colors

Whenever colors are read in, keep a table of custom theme-based colors so you can change things out automatically. E.g.

deck.rb

text data['Title'], layout: :title, color: :title

config.yml

colors:
  title: '#abc'

Unit conversion breaks on extends

If we have this situation in a layout file, we get an error:

Attack:
  x: 1in

Defend:
  extends: Attack
  x: += 2in

Really the second being inches is not needed - basically extends doesn't do unit conversion and probably should

Release v0.4.0

  • CHANGELOG is written for all new changes
  • README is updated
  • Samples are updated
  • rake doc
  • Check that sample regression tests are all enabled
  • Bump version.rb
  • Do a full rake locally
  • Travis is passing on dev branch
  • Merge master branch
  • Create GitHub release tag
  • gem push pkg/squib-x.y.z.gem
  • Github milestone closed
  • Push rake doc to website
  • Bump version.rb to the next alpha

Allow for a Cairo::SVGSurface back end instead of Cairo::ImageSurface

Currently Squib works on raw bitmaps in memory with ImageSurface. This is fast, but it can gobble up memory like crazy on really big files. Also, rendering to PDFs is done by stitching together images, which can print differently than vector.

Fortunately, Cairo does have an SVGSurface back end. It works entirely like ImageSurface, except it requires a file up front in the constructor. This would amount to a temp file for each card in the deck, so we need a temp directory.

We also might have issues with pixels and dpi. One point in SVGSurface is 1/72 of an inch, which is different than our 300dpi. But my initial hacking didn't run into this issue. Perhaps it's fine that we just think in pixels?

Needed for this:

  • New config options for backends and tmp
  • Make sure it's logged on the INFO level
  • New unit tests
  • Check an actual PDF that should be huge and make sure it's all vector
  • New sample demonstrating this
  • Document on README

Nil error on empty layout field

The extends functionality doesn't account for a possible nil in a layout yaml file like this:

title:
    #nothing here - yaml defaults to nil
subtitle:
    font: 'Sans'

Add in warning about OSX Yosemite

When rcairo 14.2 comes out, this should go away. But for now, it's still at cairo 14.1. Here's the warning:

<Error>: The function ‘CGFontGetGlyphPath’ is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.

Document this in the next version of Squib as a known issue.

Do we want Google Sheets integration?

Much like xlsx and csv, maybe a method to get data from Google Sheets?

Pros:

  • Many people often use Google Sheets more than Excel these days.

Cons:

  • Yet another dependency
  • Chasing Google's ever-changing APIs

Thoughts? Post your votes here!

Switch from `prefix:` to format string

Should be easy once the new Args architecture is in place. The prefix arg for saving files is a bit lame. Perhaps a format string is better. Something like

'%02d.png' % card_num #e.g. 

Release v0.2

  • Github milestone closed
  • CHANGELOG is written for all new changes
  • README is updated
  • Samples are updated
  • rake doc
  • Check that sample regression tests are all enabled
  • Bump version.rb
  • Do a full rake locally
  • Travis is passing on dev branch
  • Merge master branch
  • Create GitHub release tag
  • gem push pkg/squib-x.y.z.gem
  • Push rake doc to website
  • Bump version.rb to the next alpha

Default-driven option handling

The Ruby named parameters thing doesn't handle so well when we have options that override other options as in layouts. So, let's go back to using hashes in all of our API commands, but implement a more complex set of defaults

The precedence order goes like this:

  1. System-wide defaults, such as :x => 0.
  2. Command-level defaults override system-wide. e.g. `:color => :black' for text
  3. config.yml settings, wherever we support those.
  4. Settings specified by the commands themselves, e.g.text 'blah', x: 5, color: :blue

This means we'll need to change away from Ruby parameters and make use of hash merges along with input handlers that just modify the parameters.

Can't do masking of SVGs onto SVG back end without rasterizing

Currently, I just create an ImageSurface when doing the masking operation on SVGs. When the back end is SVG, then you lose your vectors. Would be nice if that didn't happen.

Technically, this is possible but it involves creating an empty SVG as an intermediate step. I don't want to generate a temp file because that just adds overhead and complicates things. Cairo does support in-memory SVGs, but rcairo doesn't seem to want take nil in Cairo::SVGSurface.new.

Allow rotation about arbitrary points instead of always upper-left

Currently, things like text rotation rotate about the upper left corner. It would be nice if we could do something like:

text str: 'Hello', rotate: Math::PI / 2, rotate_x: 50, rotate_y: 50

Maybe even something handy like this:

# yay, one less math problem for Squibbers!
text str: 'Hello', rotate: Math::PI / 2, rotate_x: :middle, rotate_y: :middle 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.