Created
April 11, 2012 11:54
-
-
Save ashbb/2358860 to your computer and use it in GitHub Desktop.
Asteroids game for Green and Purple Shoes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# asteroids game by lljk | |
# have fun! | |
# revised for Green and Purple Shoes by ashbb | |
# But in this code, the ship doesn't rotate on Green Shoes | |
class Shoes::Widget | |
def move x, y | |
@ele.move x, y | |
end | |
def clear | |
@ele.clear | |
end | |
end | |
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 | |
@ele = oval(0, 0, 5, 5) | |
self.move(@x, @y) | |
end | |
end | |
class FirstClassFlyingShip < Shoes::Widget | |
attr_accessor :center_x, :center_y, :shots, :paused | |
def initialize(x, y) | |
@paused = false | |
@x, @y = x, y | |
@center_x = x; @center_y = y | |
@shots = [] | |
@x_vec = 0; @y_vec = 0 | |
@start_angle = 0 | |
@rotate_by = 0 | |
draw_ship | |
@m = motion do |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 | |
end | |
@c = click do |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 | |
def clear | |
[*@shots, @m, @c].each{|e| e.clear if e} | |
@shots.clear | |
super | |
end | |
def draw_ship | |
@ele = shape(left: 350, top: 315, width: 20, height: 24){ | |
move_to(10, 0) | |
line_to(20, 24) | |
line_to(10, 20) | |
line_to(0, 24) | |
line_to(10, 0) | |
} unless @ele | |
@ele.rotate = [-@start_angle, @ele.left+10, @ele.top+12] # Need to comment out this line for Green Shoes | |
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 | |
@ele.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.clear | |
@shots.delete(bullet) | |
else | |
bullet.move(bullet.x, bullet.y) | |
end | |
} | |
end | |
end | |
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) | |
@ele = shape do | |
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 > 630; y = 630 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 | |
####################### | |
Shoes.app width: 700, height: 630 do | |
[Shoes::Title, Shoes::Banner, Shoes::Para].each{|klass| style klass, stroke: lime, align: "center"} | |
stroke lime | |
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 " ", top: 5 | |
end | |
init_level(1) | |
end | |
def init_level(level) | |
update_status(@lives, @score, @level) | |
unless @rocks.empty? | |
@rocks.each{|rock| rock.clear} | |
@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"] | |
@congrats = title "#{salutations[rand(5)]} #{names[rand(5)]}, ", | |
"You #{actions[rand(5)]} Level #{@level - 1}! On To...", top: 100 | |
timer(3){@congrats.clear} | |
end | |
@level_info = banner "level #{@level}", top: 280 | |
timer(3){ | |
@level_info.clear | |
@ship = first_class_flying_ship(350, 315) | |
n = @level | |
n.times{ | |
@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.clear | |
init_level(@level) | |
end | |
def destroy_ship | |
@game_motion.stop | |
@ship.clear | |
@debris = [] | |
50.times{ | |
blasted_bit = oval(@ship.center_x + (rand(51) - 25), (@ship.center_y + (rand(51) - 25) + 30), 3, 3, fill: lime) | |
@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.clear} | |
@debris.clear | |
init_level(@level) | |
} | |
end | |
end | |
def game_over | |
@game_over = true | |
@go_msg = [] | |
@go_msg << banner("GAME OVER", top: 200) | |
@go_msg << title("press space to restart", top: 250) | |
end | |
def start_motion | |
@game_motion = animate 16 do | |
unless @game_motion.pause? | |
@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.clear | |
@ship.shots.delete(bullet); bullet.clear | |
break_rock(rock.size, rock.x, rock.y) | |
end | |
} | |
} | |
end | |
end | |
end | |
end | |
@first_run = true | |
stack width: 700, margin_top: 100 do | |
stack do | |
banner "ASTEROIDS!\n" | |
para "move mouse to rotate ship" | |
para "use right mouse button to accelerate towards the pointer" | |
para "use left mouse button to shoot\n\n" | |
title "press space to start and pause" | |
end | |
end | |
@pause_message = title("paused", top: 230) | |
@pause_message.hide | |
keypress{|key| | |
if key == " " | |
if @game_over | |
[@go_msg, @debris, @rocks].each do |a| | |
a.each &:clear | |
a.clear | |
end | |
@status_info.clear | |
@first_run = true | |
end | |
if @first_run | |
clear{init_game} | |
@first_run = false | |
elsif @paused | |
@pause_message.hide | |
@game_motion.pause; @paused = false; @ship.paused = false | |
else | |
@game_motion.pause; @paused = true; @ship.paused = true | |
@pause_message.show | |
end | |
end | |
} | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Original code, Asteroids Game for Red Shoes, was created by lljk (j. kaiden).
I've just revised the code for Green and Purple Shoes. Watch the following streaming flash demo.
Note: This revised code works both with Green and Purple. But in Green, need to comment out line 76. The ship doesn't rotate well in this code.