Skip to content

Instantly share code, notes, and snippets.

@shawn42
Created May 11, 2012 18:17
Show Gist options
  • Save shawn42/2661476 to your computer and use it in GitHub Desktop.
Save shawn42/2661476 to your computer and use it in GitHub Desktop.
The guts of omg_aliens
# src/actors/alien.rb
define_actor :alien do
has_attributes action: :march, view: :graphical_actor_view
has_behaviors do
animated frame_update_time: 900
collidable shape: :polygon, cw_local_points: [[4,4],[44,4],[44,44],[4,44]]
projectile speed: 0.01, direction: vec2(1,0)
reversable_direction
increasing_speed accel: 0.001
drops fall_amount: 25
shooter shoots: :alien_missile, direction: vec2(0,-1)
end
end
# src/actors/alien_missile.rb
define_actor :alien_missile do
has_behaviors do
in_bounds_or_death bounds: [0,0,:viewport_width,:viewport_height]
projectile speed: 0.3, direction: vec2(0, 1)
collidable shape: :polygon, cw_local_points: [[0,0],[8,0],[4,10]]
end
view do
draw do |target, x_offset, y_offset, z|
target.fill(actor.x, actor.y, actor.x+actor.radius/2.0, actor.y-actor.radius*2, [0xff, 0xff, 0xff], z)
end
end
end
# src/actors/frickin_laser.rb
define_actor :frickin_laser do
has_behaviors do
in_bounds_or_death bounds: [0,30,:viewport_width,:viewport_height]
projectile speed: 0.4, direction: vec2(0, -1)
collidable shape: :circle, :radius => 4
end
view do
draw do |target, x_offset, y_offset, z|
target.fill(actor.x, actor.y, actor.x+actor.radius/2.0, actor.y-actor.radius*2, [0xff, 0xff, 0xff], z)
end
end
end
# src/actors/player.rb
define_actor :player do
has_behaviors do
graphical
audible
keyboard_movement
keyboard_shooting
collidable shape: :circle, :radius => 20
shooter shoots: :frickin_laser, direction: vec2(0,1)
mover speed: 0.14
end
end
# src/actors/score_fade.rb
define_actor :score_fade do
# label fader behavior
behavior do
requires :director, :stage
setup do
actor.has_attributes initial_ttl: actor.ttl,
label: stage.create_actor(:label, actor.attributes.merge(text: actor.score, layer: 99))
director.when :update do |time|
actor.ttl -= time
if actor.ttl <= 0
actor.remove
else
percent_time_left = actor.ttl / actor.initial_ttl.to_f
color_val = 255 * percent_time_left
actor.label.color = Color.new color_val, color_val, color_val, color_val
end
end
actor.when :remove_me do
director.unsubscribe_all self
actor.label.remove
end
end
end
end
# src/actors/ufo.rb
define_actor :ufo do
has_behaviors do
graphical
audible
projectile speed: 0.12, direction: vec2(1, 0)
collidable shape: :circle, radius: 10
in_bounds_or_death bounds: [0,0,:viewport_width,:viewport_height]
# TODO clean up viewport access?
end
behavior do
setup do
actor.react_to :play_sound, :ufo_flying, looping: true
actor.when :remove_me do
actor.react_to :stop_sound, :ufo_flying
end
end
end
end
# src/app.rb
#!/usr/bin/env ruby
$: << "#{File.dirname(__FILE__)}/../config"
require 'environment'
if $0 == __FILE__
GameboxApp.run ARGV, ENV
end
# src/behaviors/drop_down.rb
define_behavior :drops do
setup do
actor.has_attributes fall_amount: opts[:fall_amount]
reacts_with :drop_down
end
helpers do
def drop_down
actor.y += actor.fall_amount
end
end
end
# src/behaviors/in_bounds_or_death.rb
define_behavior :in_bounds_or_death do
requires :director, :viewport
setup do
bounds = opts[:bounds].map do |v|
if v == :viewport_width
viewport.width
elsif v == :viewport_height
viewport.height
else
v
end
end
actor.has_attributes safe_bounds: Rect.new(bounds)
director.when :update do |time|
actor.remove unless actor.safe_bounds.collide_point? actor.x, actor.y
end
actor.when :remove_me do
director.unsubscribe_all self
end
end
end
# src/behaviors/increasing_speed.rb
define_behavior :increasing_speed do
requires :backstage
setup do
actor.has_attributes speed: 0, accel: 0
reacts_with :increase_speed
end
helpers do
def increase_speed
actor.speed += actor.accel * backstage[:wave]
end
end
end
# src/behaviors/keyboard_movement.rb
define_behavior :keyboard_movement do
requires :input_manager
setup do
actor.has_attributes :move_left, :move_right
i = input_manager
i.while_pressed KbLeft, actor, :move_left
i.while_pressed KbRight, actor, :move_right
end
end
# src/behaviors/keyboard_shooting.rb
define_behavior :keyboard_shooting do
requires :input_manager
setup do
input_manager.reg :keyboard_down, KbSpace do
actor.react_to :shoot
end
end
end
# src/behaviors/mover.rb
define_behavior :mover do
requires_behaviors :positioned
requires :director, :viewport
setup do
actor.has_attributes speed: opts[:speed]
director.when :update do |time|
velocity = actor.speed * time
actor.x += velocity if actor.move_right?
actor.x -= velocity if actor.move_left?
stage_left = 0
stage_right = viewport.width-20
if actor.x > stage_right
actor.x = stage_right
elsif actor.x < stage_left
actor.x = stage_left
end
end
end
end
# src/behaviors/projectile.rb
define_behavior :projectile do
requires_behaviors :positioned
requires :director
setup do
actor.has_attributes direction: opts[:direction].dup,
speed: opts[:speed]
director.when :update do |time|
move_vector = actor.direction * time * actor.speed
actor.x += move_vector.x
actor.y += move_vector.y
end
end
end
# src/behaviors/reversable_direction.rb
define_behavior :reversable_direction do
setup do
actor.has_attributes direction: vec2(0,0).dup
reacts_with :reverse_direction
end
helpers do
def reverse_direction
# Ftor#reverse!
actor.direction.reverse!
end
end
end
# src/behaviors/shooter.rb
define_behavior :shooter do
requires :input_manager, :stage
requires_behaviors :positioned
setup do
actor.has_attributes can_shoot: true
reacts_with :shoot
end
helpers do
def shoot
if actor.can_shoot?
actor.can_shoot = false
actor.react_to :play_sound, :shoot
ammunition = stage.create_actor opts[:shoots], x: actor.x + (actor.image.width/2), y: actor.y
ammunition.when :remove_me do
actor.can_shoot = true
end
end
end
end
end
# src/demo_stage.rb
class DemoStage < Stage
def setup
super
backstage[:wave] ||= 0
backstage[:wave] += 1
@player = create_actor :player, x: 200, y: 550
input_manager.reg :down, KbW do
@aliens = []
end
@score = create_actor :score, x: 10, y: 10
create_actor :fps, x: 400, y: 10
create_actor :logo, x: 480, y: 460
@aliens = []
columns = 8
rows = 2 + backstage[:wave]
columns.times do |c|
rows.times do |r|
alien = create_actor :alien, x: 20+c*60, y: 40+r*60
alien.when :remove_me do
if @aliens.size % 3 == 0
@aliens.each{|a|a.react_to :increase_speed}
end
end
@aliens << alien
end
end
input_manager.reg :down, KbP do
pause
end
on_unpause do
sound_manager.play_sound :pause
sound_manager.play_music :rush_remix
sound_manager.play_sound :ufo_flying, repeats: -1 if @ufo
@pause.remove
end
on_pause do
sound_manager.stop_sound :ufo_flying if @ufo and @ufo.alive?
sound_manager.pause_music :rush_remix
sound_manager.play_sound :pause
@pause = create_actor :label, text: "pause", x: 280, y: 300, size: 20
input_manager.reg :down, KbP do
unpause
end
end
on_collision_of :ufo, :frickin_laser do |ufo,laser|
ufo_shot ufo, laser
end
on_collision_of :alien, :frickin_laser do |alien,laser|
alien_shot alien, laser
end
on_collision_of :player, [:alien,:alien_missile] do |player,bad_thing|
you_lose
end
add_timer :alien_shoot, (4-backstage[:wave])*1_000 do
@aliens[rand(@aliens.size)].react_to :shoot unless @aliens.empty?
end
add_timer :ufo_create_actor, 9_000 do
if @ufo.nil?
if (@aliens.size > 7)
@ufo = create_actor :ufo, x: 10, y: 30
@ufo.when :remove_me do
@ufo = nil
end
end
end
end
sound_manager.play_music :rush_remix if backstage[:wave] == 1
end
def ufo_shot(ufo, laser)
sound_manager.play_sound :ufo_death
create_actor :score_fade, x: ufo.x, y: ufo.y, score: 1000, ttl: 1000
ufo.remove
laser.remove
@score.react_to :add, 1000
@ufo = nil
end
def alien_shot(alien, laser)
create_actor :score_fade, x: alien.x, y: alien.y, score: 100, ttl: 1000
@aliens.delete alien
alien.remove
laser.remove
sound_manager.play_sound :death
@score.react_to :add, 100
end
def rebuild_bounding_box
return if @aliens.empty?
alien_x_values = @aliens.collect &:x
alien_y_values = @aliens.collect &:y
min_x = alien_x_values.min
max_x = alien_x_values.max
max_y = [email protected]
dir = @aliens.first.direction.x
if (max_x > [email protected] and dir == 1) or
(min_x < 20 and dir == -1)
@aliens.each{|a|
a.react_to :increase_speed
a.react_to :drop_down
a.react_to :reverse_direction
}
end
if max_y > @player.y
you_lose
end
end
def you_lose
if @player.alive?
sound_manager.play_sound :player_death
create_actor :label, text: "YOU LOSE!", x: 150, y: 100, size: 90
@player.remove
add_timer :you_lose, 1_500 do
fire :prev_stage
end
end
end
def update(time)
super
rebuild_bounding_box
if @aliens.empty?
@player.remove
if backstage[:wave] == 3
fire :next_stage
else
fire :restart_stage
end
end
end
def add_timer(*args, &blk)
timer_manager.add_timer *args, &blk
end
end
# src/win_stage.rb
class WinStage < Stage
def setup
super
create_actor :logo, :x => 480, :y => 360
create_actor :label, :text => "YOU WIN!", :x => 150, :y => 100, :size => 90
create_actor :label, :text => "SCORE:", :x => 40, :y => 200, :size => 90
create_actor :label, :text => backstage[:score], :x => 300, :y => 200, :size => 90
end
def draw(target)
target.fill [0]*3
super
end
end
# config/environment.rb
APP_ROOT = "#{File.join(File.dirname(__FILE__),"..")}/"
require 'gamebox'
Gamebox.configure do |config|
config.config_path = APP_ROOT + "config/"
config.data_path = APP_ROOT + "data/"
config.music_path = APP_ROOT + "data/music/"
config.sound_path = APP_ROOT + "data/sounds/"
config.gfx_path = APP_ROOT + "data/graphics/"
config.fonts_path = APP_ROOT + "data/fonts"
config.gb_config_path = GAMEBOX_PATH + "config/"
config.gb_data_path = GAMEBOX_PATH + "data/"
config.gb_music_path = GAMEBOX_PATH + "data/music/"
config.gb_sound_path = GAMEBOX_PATH + "data/sounds/"
config.gb_gfx_path = GAMEBOX_PATH + "data/graphics/"
config.gb_fonts_path = GAMEBOX_PATH + "data/fonts"
config.stages = [:demo, :win]
config.game_name = "OMG Aliens"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment