Skip to content

Instantly share code, notes, and snippets.

@tokoroten
Created February 9, 2012 17:32
Show Gist options
  • Save tokoroten/1781444 to your computer and use it in GitHub Desktop.
Save tokoroten/1781444 to your computer and use it in GitHub Desktop.
particles in Ruby/SDL
require 'sdl'
WINDOW_SIZE = [1280, 768]
PARTICLE_SIZE = 8
EFFECT_LENGTH = 16
class GameManager
def initialize(screen)
@screen = screen
@particles = Array.new
for i in 0..300
x = Float(rand WINDOW_SIZE[0]) + rand()
y = Float(rand WINDOW_SIZE[1]) + rand()
@particles.push(Particle.new(x, y))
end
end
def collision1()
for p1 in @particles
for p2 in @particles
next if p1.equal?(p2)
dx = p1.x - p2.x
dy = p1.y - p2.y
r = (dx**2 + dy**2) ** 0.5
next if r > EFFECT_LENGTH
r += 0.001
cos = dx / r
sin = dy / r
vec = 40 / (r ** 2)
p1.vx += vec * cos
p1.vy += vec * sin
end
end
end
def collision2()
w = WINDOW_SIZE[0] / EFFECT_LENGTH
h = WINDOW_SIZE[1] / EFFECT_LENGTH
#p w,h
grid = Array.new(h, nil)
h.times{|i|
grid[i] = Array.new(w, Array.new())
}
for p in @particles
x = Integer(p.x / EFFECT_LENGTH)
y = Integer(p.y / EFFECT_LENGTH)
grid[y][x].push(p)
end
for p1 in @particles
x = Integer(p1.x / EFFECT_LENGTH)
y = Integer(p1.y / EFFECT_LENGTH)
nearParticles = []
nearParticles.concat(grid[y][x])
nearParticles.concat(grid[y-1][x-1]) if (x > 0 && y > 0)
nearParticles.concat(grid[y-1][x]) if (y > 0)
nearParticles.concat(grid[y-1][x+1]) if (x < w-1 && y > 0)
nearParticles.concat(grid[y][x-1]) if (x > 0)
nearParticles.concat(grid[y][x+1]) if (x < w-1 )
nearParticles.concat(grid[y+1][x-1]) if (x > 0 && y < h-1)
nearParticles.concat(grid[y+1][x]) if (y < h-1)
nearParticles.concat(grid[y+1][x+1]) if (x < w-1 && y < h-1)
for p2 in nearParticles
next if p1.equal?(p2)
dx = p1.x - p2.x
dy = p1.y - p2.y
r = (dx**2 + dy**2) ** 0.5
next if r > EFFECT_LENGTH
r += 0.001
cos = dx / r
sin = dy / r
vec = 40 / (r ** 2)
p1.vx += vec * cos
p1.vy += vec * sin
end
end
end
def mouseAction()
mouseState = SDL::Mouse.state
return if not mouseState[2]
mx = mouseState[0]
my = mouseState[1]
for p in @particles
dx = p.x - mx
dy = p.y - my
r = (dx**2 + dy**2) ** 0.5
if r == 0
next
end
cos = dx / r
sin = dy / r
vec = 100 / (r + 100)
p.vx += vec * cos
p.vy += vec * sin
end
end
def run()
#collision1()
collision2()
mouseAction()
for particle in @particles
particle.run()
end
end
def draw()
@screen.fillRect(0, 0, @screen.w, @screen.h, [0, 0, 0])
for particle in @particles
particle.draw(@screen)
end
end
end
class Particle
def initialize(x, y)
@x = x
@y = y
@vx = 0
@vy = 0
end
attr_accessor :x, :y, :vx, :vy
def run()
@x += @vx
@y += @vy
@vx *= 0.9
@vy *= 0.9
#@vy += 0.1
cx = WINDOW_SIZE[0] / 2
cy = WINDOW_SIZE[1] / 2
dx = @x - cx
dy = @y - cy
r = (dx**2 + dy**2) ** 0.5
if r > 10
cos = dx / r
sin = dy / r
@vx -= cos / 10
@vy -= sin / 10
end
if @x < PARTICLE_SIZE
@vx = 0
@x = PARTICLE_SIZE
end
if @y < PARTICLE_SIZE
@vy = 0
@y = PARTICLE_SIZE
end
if @x > WINDOW_SIZE[0] - PARTICLE_SIZE
@vx = 0
@x = WINDOW_SIZE[0] - PARTICLE_SIZE
end
if @y > WINDOW_SIZE[1] - PARTICLE_SIZE
@vy = 0
@y = WINDOW_SIZE[1] - PARTICLE_SIZE
end
end
def draw(screen)
screen.drawCircle(@x, @y, PARTICLE_SIZE, [ 255, 255, 255 ])
end
end
def main()
SDL.init( SDL::INIT_VIDEO )
screen = SDL.setVideoMode( WINDOW_SIZE[0], WINDOW_SIZE[1], 16, SDL::SWSURFACE )
gameManager = GameManager.new(screen)
loop do # (4)
while event = SDL::Event2.poll
case event
when SDL::Event2::Quit, SDL::Event2::KeyDown
exit
end
end
#update
gameManager.run()
#draw
gameManager.draw()
screen.updateRect( 0, 0, 0, 0 )
end
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment