Last active
May 8, 2019 21:53
-
-
Save amirrajan/60ccfc0285333dd6b5e1efdf9e445ebe to your computer and use it in GitHub Desktop.
subspace2.rb
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
# Press escape the open up the DragonRuby Hud and type the following code | |
def after_tick game_state | |
game_state.solids << [0, 0, 100, 100, 255, 0, 0] | |
end | |
# after typing the code above press Shift+Enter |
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
class Game | |
attr_accessor :_ | |
def tick | |
defaults | |
render | |
calc | |
input | |
end | |
def defaults | |
default_coordinate_system | |
_.flames ||= [] | |
_.bullets ||= [] | |
_.ship_blue_score ||= 0 | |
_.ship_red_score ||= 0 | |
_.ship_blue ||= default_ship(-400, 0, 0) | |
_.ship_red ||= default_ship( 400, 0, 180) | |
default_universe | |
end | |
def render | |
render_score | |
render_universe | |
render_ships | |
render_flames | |
render_bullets | |
end | |
def calc | |
calc_thrusts | |
calc_ships | |
calc_bullets | |
calc_winner | |
end | |
def input | |
input_accelerate | |
input_turn | |
input_bullets_and_mines | |
end | |
def default_ship x, y, heading | |
_.new(:ship) do |s| | |
s.x = x | |
s.y = y | |
s.dy = 0 | |
s.dx = 0 | |
s.damage = 0 | |
s.dead = false | |
s.heading = heading | |
end | |
end | |
def red_color | |
[255, 90, 90] | |
end | |
def blue_color | |
[110, 140, 255] | |
end | |
def default_universe | |
_.stars ||= 100.times.map do |i| | |
size = 1 * rand + 1 | |
[rand * _.screen.w_half * [1, -1].sample, | |
rand * _.screen.h_half * [1, -1].sample, size, size, 128 * rand + 128, 255, 255] | |
end | |
end | |
def default_coordinate_system | |
_.origin_x = 640 | |
_.origin_y = 360 | |
_.pos_y_direction = -1 | |
_.pos_x_direction = 1 | |
end | |
def render_score | |
_.labels << [-_.screen.w.fdiv(2) + 80, _.screen.h.fdiv(2) - 80, _.ship_blue_score, 2, 1, *blue_color] | |
_.labels << [ _.screen.w.fdiv(2) - 80, _.screen.h.fdiv(2) - 80, _.ship_red_score, 2, 1, *red_color] | |
end | |
def render_universe | |
_.solids << [-_.screen.w, -_.screen.h, _.screen.w * 2, _.screen.h * 2, 0, 0, 0] | |
_.solids += _.stars | |
end | |
def apply_round_finished_alpha entity | |
return entity unless _.round_finished_debounce | |
entity[-1] *= _.round_finished_debounce.fdiv_perc(120) | |
return entity | |
end | |
def update_sprite path, ship | |
ship.sprite = | |
apply_round_finished_alpha [path, | |
ship.x - 16, ship.y - 16, 33, 33, | |
ship.heading, | |
ship.dead ? 0 : 255 * ship.__elapsed_ticks_since_creation__.fdiv_perc(120)] | |
end | |
def render_ships | |
_.sprites << update_sprite('ship_blue.png', _.ship_blue) | |
_.sprites << update_sprite('ship_red.png', _.ship_red) | |
_.labels << apply_round_finished_alpha([_.ship_blue.x, _.ship_blue.y + 20, "." * (5 - _.ship_blue.damage), 0, 1, *blue_color, 255]) | |
_.labels << apply_round_finished_alpha([_.ship_red.x, _.ship_red.y + 20, "." * (5 - _.ship_red.damage), 0, 1, *red_color, 255]) | |
end | |
def render_flames | |
_.solids += _.flames.map do |p| | |
percentage = p.lifetime.minus(p.__elapsed_ticks_since_creation__).fdiv_perc(p.lifetime) | |
max_alpha = p.max_alpha || 255 | |
apply_round_finished_alpha [-1 + p.x, -1 + p.y, 3, 3, 255, 200, 75, max_alpha * percentage] | |
end | |
end | |
def render_bullets | |
_.solids += _.bullets.map do |b| | |
max_alpha = b.max_alpha || 255 | |
bullet_sprite = if b.owner == _.ship_blue.__id__ | |
[-2 + b.x, -2 + b.y, 5, 5, *blue_color, max_alpha] | |
elsif b.owner == _.ship_red.__id__ | |
[-2 + b.x, -2 + b.y, 5, 5, *red_color, max_alpha] | |
else | |
[-2 + b.x, -2 + b.y, 5, 5, 255, 255, 255, 0] | |
end | |
apply_round_finished_alpha bullet_sprite | |
end | |
end | |
def calc_wrap_location location | |
location.x = _.screen.w_half * -1 if location.x > _.screen.w_half | |
location.x = _.screen.w_half if location.x < _.screen.w_half * -1 | |
location.y = _.screen.h_half * -1 if location.y > _.screen.h_half | |
location.y = _.screen.h_half if location.y < _.screen.h_half * -1 | |
end | |
def calc_thrusts | |
_.flames.each do |p| | |
p.speed *= 0.9 | |
p.y += p.speed * p.heading.y_vector | |
p.x += p.speed * p.heading.x_vector | |
calc_wrap_location p | |
end | |
_.flames.reject! { |p| p.__elapsed_ticks_since_creation__ >= p.lifetime } | |
end | |
def all_ships | |
[_.ship_blue, _.ship_red] | |
end | |
def calc_bullet bullet | |
bullet.y += bullet.speed * bullet.heading.y_vector | |
bullet.x += bullet.speed * bullet.heading.x_vector | |
calc_wrap_location bullet | |
explode_bullet bullet if bullet.__elapsed_ticks_since_creation__ >= bullet.lifetime | |
return if bullet.exploded | |
all_ships.reject { |s| s.dead || s.__id__ == bullet.owner }.each do |s| | |
if s.sprite[1..4].intersects_rect?([bullet.x - 2, bullet.y - 2, 5, 5]) | |
explode_bullet bullet, 20, 5, 30 | |
s.damage += 1 | |
end | |
end | |
end | |
def calc_bullets | |
_.bullets.each { |b| calc_bullet b } | |
_.bullets.reject! { |b| b.exploded } | |
end | |
def create_explosion type, entity, flame_count, max_speed, lifetime | |
flame_count.times do | |
_.flames << _.new(type) do |s| | |
s.heading = 360 * rand | |
s.speed = max_speed * rand | |
s.lifetime = lifetime | |
s.x = entity.x | |
s.y = entity.y | |
end | |
end | |
end | |
def explode_bullet bullet, flame_override = 5, max_speed = 5, lifetime = 10 | |
bullet.exploded = true | |
create_explosion :bullet_explosion, bullet, flame_override, max_speed, lifetime | |
end | |
def calc_ship ship | |
ship.x += ship.dx | |
ship.y += ship.dy | |
calc_wrap_location ship | |
end | |
def calc_ships | |
all_ships.each { |s| calc_ship s } | |
return if all_ships.any? { |s| s.dead } | |
if _.ship_blue.sprite[1..4].intersects_rect?(_.ship_red.sprite[1..4]) | |
_.ship_blue.damage = 5 | |
_.ship_red.damage = 5 | |
end | |
end | |
def create_thruster_flames ship | |
_.flames << _.new(:ship_thruster) do |s| | |
s.heading = ship.heading + 180 + [1, -1].sample.mult(rand * 20) | |
s.speed = 10 * rand | |
s.max_alpha = 255 * ship.__elapsed_ticks_since_creation__.fdiv_perc(120) | |
s.lifetime = 30 | |
s.x = ship.x + 19 * s.heading.x_vector | |
s.y = ship.y + 19 * s.heading.y_vector | |
end | |
end | |
def input_accelerate_ship should_move_ship, ship | |
return if ship.dead | |
if should_move_ship | |
create_thruster_flames ship | |
ship.dx += 0.050 * ship.heading.x_vector | |
ship.dy += 0.050 * ship.heading.y_vector | |
else | |
ship.dx *= 0.99 | |
ship.dy *= 0.99 | |
end | |
end | |
def input_accelerate | |
input_accelerate_ship _.player_1_r1_key_held, _.ship_blue | |
input_accelerate_ship _.player_2_r1_key_held, _.ship_red | |
end | |
def input_turn_ship direction, ship | |
ship.heading += 3 * direction | |
end | |
def input_turn | |
input_turn_ship( 1, _.ship_blue) if _.player_1_left_key_held | |
input_turn_ship(-1, _.ship_blue) if _.player_1_right_key_held | |
input_turn_ship( 1, _.ship_red) if _.player_2_left_key_held | |
input_turn_ship(-1, _.ship_red) if _.player_2_right_key_held | |
end | |
def input_bullet create_bullet, ship | |
return unless create_bullet | |
return if ship.dead | |
_.bullets << _.new(:ship_bullet) do |s| | |
s.owner = ship.__id__ | |
s.heading = ship.heading | |
s.max_alpha = 255 * ship.__elapsed_ticks_since_creation__.fdiv_perc(120) | |
s.speed = 5 + ship.dx.mult(ship.heading.x_vector) + ship.dy.mult(ship.heading.y_vector) | |
s.lifetime = 120 | |
s.x = ship.x + ship.heading.x_vector * 15 | |
s.y = ship.y + ship.heading.y_vector * 15 | |
end | |
end | |
def input_mine create_mine, ship | |
return unless create_mine | |
return if ship.dead | |
_.bullets << _.new(:ship_bullet) do |s| | |
s.owner = ship.__id__ | |
s.heading = 360 * rand | |
s.max_alpha = 255 * ship.__elapsed_ticks_since_creation__.fdiv_perc(120) | |
s.speed = 0.02 | |
s.lifetime = 600 | |
s.x = ship.x + ship.heading.x_vector * -20 | |
s.y = ship.y + ship.heading.y_vector * -20 | |
end | |
end | |
def input_bullets_and_mines | |
input_bullet(_.player_1_a_key_down && _.tick_count.mod_zero?(10) || | |
_.player_1_a_key_down == _.tick_count - 1, | |
_.ship_blue) | |
input_mine(_.player_1_b_key_down && _.tick_count.mod_zero?(10) || | |
_.player_1_b_key_down == _.tick_count - 1, | |
_.ship_blue) | |
input_bullet(_.player_2_a_key_down && _.tick_count.mod_zero?(10) || | |
_.player_2_a_key_down == _.tick_count - 1, | |
_.ship_red) | |
input_mine(_.player_2_b_key_down && _.tick_count.mod_zero?(10) || | |
_.player_2_b_key_down == _.tick_count - 1, | |
_.ship_red) | |
end | |
def calc_kill_ships | |
all_ships.each do |s| | |
if s.damage >= 5 | |
create_explosion :ship_explosion, s, 20, 20, 30 if !s.dead | |
s.dead = true | |
end | |
end | |
end | |
def calc_score | |
return if _.round_over | |
alive_ships = all_ships.find_all { |s| !s.dead } | |
return if alive_ships.length > 1 | |
if alive_ships.length == 1 | |
if alive_ships.first.__id__ == _.ship_red.__id__ | |
_.ship_red_score += 1 | |
elsif alive_ships.first.__id__ == _.ship_blue.__id__ | |
_.ship_blue_score += 1 | |
end | |
end | |
_.round_over = true | |
end | |
def calc_new_round | |
_.ship_blue = default_ship(-400, [-300, 300].sample * rand, 0) | |
_.ship_red = default_ship( 400, [-300, 300].sample * rand, 180) | |
_.round_over = false | |
_.round_finished_debounce = nil | |
_.flames.clear | |
_.bullets.clear | |
end | |
def calc_reset_ships | |
return unless _.round_over | |
_.round_finished_debounce ||= 120 | |
_.round_finished_debounce -= 1 | |
return if _.round_finished_debounce > 0 | |
calc_new_round | |
end | |
def calc_winner | |
calc_kill_ships | |
calc_score | |
calc_reset_ships | |
end | |
end | |
$game = Game.new | |
def tick game_state | |
$game._ = game_state | |
$game.tick | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment