Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: b4d027511a
Fetching contributors…

Cannot retrieve contributors at this time

379 lines (320 sloc) 8.539 kB
# asteroids game by lljk
# have fun!
class LaserBulletThing < Shoes::Widget
attr_accessor :x, :y, :x_vec, :y_vec
def initialize(x, y)
@x = x; @y = y
@x_vec = 0; @y_vec = 0
fill lime; oval(0, 0, 5)
self.move(@x, @y)
end
end #LaserBulletThing
class FirstClassFlyingShip < Shoes::Widget
attr_accessor :center_x, :center_y, :shots, :paused
def initialize(x, y)
@paused = false
@x = x - 10; @y = y - 12
@center_x = x; @center_y = y
@shots = []
@x_vec = 0; @y_vec = 0
@start_angle = 0
@rotate_by = 0
@slot = stack fill: black, stroke: lime
@slot.move(@x, @y)
draw_ship
motion{|x, y|
unless @paused
@rads = Math.atan2(y - @center_y, x - @center_x)
degs = 270 - (@rads * (180 / Math::PI)).round(2)
@rotate_by = degs - @start_angle
@start_angle = degs
draw_ship
end
}
#put this bit in a slot, or it won't work
stack width: 700, height: 600, top: 0, left: 0 do
click{|btn, x, y|
unless @paused
shoot if btn == 1
if btn == 3
@x_vec += 1 if x > @x + 20
@x_vec -= 1 if x < @x
@y_vec +=1 if y > @y + 24
@y_vec -= 1 if y < @y
end
end
}
end
end #init
def draw_ship
@slot.clear
@slot.append{
rotate @rotate_by
@ship = shape{
move_to(10, 0)
line_to(20, 24)
line_to(10, 20)
line_to(0, 24)
line_to(10, 0)
}
}
end
def move_ship
@x += @x_vec
@y += @y_vec
@x = 0 if @x > 700; @y = 0 if @y > 600
@x = 700 if @x < 0; @y = 600 if @y < 0
@center_x = @x + 10; @center_y = @y + 12
@slot.move(@x, @y)
draw_shots unless @shots.empty?
end
def shoot
if @rads
bullet_x = ((15 * Math.cos(@rads)) + @center_x).round
bullet_y = ((15 * Math.sin(@rads)) + @center_y).round
bullet = laser_bullet_thing(bullet_x, bullet_y)
bullet.x_vec = bullet_x - @center_x
bullet.y_vec = bullet_y - @center_y
@shots << bullet
end
end
def draw_shots
@shots.each{|bullet|
bullet.x += bullet.x_vec
bullet.y += bullet.y_vec
if bullet.x < 0 || bullet.x > 695 || bullet.y < 0 || bullet.y > 595
bullet.remove
@shots.delete(bullet)
else
bullet.move(bullet.x, bullet.y)
end
}
end
end #Ship
class Asteroid < Shoes::Widget
attr_accessor :x, :y, :x_vec, :y_vec, :size, :area
def initialize(size, x, y)
@size = size
@x_vec = 0; @y_vec = 0
until @x_vec != 0
@x_vec = (30 / size).round + ((rand(5) - 2) * (rand(3) - 1))
end
until @y_vec != 0
@y_vec = (30 / size).round + ((rand(5) - 2) * (rand(3) - 1))
end
x1 = rand(size * 0.1).round + (size * 0.1); y1 = rand(size * 0.1).round + (size * 0.1)
x2 = x1 + rand(size * 0.4).round; y2 = 0
x3 = size - (rand(size * 0.1).round + (size * 0.1)); y3 = rand(size * 0.1).round + (size * 0.1)
x4 = size - (rand(size * 0.1).round + (size * 0.1)); y4 = rand(size * 0.1).round + (size * 0.1)
x5 = size; y5 = y4 + rand(size * 0.4).round
x6 = size - (rand(size * 0.1).round + (size * 0.1)); y6 = size - (rand(size * 0.1).round + (size * 0.1))
x7 = size - (rand(size * 0.1).round + (size * 0.1)); y7 = size - (rand(size * 0.1).round + (size * 0.1))
x8 = x7 - rand(size * 0.4).round; y8 = size
x9 = rand(size * 0.1).round + (size * 0.1); y9 = size - (rand(size * 0.1).round + (size * 0.1))
x10 = rand(size * 0.1).round + (size * 0.1); y10 = size - (rand(size * 0.1).round + (size * 0.1))
x11 = 0; y11 = y10 - rand(size * 0.4).round
x12 = rand(size * 0.1).round + (size * 0.1); y12 = rand(size * 0.1).round + (size * 0.1)
@slot = stack top: 30, do
shape{
fill black
stroke lime
move_to(x1, y1)
line_to(x2, y2)
line_to(x3, y3)
line_to(x4, y4)
line_to(x5, y5)
line_to(x6, y6)
line_to(x7, y7)
line_to(x8, y8)
line_to(x9, y9)
line_to(x10, y10)
line_to(x11, y11)
line_to(x12, y12)
line_to(x1, y1)
}
end
set_coords(x, y)
end
def set_coords(x, y)
x = 0 if x > 700; x = 700 if x < 0 - @size
y = 0 if y > 600; y = 600 if y < 0
@x = x; @y = y
@area = [@x..(@x + @size), @y..(@y + @size)]
self.move(@x, @y)
end
def move_asteroid
x = @x + @x_vec; y = @y + @y_vec
set_coords(x, y)
end
def check_hits(x, y)
if @area[0].include?(x) && @area[1].include?(y)
@hit = true
end
end
def hit?
@hit
end
end #Asteroid
#######################
Shoes.app width: 700, height: 630 do
background black
def init_game
@lives = 3
@score = 0
@level = 1
@rocks = []
@game_over = false
status_area = flow height: 30 do
border lime
@status_info = para " ", stroke: lime, align: "center", top: 2
end
init_level(1)
end
def init_level(level)
update_status(@lives, @score, @level)
unless @rocks.empty?
@rocks.each{|rock| rock.remove}
@rocks.clear
end
unless @level == 1 || @no_congrats
salutations = ["Hey There", "Woah", "Nice One", "Well Done", "Awesome"]
names = ["Dude", "Buddy", "Pal", "Friend", "Amigo"]
actions = ["Rocked", "Destroyed", "Annihilated", "Kicked Butt On", "Creamed"]
self.append{
@congrats = title "#{salutations[rand(5)]} #{names[rand(5)]},
You #{actions[rand(5)]} Level #{@level - 1}!
On To...", stroke: lime, align: "center", top: 100
}
timer(3){@congrats.remove}
end
self.append{
@level_info = banner "level #{@level}", stroke: lime, align: "center", top: 280
}
timer(3){
@level_info.remove
self.append{@ship = first_class_flying_ship(350, 300)}
n = @level
n.times{
self.append{@rock = asteroid(60, rand(80) - 70, rand(80) - 70)}
@rocks << @rock
}
@no_congrats = false
start_motion
}
end
def update_status(lives, level, score)
@status_info.text = "lives: #{@lives} score: #{@score} level: #{@level}"
end
def break_rock(size, x, y)
case size
when 60
self.append{@rock1 = asteroid(30, x + 25, y)}
self.append{@rock2 = asteroid(30, x -25, y)}
@rocks << @rock1 << @rock2
@score += 25
when 30
self.append{@rock1 = asteroid(15, x + 25, y)}
self.append{@rock2 = asteroid(15, x - 25, y)}
self.append{@rock3 = asteroid(15, x, y - 25)}
@rocks << @rock1 << @rock2 << @rock3
@score += 50
when 15
@score += 100
end
update_status(@lives, @score, @level)
new_level if @rocks.empty?
end
def new_level
@game_motion.stop
@level += 1
update_status(@lives, @score, @level)
@ship.remove
init_level(@level)
end
def destroy_ship
@game_motion.stop
@ship.remove
@debris = []
fill lime
50.times{
blasted_bit = oval(@ship.center_x + (rand(51) - 25), (@ship.center_y + (rand(51) - 25) + 30), 3)
@debris << blasted_bit
}
@lives -= 1
update_status(@lives, @score, @level)
if @lives == 0
game_over
else
@no_congrats = true
timer(3){
@debris.each{|bit| bit.remove}
init_level(@level)
}
end
end
def game_over
@game_over = true
sorry = stack width: 700 do
banner "GAME OVER", stroke: lime, align: "center"
title "press space to restart", stroke: lime, align: "center"
end
sorry.move(0, 200)
keypress{|key|
if key == " " && @game_over
clear
init_game
end
}
end
def start_motion
@game_motion = animate(16){
@ship.move_ship
@rocks.each{|rock|
rock.move_asteroid
rock.check_hits(@ship.center_x, @ship.center_y)
if rock.hit?
destroy_ship
end
}
unless @ship.shots.empty?
@ship.shots.each{|bullet|
@rocks.each{|rock|
rock.check_hits(bullet.x, bullet.y)
if rock.hit?
@rocks.delete(rock); rock.remove
@ship.shots.delete(bullet); bullet.remove
break_rock(rock.size, rock.x, rock.y)
end
}
}
end
}
end
@first_run = true
intro = stack width: 700 do
banner "ASTEROIDS!\n", stroke: lime, align: "center"
para "move mouse to rotate ship", stroke: lime, align: "center"
para "use right mouse button to accelerate towards the pointer", stroke: lime, align: "center"
para "use left mouse button to shoot\n\n", stroke: lime, align: "center"
title "press space to start and pause", stroke: lime, align: "center"
end
intro.move(0, 100)
keypress{|key|
if key == " "
if @first_run
clear
init_game
@first_run = false
elsif @paused
@pause_message.remove
@game_motion.start; @paused = false; @ship.paused = false
else
@game_motion.stop; @paused = true; @ship.paused = true
@pause_message = stack width: 700 do
title "paused", stroke: lime, align: "center"
end
@pause_message.move(0, 200)
end
end
}
end
Jump to Line
Something went wrong with that request. Please try again.