Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added asteroids game

  • Loading branch information...
commit b4d027511adec7049b0ffc2cd502ed8ba1191e71 1 parent 6e1a12c
@lljk authored
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.
Please sign in to comment.
Something went wrong with that request. Please try again.