mirror of
https://github.com/SleepingInsomniac/asteroids
synced 2024-12-25 21:59:23 +01:00
Initial Commit
This commit is contained in:
commit
6d450f1871
19 changed files with 590 additions and 0 deletions
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.cr]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/docs/
|
||||||
|
/lib/
|
||||||
|
/bin/
|
||||||
|
/.shards/
|
||||||
|
*.dwarf
|
||||||
|
/build/
|
26
Info.plist
Normal file
26
Info.plist
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>Asteroids</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>asteroids</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.alexclink.asteroids</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Asteroids</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>asteroids.icns</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>0.01</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>IFMajorVersion</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>IFMinorVersion</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2021 Alex Clink <alexclink@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
27
README.md
Normal file
27
README.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# asteroids
|
||||||
|
|
||||||
|
TODO: Write a description here
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
TODO: Write installation instructions here
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
TODO: Write usage instructions here
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
TODO: Write development instructions here
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork it (<https://github.com/your-github-user/asteroids/fork>)
|
||||||
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||||
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
||||||
|
4. Push to the branch (`git push origin my-new-feature`)
|
||||||
|
5. Create a new Pull Request
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- [Alex Clink](https://github.com/your-github-user) - creator and maintainer
|
10
lib-sdl.yaml
Normal file
10
lib-sdl.yaml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
name: LibSDL
|
||||||
|
ldflags: -lsdl2
|
||||||
|
packages: sdl2
|
||||||
|
destdir: src/lib_sdl
|
||||||
|
definitions:
|
||||||
|
sdl:
|
||||||
|
includes:
|
||||||
|
- SDL2/SDL.h
|
||||||
|
prefixes:
|
||||||
|
- sdl
|
84
package.rb
Executable file
84
package.rb
Executable file
|
@ -0,0 +1,84 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
|
APP_NAME = 'Asteroids'
|
||||||
|
BUILD_DIR = "build/#{APP_NAME}.app/Contents"
|
||||||
|
BINARY = 'asteroids'
|
||||||
|
|
||||||
|
def gather_libs(file)
|
||||||
|
libs = `otool -L #{file}`.lines
|
||||||
|
.map { |l| l[/^.+\.dylib/i]&.strip }
|
||||||
|
.reject do |l|
|
||||||
|
l.nil? ||
|
||||||
|
l.empty? ||
|
||||||
|
l.start_with?("/System/Library") ||
|
||||||
|
l.start_with?("/usr/lib") ||
|
||||||
|
l.start_with?("@rpath")
|
||||||
|
end
|
||||||
|
|
||||||
|
libs.each do |l_path|
|
||||||
|
lib_name = File.basename(l_path)
|
||||||
|
dest_dir = "#{BUILD_DIR}/Frameworks"
|
||||||
|
dest_path = "#{dest_dir}/#{lib_name}"
|
||||||
|
|
||||||
|
puts "#{lib_name}"
|
||||||
|
|
||||||
|
if File.exist?("#{BUILD_DIR}/Frameworks/#{lib_name}")
|
||||||
|
puts " - Skipping #{lib_name}: Already present"
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
unless File.exist? dest_path
|
||||||
|
begin
|
||||||
|
puts " - Copy #{l_path} to #{dest_path}"
|
||||||
|
FileUtils.cp l_path, dest_path
|
||||||
|
rescue Errno::EACCES => e
|
||||||
|
puts " - ERROR: #{l_path} cannot be copied: #{e}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`chown $(id -u):$(id -g) #{dest_path} && chmod +w #{dest_path}`
|
||||||
|
|
||||||
|
unless $?.success?
|
||||||
|
puts "Could not change ownership and add write permissions to #{dest_path}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
patch_cmd = "install_name_tool -change #{l_path} @executable_path/../Frameworks/#{lib_name} #{file}"
|
||||||
|
puts " - Patching executable link: \n - #{patch_cmd}"
|
||||||
|
`#{patch_cmd}`
|
||||||
|
unless $?.success?
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Recursive copy
|
||||||
|
gather_libs dest_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Creating structure for #{APP_NAME}:"
|
||||||
|
[
|
||||||
|
BUILD_DIR,
|
||||||
|
"#{BUILD_DIR}/MacOS",
|
||||||
|
"#{BUILD_DIR}/Resources",
|
||||||
|
"#{BUILD_DIR}/Frameworks",
|
||||||
|
].each do |folder|
|
||||||
|
puts "Create: #{folder}"
|
||||||
|
FileUtils.mkdir_p folder
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Copying Info.plist"
|
||||||
|
FileUtils.cp 'Info.plist', "#{BUILD_DIR}/"
|
||||||
|
|
||||||
|
build_cmd = %{shards build --release --link-flags="-rpath @executable_path/../Frameworks -L #{`brew --prefix sfml`.chomp}/lib/ -mmacosx-version-min=10.14 -headerpad_max_install_names"}
|
||||||
|
puts "Building: `#{build_cmd}`"
|
||||||
|
puts `#{build_cmd}`
|
||||||
|
|
||||||
|
FileUtils.cp "bin/#{BINARY}", "#{BUILD_DIR}/MacOS/#{BINARY}"
|
||||||
|
|
||||||
|
puts "Gathering libs..."
|
||||||
|
gather_libs "#{BUILD_DIR}/MacOS/#{BINARY}"
|
||||||
|
|
||||||
|
puts "Done!"
|
10
shard.lock
Normal file
10
shard.lock
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
version: 2.0
|
||||||
|
shards:
|
||||||
|
crystaledge:
|
||||||
|
git: https://github.com/unn4m3d/crystaledge.git
|
||||||
|
version: 0.2.6
|
||||||
|
|
||||||
|
sdl:
|
||||||
|
git: https://github.com/ysbaddaden/sdl.cr.git
|
||||||
|
version: 0.1.0+git.commit.d2aa0fb2ee30e42fc8d046d2d00c03c76879cb17
|
||||||
|
|
20
shard.yml
Normal file
20
shard.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
name: asteroids
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- Alex Clink <alexclink@gmail.com>
|
||||||
|
|
||||||
|
targets:
|
||||||
|
asteroids:
|
||||||
|
main: src/asteroids.cr
|
||||||
|
|
||||||
|
crystal: 1.2.1
|
||||||
|
|
||||||
|
license: MIT
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
sdl:
|
||||||
|
github: ysbaddaden/sdl.cr
|
||||||
|
crystaledge:
|
||||||
|
github: unn4m3d/crystaledge
|
||||||
|
version: 0.2.6
|
9
spec/asteroids_spec.cr
Normal file
9
spec/asteroids_spec.cr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require "./spec_helper"
|
||||||
|
|
||||||
|
describe Asteroids do
|
||||||
|
# TODO: Write tests
|
||||||
|
|
||||||
|
it "works" do
|
||||||
|
false.should eq(true)
|
||||||
|
end
|
||||||
|
end
|
2
spec/spec_helper.cr
Normal file
2
spec/spec_helper.cr
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
require "spec"
|
||||||
|
require "../src/asteroids"
|
69
src/asteroids.cr
Normal file
69
src/asteroids.cr
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
require "sdl"
|
||||||
|
require "crystaledge"
|
||||||
|
include CrystalEdge
|
||||||
|
require "./lx_game/*"
|
||||||
|
include LxGame
|
||||||
|
require "./ship"
|
||||||
|
require "./bullet"
|
||||||
|
|
||||||
|
class Asteroids < Game
|
||||||
|
@ship : Ship
|
||||||
|
@controller : Controller(LibSDL::Keycode)
|
||||||
|
|
||||||
|
def initialize(*args)
|
||||||
|
super
|
||||||
|
|
||||||
|
@ship = Ship.build do |ship|
|
||||||
|
ship.position = Vector2.new(x: width / 2.0, y: height / 2.0)
|
||||||
|
end
|
||||||
|
|
||||||
|
@controller = Controller(LibSDL::Keycode).new({
|
||||||
|
LibSDL::Keycode::UP => "Thrust",
|
||||||
|
LibSDL::Keycode::RIGHT => "Rotate Right",
|
||||||
|
LibSDL::Keycode::LEFT => "Rotate Left",
|
||||||
|
LibSDL::Keycode::SPACE => "Fire",
|
||||||
|
})
|
||||||
|
|
||||||
|
@bullets = [] of Bullet
|
||||||
|
end
|
||||||
|
|
||||||
|
def wrap(position : Vector2)
|
||||||
|
position.x = 0.0 if position.x > @width
|
||||||
|
position.x = @width.to_f64 if position.x < 0.0
|
||||||
|
|
||||||
|
position.y = 0.0 if position.y > @height
|
||||||
|
position.y = @height.to_f64 if position.y < 0.0
|
||||||
|
|
||||||
|
position
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(dt : Float64)
|
||||||
|
@ship.rotate_right(dt) if @controller.action?("Rotate Right")
|
||||||
|
@ship.rotate_left(dt) if @controller.action?("Rotate Left")
|
||||||
|
@ship.thrust(dt) if @controller.action?("Thrust")
|
||||||
|
@ship.update(dt)
|
||||||
|
|
||||||
|
@ship.position = wrap(@ship.position)
|
||||||
|
|
||||||
|
if @controller.action?("Fire") && @ship.can_fire?
|
||||||
|
@bullets << @ship.fire
|
||||||
|
end
|
||||||
|
|
||||||
|
@bullets.each do |bullet|
|
||||||
|
bullet.update
|
||||||
|
bullet.age += dt
|
||||||
|
end
|
||||||
|
|
||||||
|
@bullets = @bullets.reject { |b| b.age >= 4.0 }
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw
|
||||||
|
@renderer.draw_color = SDL::Color[0, 0, 0, 255]
|
||||||
|
@renderer.clear
|
||||||
|
@ship.draw(@renderer)
|
||||||
|
@bullets.each { |b| b.draw(@renderer) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
game = Asteroids.new(200, 120, 4)
|
||||||
|
game.run!
|
13
src/bullet.cr
Normal file
13
src/bullet.cr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class Bullet < Sprite
|
||||||
|
property age : Float64 = 0.0
|
||||||
|
|
||||||
|
def update
|
||||||
|
@position += @velocity
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw(renderer)
|
||||||
|
brightness = ((4.0 - @age) / 4.0) * 255
|
||||||
|
renderer.draw_color = SDL::Color[brightness, brightness, 0]
|
||||||
|
renderer.draw_point(@position.x.to_i, @position.y.to_i)
|
||||||
|
end
|
||||||
|
end
|
31
src/lx_game/controller.cr
Normal file
31
src/lx_game/controller.cr
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
module LxGame
|
||||||
|
# Handle button to action mapping in a dynamic way
|
||||||
|
class Controller(T)
|
||||||
|
def initialize(@mapping : Hash(T, String))
|
||||||
|
@keysdown = {} of String => Bool
|
||||||
|
|
||||||
|
@mapping.values.each do |key|
|
||||||
|
@keysdown[key] = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def registered?(button)
|
||||||
|
@mapping.keys.includes?(button)
|
||||||
|
end
|
||||||
|
|
||||||
|
def press(button)
|
||||||
|
return nil unless registered?(button)
|
||||||
|
@keysdown[@mapping[button]] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def release(button)
|
||||||
|
return nil unless registered?(button)
|
||||||
|
@keysdown[@mapping[button]] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns duration of time pressed or false if not pressed
|
||||||
|
def action?(name)
|
||||||
|
@keysdown[name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
68
src/lx_game/game.cr
Normal file
68
src/lx_game/game.cr
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
module LxGame
|
||||||
|
abstract class Game
|
||||||
|
FPS_INTERVAL = 1.0
|
||||||
|
|
||||||
|
property width : Int32
|
||||||
|
property height : Int32
|
||||||
|
property scale : Int32
|
||||||
|
|
||||||
|
@fps_lasttime : Float64 = Time.monotonic.total_milliseconds # the last recorded time.
|
||||||
|
@fps_current : UInt32 = 0 # the current FPS.
|
||||||
|
@fps_frames : UInt32 = 0 # frames passed since the last recorded fps.
|
||||||
|
@last_time : Float64 = Time.monotonic.total_milliseconds
|
||||||
|
|
||||||
|
def initialize(@width, @height, @scale = 1)
|
||||||
|
SDL.init(SDL::Init::VIDEO)
|
||||||
|
at_exit { SDL.quit }
|
||||||
|
|
||||||
|
@window = SDL::Window.new("SDL test", @width * @scale, @height * @scale)
|
||||||
|
@renderer = SDL::Renderer.new(@window, flags: SDL::Renderer::Flags::SOFTWARE)
|
||||||
|
@renderer.scale = {@scale, @scale}
|
||||||
|
end
|
||||||
|
|
||||||
|
abstract def update(dt : Float64)
|
||||||
|
abstract def draw
|
||||||
|
|
||||||
|
def elapsed_time
|
||||||
|
Time.monotonic.total_milliseconds
|
||||||
|
end
|
||||||
|
|
||||||
|
def engine_update
|
||||||
|
@fps_frames += 1
|
||||||
|
et = elapsed_time
|
||||||
|
|
||||||
|
if @fps_lasttime < et - FPS_INTERVAL * 1000
|
||||||
|
@fps_lasttime = et
|
||||||
|
@fps_current = @fps_frames
|
||||||
|
@fps_frames = 0
|
||||||
|
@window.title = String.build { |io| io << "SDL test - " << @fps_current << " fps" }
|
||||||
|
end
|
||||||
|
|
||||||
|
update((et - @last_time) / 1000.0)
|
||||||
|
@last_time = et
|
||||||
|
end
|
||||||
|
|
||||||
|
def engine_draw
|
||||||
|
draw
|
||||||
|
@renderer.present
|
||||||
|
end
|
||||||
|
|
||||||
|
def run!
|
||||||
|
loop do
|
||||||
|
case event = SDL::Event.poll
|
||||||
|
when SDL::Event::Keyboard
|
||||||
|
if event.keydown?
|
||||||
|
@controller.press(event.sym)
|
||||||
|
elsif event.keyup?
|
||||||
|
@controller.release(event.sym)
|
||||||
|
end
|
||||||
|
when SDL::Event::Quit
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
engine_update
|
||||||
|
engine_draw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
39
src/lx_game/graphics.cr
Normal file
39
src/lx_game/graphics.cr
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
module LxGame
|
||||||
|
# Draw a line using Bresenham’s Algorithm
|
||||||
|
def draw_line(renderer : SDL::Renderer, p1 : Vector2, p2 : Vector2, draw_points = false)
|
||||||
|
return draw_line(renderer, p2, p1) if p1.x > p2.x
|
||||||
|
x1, y1, x2, y2 = p1.x.to_i, p1.y.to_i, p2.x.to_i, p2.y.to_i
|
||||||
|
|
||||||
|
dx = (x2 - x1).abs
|
||||||
|
dy = -(y2 - y1).abs
|
||||||
|
|
||||||
|
sx = x1 < x2 ? 1 : -1
|
||||||
|
sy = y1 < y2 ? 1 : -1
|
||||||
|
|
||||||
|
d = dx + dy
|
||||||
|
x, y = x1, y1
|
||||||
|
|
||||||
|
loop do
|
||||||
|
renderer.draw_point(x, y)
|
||||||
|
break if x == x2 && y == y2
|
||||||
|
|
||||||
|
d2 = d + d
|
||||||
|
|
||||||
|
if d2 >= dy
|
||||||
|
d += dy
|
||||||
|
x += sx
|
||||||
|
end
|
||||||
|
|
||||||
|
if d2 <= dx
|
||||||
|
d += dx
|
||||||
|
y += sy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if draw_points
|
||||||
|
renderer.draw_color = SDL::Color[255, 0, 0, 255]
|
||||||
|
renderer.draw_point(x1, y1)
|
||||||
|
renderer.draw_point(x2, y2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
23
src/lx_game/sprite.cr
Normal file
23
src/lx_game/sprite.cr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
module LxGame
|
||||||
|
abstract class Sprite
|
||||||
|
def self.build
|
||||||
|
sprite = new
|
||||||
|
yield sprite
|
||||||
|
sprite
|
||||||
|
end
|
||||||
|
|
||||||
|
property rotation : Float64
|
||||||
|
property position : Vector2
|
||||||
|
property velocity : Vector2
|
||||||
|
property rotation_speed : Float64
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@position = Vector2.new(0.0, 0.0)
|
||||||
|
@velocity = Vector2.new(0.0, 0.0)
|
||||||
|
@rotation = 0.0
|
||||||
|
@rotation_speed = 0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
abstract def draw(renderer : SDL::Renderer)
|
||||||
|
end
|
||||||
|
end
|
25
src/lx_game/vector_sprite.cr
Normal file
25
src/lx_game/vector_sprite.cr
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
module LxGame
|
||||||
|
abstract class VectorSprite < Sprite
|
||||||
|
def project_points(points : Array(Vector2), rotation = @rotation, translate : Vector2? = nil, scale : Vector2? = nil)
|
||||||
|
rc = Math.cos(rotation)
|
||||||
|
rs = Math.sin(rotation)
|
||||||
|
|
||||||
|
translation =
|
||||||
|
if t = translate
|
||||||
|
@position + t
|
||||||
|
else
|
||||||
|
@position
|
||||||
|
end
|
||||||
|
|
||||||
|
points.map do |point|
|
||||||
|
rotated = Vector2.new(point.x * rc - point.y * rs, point.y * rc + point.x * rs)
|
||||||
|
|
||||||
|
scale.try do |scale|
|
||||||
|
rotated = rotated * scale
|
||||||
|
end
|
||||||
|
|
||||||
|
translation + rotated
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
98
src/ship.cr
Normal file
98
src/ship.cr
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
class Ship < VectorSprite
|
||||||
|
getter frame : Array(Vector2)
|
||||||
|
@last_fired : Float64
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super
|
||||||
|
|
||||||
|
@r_engine = 0.03
|
||||||
|
@t_engine = 0.1
|
||||||
|
|
||||||
|
@frame = [
|
||||||
|
Vector2.new(5.0, 0.0),
|
||||||
|
Vector2.new(-3.0, 3.0),
|
||||||
|
Vector2.new(-3.0, -3.0),
|
||||||
|
]
|
||||||
|
|
||||||
|
@jet_left = [Vector2.new(2.0, -5.0), Vector2.new(2.0, -3.5)]
|
||||||
|
@jet_right = [Vector2.new(2.0, 3.5), Vector2.new(2.0, 5.0)]
|
||||||
|
@jet_rear = [Vector2.new(-7.0, 0.0), Vector2.new(-3.0, 0.0)]
|
||||||
|
|
||||||
|
@thrusting_left = false
|
||||||
|
@thrusting_right = false
|
||||||
|
@thrusting_forward = false
|
||||||
|
|
||||||
|
@last_fired = Time.monotonic.total_milliseconds
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_fire?
|
||||||
|
now = Time.monotonic.total_milliseconds
|
||||||
|
now - @last_fired > 100.0
|
||||||
|
end
|
||||||
|
|
||||||
|
def fire
|
||||||
|
@last_fired = Time.monotonic.total_milliseconds
|
||||||
|
Bullet.build do |bullet|
|
||||||
|
bullet.position = project_points([@frame[0]]).first
|
||||||
|
bullet.velocity = @velocity + Vector2.new(Math.cos(@rotation), Math.sin(@rotation)) * 0.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rotate_right(dt : Float64, amount = @r_engine)
|
||||||
|
@thrusting_left = true
|
||||||
|
@rotation_speed += amount * dt
|
||||||
|
end
|
||||||
|
|
||||||
|
def rotate_left(dt : Float64, amount = @r_engine)
|
||||||
|
@thrusting_right = true
|
||||||
|
@rotation_speed -= amount * dt
|
||||||
|
end
|
||||||
|
|
||||||
|
def thrust(dt : Float64)
|
||||||
|
@thrusting_forward = true
|
||||||
|
@velocity.x += Math.cos(@rotation) * dt * @t_engine
|
||||||
|
@velocity.y += Math.sin(@rotation) * dt * @t_engine
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(dt : Float64)
|
||||||
|
@rotation += @rotation_speed
|
||||||
|
@position += @velocity
|
||||||
|
|
||||||
|
# @rotation_speed = 0.0 if @rotation_speed < 0.001 && @rotation_speed > -0.001
|
||||||
|
# rotate_left(dt, 0.01) if @rotation_speed >= 0.01
|
||||||
|
# rotate_right(dt, 0.01) if @rotation_speed <= -0.01
|
||||||
|
end
|
||||||
|
|
||||||
|
def draw(renderer)
|
||||||
|
frame = project_points(@frame)
|
||||||
|
|
||||||
|
renderer.draw_color = SDL::Color[128, 128, 128, 255]
|
||||||
|
|
||||||
|
if @thrusting_left
|
||||||
|
@thrusting_left = false
|
||||||
|
jet_left = project_points(@jet_left, @rotation + rand(-0.5..0.5))
|
||||||
|
draw_line(renderer, jet_left[0], jet_left[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
if @thrusting_right
|
||||||
|
@thrusting_right = false
|
||||||
|
jet_right = project_points(@jet_right, @rotation + rand(-0.5..0.5))
|
||||||
|
draw_line(renderer, jet_right[0], jet_right[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
if @thrusting_forward
|
||||||
|
@thrusting_forward = false
|
||||||
|
jet_rear = project_points(@jet_rear, @rotation + rand(-0.5..0.5))
|
||||||
|
draw_line(renderer, jet_rear[0], jet_rear[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
renderer.draw_color = SDL::Color[255, 255, 255, 255]
|
||||||
|
|
||||||
|
draw_line(renderer, frame[0], frame[1])
|
||||||
|
draw_line(renderer, frame[1], frame[2])
|
||||||
|
draw_line(renderer, frame[2], frame[0])
|
||||||
|
|
||||||
|
# renderer.draw_color = SDL::Color[255, 255, 0, 255]
|
||||||
|
# renderer.draw_point(@position.x.to_i, @position.y.to_i)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue