# ashbb/shoes_tutorial_html

Switch branches/tags
Nothing to show
Fetching contributors…
Cannot retrieve contributors at this time
412 lines (312 sloc) 10.3 KB

## Gallery No.6

I found the Ruby Quiz solution with Shoes.

Ruby Quiz 197 Midpoint Displacement

Fantastic mountain! So, let me try to write my own Shoes app.

Look at online demo.

``````# gallery6.rb
# Ruby Quiz 197 Midpoint Displacement
# http://rubyquiz.strd6.com/quizzes/197/
require 'enumerator'
POINTS = [[600, 0], [0, 0], [0, 220]]

Shoes.app :title => 'Midpoint Displacement v0.1'do
def midpoint_displacement
create_stars
points = [[0, 220], [600, 220]]
n = 2

mk_midpoints = proc do
tmp = [points[0]]
n /= 2.0
points.each_cons 2 do |x1, x2|
n_rand = n * 2 * rand - n
n_rand = n_rand.abs if n == 1
y = (x1[1] + x2[1]) / 2.0
tmp << [(x1[0] + x2[0]) / 2.0, y + y * n_rand] << x2
end
points = tmp
end

t = every 1 do |i|
@mt.remove if @mt
mk_midpoints.call
@mt = shape :top => 100 do
(points+POINTS).each_with_index do |e, j|
x, y = e
move_to(x, y) if j == 0
line_to x, 400 - y
end
end
t.stop if i > 7
end
end

angle = 2 * Math::PI * t / (24 * 60) - Math::PI / 2
x, y = 300 + radius * Math.cos(angle), 250 + radius * Math.sin(angle)
[x.to_i, y.to_i]
end

def create_stars
50.times do
r, t = rand(300), rand(24 * 60)
x, y = position(r, t)
@stars << star(x, y, 5, outer = 1 + rand(10), outer / 2, :fill => white,
:stroke => white, :r => r, :t => t)
end
@a = animate(24){|i| move_stars i}
end

def move_stars i
@stars.each do |s|
x, y = position(s.style[:r], s.style[:t] + i)
s.style :left => x, :top => y
end
end

background teal..white
@stars = []
midpoint_displacement

button 'one more time' do
(@stars + [@a, @mt]).each{|s| s.remove}
midpoint_displacement
end
end
``````

gallery6.png

## Gallery No.7

The Game Snake. It's a very nice tutorial.
Let's Make a Game: Wrap Up

I was really inspired and wrote the following 55 lines Snake in Shoes.
It's a power of Shoes! ;-)

Look at online demo

``````# gallery7.rb
# 55 lines Snake in Shoes
class SnakeGame < Shoes
url '/', :index

def index
background black
game_start
end

def game_start
@score = para 'Score:', :stroke => white
@pos = {:up => [0, -10], :down => [0, 10], :left => [-10, 0], :right => [10, 0]}
@rx, @ry = proc{20 + 10*rand(56)}, proc{40 + 10*rand(44)}

@foods = []
stroke lime
50.times{@foods << rect(@rx[], @ry[], 10, 10)}

@bricks = []
stroke deepskyblue; fill '#000099'
50.times{@bricks << rect(@rx[], @ry[], 10, 10)}
20.step(570, 10){|n| @bricks << rect(n, 40, 10, 10) << rect(n, 470, 10, 10)}
40.step(470, 10){|n| @bricks << rect(10, n, 10, 10) << rect(570, n, 10, 10)}

@snake = []
stroke white; nofill
@snake << rect(300, 100, 10, 10)
@snake[0].stroke = red

dir = :left
@run  = animate 5 do
keypress{|k| dir = k if @pos.keys.include? k}
check_food
go dir
@score.text = "Score: #{@snake.length * 10}"
brick? @snake[0]
end
end

def go k
x, y = @pos[k]
@snake.unshift @snake.pop
n = @snake.length > 1 ? 1 : 0
@snake[0].move @snake[n].left + x, @snake[n].top + y
@snake[0].stroke, @snake[n].stroke = @snake[n].stroke, @snake[0].stroke
end

def check_food
(@snake << rect(0, 0, 10, 10)) if eat? @snake[0]
end

def eat? s
@foods.each_with_index do |f, i|
(f.move @rx[], @ry[]; return true) if f.left == s.left and f.top == s.top
end
return false
end

def brick? s
@bricks.each do |b|
(@run.stop; confirm('Game Over. Play again?') ? visit('/') : exit) \
if b.left == s.left and b.top == s.top
end
end
end

Shoes.app :title => 'Snake Game v0.1'
``````

gallery7.png

## Gallery No.8

Paul Harris introduced the following fancy Shoes app in the Shoes course 4th batch.

I was very impressed and then improved to move a bit more smoothly.

Look at online demo

``````# gallery8.rb
Shoes.app :width=>320, :height=>200 do
str = "../images/Parallax-scroll-example-layer-%s.gif"
imgs = []
4.times do |i|
path = str % i
imgs << [image(path), image(path), imagesize(path).first]
end

animate 24 do |i|
imgs.each_with_index do |e, n|
img1, img2, w = e
x = -(n * i % w)
img1.move x, 0
img2.move x + w, 0
end
end
end
``````

