mirror of
https://github.com/SleepingInsomniac/asteroids
synced 2024-12-25 21:59:23 +01:00
Split LxGame into separate shard PixelFaucet
This commit is contained in:
parent
3319e18747
commit
fdad655892
18 changed files with 57 additions and 511 deletions
|
@ -4,6 +4,10 @@ shards:
|
|||
git: https://github.com/unn4m3d/crystaledge.git
|
||||
version: 0.2.6
|
||||
|
||||
pixelfaucet:
|
||||
git: https://github.com/sleepinginsomniac/pixelfaucet.git
|
||||
version: 0.0.1+git.commit.5b285d55403dafd318c19b7d4ef9069b67c19625
|
||||
|
||||
sdl:
|
||||
git: https://github.com/ysbaddaden/sdl.cr.git
|
||||
version: 0.1.0+git.commit.0ded44711246feb3aa3ba28fea249c9b03be061b
|
||||
|
|
|
@ -13,8 +13,6 @@ crystal: 1.2.1
|
|||
license: MIT
|
||||
|
||||
dependencies:
|
||||
sdl:
|
||||
github: ysbaddaden/sdl.cr
|
||||
crystaledge:
|
||||
github: unn4m3d/crystaledge
|
||||
version: 0.2.6
|
||||
pixelfaucet:
|
||||
github: SleepingInsomniac/pixelfaucet
|
||||
# version: 0.0.1
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
require "./lx_game/sprite/circle_collision"
|
||||
require "./lx_game/sprite/vector_sprite"
|
||||
require "pixelfaucet/sprite"
|
||||
require "pixelfaucet/sprite/circle_collision"
|
||||
require "pixelfaucet/sprite/vector_sprite"
|
||||
|
||||
class Asteroid < Sprite
|
||||
include LxGame::CircleCollision
|
||||
include LxGame::VectorSprite
|
||||
class Asteroid < PF::Sprite
|
||||
include PF::CircleCollision
|
||||
include PF::VectorSprite
|
||||
|
||||
property size : Float64 = 1.0
|
||||
property color : Pixel = Pixel.new(128, 128, 128, 255)
|
||||
property color = PF::Pixel.new(128, 128, 128, 255)
|
||||
|
||||
def initialize
|
||||
super
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
require "sdl"
|
||||
require "crystaledge"
|
||||
include CrystalEdge
|
||||
require "./lx_game/*"
|
||||
include LxGame
|
||||
require "pixelfaucet/game"
|
||||
|
||||
require "./ship"
|
||||
require "./asteroid"
|
||||
require "./bullet"
|
||||
require "./explosion"
|
||||
|
||||
class Asteroids < Game
|
||||
class Asteroids < PF::Game
|
||||
@ship : Ship
|
||||
@asteroids = [] of Asteroid
|
||||
@bullets = [] of Bullet
|
||||
@explosions = [] of Explosion
|
||||
@controller : Controller(LibSDL::Keycode)
|
||||
@controller : PF::Controller(LibSDL::Keycode)
|
||||
@asteroid_count = 3
|
||||
@restart_timer = 0.0
|
||||
|
||||
|
@ -26,7 +26,7 @@ class Asteroids < Game
|
|||
|
||||
setup_round
|
||||
|
||||
@controller = Controller(LibSDL::Keycode).new({
|
||||
@controller = PF::Controller(LibSDL::Keycode).new({
|
||||
LibSDL::Keycode::UP => "Thrust",
|
||||
LibSDL::Keycode::RIGHT => "Rotate Right",
|
||||
LibSDL::Keycode::LEFT => "Rotate Left",
|
||||
|
@ -35,7 +35,7 @@ class Asteroids < Game
|
|||
end
|
||||
|
||||
# override to wrap the coordinates
|
||||
def draw_point(x : Int32, y : Int32, pixel : Pixel, surface = @screen)
|
||||
def draw_point(x : Int32, y : Int32, pixel : PF::Pixel, surface = @screen)
|
||||
x = x % @width
|
||||
y = y % @height
|
||||
|
||||
|
@ -61,7 +61,7 @@ class Asteroids < Game
|
|||
|
||||
size = rand(20.0..35.0)
|
||||
a.mass = size
|
||||
a.frame = VectorSprite.generate_circle(size.to_i, size: size, jitter: 3.0)
|
||||
a.frame = PF::VectorSprite.generate_circle(size.to_i, size: size, jitter: 3.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -145,7 +145,7 @@ class Asteroids < Game
|
|||
size = asteroid.average_radius / 2
|
||||
a.mass = size
|
||||
points = size < 6 ? 6 : size.to_i
|
||||
a.frame = VectorSprite.generate_circle(points, size: size, jitter: 3.0)
|
||||
a.frame = PF::VectorSprite.generate_circle(points, size: size, jitter: 3.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -187,14 +187,14 @@ class Asteroids < Game
|
|||
end
|
||||
end
|
||||
|
||||
def draw(engine)
|
||||
engine.clear
|
||||
@ship.draw(engine)
|
||||
@bullets.each { |b| b.draw(engine) }
|
||||
@asteroids.each { |a| a.draw(engine) }
|
||||
@explosions.each { |e| e.draw(engine) }
|
||||
def draw
|
||||
clear
|
||||
@ship.draw(self)
|
||||
@bullets.each { |b| b.draw(self) }
|
||||
@asteroids.each { |a| a.draw(self) }
|
||||
@explosions.each { |e| e.draw(self) }
|
||||
end
|
||||
end
|
||||
|
||||
game = Asteroids.new(500, 400, 2)
|
||||
game = Asteroids.new(600, 400, 2)
|
||||
game.run!
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
require "./lx_game/sprite/age"
|
||||
require "pixelfaucet/sprite"
|
||||
require "pixelfaucet/sprite/age"
|
||||
|
||||
class Bullet < Sprite
|
||||
include LxGame::SpriteAge
|
||||
class Bullet < PF::Sprite
|
||||
include PF::SpriteAge
|
||||
|
||||
@lifespan = 4.0
|
||||
@lifespan = 2.5
|
||||
|
||||
def update(dt)
|
||||
update_age(dt)
|
||||
|
@ -13,11 +14,11 @@ class Bullet < Sprite
|
|||
|
||||
def draw(engine)
|
||||
brightness = (((4.0 - self.age) / 4.0) * 255).to_u8
|
||||
color = Pixel.new(r: brightness, g: brightness, b: 0_u8)
|
||||
color = PF::Pixel.new(r: brightness, g: brightness, b: 0_u8)
|
||||
engine.draw_point(@position.x.to_i, @position.y.to_i, color)
|
||||
end
|
||||
|
||||
def collides_with?(other : VectorSprite)
|
||||
def collides_with?(other : PF::VectorSprite)
|
||||
@position.distance(other.position) < other.radius
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
require "./lx_game/sprite/age"
|
||||
require "pixelfaucet/emitter"
|
||||
require "pixelfaucet/sprite/age"
|
||||
|
||||
class Explosion < LxGame::Emitter
|
||||
include LxGame::SpriteAge
|
||||
class Explosion < PF::Emitter
|
||||
include PF::SpriteAge
|
||||
|
||||
def update(dt)
|
||||
update_age(dt)
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
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
|
|
@ -1,55 +0,0 @@
|
|||
require "./sprite"
|
||||
require "./particle"
|
||||
|
||||
module LxGame
|
||||
class Emitter < Sprite
|
||||
property emitting : Bool = true
|
||||
property particles = [] of Particle
|
||||
property max_age : Float64 = 1.0
|
||||
property emit_freq : Float64 = 0.05
|
||||
property strength : Float64 = 50.0
|
||||
getter last_emitted : Float64 = 0.0
|
||||
property emit_angle : Float64 = 2 * Math::PI
|
||||
property size : Float64 = 0.0
|
||||
|
||||
# property color : Pixel = Pixel.new
|
||||
|
||||
def generate_particle
|
||||
Particle.build do |particle|
|
||||
particle.position = @position
|
||||
|
||||
if @size > 0.0
|
||||
particle.position.x += rand(-@size..@size)
|
||||
particle.position.y += rand(-@size..@size)
|
||||
end
|
||||
|
||||
direction = rand((@rotation - @emit_angle)..(@rotation + @emit_angle))
|
||||
particle.velocity = @velocity + Vector2.new(Math.cos(direction), Math.sin(direction)) * @strength
|
||||
particle.lifespan = @max_age
|
||||
end
|
||||
end
|
||||
|
||||
def update(dt : Float64)
|
||||
update_position(dt)
|
||||
|
||||
@last_emitted += dt
|
||||
|
||||
if @emitting && @last_emitted >= @emit_freq
|
||||
particle_count, remaining = @last_emitted.divmod(@emit_freq)
|
||||
particle_count.to_i.times do
|
||||
@particles << generate_particle
|
||||
end
|
||||
@last_emitted = remaining
|
||||
end
|
||||
|
||||
@particles.each { |particle| particle.update(dt) }
|
||||
@particles.reject!(&.dead?)
|
||||
end
|
||||
|
||||
def draw(engine)
|
||||
@particles.each do |particle|
|
||||
particle.draw(engine)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,121 +0,0 @@
|
|||
require "./lib_sdl"
|
||||
require "./pixel"
|
||||
|
||||
module LxGame
|
||||
abstract class Game
|
||||
FPS_INTERVAL = 1.0
|
||||
|
||||
property width : Int32
|
||||
property height : Int32
|
||||
property scale : Int32
|
||||
property title : String
|
||||
|
||||
@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, @title = self.class.name)
|
||||
SDL.init(SDL::Init::VIDEO)
|
||||
@window = SDL::Window.new(@title, @width * @scale, @height * @scale)
|
||||
@renderer = SDL::Renderer.new(@window, flags: SDL::Renderer::Flags::PRESENTVSYNC) # , flags: SDL::Renderer::Flags::SOFTWARE)
|
||||
@renderer.scale = {@scale, @scale}
|
||||
@screen = SDL::Surface.new(LibSDL.create_rgb_surface(
|
||||
flags: 0, width: @width, height: @height, depth: 32,
|
||||
r_mask: 0xFF000000, g_mask: 0x00FF0000, b_mask: 0x0000FF00, a_mask: 0x000000FF
|
||||
))
|
||||
end
|
||||
|
||||
abstract def update(dt : Float64)
|
||||
abstract def draw(engine : Game)
|
||||
|
||||
def elapsed_time
|
||||
Time.monotonic.total_milliseconds
|
||||
end
|
||||
|
||||
def clear(r = 0, g = 0, b = 0)
|
||||
@screen.fill(0, 0, 0)
|
||||
end
|
||||
|
||||
def draw_point(x : Int32, y : Int32, pixel : Pixel, surface = @screen)
|
||||
target = surface.pixels + (y * surface.pitch) + (x * 4)
|
||||
target.as(Pointer(UInt32)).value = pixel.format(surface.format)
|
||||
end
|
||||
|
||||
# Draw a line using Bresenham’s Algorithm
|
||||
def draw_line(p1 : Vector2, p2 : Vector2, pixel : Pixel, surface = @screen)
|
||||
return draw_line(p2, p1, pixel, surface) 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
|
||||
draw_point(x, y, pixel, surface)
|
||||
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
|
||||
end
|
||||
|
||||
private 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 << @title << " - " << @fps_current << " fps" }
|
||||
end
|
||||
|
||||
update((et - @last_time) / 1000.0)
|
||||
@last_time = et
|
||||
end
|
||||
|
||||
private def engine_draw
|
||||
@screen.lock do
|
||||
draw(self)
|
||||
end
|
||||
|
||||
@renderer.copy(SDL::Texture.from(@screen, @renderer))
|
||||
@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
|
||||
ensure
|
||||
SDL.quit
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,43 +0,0 @@
|
|||
module LxGame
|
||||
# Draw a line using Bresenham’s Algorithm
|
||||
def draw_line(renderer : SDL::Renderer, p1 : Vector2, p2 : Vector2, draw_points = false, point_color = SDL::Color[255, 0, 0, 255])
|
||||
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
|
||||
draw_point(renderer, 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 = point_color
|
||||
draw_point(renderer, x1, y1)
|
||||
draw_point(renderer, x2, y2)
|
||||
end
|
||||
end
|
||||
|
||||
def draw_point(renderer, x1, y1)
|
||||
renderer.draw_point(x1, y1)
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
module SDL
|
||||
class Surface
|
||||
def pixels
|
||||
surface.pixels
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
require "./sprite"
|
||||
require "./sprite/age"
|
||||
|
||||
module LxGame
|
||||
class Particle < Sprite
|
||||
include SpriteAge
|
||||
|
||||
def update(dt : Float64)
|
||||
update_age(dt)
|
||||
return if dead?
|
||||
update_position(dt)
|
||||
end
|
||||
|
||||
def draw(engine)
|
||||
return if dead?
|
||||
brightness = ((((@lifespan - @age) / @lifespan) * 255) / 2).to_u8
|
||||
color = Pixel.new(r: brightness, g: brightness, b: brightness)
|
||||
engine.draw_point(@position.x.to_i, @position.y.to_i, color)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,16 +0,0 @@
|
|||
module LxGame
|
||||
struct Pixel
|
||||
def self.random
|
||||
new(rand(0_u8..0xFF_u8), rand(0_u8..0xFF_u8), rand(0_u8..0xFF_u8), 0xFF_u8)
|
||||
end
|
||||
|
||||
property r, g, b, a
|
||||
|
||||
def initialize(@r : UInt8 = 255, @g : UInt8 = 255, @b : UInt8 = 255, @a : UInt8 = 255)
|
||||
end
|
||||
|
||||
def format(format)
|
||||
LibSDL.map_rgba(format, @r, @g, @b, @a)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,36 +0,0 @@
|
|||
module LxGame
|
||||
abstract class Sprite
|
||||
def self.build
|
||||
sprite = new
|
||||
yield sprite
|
||||
sprite
|
||||
end
|
||||
|
||||
property position : Vector2
|
||||
property velocity : Vector2
|
||||
property scale : Vector2
|
||||
property rotation : Float64
|
||||
property rotation_speed : Float64
|
||||
property mass : Float64 = 10.0
|
||||
|
||||
def initialize
|
||||
@position = Vector2.new(0.0, 0.0)
|
||||
@velocity = Vector2.new(0.0, 0.0)
|
||||
@scale = Vector2.new(1.0, 1.0)
|
||||
@rotation = 0.0
|
||||
@rotation_speed = 0.0
|
||||
end
|
||||
|
||||
def update_position(dt : Float64)
|
||||
@rotation += @rotation_speed * dt
|
||||
@position += @velocity * dt
|
||||
end
|
||||
|
||||
def distance_between(other)
|
||||
self.position.distance(other.position)
|
||||
end
|
||||
|
||||
abstract def update(dt : Float64)
|
||||
abstract def draw(engine : Game)
|
||||
end
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
module LxGame
|
||||
module SpriteAge
|
||||
property lifespan : Float64 = Float64::INFINITY
|
||||
property age : Float64 = 0.0
|
||||
|
||||
def dead?
|
||||
self.age >= self.lifespan
|
||||
end
|
||||
|
||||
def update_age(dt : Float64)
|
||||
self.age += dt
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,48 +0,0 @@
|
|||
module LxGame
|
||||
module CircleCollision
|
||||
property radius : Float64 = 1.0
|
||||
|
||||
# Check if two circles are colliding
|
||||
def collides_with?(other : Sprite)
|
||||
distance_between(other) < radius + other.radius
|
||||
end
|
||||
|
||||
# Move objects so that they don't overlap
|
||||
def offset_collision(other : Sprite)
|
||||
distance = distance_between(other)
|
||||
overlap = distance - radius - other.radius
|
||||
offset = ((position - other.position) * (overlap / 2)) / distance
|
||||
|
||||
self.position -= offset
|
||||
other.position += offset
|
||||
end
|
||||
|
||||
# Resolve a collision by offsetting the two positions
|
||||
# and transfering the momentum
|
||||
def resolve_collision(other : VectorSprite)
|
||||
offset_collision(other)
|
||||
distance = distance_between(other)
|
||||
|
||||
# Calculate the new velocities
|
||||
normal_vec = (position - other.position) / distance
|
||||
tangental_vec = Vector2.new(-normal_vec.y, normal_vec.x)
|
||||
|
||||
# Dot product of velocity with the tangent
|
||||
# (the direction in which to bounce towards)
|
||||
dp_tangent_a = velocity.dot(tangental_vec)
|
||||
dp_tangent_b = other.velocity.dot(tangental_vec)
|
||||
|
||||
# Dot product of the normal
|
||||
dp_normal_a = velocity.dot(normal_vec)
|
||||
dp_normal_b = other.velocity.dot(normal_vec)
|
||||
|
||||
# conservation of momentum
|
||||
ma = (dp_normal_a * (mass - other.mass) + 2.0 * other.mass * dp_normal_b) / (mass + other.mass)
|
||||
mb = (dp_normal_b * (other.mass - mass) + 2.0 * mass * dp_normal_a) / (mass + other.mass)
|
||||
|
||||
# Set the new velocities
|
||||
self.velocity = (tangental_vec * dp_tangent_a) + (normal_vec * ma)
|
||||
other.velocity = (tangental_vec * dp_tangent_b) + (normal_vec * mb)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,71 +0,0 @@
|
|||
module LxGame
|
||||
module VectorSprite
|
||||
def self.generate_circle(num_points : Int, size = 1.0, jitter = 0.0) : Array(Vector2)
|
||||
0.upto(num_points).map do |n|
|
||||
angle = (2 * Math::PI) * (n / num_points)
|
||||
|
||||
x = size + rand(-jitter..jitter)
|
||||
|
||||
rc = Math.cos(angle)
|
||||
rs = Math.sin(angle)
|
||||
Vector2.new(0.0 * rc - x * rs, x * rc + 0.0 * rs)
|
||||
end.to_a
|
||||
end
|
||||
|
||||
property frame = [] of Vector2
|
||||
@average_radius : Float64? = nil
|
||||
|
||||
def project_points(points : Array(Vector2), rotation = self.rotation, translate : Vector2? = nil, scale : Vector2? = nil)
|
||||
rc = Math.cos(rotation)
|
||||
rs = Math.sin(rotation)
|
||||
|
||||
translation =
|
||||
if t = translate
|
||||
self.position + t
|
||||
else
|
||||
self.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
|
||||
|
||||
# Calculated as the average R for all points in the frame
|
||||
def radius
|
||||
average_radius
|
||||
end
|
||||
|
||||
# Calculated as the average R for all points in the frame
|
||||
def average_radius
|
||||
@average_radius ||= begin
|
||||
# calculate length from center for all points
|
||||
lengths = frame.map do |vec|
|
||||
Math.sqrt(vec.x ** 2 + vec.y ** 2)
|
||||
end
|
||||
|
||||
# get the average of the lengths
|
||||
lengths.reduce { |t, p| t + p } / frame.size.to_f
|
||||
end
|
||||
end
|
||||
|
||||
def draw_frame(engine : Game, frame = @frame, color : Pixel = Pixel.new)
|
||||
0.upto(frame.size - 1) do |n|
|
||||
engine.draw_line(frame[n], frame[(n + 1) % frame.size], color)
|
||||
end
|
||||
end
|
||||
|
||||
def draw_radius(engine : Game, points = 30, color : Pixel = Pixel.new)
|
||||
circle = self.class.generate_circle(points, average_radius).map do |point|
|
||||
point + @position
|
||||
end
|
||||
draw_frame(engine, frame: circle, color: color)
|
||||
end
|
||||
end
|
||||
end
|
30
src/ship.cr
30
src/ship.cr
|
@ -1,16 +1,20 @@
|
|||
require "./lx_game/sprite/vector_sprite"
|
||||
require "pixelfaucet/sprite"
|
||||
require "pixelfaucet/sprite/vector_sprite"
|
||||
require "pixelfaucet/emitter"
|
||||
|
||||
class Ship < Sprite
|
||||
include LxGame::VectorSprite
|
||||
class Ship < PF::Sprite
|
||||
include PF::VectorSprite
|
||||
|
||||
@fire_cooldown : Float64 = 0.0
|
||||
@fire_rate : Float64 = 0.2
|
||||
@emitter : Emitter
|
||||
@l_emitter : Emitter
|
||||
@r_emitter : Emitter
|
||||
@fire_speed = 125.0
|
||||
@fire_recoil = 3.0
|
||||
@emitter : PF::Emitter
|
||||
@l_emitter : PF::Emitter
|
||||
@r_emitter : PF::Emitter
|
||||
@projected_points : Array(Vector2)? = nil
|
||||
property blew_up : Bool = false
|
||||
@color = Pixel.new
|
||||
@color = PF::Pixel.new
|
||||
|
||||
def initialize
|
||||
super
|
||||
|
@ -24,7 +28,7 @@ class Ship < Sprite
|
|||
Vector2.new(-3.0, -3.0),
|
||||
]
|
||||
|
||||
@emitter = Emitter.build do |e|
|
||||
@emitter = PF::Emitter.build do |e|
|
||||
e.position = @position
|
||||
e.emit_freq = 0.01
|
||||
e.emit_angle = 0.5
|
||||
|
@ -32,7 +36,7 @@ class Ship < Sprite
|
|||
e.max_age = 0.25
|
||||
end
|
||||
|
||||
@l_emitter = Emitter.build do |e|
|
||||
@l_emitter = PF::Emitter.build do |e|
|
||||
e.position = @position
|
||||
e.emit_freq = 0.01
|
||||
e.emit_angle = 0.3
|
||||
|
@ -40,7 +44,7 @@ class Ship < Sprite
|
|||
e.max_age = 0.25
|
||||
end
|
||||
|
||||
@r_emitter = Emitter.build do |e|
|
||||
@r_emitter = PF::Emitter.build do |e|
|
||||
e.position = @position
|
||||
e.emit_freq = 0.01
|
||||
e.emit_angle = 0.3
|
||||
|
@ -55,11 +59,11 @@ class Ship < Sprite
|
|||
|
||||
def fire
|
||||
@fire_cooldown = @fire_rate
|
||||
@velocity.x -= Math.cos(@rotation) * 3.0
|
||||
@velocity.y -= Math.sin(@rotation) * 3.0
|
||||
@velocity.x -= Math.cos(@rotation) * @fire_recoil
|
||||
@velocity.y -= Math.sin(@rotation) * @fire_recoil
|
||||
Bullet.build do |bullet|
|
||||
bullet.position = project_points([@frame[0]]).first
|
||||
bullet.velocity = @velocity + Vector2.new(Math.cos(@rotation), Math.sin(@rotation)) * 100.0
|
||||
bullet.velocity = @velocity + Vector2.new(Math.cos(@rotation), Math.sin(@rotation)) * @fire_speed
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue