The Image Block At The Bottom Of Shoes
In Shoes, images have been much as they are in HTML. Generally, a path to the image. And maybe its width and height.
Shoes.app do
image "static/shoes-icon.png"
end
You have a picture window.
In recent times, some Shoesers have been eschewing images and preferring to fabricate the shapes on their own. An example would be the minesweeper clone, which paints the circles and lines for all the bombs and flags. Probably to keep things as a single Ruby script.
The little bombs get drawn with something akin to this bomb
method.
module Arsenal
def bomb x, y
nostroke
fill "#000"
oval x+3, y+3, 13
fill "#333"
oval x+5, y+5, 7
fill "#AAA"
oval x+6, y+6, 3
fill "#000"
stroke "#222"
strokewidth 2
oval x+12, y+3, 2
oval x+14, y+3, 1
end
end
Shoes.app do
extend Arsenal
background white
bomb 0, 0
end
So, the bomb gets drawn at 0, 0
. Holy goalie, though. Look at all that math. And the worst part of it is that every time you move the bomb, you’ve got to recompute and redraw everything. Either that or you’ve got to move each little oval individually.
Rather, let’s draw a bomb inside an image block.
module Arsenal
def bomb x, y
image 20, 20, :top => x, :left => y do
nostroke
fill "#000"
oval 3, 3, 13
fill "#333"
oval 5, 5, 7
fill "#AAA"
oval 6, 6, 3
fill "#000"
stroke "#222"
strokewidth 2
oval 12, 3, 2
oval 14, 3, 1
end
end
end
This image syntax creates a bitmap surface in memory. In this case: 20 pixels by 20 pixels. Upon which shapes are drawn on to. And it’s then treated like an image loaded from a file.
The advantages in this case are:
- The image block is only drawn once. So faster paint times. Shapes aren’t constantly recomputed.
- Everything is positioned according to the image’s origin. Less math. (Notice no
x
andy
used in the image block.) - Image effects (such as
blur
andshadow
effects) can be applied to this image. - Can be moved and resized as a single image. Conceptually easier, I guess.
Shoes is pretty meager on image effects right now, but a good example of using the blur
effect is in samples/simple-sphere.rb.
Alls I did was follow this Photoshop tutorial, each of its steps for piling on the inner and outer glows and gradients. This was a lot of fun to do and I think could be the basis of a pretty inspiring class for kids. Give them a Photoshop tutorial and work through expressing each of its steps in code.
You will need a recent build to make any of this fly, though.
Tieg
I don’t know what kind of magic just happened, but updating to the recent build just made my current script much faster! Unfortunately I don’t think that’ll make my coding skills any faster, but I must learn patience.
Matt
It would be easy to paint the bomb in different places if Shoes had an affine transform per drawing context, like Java2D or OpenGL. You could write a bomb method that drew a bomb at 0,0. Then to draw a bomb at (x, y) you could just use the code “x,y); bomb;”.
_why
Matt: True, good point! You can accomplish an affine transform in Shoes with the
rotate
,skew
orscale
methods, followed by atranslate
.failureontheweb
I wonder if there is a practical way to pull in an OpenGL library into shoes….
zverok
I should say dislike the API . The ethernal problem of graphic APIs is their imperativitiy: we typically say “set fill; then draw somethings”, while having in mind “draw something with fill”. Like this
Next: for parameters (oval) seems to bee already as much as it requires parameter naming (through hash). It may seem bit too verbose, but with upcoming ruby1.9 hashes (like `width: 100`) and parameters abbreviations (`w: 100, h: 200, :f => ‘#4df’, :b => ‘20%’) it seems to be “just right”.
And next: z-order question is also solved in imperative way (“A is drawn on top of B because A is drawn after B”). Why not to solve it through nesting of drawing commands? (“Oval, having oval and text inside it”). This solution also allows usage of “relative” sizes (like “50%”) and maybe even fills (transformations in HSV space?). Think about reusable function drawing this image with sphere (with changable width, height and color parameters). With current solution, you should calculate all sizes of ovals when drawing with another width/height, but having relative sizes, you can handle this case naturally.
danield
Nice blog!
What is the window theme you use with Shoes and GTK /Gnome?
zverok
one more example with changed API : bomb method
someguy
I’m encouraged to see the progress on Shoes; when will this translate into some work on hackety hack? I was using it with some kids but stopped when development seemed to cease.
_why
zverok: Shoes already allows that hash syntax. Most things even accept
:stroke
and:fill
. I’m just using the shorter syntax above. Rather than:x
,:y
and:r
, you’d use:left
,:top
and:radius
.This and your z-order question make me think you didn’t read this post and haven’t really done your homework on Shoes at all. Have you ever written anything in Shoes?
someguy: Stick around, this stuff just needs to get completely stable.
someotherguy
Thanks _why, I’ll keep my eyes open. Except when I’m sleeping.
kamran
So i want to create 2 different kinds of blocks, one blue and one green, but i want to make many of them. Should i assign the image block for creating them to variables, and then just copy that variable when i need a copy of the image, or is there a better way to do that? I really enjoy using shoes, and for zverok, i’d try checking out Nobody Knows Shoes, a very useful book if your interested in this toolkit.
Comments are closed for this entry.