gallery8.png

NOTE
If you have the faster machine than mine. It might be occured this error:

• undefined method `first` for nil:NilClass

If it'll happen, try to modify the code, line 7, like this:

``````width = imagesize(path).first
fs << [image(path), image(path), width]
``````

This tip was presented by Paul Harris.

## Gallery No.9

The Scatter Pack. This is a swarm of frightened bubbles. They run away from the green circle, the extent of mouse position.

Original Shoes app is this:
The Scatter Pack

Hacked from scratch. :)

Look at the online demo.

``````# gallery9.rb
# ScatterPack: Scatters like a school of fish

Shoes::Shape.class_eval do
[:v, :flag].each do |m|
define_method(m){style[m]}
define_method(m.to_s + '='){|v| style m => v}
end
end

Shoes.app :width => 300, :height => 300, :title => 'Scatter Pack v0.1' do
nostroke; nofill
colors = []
5.times{colors << rgb(rand(255), rand(255), rand(255), (0.5..1.0).rand)}

discs = []
50.times do
vx = vy = 0
(vx, vy = (-3..3).rand, (-3..3).rand) while [vx, vy] == [0, 0]
r = (5..100).rand
discs << oval(rand(width - r), rand(height - r), (5..100).rand,
:fill => colors[rand(5)], :v => [vx, vy], :flag => true)
end
@area = oval 0, 0, 100, :stroke => green

def disc_move disc
vx, vy = disc.v
nx, ny = disc.left + vx, disc.top + vy

vx = -vx  if nx + disc.width > width or nx < 0
vy = -vy  if ny + disc.width > height or ny < 0

if near_mouse?(disc)
(vx, vy = -vx * 2, -vy * 2) if disc.flag
disc.flag = false
else
(vx, vy = vx / 2, vy / 2) unless disc.flag
disc.flag = true
end

disc.move nx , ny
disc.v = [vx, vy]
end

def near_mouse? disc
r = disc.width / 2
x, y = disc.left + r, disc.top + r
Math.sqrt((mouse[1] - x)**2 + (mouse[2] - y)**2) < (@area.width / 2 + r)
end

keys = {'+' => 10, '-' => -10}
animate 12 do
discs.each{|disc| disc_move disc}
@area.left = mouse[1] - @area.width / 2
@area.top = mouse[2] - @area.width / 2
keypress do |k|
val = @area.width + keys[k].to_i
@area.width = val if val > 10
end
end
end
``````

gallery9.png

## Gallery No.10

A Very Simple Boids Program.

Paul Harris introduced the following fancy Shoes app in the Shoes course 4th batch.

Hungry Boids

I read the code and found the link to this web site:
Boids Pseudocode

So simple! Most impressive indeed!

I attempted coding a tiny Shoes app just by following the algorithm.

Look at online demo.

``````# gallery10.rb
require 'matrix'
require 'gallery10-image'
require 'gallery10-rules'

Shoes.app :title => 'A Very Simple Boids v0.1' do
extend Rules
@boids = []
N.times do
x, y = rand(200), rand(200)
vx, vy = rand(2), rand(2)
@boids << image('../images/gallery10-kamome.png',
:left => x, :top => y, :pos => Vector[x, y], :vel => Vector[vx, vy])
end

animate 12 do
@boids.each do |boid|
boid.vel = boid.vel + rule1(boid) + rule2(boid) + rule3(boid) + rule4(boid)
boid.pos = boid.pos + boid.vel
boid.move boid.x, boid.y
end
end
end
``````

4 rules:

``````# gallery10-rules.rb
N = 12
BOUND = 3

module Rules
def rule1 boid
c = @boids.collect{|b| b.pos}.inject{|i, j| i + j} - boid.pos
c *= 1 / (N - 1.0)
(c - boid.pos) * 0.01
end

def rule2 boid
c = Vector[0, 0]
@boids.each do |b|
dist = b.pos - boid.pos
(c -= b.pos - boid.pos) if (b != boid and dist[0].to_i.abs < 5 and dist[1].to_i.abs < 5)
end
c
end

def rule3 boid
c = @boids.collect{|b| b.vel}.inject{|i, j| i + j} - boid.vel
c *= 1 / (N - 1.0)
(c - boid.vel) * (1 / 16.0)
end

def rule4 boid
vx, vy = 0, 0
x, y = boid.pos[0], boid.pos[1]
vx = BOUND if x < 20
vx = -BOUND if x > 580
vy = BOUND if y < 20
vy = -BOUND if y > 480
Vector[vx, vy]
end
end
``````

Helper methods for writing the simple code:

``````# gallery10-image.rb
Shoes::Image.class_eval do
[:vel, :pos].each do |m|
define_method(m){style[m]}
define_method("#{m}="){|arg| style m => arg}
end

[:x, :y].each_with_index{|m, i| define_method(m){pos[i].to_i}}
end
``````

gallery10.png

## Policeman

Gallery 6, 7 and 8 worked well with Shoes-0.r1263.

Gallery 9 and 10 worked well after replaced `class` to `class_eval`.