Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ irb(main):002> mural.users.current_user

### Upload a file to a mural

To upload a `my.pdf` file that's located in the same directory as where you are
To upload a `my.pdf` file thats located in the same directory as where you are
running the script:

```rb
Expand Down Expand Up @@ -161,9 +161,41 @@ an email notification.

![mind map example](./img/mind-map.png)

- Likewise, smart planners are collection of widgets, and the API doesn't
- Likewise, smart planners are collection of widgets, and the API doesnt
specify anything about them.

![smart planner example](./img/smart-planner.png)

[register-app]: https://developers.mural.co/public/docs/register-your-app

## Invaders module!

How about some good ol’ nostalgia? Let’s bring in the
[space invaders](https://en.wikipedia.org/wiki/Space_Invaders) in a mural!

![space invaders demo](./img/space-invaders-demo.png)

To accomplish this, simply create a script with the following code:

```rb
require 'mural'

MURAL_ID = 'mural-1' # some mural you have write access to

client = Mural::Client.from_env

begin
board = Mural::Invader::Board.new(client, MURAL_ID)

draw_invader_params = Mural::Invader::DrawInvaderParams.new.tap do |params|
params.origin = [0, 0]
params.pixel_width = 10 # default, and the minimum size for the square shape
params.variant = 0
end

board.draw_invader_grid(draw_invader_params)
rescue Mural::Error => e
puts "\n--- ☠️☠️☠️ MURAL ERROR ☠️☠️☠️ ---"
puts e.inspect
end
```
Binary file added img/space-invaders-demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 112 additions & 0 deletions lib/mural/invader/board.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# frozen_string_literal: true

module Mural
module Invader
class Board
INVADER = {
'crab' => 'Mural::Invader::Crab::SPRITE',
'octopus' => 'Mural::Invader::Octopus::SPRITE',
'squid' => 'Mural::Invader::Squid::SPRITE'
}.freeze

ROWS = [
['squid', '#69ED36FF'],
['crab', '#69ED36FF'],
['crab', '#68F1F4FF'],
['octopus', '#68F1F4FF'],
['octopus', '#D937EEFF']
].freeze
COLS = 11

# the widest invader (octopus) is 12 "pixels" wide
MAX_INVADER_WIDTH = 12

# they are all the same height
MAX_INVADER_HEIGHT = 8

# the gitter scale with the size of the "pixel"
GUTTER_SIZE = 3

# how many shapes can we send in a single request
MAX_SHAPES_IN_PAYLOAD = 1_000

attr_reader :client, :mural_id

def initialize(client, mural_id)
@client = client
@mural_id = mural_id
end

def draw_invader_grid(draw_invader_params) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
draw_invader_params.to_h => { origin:, pixel_width:, variant: }
origin_x, origin_y = origin

cell_width = (MAX_INVADER_WIDTH + GUTTER_SIZE) * pixel_width
cell_height = (MAX_INVADER_HEIGHT + GUTTER_SIZE) * pixel_width

payload = ROWS.flat_map.with_index do |invader, row|
invader_kind, invader_color = invader

(0...COLS).flat_map do |col|
cell_origin = [
origin_x + (cell_width * col),
origin_y + (cell_height * row)
]

cell_invader_params =
Mural::Invader::DrawInvaderParams.new.tap do |params|
params.color = invader_color
params.origin = cell_origin
params.variant = variant
params.pixel_width = pixel_width
end

invader_shape(invader_kind, cell_invader_params)
end
end

payload.each_slice(MAX_SHAPES_IN_PAYLOAD) do |shapes|
client.mural_content.create_shapes(mural_id, shapes)
end
end

def draw_invader(kind, draw_invader_params)
client
.mural_content
.create_shapes(mural_id, invader_shape(kind, draw_invader_params))
end

def invader_shape( # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
kind,
draw_invader_params
)
draw_invader_params.to_h => { color:, origin:, pixel_width:, variant: }
sprite = Object.const_get(INVADER[kind])[variant]
origin_x, origin_y = origin

sprite.flat_map.with_index do |row_content, row|
row_content.map.with_index do |cell, col|
next unless cell == 1

Mural::Widget::CreateShapeParams.new.tap do |params|
params.x = origin_x + (col * pixel_width)
params.y = origin_y + (row * pixel_width)
params.width = pixel_width
params.height = pixel_width
params.shape = 'square'

params.style =
Mural::Widget::CreateShapeParams::Style.new.tap do |style|
style.background_color = color

# We want a transparent border, else the "pixel" is wider than
# the desired dimension
style.border_color = '#00000000'
end
end
end
end.compact
end
end
end
end
30 changes: 30 additions & 0 deletions lib/mural/invader/crab.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Mural
module Invader
class Crab
SPRITE = [
[
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0]
],
[
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0]
]
].freeze
end
end
end
25 changes: 25 additions & 0 deletions lib/mural/invader/draw_invader_params.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module Mural
module Invader
class DrawInvaderParams
attr_accessor :pixel_width, :color, :origin, :variant

def initialize
@pixel_width = 10
@color = '#000000FF'
@origin = [0, 0]
@variant = 0
end

def to_h
{
pixel_width: pixel_width,
color: color,
origin: origin,
variant: variant
}
end
end
end
end
30 changes: 30 additions & 0 deletions lib/mural/invader/octopus.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Mural
module Invader
class Octopus
SPRITE = [
[
[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
],
[
[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0],
[0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0],
[0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0]
]
].freeze
end
end
end
30 changes: 30 additions & 0 deletions lib/mural/invader/squid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Mural
module Invader
class Squid
SPRITE = [
[
[0, 0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 1, 1, 0, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 0, 1, 1, 0, 1, 0],
[1, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 1, 0]
],
[
[0, 0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 0, 1, 1, 0, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 1, 0, 0, 1, 0, 0],
[0, 1, 0, 1, 1, 0, 1, 0],
[1, 0, 1, 0, 0, 1, 0, 1]
]
].freeze
end
end
end