mirror of
https://github.com/cyberarm/i-mic-fps.git
synced 2025-12-16 16:12:35 +00:00
Compare commits
20 Commits
map_editor
...
v0.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 95fc6272b8 | |||
| d3603947cc | |||
| 029d9b1951 | |||
| 6520051938 | |||
| 8d956131d1 | |||
| 7f16efe0a4 | |||
| c92ea9ec73 | |||
| c9ba1ab94a | |||
| 2000f601d8 | |||
| a078645b94 | |||
| c1eb02a106 | |||
| a3b4c6e651 | |||
| fd3785cdcd | |||
| 06fb2c0e43 | |||
| d524c21332 | |||
| 85dd90b2f4 | |||
| 1629cf4605 | |||
| f3c3a1047f | |||
| face4b092a | |||
| 75185425b6 |
5
Gemfile
5
Gemfile
@@ -1,8 +1,13 @@
|
|||||||
source "https://rubygems.org"
|
source "https://rubygems.org"
|
||||||
|
gem "rake"
|
||||||
gem "opengl-bindings", require: "opengl"
|
gem "opengl-bindings", require: "opengl"
|
||||||
gem "cyberarm_engine", git: "https://github.com/cyberarm/cyberarm_engine"
|
gem "cyberarm_engine", git: "https://github.com/cyberarm/cyberarm_engine"
|
||||||
gem "nokogiri", ">= 1.11.0.rc1"
|
gem "nokogiri", ">= 1.11.0.rc1"
|
||||||
|
gem "async-websocket"
|
||||||
|
|
||||||
group(:packaging) do
|
group(:packaging) do
|
||||||
|
gem "releasy", github: "gosu/releasy"
|
||||||
gem "ocra"
|
gem "ocra"
|
||||||
|
gem "rubyzip"
|
||||||
|
gem "excon"
|
||||||
end
|
end
|
||||||
|
|||||||
55
Gemfile.lock
55
Gemfile.lock
@@ -1,33 +1,84 @@
|
|||||||
GIT
|
GIT
|
||||||
remote: https://github.com/cyberarm/cyberarm_engine
|
remote: https://github.com/cyberarm/cyberarm_engine
|
||||||
revision: 4055f645f3446c61f57ad1c7748284106c1516ff
|
revision: 0850336e55891f1f10dcb10e3b4b42e5f7379b33
|
||||||
specs:
|
specs:
|
||||||
cyberarm_engine (0.13.1)
|
cyberarm_engine (0.14.0)
|
||||||
gosu (~> 0.15.0)
|
gosu (~> 0.15.0)
|
||||||
gosu_more_drawables (~> 0.3)
|
gosu_more_drawables (~> 0.3)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/gosu/releasy.git
|
||||||
|
revision: e8a24c079c4930c6ddbab17fc444027ba41491ca
|
||||||
|
specs:
|
||||||
|
releasy (0.2.3)
|
||||||
|
bundler (>= 1.2.1)
|
||||||
|
cri (~> 2.1.0)
|
||||||
|
ocra (~> 1.3.0)
|
||||||
|
rake (>= 0.9.2.2)
|
||||||
|
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
|
async (1.26.0)
|
||||||
|
console (~> 1.0)
|
||||||
|
nio4r (~> 2.3)
|
||||||
|
timers (~> 4.1)
|
||||||
|
async-http (0.52.2)
|
||||||
|
async (~> 1.25)
|
||||||
|
async-io (~> 1.28)
|
||||||
|
async-pool (~> 0.2)
|
||||||
|
protocol-http (~> 0.19.0)
|
||||||
|
protocol-http1 (~> 0.13.0)
|
||||||
|
protocol-http2 (~> 0.14.0)
|
||||||
|
async-io (1.29.0)
|
||||||
|
async (~> 1.14)
|
||||||
|
async-pool (0.3.1)
|
||||||
|
async (~> 1.25)
|
||||||
|
async-websocket (0.14.0)
|
||||||
|
async-http (~> 0.51)
|
||||||
|
async-io (~> 1.23)
|
||||||
|
protocol-websocket (~> 0.7.0)
|
||||||
|
console (1.8.2)
|
||||||
|
cri (2.1.0)
|
||||||
|
excon (0.73.0)
|
||||||
gosu (0.15.1)
|
gosu (0.15.1)
|
||||||
gosu (0.15.1-x64-mingw32)
|
gosu (0.15.1-x64-mingw32)
|
||||||
gosu_more_drawables (0.3.0)
|
gosu_more_drawables (0.3.0)
|
||||||
mini_portile2 (2.5.0)
|
mini_portile2 (2.5.0)
|
||||||
|
nio4r (2.5.2)
|
||||||
nokogiri (1.11.0.rc2)
|
nokogiri (1.11.0.rc2)
|
||||||
mini_portile2 (~> 2.5.0)
|
mini_portile2 (~> 2.5.0)
|
||||||
nokogiri (1.11.0.rc2-x64-mingw32)
|
nokogiri (1.11.0.rc2-x64-mingw32)
|
||||||
ocra (1.3.11)
|
ocra (1.3.11)
|
||||||
opengl-bindings (1.6.10)
|
opengl-bindings (1.6.10)
|
||||||
|
protocol-hpack (1.4.2)
|
||||||
|
protocol-http (0.19.0)
|
||||||
|
protocol-http1 (0.13.0)
|
||||||
|
protocol-http (~> 0.19)
|
||||||
|
protocol-http2 (0.14.0)
|
||||||
|
protocol-hpack (~> 1.4)
|
||||||
|
protocol-http (~> 0.18)
|
||||||
|
protocol-websocket (0.7.4)
|
||||||
|
protocol-http (~> 0.2)
|
||||||
|
protocol-http1 (~> 0.2)
|
||||||
|
rake (13.0.1)
|
||||||
|
rubyzip (2.3.0)
|
||||||
|
timers (4.3.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
x64-mingw32
|
x64-mingw32
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
async-websocket
|
||||||
cyberarm_engine!
|
cyberarm_engine!
|
||||||
|
excon
|
||||||
nokogiri (>= 1.11.0.rc1)
|
nokogiri (>= 1.11.0.rc1)
|
||||||
ocra
|
ocra
|
||||||
opengl-bindings
|
opengl-bindings
|
||||||
|
rake
|
||||||
|
releasy!
|
||||||
|
rubyzip
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.1.4
|
2.1.4
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# I-MIC FPS
|
# I-MIC FPS
|
||||||
An endeavor to create a multiplayer first-person-shooter in pure Ruby; Using C extensions only for Rendering, Sound, and Input. ([Gosu](https://libgosu.org) and [opengl-bindings](https://github.com/vaiorabbit/ruby-opengl/))
|
Creating a multiplayer first-person-shooter in pure Ruby; Using C extensions only for Rendering, Sound, and Input. ([Gosu](https://libgosu.org) and [opengl-bindings](https://github.com/vaiorabbit/ruby-opengl/))
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Using
|
## Using
|
||||||
Requires a Ruby runtime that supports the gosu and opengl-bindings C-extensions (truffleruby 1.0.0-rc12 did not work when tested. Rubinus was not tested.)
|
Requires a Ruby runtime that supports the gosu and opengl-bindings C-extensions (truffleruby 1.0.0-rc12 did not work when tested. Rubinus was not tested.)
|
||||||
|
|||||||
12
Rakefile
12
Rakefile
@@ -1,10 +1,16 @@
|
|||||||
|
require "json"
|
||||||
|
require "tmpdir"
|
||||||
|
require "fileutils"
|
||||||
|
|
||||||
|
require "zip"
|
||||||
|
require "excon"
|
||||||
require "releasy"
|
require "releasy"
|
||||||
require 'bundler/setup' # Releasy requires that your application uses bundler.
|
require 'bundler/setup' # Releasy requires that your application uses bundler.
|
||||||
require_relative "lib/version"
|
require_relative "lib/version"
|
||||||
|
|
||||||
Releasy::Project.new do
|
Releasy::Project.new do
|
||||||
name "I-MIC FPS"
|
name IMICFPS::NAME
|
||||||
version "#{IMICFPS::VERSION}"
|
version IMICFPS::VERSION
|
||||||
|
|
||||||
executable "i-mic-fps.rb"
|
executable "i-mic-fps.rb"
|
||||||
files ["lib/**/*.*", "assets/**/*.*", "blends/**/*.*", "shaders/**/*.*", "static/**/*.*", "maps/**/*.*", "data/**/*.*"]
|
files ["lib/**/*.*", "assets/**/*.*", "blends/**/*.*", "shaders/**/*.*", "static/**/*.*", "maps/**/*.*", "data/**/*.*"]
|
||||||
@@ -12,7 +18,7 @@ Releasy::Project.new do
|
|||||||
verbose
|
verbose
|
||||||
|
|
||||||
add_build :windows_folder do
|
add_build :windows_folder do
|
||||||
# icon "assets/icon.ico"
|
icon "static/icon.ico"
|
||||||
executable_type :console # Assuming you don't want it to run with a console window.
|
executable_type :console # Assuming you don't want it to run with a console window.
|
||||||
add_package :exe # Windows self-extracting archive.
|
add_package :exe # Windows self-extracting archive.
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
require "gosu"
|
begin
|
||||||
require_relative "lib/objects/text"
|
require_relative "../cyberarm_engine/lib/cyberarm_engine"
|
||||||
|
rescue LoadError
|
||||||
|
require "cyberarm_engine"
|
||||||
|
end
|
||||||
|
|
||||||
class Window < Gosu::Window
|
class Window < Gosu::Window
|
||||||
def initialize
|
def initialize
|
||||||
@@ -9,8 +12,8 @@ class Window < Gosu::Window
|
|||||||
@slope = 250
|
@slope = 250
|
||||||
@color_step = 10
|
@color_step = 10
|
||||||
@base_color = Gosu::Color.rgb(255, 127, 0)
|
@base_color = Gosu::Color.rgb(255, 127, 0)
|
||||||
@title = Text.new("I-MIC FPS", color: Gosu::Color.rgb(255,127,0), size: 100, x: 0, y: 15, alignment: :center)
|
@title = CyberarmEngine::Text.new("I-MIC FPS", color: Gosu::Color.rgb(255,127,0), size: 100, x: 0, y: 15, alignment: :center)
|
||||||
@singleplayer = Text.new("Singleplayer", color: Gosu::Color.rgb(0,127,127), size: 50, x: 0, y: 150, alignment: :center)
|
@singleplayer = CyberarmEngine::Text.new("Singleplayer", color: Gosu::Color.rgb(0,127,127), size: 50, x: 0, y: 150, alignment: :center)
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
|
|||||||
3
assets/base/editor/manifest.yaml
Normal file
3
assets/base/editor/manifest.yaml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
name: "editor"
|
||||||
|
model: "editor.obj"
|
||||||
|
collision: "mesh"
|
||||||
32
assets/base/editor/model/editor.mtl
Normal file
32
assets/base/editor/model/editor.mtl
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Blender MTL File: 'editor.blend'
|
||||||
|
# Material Count: 3
|
||||||
|
|
||||||
|
newmtl body
|
||||||
|
Ns 225.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.011935 0.113782 0.401969
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
newmtl energy
|
||||||
|
Ns 225.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.000000 0.653036 0.800000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
|
|
||||||
|
newmtl eye
|
||||||
|
Ns 225.000000
|
||||||
|
Ka 1.000000 1.000000 1.000000
|
||||||
|
Kd 0.710554 0.177754 0.000000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.000000
|
||||||
|
Ni 1.450000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
||||||
4703
assets/base/editor/model/editor.obj
Normal file
4703
assets/base/editor/model/editor.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
blends/editor.blend
Normal file
BIN
blends/editor.blend
Normal file
Binary file not shown.
BIN
blends/editor.blend1
Normal file
BIN
blends/editor.blend1
Normal file
Binary file not shown.
9
i-mic-fps-server.rb
Normal file
9
i-mic-fps-server.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
IMICFPS_SERVER_MODE = true
|
||||||
|
require_relative "i-mic-fps"
|
||||||
|
|
||||||
|
director = IMICFPS::Networking::Director.new(mode: :server, hostname: "0.0.0.0", port: 56789, interface: IMICFPS::Networking::MemoryServer)
|
||||||
|
director.define_singleton_method(:tick) do |dt|
|
||||||
|
puts "Ticked: #{dt}"
|
||||||
|
end
|
||||||
|
|
||||||
|
director.run.join
|
||||||
66
i-mic-fps.rb
66
i-mic-fps.rb
@@ -3,10 +3,13 @@ require "yaml"
|
|||||||
require "json"
|
require "json"
|
||||||
require "abbrev"
|
require "abbrev"
|
||||||
require "time"
|
require "time"
|
||||||
|
require "socket"
|
||||||
|
require "tmpdir"
|
||||||
|
|
||||||
require "opengl"
|
require "opengl"
|
||||||
require "glu"
|
require "glu"
|
||||||
require "nokogiri"
|
require "nokogiri"
|
||||||
|
require "async/websocket"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
require_relative "../cyberarm_engine/lib/cyberarm_engine"
|
require_relative "../cyberarm_engine/lib/cyberarm_engine"
|
||||||
@@ -56,12 +59,21 @@ require_relative "lib/ui/console"
|
|||||||
require_relative "lib/ui/menus/main_menu"
|
require_relative "lib/ui/menus/main_menu"
|
||||||
require_relative "lib/ui/menus/settings_menu"
|
require_relative "lib/ui/menus/settings_menu"
|
||||||
require_relative "lib/ui/menus/extras_menu"
|
require_relative "lib/ui/menus/extras_menu"
|
||||||
|
require_relative "lib/ui/menus/multiplayer_menu"
|
||||||
require_relative "lib/ui/menus/level_select_menu"
|
require_relative "lib/ui/menus/level_select_menu"
|
||||||
require_relative "lib/ui/menus/game_pause_menu"
|
require_relative "lib/ui/menus/game_pause_menu"
|
||||||
|
|
||||||
|
require_relative "lib/states/game_states/boot"
|
||||||
|
require_relative "lib/states/game_states/close"
|
||||||
require_relative "lib/states/game_states/game"
|
require_relative "lib/states/game_states/game"
|
||||||
require_relative "lib/states/game_states/loading_state"
|
require_relative "lib/states/game_states/loading_state"
|
||||||
|
|
||||||
|
require_relative "lib/hud"
|
||||||
|
require_relative "lib/hud/widget"
|
||||||
|
require_relative "lib/hud/widgets/ammo"
|
||||||
|
require_relative "lib/hud/widgets/radar"
|
||||||
|
require_relative "lib/hud/widgets/health"
|
||||||
|
|
||||||
require_relative "lib/subscription"
|
require_relative "lib/subscription"
|
||||||
require_relative "lib/publisher"
|
require_relative "lib/publisher"
|
||||||
require_relative "lib/event"
|
require_relative "lib/event"
|
||||||
@@ -106,23 +118,53 @@ require_relative "lib/scenes/turn_table"
|
|||||||
require_relative "lib/crosshair"
|
require_relative "lib/crosshair"
|
||||||
require_relative "lib/demo"
|
require_relative "lib/demo"
|
||||||
|
|
||||||
|
require_relative "lib/networking/director"
|
||||||
|
require_relative "lib/networking/packet_handler"
|
||||||
|
require_relative "lib/networking/client"
|
||||||
|
require_relative "lib/networking/server"
|
||||||
|
require_relative "lib/networking/connection"
|
||||||
|
|
||||||
|
require_relative "lib/networking/backends/memory_server"
|
||||||
|
require_relative "lib/networking/backends/memory_connection"
|
||||||
|
|
||||||
require_relative "lib/overlay"
|
require_relative "lib/overlay"
|
||||||
require_relative "lib/window"
|
require_relative "lib/window"
|
||||||
|
|
||||||
require_relative "lib/tools/asset_viewer"
|
require_relative "lib/tools/asset_viewer"
|
||||||
require_relative "lib/tools/map_editor"
|
require_relative "lib/tools/map_editor"
|
||||||
|
|
||||||
if ARGV.join.include?("--profile")
|
# Don't launch game if IMICFPS_SERVER_MODE is defined
|
||||||
begin
|
# or if game is being packaged
|
||||||
require "ruby-prof"
|
def prevent_launch?
|
||||||
RubyProf.start
|
packaging_lockfile = File.expand_path("i-mic-fps-packaging.lock", Dir.tmpdir)
|
||||||
IMICFPS::Window.new.show
|
m = "Game client not launched"
|
||||||
result = RubyProf.stop
|
|
||||||
printer = RubyProf::MultiPrinter.new(result)
|
return [true, "#{m}: Server is running"] if defined?(IMICFPS_SERVER_MODE) && IMICFPS_SERVER_MODE
|
||||||
printer.print(path: ".", profile: "profile", min_percent: 2)
|
|
||||||
rescue LoadError
|
return [true, "#{m}: Packaging is running"] if defined?(Ocra)
|
||||||
puts "ruby-prof not installed!"
|
|
||||||
|
if File.exist?(packaging_lockfile) && File.read(packaging_lockfile).strip == IMICFPS::VERSION
|
||||||
|
return [true, "#{m}: Packaging lockfile is present (#{packaging_lockfile})"]
|
||||||
|
end
|
||||||
|
|
||||||
|
return [false, ""]
|
||||||
|
end
|
||||||
|
|
||||||
|
unless prevent_launch?[0]
|
||||||
|
if ARGV.join.include?("--profile")
|
||||||
|
begin
|
||||||
|
require "ruby-prof"
|
||||||
|
RubyProf.start
|
||||||
|
IMICFPS::Window.new.show
|
||||||
|
result = RubyProf.stop
|
||||||
|
printer = RubyProf::MultiPrinter.new(result)
|
||||||
|
printer.print(path: ".", profile: "profile", min_percent: 2)
|
||||||
|
rescue LoadError
|
||||||
|
puts "ruby-prof not installed!"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
IMICFPS::Window.new.show
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
IMICFPS::Window.new.show
|
puts prevent_launch?[1]
|
||||||
end
|
end
|
||||||
@@ -39,8 +39,53 @@ class IMICFPS
|
|||||||
def draw_quad(*args)
|
def draw_quad(*args)
|
||||||
window.draw_quad(*args)
|
window.draw_quad(*args)
|
||||||
end
|
end
|
||||||
def fill(color = Gosu::Color::WHITE)
|
def fill(color = Gosu::Color::WHITE, z = 0)
|
||||||
draw_rect(0, 0, window.width, window.height, color)
|
draw_rect(0, 0, window.width, window.height, color, z)
|
||||||
|
end
|
||||||
|
def fill_quad(x1, y1, x2, y2, x3, y3, x4, y4, color = Gosu::Color::WHITE, z = 0, mode = :default)
|
||||||
|
draw_quad(
|
||||||
|
x1,y1, color,
|
||||||
|
x2,y2, color,
|
||||||
|
x3,y3, color,
|
||||||
|
x4,y4, color,
|
||||||
|
z, mode
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def menu_background(primary_color, accent_color, color_step, transparency, bar_size, slope)
|
||||||
|
((Gosu.screen_height + slope) / bar_size).times do |i|
|
||||||
|
color = Gosu::Color.rgba(
|
||||||
|
primary_color.red - i * color_step,
|
||||||
|
primary_color.green - i * color_step,
|
||||||
|
primary_color.blue - i * color_step,
|
||||||
|
transparency
|
||||||
|
)
|
||||||
|
|
||||||
|
fill_quad(
|
||||||
|
0, i * bar_size,
|
||||||
|
0, slope + (i * bar_size),
|
||||||
|
window.width / 2, (-slope) + (i * bar_size),
|
||||||
|
window.width / 2, i * bar_size,
|
||||||
|
color,
|
||||||
|
-2
|
||||||
|
)
|
||||||
|
fill_quad(
|
||||||
|
window.width, i * bar_size,
|
||||||
|
window.width, slope + (i * bar_size),
|
||||||
|
window.width / 2, (-slope) + (i * bar_size),
|
||||||
|
window.width / 2, i * bar_size,
|
||||||
|
color,
|
||||||
|
-2
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
Gosu.draw_quad(
|
||||||
|
0, 0, primary_color,
|
||||||
|
window.width, 0, primary_color,
|
||||||
|
window.width, window.height, accent_color,
|
||||||
|
0, window.height, accent_color,
|
||||||
|
-2
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def gl_error?
|
def gl_error?
|
||||||
|
|||||||
23
lib/hud.rb
Normal file
23
lib/hud.rb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class HUD
|
||||||
|
def initialize(player)
|
||||||
|
@ammo = AmmoWidget.new({ player: player })
|
||||||
|
@radar = RadarWidget.new({ player: player })
|
||||||
|
@health = HealthWidget.new({ player: player })
|
||||||
|
|
||||||
|
@hud_elements = [
|
||||||
|
@ammo,
|
||||||
|
@radar,
|
||||||
|
@health,
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
@hud_elements.each(&:draw)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@hud_elements.each(&:update)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
25
lib/hud/widget.rb
Normal file
25
lib/hud/widget.rb
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class HUD
|
||||||
|
class Widget
|
||||||
|
include CommonMethods
|
||||||
|
attr_reader :options
|
||||||
|
|
||||||
|
def initialize(options = {})
|
||||||
|
@options = options
|
||||||
|
@player = options[:player]
|
||||||
|
@margin = 10
|
||||||
|
|
||||||
|
setup
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
29
lib/hud/widgets/ammo.rb
Normal file
29
lib/hud/widgets/ammo.rb
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class HUD
|
||||||
|
class AmmoWidget < HUD::Widget
|
||||||
|
def setup
|
||||||
|
@text = Text.new("")
|
||||||
|
@background = Gosu::Color.new(0x88222222)
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
Gosu.draw_rect(
|
||||||
|
@text.x - @margin, @text.y - @margin,
|
||||||
|
@text.width + @margin * 2, @text.height + @margin * 2,
|
||||||
|
@background
|
||||||
|
)
|
||||||
|
@text.draw
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
if (Gosu.milliseconds / 1000.0) % 1.0 >= 0.9
|
||||||
|
random = "#{rand(0..999)}".rjust(3, "0")
|
||||||
|
@text.text = "Pistol\nAMMO: #{random}"
|
||||||
|
end
|
||||||
|
|
||||||
|
@text.x = window.width - (@margin * 2 + @text.width)
|
||||||
|
@text.y = window.height - (@margin * 2 + @text.height)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
48
lib/hud/widgets/health.rb
Normal file
48
lib/hud/widgets/health.rb
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class HUD
|
||||||
|
class HealthWidget < HUD::Widget
|
||||||
|
def setup
|
||||||
|
@spacer = 0
|
||||||
|
@text = Text.new("")
|
||||||
|
@width = 512
|
||||||
|
@height = 24
|
||||||
|
@slant = 32
|
||||||
|
|
||||||
|
@color = Gosu::Color.rgba(100, 100, 200, 128)
|
||||||
|
@shield = Gosu::Color.rgba(200, 100, 50, 200)
|
||||||
|
|
||||||
|
@health = 0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
@text.draw
|
||||||
|
fill_quad(
|
||||||
|
window.width / 2 - @width / 2, @spacer, # TOP LEFT
|
||||||
|
window.width / 2 + @width / 2, @spacer, # TOP RIGHT
|
||||||
|
window.width / 2 + @width / 2 - @slant, @spacer + @height, # BOTTOM RIGHT
|
||||||
|
window.width / 2 - @width / 2 + @slant, @spacer + @height, # BOTTOM LEFT
|
||||||
|
@color
|
||||||
|
)
|
||||||
|
|
||||||
|
# Current Health
|
||||||
|
fill_quad(
|
||||||
|
window.width / 2 - @width / 2, @spacer, # TOP LEFT
|
||||||
|
(window.width / 2 - @width / 2) + @width * @health, @spacer, # TOP RIGHT
|
||||||
|
(window.width / 2 - @width / 2) + @width * @health - @slant, @spacer + @height, # BOTTOM RIGHT
|
||||||
|
window.width / 2 - @width / 2 + @slant, @spacer + @height, # BOTTOM LEFT
|
||||||
|
@shield
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
percentage = "#{(@health * 100).round}".rjust(3, "0")
|
||||||
|
@text.text = "[Health #{percentage}%]"
|
||||||
|
@text.x = window.width / 2 - @text.width / 2
|
||||||
|
@text.y = @spacer + @height / 2 - @text.height / 2
|
||||||
|
|
||||||
|
@health += 0.1 * window.dt
|
||||||
|
@health = 0 if @health > 1.0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
28
lib/hud/widgets/radar.rb
Normal file
28
lib/hud/widgets/radar.rb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class HUD
|
||||||
|
class RadarWidget < HUD::Widget
|
||||||
|
def setup
|
||||||
|
@size = 256
|
||||||
|
@color = Gosu::Color.new(0x88222222)
|
||||||
|
|
||||||
|
@text = Text.new("RADAR")
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
Gosu.draw_rect(
|
||||||
|
@margin, window.height - (@size + @margin),
|
||||||
|
@size, @size,
|
||||||
|
@color
|
||||||
|
)
|
||||||
|
|
||||||
|
@text.draw
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@text.text = "RADAR: X #{@player.position.x.round(1)} Y #{@player.position.z.round(1)}"
|
||||||
|
@text.x = @margin + @size / 2 - @text.width / 2
|
||||||
|
@text.y = window.height - (@margin + @size)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class NetworkManager
|
||||||
|
MULTICAST_ADDRESS = "224.0.0.1"
|
||||||
|
MULTICAST_PORT = 30_000
|
||||||
|
|
||||||
|
REMOTE_GAMEHUB = "i-mic.rubyclan.org"
|
||||||
|
REMOTE_GAMEHUB_PORT = 98765
|
||||||
|
|
||||||
|
DEFAULT_SERVER_HOST = "0.0.0.0"
|
||||||
|
DEFAULT_SERVER_PORT = 56789
|
||||||
|
DEFAULT_SERVER_QUERY_PORT = 28900
|
||||||
|
def initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://github.com/jpignata/blog/blob/master/articles/multicast-in-ruby.md
|
||||||
|
def broadcast_lan_lobby
|
||||||
|
socket = UDPSocket.open
|
||||||
|
socket.setsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL, 1)
|
||||||
|
socket.send("IMICFPS_LAN_LOBBY", 0, MULTICAST_ADDRESS, MULTICAST_PORT)
|
||||||
|
socket.close
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_lan_multicast
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -61,7 +61,6 @@ class IMICFPS
|
|||||||
@collision_manager.update
|
@collision_manager.update
|
||||||
|
|
||||||
@entities.each(&:update)
|
@entities.each(&:update)
|
||||||
# @lights.each(&:update)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
6
lib/networking/backends/memory_connection.rb
Normal file
6
lib/networking/backends/memory_connection.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class MemoryConnection < Connection
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
6
lib/networking/backends/memory_server.rb
Normal file
6
lib/networking/backends/memory_server.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class MemoryServer < Server
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
18
lib/networking/client.rb
Normal file
18
lib/networking/client.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class Client
|
||||||
|
def initialize(socket:)
|
||||||
|
@socket = socket
|
||||||
|
end
|
||||||
|
|
||||||
|
def read
|
||||||
|
end
|
||||||
|
|
||||||
|
def write
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
17
lib/networking/connection.rb
Normal file
17
lib/networking/connection.rb
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class Connection
|
||||||
|
def initialize(hostname:, port:)
|
||||||
|
end
|
||||||
|
|
||||||
|
def connect
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
61
lib/networking/director.rb
Normal file
61
lib/networking/director.rb
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class Director
|
||||||
|
attr_reader :mode, :hostname, :port, :tick_rate, :storage
|
||||||
|
def initialize(mode:, hostname:, port:, interface:, state: nil, tick_rate: 2)
|
||||||
|
@mode = mode
|
||||||
|
@hostname = hostname
|
||||||
|
@port = port
|
||||||
|
@state = state
|
||||||
|
@tick_rate = (1000.0 / tick_rate) / 1000.0
|
||||||
|
|
||||||
|
case @mode
|
||||||
|
when :server
|
||||||
|
@server = interface.new(hostname: @hostname, port: @port)
|
||||||
|
when :connection
|
||||||
|
@connection = interface.new(hostname: @hostname, port: @port)
|
||||||
|
when :memory
|
||||||
|
@server = interface[:server].new(hostname: @hostname, port: @port)
|
||||||
|
@connection = interface[:connection].new(hostname: @hostname, port: @port)
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Expected mode to be :server, :connection, or :memory, not #{mode.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
@last_tick_time = milliseconds
|
||||||
|
@directing = true
|
||||||
|
@storage = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
Thread.start do |thread|
|
||||||
|
while(@directing)
|
||||||
|
dt = milliseconds - @last_tick_time
|
||||||
|
|
||||||
|
tick(dt)
|
||||||
|
|
||||||
|
@server.update if @server
|
||||||
|
@connection.update if @connection
|
||||||
|
|
||||||
|
@last_tick_time = milliseconds
|
||||||
|
sleep(@tick_rate)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tick(dt)
|
||||||
|
end
|
||||||
|
|
||||||
|
def shutdown
|
||||||
|
@directing = false
|
||||||
|
|
||||||
|
@clients.each(&:close)
|
||||||
|
@server.update if @server
|
||||||
|
@connection.update if @connection
|
||||||
|
end
|
||||||
|
|
||||||
|
def milliseconds
|
||||||
|
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
11
lib/networking/events.rb
Normal file
11
lib/networking/events.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
module Events
|
||||||
|
def on_connect(client)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_disconnect(client)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
18
lib/networking/packet.rb
Normal file
18
lib/networking/packet.rb
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class Packet
|
||||||
|
def initialize(type:, payload:)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.encode(packet)
|
||||||
|
"#{packet.type}|#{packet.payload}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.decode(string)
|
||||||
|
split = string.split("|")
|
||||||
|
|
||||||
|
Packet.new(split.first, split.last)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
6
lib/networking/packet_handler.rb
Normal file
6
lib/networking/packet_handler.rb
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
class PacketHandler
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
29
lib/networking/server.rb
Normal file
29
lib/networking/server.rb
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
class IMICFPS
|
||||||
|
module Networking
|
||||||
|
MAX_CLIENTS = 32
|
||||||
|
|
||||||
|
class Server
|
||||||
|
attr_reader :hostname, :port, :max_clients, :clients
|
||||||
|
def initialize(hostname:, port:, max_clients: MAX_CLIENTS)
|
||||||
|
@hostname = hostname
|
||||||
|
@port = port
|
||||||
|
@max_clients = max_clients
|
||||||
|
|
||||||
|
@clients = []
|
||||||
|
@socket = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def bind
|
||||||
|
end
|
||||||
|
|
||||||
|
def broadcast(packet)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -34,7 +34,7 @@ class IMICFPS
|
|||||||
|
|
||||||
if window.config.get(:debug_options, :stats)
|
if window.config.get(:debug_options, :stats)
|
||||||
create_slot "Vertices: #{formatted_number(window.number_of_vertices)}"
|
create_slot "Vertices: #{formatted_number(window.number_of_vertices)}"
|
||||||
create_slot "Face: #{formatted_number(window.number_of_vertices / 3)}"
|
create_slot "Faces: #{formatted_number(window.number_of_vertices / 3)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if window.config.get(:debug_options, :boundingboxes)
|
if window.config.get(:debug_options, :boundingboxes)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render(camera, lights, entities)
|
def render(camera, lights, entities)
|
||||||
if Shader.available?("default") && Shader.available?("render_screen")
|
if window.config.get(:debug_options, :use_shaders) && Shader.available?("default") && Shader.available?("render_screen")
|
||||||
@g_buffer.bind_for_writing
|
@g_buffer.bind_for_writing
|
||||||
gl_error?
|
gl_error?
|
||||||
|
|
||||||
|
|||||||
53
lib/states/game_states/boot.rb
Normal file
53
lib/states/game_states/boot.rb
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class Boot < GameState
|
||||||
|
def setup
|
||||||
|
@title = Text.new(IMICFPS::NAME, size: 100, z: 0, color: Gosu::Color.new(0xff000000), shadow: false, font: "Droid Serif")
|
||||||
|
@logo = get_image(IMICFPS::GAME_ROOT_PATH + "/static/logo.png")
|
||||||
|
|
||||||
|
@start_time = Gosu.milliseconds
|
||||||
|
@time_to_live = 3_000
|
||||||
|
|
||||||
|
window.needs_cursor = false
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
fraction_left = ((Gosu.milliseconds - @start_time) / (@time_to_live - 200).to_f)
|
||||||
|
|
||||||
|
menu_background(Menu::PRIMARY_COLOR, Menu::ACCENT_COLOR, Menu::BAR_COLOR_STEP, Menu::BAR_ALPHA, Menu::BAR_SIZE, Menu::BAR_SLOPE)
|
||||||
|
|
||||||
|
if fraction_left <= 1.0
|
||||||
|
Gosu.draw_circle(
|
||||||
|
window.width / 2,
|
||||||
|
window.height / 2,
|
||||||
|
@logo.width / 2, 128, Gosu::Color.new(0x11ffffff)
|
||||||
|
)
|
||||||
|
|
||||||
|
Gosu.draw_arc(
|
||||||
|
window.width / 2,
|
||||||
|
window.height / 2,
|
||||||
|
@logo.width / 2, fraction_left.clamp(0.0, 1.0), 128, 8, Gosu::Color.new(0x33ff8800)
|
||||||
|
)
|
||||||
|
|
||||||
|
@logo.draw(window.width / 2 - @logo.width / 2, window.height / 2 - @logo.height / 2, 0)
|
||||||
|
|
||||||
|
@title.draw
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@title.x = window.width / 2 - @title.width / 2
|
||||||
|
@title.y = 0
|
||||||
|
|
||||||
|
push_state(MainMenu) if Gosu.milliseconds - @start_time >= @time_to_live
|
||||||
|
end
|
||||||
|
|
||||||
|
def button_up(id)
|
||||||
|
if id == Gosu::KbEscape or
|
||||||
|
(id >= Gosu::GP_LEFT and id >= Gosu::GP_BUTTON_15) or
|
||||||
|
id == Gosu::MsLeft
|
||||||
|
push_state(MainMenu)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
49
lib/states/game_states/close.rb
Normal file
49
lib/states/game_states/close.rb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class Close < GameState
|
||||||
|
def setup
|
||||||
|
@slope = Menu::BAR_SLOPE
|
||||||
|
|
||||||
|
@logo = get_image(IMICFPS::GAME_ROOT_PATH + "/static/logo.png")
|
||||||
|
|
||||||
|
@start_time = Gosu.milliseconds
|
||||||
|
@time_to_live = 3_000
|
||||||
|
|
||||||
|
window.needs_cursor = false
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
fraction_left = 1 - ((Gosu.milliseconds - @start_time) / (@time_to_live - 200).to_f)
|
||||||
|
|
||||||
|
menu_background(Menu::PRIMARY_COLOR, Menu::ACCENT_COLOR, Menu::BAR_COLOR_STEP, Menu::BAR_ALPHA, Menu::BAR_SIZE, @slope.round)
|
||||||
|
|
||||||
|
Gosu.draw_circle(
|
||||||
|
window.width / 2,
|
||||||
|
window.height / 2,
|
||||||
|
@logo.width / 2, 128, Gosu::Color.new(0x11ffffff)
|
||||||
|
)
|
||||||
|
|
||||||
|
Gosu.draw_arc(
|
||||||
|
window.width / 2,
|
||||||
|
window.height / 2,
|
||||||
|
@logo.width / 2, fraction_left.clamp(0.0, 1.0), 128, 8, Gosu::Color.new(0x33ff8800)
|
||||||
|
)
|
||||||
|
|
||||||
|
@logo.draw(window.width / 2 - @logo.width / 2, window.height / 2 - @logo.height / 2, 0)
|
||||||
|
|
||||||
|
fill(Gosu::Color.rgba(0,0,0, 255 * (1.1 - fraction_left)))
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
window.close! if Gosu.milliseconds - @start_time >= @time_to_live
|
||||||
|
@slope -= 25 * window.dt
|
||||||
|
end
|
||||||
|
|
||||||
|
def button_up(id)
|
||||||
|
if id == Gosu::KbEscape or
|
||||||
|
(id >= Gosu::GP_LEFT and id >= Gosu::GP_BUTTON_15) or
|
||||||
|
id == Gosu::MsLeft
|
||||||
|
window.close!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -9,8 +9,10 @@ class IMICFPS
|
|||||||
@player = @map.find_entity_by(name: "character")
|
@player = @map.find_entity_by(name: "character")
|
||||||
@camera = Camera.new(position: @player.position.clone)
|
@camera = Camera.new(position: @player.position.clone)
|
||||||
@camera.attach_to(@player)
|
@camera.attach_to(@player)
|
||||||
|
@director = Networking::Director.new(mode: :memory, hostname: "i-mic.rubyclan.org", port: 56789, interface: { server: Networking::MemoryServer, connection: Networking::MemoryConnection }, state: self)
|
||||||
|
|
||||||
@crosshair = Crosshair.new
|
@crosshair = Crosshair.new
|
||||||
|
@hud = HUD.new(@player)
|
||||||
|
|
||||||
@text = Text.new("Pending...", x: 10, y: 22, z: 1, size: 18, font: "DejaVu Sans", shadow_color: Gosu::Color::BLACK)
|
@text = Text.new("Pending...", x: 10, y: 22, z: 1, size: 18, font: "DejaVu Sans", shadow_color: Gosu::Color::BLACK)
|
||||||
|
|
||||||
@@ -26,6 +28,7 @@ class IMICFPS
|
|||||||
@map.render(@camera)
|
@map.render(@camera)
|
||||||
|
|
||||||
@crosshair.draw
|
@crosshair.draw
|
||||||
|
@hud.draw
|
||||||
@text.draw
|
@text.draw
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -37,8 +40,10 @@ class IMICFPS
|
|||||||
@map.update
|
@map.update
|
||||||
|
|
||||||
control_player
|
control_player
|
||||||
|
@hud.update
|
||||||
|
|
||||||
@camera.update
|
@camera.update
|
||||||
|
@director.tick(window.dt)
|
||||||
|
|
||||||
if window.config.get(:debug_options, :stats)
|
if window.config.get(:debug_options, :stats)
|
||||||
@text.text = update_text
|
@text.text = update_text
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class IMICFPS
|
|||||||
raise "Unable to load map, missing :map_file or :map_parser"
|
raise "Unable to load map, missing :map_file or :map_parser"
|
||||||
end
|
end
|
||||||
|
|
||||||
title "I-MIC FPS"
|
title IMICFPS::NAME
|
||||||
@subheading = Text.new("Loading Map: #{@map_parser.metadata.name}", y: 100, size: 50, alignment: :center)
|
@subheading = Text.new("Loading Map: #{@map_parser.metadata.name}", y: 100, size: 50, alignment: :center)
|
||||||
@description = Text.new("Map created by: #{@map_parser.metadata.authors.join(", ")}\n#{@map_parser.metadata.description}", y: 180, size: 24, alignment: :center)
|
@description = Text.new("Map created by: #{@map_parser.metadata.authors.join(", ")}\n#{@map_parser.metadata.description}", y: 180, size: 24, alignment: :center)
|
||||||
@state = Text.new("Preparing...", y: window.height/2-40, size: 40, alignment: :center)
|
@state = Text.new("Preparing...", y: window.height/2-40, size: 40, alignment: :center)
|
||||||
@@ -34,7 +34,8 @@ class IMICFPS
|
|||||||
@completed_for_ms = 0
|
@completed_for_ms = 0
|
||||||
@lock = false
|
@lock = false
|
||||||
|
|
||||||
@base_color = Gosu::Color.rgb(0, 180, 180)
|
@primary_color = Gosu::Color.rgba(0, 180, 180, 200)
|
||||||
|
@accent_color = Gosu::Color.rgba(0, 90, 90, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
@@ -115,9 +116,9 @@ class IMICFPS
|
|||||||
progress = (@asset_index.to_f/@assets.count)*window.width/2
|
progress = (@asset_index.to_f/@assets.count)*window.width/2
|
||||||
height = 100
|
height = 100
|
||||||
|
|
||||||
dark_color= Gosu::Color.rgb(@base_color.red - 100, @base_color.green - 100, @base_color.blue - 100)#Gosu::Color.rgb(64, 127, 255)
|
dark_color= Gosu::Color.rgb(@primary_color.red - 100, @primary_color.green - 100, @primary_color.blue - 100)#Gosu::Color.rgb(64, 127, 255)
|
||||||
color = Gosu::Color.rgb(@base_color.red - 50, @base_color.green - 50, @base_color.blue - 50)#Gosu::Color.rgb(0,127,127)
|
color = Gosu::Color.rgb(@primary_color.red - 50, @primary_color.green - 50, @primary_color.blue - 50)#Gosu::Color.rgb(0,127,127)
|
||||||
color_two = Gosu::Color.rgb(@base_color.red + 50, @base_color.green + 50, @base_color.blue + 50)#Gosu::Color.rgb(64, 127, 255)
|
color_two = Gosu::Color.rgb(@primary_color.red + 50, @primary_color.green + 50, @primary_color.blue + 50)#Gosu::Color.rgb(64, 127, 255)
|
||||||
|
|
||||||
draw_rect(x, y-2, x + window.width/4, height+4, dark_color)
|
draw_rect(x, y-2, x + window.width/4, height+4, dark_color)
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class AssetViewerTool
|
class AssetViewerTool
|
||||||
class MainMenu < CyberarmEngine::GuiState
|
class MainMenu < Menu
|
||||||
def setup
|
def setup
|
||||||
window.needs_cursor = true
|
window.needs_cursor = true
|
||||||
|
|
||||||
label "#{IMICFPS::NAME}", text_size: 50
|
|
||||||
label "Asset Viewer", text_size: 28
|
|
||||||
|
|
||||||
@manifests = []
|
@manifests = []
|
||||||
Dir.glob(GAME_ROOT_PATH + "/assets/**/manifest.yaml").each do |manifest|
|
Dir.glob(GAME_ROOT_PATH + "/assets/**/manifest.yaml").each do |manifest|
|
||||||
begin
|
begin
|
||||||
@@ -18,14 +15,23 @@ class IMICFPS
|
|||||||
|
|
||||||
@manifests.sort_by! { |m| m.name.downcase }
|
@manifests.sort_by! { |m| m.name.downcase }
|
||||||
|
|
||||||
button "Back", margin_bottom: 25 do
|
label "#{IMICFPS::NAME}", text_size: 100, color: Gosu::Color::BLACK
|
||||||
pop_state
|
label "Asset Viewer", text_size: 50
|
||||||
end
|
|
||||||
|
|
||||||
flow(margin: 10) do
|
flow(width: 1.0, height: 1.0) do
|
||||||
@manifests.each do |manifest|
|
stack(width: 0.25, height: 1.0) do
|
||||||
button manifest.name do
|
button "Back", margin_bottom: 25 do
|
||||||
push_state(TurnTable, manifest: manifest)
|
pop_state
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 0.5, height: 1.0) do
|
||||||
|
flow(width: 1.0, height: 1.0) do
|
||||||
|
@manifests.each do |manifest|
|
||||||
|
button manifest.name do
|
||||||
|
push_state(TurnTable, manifest: manifest)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class MapEditorTool
|
class MapEditorTool
|
||||||
class MainMenu < CyberarmEngine::GuiState
|
class MainMenu < Menu
|
||||||
def setup
|
def setup
|
||||||
window.needs_cursor = true
|
window.needs_cursor = true
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class Menu < IMICFPS::GameState
|
class Menu < IMICFPS::GuiState
|
||||||
|
include CommonMethods
|
||||||
|
|
||||||
|
PRIMARY_COLOR = Gosu::Color.rgba(255, 127, 0, 200)
|
||||||
|
ACCENT_COLOR = Gosu::Color.rgba(155, 27, 0, 200)
|
||||||
|
|
||||||
|
BAR_SIZE = 50
|
||||||
|
BAR_SLOPE = 250
|
||||||
|
BAR_COLOR_STEP = 10
|
||||||
|
BAR_ALPHA = 200
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
@elements = []
|
@elements = []
|
||||||
@size = 50
|
@bar_size = BAR_SIZE
|
||||||
@slope = 250
|
@bar_slope = BAR_SLOPE
|
||||||
@color_step = 10
|
@bar_color_step = BAR_COLOR_STEP
|
||||||
@base_color = Gosu::Color.rgb(255, 127, 0)
|
@bar_alpha = BAR_ALPHA
|
||||||
@background_alpha = 200
|
@primary_color = PRIMARY_COLOR
|
||||||
|
@accent_color = ACCENT_COLOR
|
||||||
window.needs_cursor = true
|
window.needs_cursor = true
|
||||||
|
|
||||||
@__version_text = CyberarmEngine::Text.new("<b>#{IMICFPS::NAME}</b> v#{IMICFPS::VERSION} (#{IMICFPS::RELEASE_NAME})")
|
@__version_text = CyberarmEngine::Text.new("<b>#{IMICFPS::NAME}</b> v#{IMICFPS::VERSION} (#{IMICFPS::RELEASE_NAME})")
|
||||||
@@ -15,7 +26,7 @@ class IMICFPS
|
|||||||
super(*args)
|
super(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def title(text, color = @base_color)
|
def title(text, color = Gosu::Color::BLACK)
|
||||||
@elements << Text.new(text, color: color, size: 100, x: 0, y: 15)
|
@elements << Text.new(text, color: color, size: 100, x: 0, y: 15)
|
||||||
@_title = @elements.last
|
@_title = @elements.last
|
||||||
end
|
end
|
||||||
@@ -31,7 +42,7 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
|
|
||||||
def draw
|
def draw
|
||||||
draw_background
|
menu_background(@primary_color, @accent_color, @bar_color_step, @bar_alpha, @bar_size, @bar_slope)
|
||||||
draw_menu_box
|
draw_menu_box
|
||||||
draw_menu
|
draw_menu
|
||||||
|
|
||||||
@@ -44,34 +55,15 @@ class IMICFPS
|
|||||||
|
|
||||||
window.scene.draw
|
window.scene.draw
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def draw_background
|
super
|
||||||
((Gosu.screen_height+@slope)/@size).times do |i|
|
|
||||||
fill_quad(
|
|
||||||
0, i*@size,
|
|
||||||
0, @slope+(i*@size),
|
|
||||||
window.width/2, (-@slope)+(i*@size),
|
|
||||||
window.width/2, i*@size,
|
|
||||||
Gosu::Color.rgba(@base_color.red-i*@color_step, @base_color.green-i*@color_step, @base_color.blue-i*@color_step, @background_alpha),
|
|
||||||
-2
|
|
||||||
)
|
|
||||||
fill_quad(
|
|
||||||
window.width, i*@size,
|
|
||||||
window.width, @slope+(i*@size),
|
|
||||||
window.width/2, (-@slope)+(i*@size),
|
|
||||||
window.width/2, i*@size,
|
|
||||||
Gosu::Color.rgba(@base_color.red-i*@color_step, @base_color.green-i*@color_step, @base_color.blue-i*@color_step, @background_alpha),
|
|
||||||
-2
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def draw_menu_box
|
def draw_menu_box
|
||||||
draw_rect(
|
draw_rect(
|
||||||
window.width/4, 0,
|
window.width / 4, 0,
|
||||||
window.width/2, window.height,
|
window.width / 2, window.height,
|
||||||
Gosu::Color.rgba(0, 0, 0, 150),
|
Gosu::Color.new(0x11ffffff),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -83,7 +75,7 @@ class IMICFPS
|
|||||||
|
|
||||||
def update
|
def update
|
||||||
@elements.each do |e|
|
@elements.each do |e|
|
||||||
e.x = window.width / 2 - e.width / 2
|
e.x = (window.width / 2 - e.width / 2).round
|
||||||
e.update
|
e.update
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -91,20 +83,12 @@ class IMICFPS
|
|||||||
window.scene.update(window.dt)
|
window.scene.update(window.dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
|
||||||
@__version_text.x = window.width - (@__version_text.width + 10)
|
@__version_text.x = window.width - (@__version_text.width + 10)
|
||||||
@__version_text.y = window.height - (@__version_text.height + 10)
|
@__version_text.y = window.height - (@__version_text.height + 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_quad(x1, y1, x2, y2, x3, y3, x4, y4, color = Gosu::Color::WHITE, z = 0, mode = :default)
|
|
||||||
draw_quad(
|
|
||||||
x1,y1, color,
|
|
||||||
x2,y2, color,
|
|
||||||
x3,y3, color,
|
|
||||||
x4,y4, color,
|
|
||||||
z, mode
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def button_up(id)
|
def button_up(id)
|
||||||
if id == Gosu::MsLeft
|
if id == Gosu::MsLeft
|
||||||
@elements.each do |e|
|
@elements.each do |e|
|
||||||
@@ -114,6 +98,8 @@ class IMICFPS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def mouse_over?(object)
|
def mouse_over?(object)
|
||||||
@@ -126,19 +112,17 @@ class IMICFPS
|
|||||||
def initialize(text, host, block)
|
def initialize(text, host, block)
|
||||||
@text, @host, @block = text, host, block
|
@text, @host, @block = text, host, block
|
||||||
@color = @text.color
|
@color = @text.color
|
||||||
@hover_color = Gosu::Color.rgb(64, 127, 255)
|
@hover_color = Gosu::Color.rgb(64, 128, 255)
|
||||||
|
@text.shadow_color= Gosu::Color::BLACK
|
||||||
|
@text.shadow_size = 2
|
||||||
@text.shadow_alpha = 100
|
@text.shadow_alpha = 100
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
if @host.mouse_over?(self)
|
if @host.mouse_over?(self)
|
||||||
@text.color = @hover_color
|
@text.color = @hover_color
|
||||||
@text.shadow_color= Gosu::Color::BLACK
|
|
||||||
@text.shadow_size = 3
|
|
||||||
else
|
else
|
||||||
@text.color = @color
|
@text.color = @color
|
||||||
@text.shadow_color = nil
|
|
||||||
@text.shadow_size = 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class ExtrasMenu < Menu
|
class ExtrasMenu < Menu
|
||||||
def setup
|
def setup
|
||||||
title "I-MIC FPS"
|
title IMICFPS::NAME
|
||||||
subtitle "Extras"
|
subtitle "Extras"
|
||||||
|
|
||||||
link "Asset Viewer" do
|
link "Asset Viewer" do
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class GamePauseMenu < Menu
|
class GamePauseMenu < Menu
|
||||||
def setup
|
def setup
|
||||||
@background_alpha = 50
|
@bar_alpha = 50
|
||||||
title "I-MIC FPS"
|
title IMICFPS::NAME
|
||||||
subtitle "Paused"
|
subtitle "Paused"
|
||||||
|
|
||||||
link "Resume" do
|
link "Resume" do
|
||||||
@@ -13,7 +13,7 @@ class IMICFPS
|
|||||||
push_state(SettingsMenu)
|
push_state(SettingsMenu)
|
||||||
end
|
end
|
||||||
|
|
||||||
link "Quit" do
|
link "Leave" do
|
||||||
push_state(MainMenu)
|
push_state(MainMenu)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class LevelSelectMenu < Menu
|
class LevelSelectMenu < Menu
|
||||||
def setup
|
def setup
|
||||||
title "I-MIC FPS"
|
title IMICFPS::NAME
|
||||||
subtitle "Choose a Map"
|
subtitle "Choose a Map"
|
||||||
|
|
||||||
Dir.glob(GAME_ROOT_PATH + "/maps/*.json").map { |file| [file, MapParser.new(map_file: file)]}.each do |file, map|
|
Dir.glob(GAME_ROOT_PATH + "/maps/*.json").map { |file| [file, MapParser.new(map_file: file)]}.each do |file, map|
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class MainMenu < Menu
|
class MainMenu < Menu
|
||||||
def setup
|
def setup
|
||||||
title "I-MIC FPS"
|
title IMICFPS::NAME
|
||||||
|
|
||||||
link "Single Player" do
|
link "Single Player" do
|
||||||
push_state(LevelSelectMenu)
|
push_state(LevelSelectMenu)
|
||||||
# push_state(LoadingState.new(forward: Game, map_file: GAME_ROOT_PATH + "/maps/test_map.json"))
|
# push_state(LoadingState.new(forward: Game, map_file: GAME_ROOT_PATH + "/maps/test_map.json"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
link "Multiplayer" do
|
||||||
|
push_state(MultiplayerMenu)
|
||||||
|
end
|
||||||
|
|
||||||
link "Settings" do
|
link "Settings" do
|
||||||
push_state(SettingsMenu)
|
push_state(SettingsMenu)
|
||||||
end
|
end
|
||||||
|
|||||||
14
lib/ui/menus/multiplayer_menu.rb
Normal file
14
lib/ui/menus/multiplayer_menu.rb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
class IMICFPS
|
||||||
|
class MultiplayerMenu < Menu
|
||||||
|
def setup
|
||||||
|
title IMICFPS::NAME
|
||||||
|
subtitle "Multiplayer"
|
||||||
|
|
||||||
|
link "Online"
|
||||||
|
link "LAN"
|
||||||
|
link "Back" do
|
||||||
|
pop_state
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,14 +1,208 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class SettingsMenu < Menu
|
class SettingsMenu < Menu
|
||||||
|
include CommonMethods
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
title "I-MIC FPS"
|
@categories = [
|
||||||
subtitle "Settings"
|
"Display",
|
||||||
|
"Graphics",
|
||||||
|
"Audio",
|
||||||
|
"Controls",
|
||||||
|
"Multiplayer"
|
||||||
|
]
|
||||||
|
@pages = {}
|
||||||
|
@current_page = nil
|
||||||
|
|
||||||
link "\"There is no spoon.\""
|
label "Settings", text_size: 100, color: Gosu::Color::BLACK
|
||||||
|
|
||||||
link "Back" do
|
flow(width: 1.0, height: 1.0) do
|
||||||
pop_state
|
stack(width: 0.25, height: 1.0) do
|
||||||
|
@categories.each do |category|
|
||||||
|
button category, width: 1.0 do
|
||||||
|
show_page(:"#{category}".downcase)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
button "Back", width: 1.0, margin_top: 64 do
|
||||||
|
pop_state
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@categories.each do |category|
|
||||||
|
stack(width: 0.5, height: 1.0) do |element|
|
||||||
|
@pages[:"#{category}".downcase] = element
|
||||||
|
element.hide
|
||||||
|
|
||||||
|
if respond_to?(:"create_page_#{category}".downcase)
|
||||||
|
self.send(:"create_page_#{category}".downcase)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
show_page(:display)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_page(page)
|
||||||
|
if element = @pages.dig(page)
|
||||||
|
@current_page.hide if @current_page
|
||||||
|
@current_page = element
|
||||||
|
element.show
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_page_display
|
||||||
|
label "Display", text_size: 50
|
||||||
|
|
||||||
|
label "Resolution"
|
||||||
|
flow do
|
||||||
|
stack do
|
||||||
|
label "Width"
|
||||||
|
label "Height"
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
edit_line "#{window.width}"
|
||||||
|
edit_line "#{window.height}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
check_box "Fullscreen", padding_top: 25, padding_bottom: 25
|
||||||
|
|
||||||
|
flow do
|
||||||
|
stack do
|
||||||
|
label "Gamma Correction"
|
||||||
|
label "Brightness"
|
||||||
|
label "Contrast"
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
slider
|
||||||
|
slider
|
||||||
|
slider
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
label "0.0"
|
||||||
|
label "0.0"
|
||||||
|
label "0.0"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_page_audio
|
||||||
|
label "Audio", text_size: 50
|
||||||
|
|
||||||
|
flow do
|
||||||
|
stack do
|
||||||
|
label "Master Volume"
|
||||||
|
label "Sound Effects"
|
||||||
|
label "Dialog"
|
||||||
|
label "Cinematic"
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
slider range: 0.0..1.0, value: 1.0
|
||||||
|
slider range: 0.0..1.0, value: 1.0
|
||||||
|
slider range: 0.0..1.0, value: 1.0
|
||||||
|
slider range: 0.0..1.0, value: 1.0
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
label "0.0"
|
||||||
|
label "0.0"
|
||||||
|
label "0.0"
|
||||||
|
label "0.0"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_page_controls
|
||||||
|
label "Controls", text_size: 50
|
||||||
|
|
||||||
|
InputMapper.keymap.each do |key, values|
|
||||||
|
flow do
|
||||||
|
label "#{key}"
|
||||||
|
|
||||||
|
[values].flatten.each do |value|
|
||||||
|
button Gosu.button_id_to_char(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_page_graphics
|
||||||
|
label "Graphics", text_size: 50
|
||||||
|
|
||||||
|
flow do
|
||||||
|
check_box "V-Sync"
|
||||||
|
label "(No Supported)"
|
||||||
|
end
|
||||||
|
|
||||||
|
flow do
|
||||||
|
label "Field of View"
|
||||||
|
slider range: 70.0..110.0
|
||||||
|
label "90.0"
|
||||||
|
end
|
||||||
|
|
||||||
|
flow do
|
||||||
|
stack do
|
||||||
|
label "Detail"
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
slider range: 1..3
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
label "High"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
advanced_mode = check_box "Advanced Mode"
|
||||||
|
|
||||||
|
advanced_settings = stack do |element|
|
||||||
|
element.hide
|
||||||
|
|
||||||
|
flow do
|
||||||
|
stack do
|
||||||
|
label "Geometry Detail"
|
||||||
|
label "Shadow Detail"
|
||||||
|
label "Texture Detail"
|
||||||
|
label "Particle Detail"
|
||||||
|
label "Surface Effect Detail"
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
slider
|
||||||
|
slider
|
||||||
|
slider
|
||||||
|
slider
|
||||||
|
slider
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
label "High"
|
||||||
|
label "High"
|
||||||
|
label "High"
|
||||||
|
label "High"
|
||||||
|
label "High"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow do
|
||||||
|
stack do
|
||||||
|
label "Lighting Mode"
|
||||||
|
edit_line ""
|
||||||
|
end
|
||||||
|
stack do
|
||||||
|
label "Texture Filtering"
|
||||||
|
edit_line ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
advanced_mode.subscribe(:changed) do |element, value|
|
||||||
|
advanced_settings.show if value
|
||||||
|
advanced_settings.hide unless value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_page_multiplayer
|
||||||
|
label "Multiplayer", text_size: 50
|
||||||
|
|
||||||
|
check_box "Show player names"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
class IMICFPS
|
class IMICFPS
|
||||||
class Window < CyberarmEngine::Engine
|
class Window < CyberarmEngine::Window
|
||||||
attr_accessor :number_of_vertices, :needs_cursor
|
attr_accessor :number_of_vertices, :needs_cursor
|
||||||
attr_reader :renderer, :scene, :config
|
attr_reader :renderer, :scene, :config
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ class IMICFPS
|
|||||||
@config.save!
|
@config.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
push_state(MainMenu)
|
push_state(Boot)
|
||||||
|
|
||||||
@delta_time = Gosu.milliseconds
|
@delta_time = Gosu.milliseconds
|
||||||
end
|
end
|
||||||
@@ -73,6 +73,10 @@ class IMICFPS
|
|||||||
@delta_time = Gosu.milliseconds
|
@delta_time = Gosu.milliseconds
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
push_state(Close)
|
||||||
|
end
|
||||||
|
|
||||||
def button_down(id)
|
def button_down(id)
|
||||||
if @show_console
|
if @show_console
|
||||||
@console.button_down(id)
|
@console.button_down(id)
|
||||||
|
|||||||
BIN
pixel_test.png
BIN
pixel_test.png
Binary file not shown.
|
Before Width: | Height: | Size: 162 B |
166
rakelib/release.rake
Normal file
166
rakelib/release.rake
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
PACKAGING_LOCKFILE = File.expand_path("i-mic-fps-packaging.lock", Dir.tmpdir)
|
||||||
|
GITHUB_API_URL = "https://api.github.com/repos/cyberarm/i-mic-fps"
|
||||||
|
USERAGENT = "cyberarm +i-mic-fps"
|
||||||
|
DEFAULT_HEADERS = {"Authorization": "token #{ENV["GITHUB_TOKEN"]}", "User-Agent": USERAGENT}
|
||||||
|
|
||||||
|
def sh_with_status(command)
|
||||||
|
outbuf = IO.popen(command, :err => [:child, :out], &:read)
|
||||||
|
status = $?
|
||||||
|
|
||||||
|
return [outbuf, status]
|
||||||
|
end
|
||||||
|
|
||||||
|
def version
|
||||||
|
IMICFPS::VERSION
|
||||||
|
end
|
||||||
|
|
||||||
|
def version_tag
|
||||||
|
"v#{version}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def release_name
|
||||||
|
"#{IMICFPS::NAME.gsub(" ", "-").downcase}_#{version_tag}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean?
|
||||||
|
sh_with_status("git diff --exit-code")[1].success?
|
||||||
|
end
|
||||||
|
|
||||||
|
def committed?
|
||||||
|
sh_with_status("git diff-index --quiet --cached HEAD")[1].success?
|
||||||
|
end
|
||||||
|
|
||||||
|
def guard_clean
|
||||||
|
clean? && committed? || abort(" There are files that need to be committed.")
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_version
|
||||||
|
sh "git tag -m \"Version #{version}\" #{version_tag}"
|
||||||
|
puts " Tagged #{version_tag}."
|
||||||
|
rescue RuntimeError
|
||||||
|
puts " Untagging #{version_tag} due to error."
|
||||||
|
sh_with_status "git tag -d #{version_tag}"
|
||||||
|
abort
|
||||||
|
end
|
||||||
|
|
||||||
|
def already_tagged?
|
||||||
|
return false unless sh_with_status("git tag")[0].split(/\n/).include?(version_tag)
|
||||||
|
abort " Tag #{version_tag} has already been created."
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_lockfile
|
||||||
|
File.open(PACKAGING_LOCKFILE, "w") { |f| f.write version }
|
||||||
|
end
|
||||||
|
def remove_lockfile
|
||||||
|
File.delete(PACKAGING_LOCKFILE)
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_directory(dir)
|
||||||
|
levels = dir.split("/")
|
||||||
|
location = ""
|
||||||
|
levels.each do |level|
|
||||||
|
location +="#{level}/"
|
||||||
|
mkdir_p location unless File.exist?(location)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_package(path)
|
||||||
|
abort " Package folder already exists!" if File.exist?(path)
|
||||||
|
sh "rake build:windows:folder"
|
||||||
|
end
|
||||||
|
|
||||||
|
def patch_windows_package(folder)
|
||||||
|
patch = "require_relative \"i-mic-fps/i-mic-fps\""
|
||||||
|
patch_file = "#{folder}/src/i-mic-fps.rb"
|
||||||
|
|
||||||
|
File.open(patch_file, "w") { |f| f.write patch }
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_archive(folder, archive)
|
||||||
|
abort " Archive already exists!" if File.exist?(archive)
|
||||||
|
Zip::File.open(archive, Zip::File::CREATE) do |zipfile|
|
||||||
|
Dir["#{folder}/**/**"].each do |file|
|
||||||
|
zipfile.add(file.sub(folder + '/', ''), file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_release
|
||||||
|
url = "#{GITHUB_API_URL}/releases"
|
||||||
|
request = Excon.get(url, headers: DEFAULT_HEADERS)
|
||||||
|
|
||||||
|
if request.status == 200
|
||||||
|
release = JSON.parse(request.body).find { |r| r["tag_name"] == version_tag }
|
||||||
|
return release
|
||||||
|
else
|
||||||
|
abort " Getting repo releases failed! (#{request.status})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload_asset(asset)
|
||||||
|
github_token = ENV["GITHUB_TOKEN"]
|
||||||
|
abort " GITHUB_TOKEN not set!" unless github_token
|
||||||
|
|
||||||
|
release = get_release
|
||||||
|
upload_url = release["upload_url"].split("{?").first + "?name=#{asset.split("/").last}"
|
||||||
|
|
||||||
|
file = File.read(asset)
|
||||||
|
|
||||||
|
headers = DEFAULT_HEADERS
|
||||||
|
headers["Content-Type"] = "application/zip"
|
||||||
|
headers["Content-Length"] = file.size
|
||||||
|
|
||||||
|
request = Excon.post(upload_url, body: file, headers: headers)
|
||||||
|
abort " Upload failed! #{request.body} (#{request.status})" unless request.status.between?(200, 201)
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace "game" do
|
||||||
|
desc "Create git tag, build, and release package"
|
||||||
|
task :release do
|
||||||
|
puts "Checking for uncommited changes..."
|
||||||
|
guard_clean
|
||||||
|
puts "Checking git tag for #{version_tag}..."
|
||||||
|
already_tagged?
|
||||||
|
puts "Committing git tag #{version_tag}..."
|
||||||
|
tag_version
|
||||||
|
puts "Pushing changes..."
|
||||||
|
sh "git push origin master"
|
||||||
|
sh "git push origin master --tags"
|
||||||
|
|
||||||
|
path = File.expand_path("../pkg/#{release_name}_WIN32", __dir__)
|
||||||
|
|
||||||
|
puts "Building release package '#{release_name}', this may take a while..."
|
||||||
|
create_lockfile
|
||||||
|
build_package(path)
|
||||||
|
puts "Patching..."
|
||||||
|
patch_windows_package(path)
|
||||||
|
puts "Creating archive..."
|
||||||
|
create_archive(path, "#{path}.zip")
|
||||||
|
remove_lockfile
|
||||||
|
|
||||||
|
puts "Pushing package to github..."
|
||||||
|
upload_asset("#{path}.zip")
|
||||||
|
puts "Done."
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Remove packaging assets"
|
||||||
|
task "release:cleanup" do
|
||||||
|
path = File.expand_path("../pkg", __dir__)
|
||||||
|
|
||||||
|
if File.exist?(path)
|
||||||
|
puts "Cleaning up..."
|
||||||
|
|
||||||
|
Dir["#{path}/**"].each do |file|
|
||||||
|
puts "Removing #{file}..."
|
||||||
|
if File.directory?(file)
|
||||||
|
FileUtils.remove_entry_secure(file)
|
||||||
|
else
|
||||||
|
File.delete(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Done."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
BIN
screenshots/screenshot-game.png
Normal file
BIN
screenshots/screenshot-game.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 377 KiB |
BIN
screenshots/screenshot-main-menu.png
Normal file
BIN
screenshots/screenshot-main-menu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
BIN
static/icon.ico
Normal file
BIN
static/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
static/logo.png
Normal file
BIN
static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
128
svg/logo.svg
Normal file
128
svg/logo.svg
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="232"
|
||||||
|
height="232"
|
||||||
|
viewBox="0 0 61.383334 61.383334"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
sodipodi:docname="logo.svg"
|
||||||
|
inkscape:export-filename="/home/cyberarm/Code/i-mic-fps/static/logo.png"
|
||||||
|
inkscape:export-xdpi="211.86208"
|
||||||
|
inkscape:export-ydpi="211.86208"
|
||||||
|
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4142136"
|
||||||
|
inkscape:cx="28.822764"
|
||||||
|
inkscape:cy="101.19387"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
units="px"
|
||||||
|
borderlayer="true"
|
||||||
|
inkscape:showpageshadow="false"
|
||||||
|
inkscape:snap-bbox="true"
|
||||||
|
inkscape:snap-intersection-paths="true"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1010"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid10"
|
||||||
|
empspacing="8"
|
||||||
|
originx="0"
|
||||||
|
originy="2.2411203e-09"
|
||||||
|
dotted="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-33.940008,-296.21455)">
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#e9b96e;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 69.448977,318.17079 h -9.524999 l 4.7625,4.7625 z"
|
||||||
|
id="path42"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#8f5902;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 51.986478,310.23329 7.9375,7.9375 h 9.524999 l 7.9375,-7.9375 z"
|
||||||
|
id="path30"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#ce5c00;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 69.448977,318.17079 16.485815,16.48581 7.9375,-7.9375 -16.485815,-16.48581 z"
|
||||||
|
id="path47"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#ce5c00;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 64.686478,322.93329 v 32.97163 L 85.934792,334.6566 69.448977,318.17079 Z"
|
||||||
|
id="path50"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="M 59.923978,318.17079 43.438163,334.6566 64.686478,355.90492 V 322.93329 Z"
|
||||||
|
id="path45"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 51.986478,310.23329 -16.485815,16.48581 7.9375,7.9375 16.485815,-16.48581 z"
|
||||||
|
id="path28"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 64.686478,297.53329 -12.7,12.7 h 12.7 z"
|
||||||
|
id="path53"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="opacity:1;fill:#ce5c00;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
|
||||||
|
d="m 64.686478,297.53329 v 12.7 h 12.699999 z"
|
||||||
|
id="rect22"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:'Droid Serif';-inkscape-font-specification:'Droid Serif';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="99.88446"
|
||||||
|
y="329.00253"
|
||||||
|
id="text14"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan12"
|
||||||
|
x="99.88446"
|
||||||
|
y="329.00253"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Droid Serif';-inkscape-font-specification:'Droid Serif';fill:#000000;stroke-width:0.26458332">I-MIC FPS</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.0 KiB |
Reference in New Issue
Block a user