Skip to content
Browse files

added asteroids game

  • Loading branch information...
1 parent 6e1a12c commit b4d027511adec7049b0ffc2cd502ed8ba1191e71 @lljk committed Apr 6, 2012
Showing with 379 additions and 0 deletions.
  1. +379 −0 asteroids.rb
  2. BIN asteroids_screenshot.png
View
379 asteroids.rb
@@ -0,0 +1,379 @@
+# 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
View
BIN asteroids_screenshot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b4d0275

Please sign in to comment.
Something went wrong with that request. Please try again.