particle
Particle system written in V
Example main.v
module main
import time
import sokol
import sokol.sapp
import sokol.gfx
import sokol.sgl
import particle
import particle.vec
const (
used_import = sokol.used_import
)
fn main() {
mut app := &App{
width: 1200
height: 800
pass_action: gfx.create_clear_pass(0.0, 0.0, 0.0, 1.0)
}
app.init()
app.run()
}
struct App {
pass_action C.sg_pass_action
mut:
width int
height int
last i64
ps &particle.System = 0
alpha_pip C.sgl_pipeline
}
fn (mut a App) init() {
a.ps = &particle.System{
width: a.width
height: a.height
}
e := particle.Emitter{
//enabled: false
rate: 200
velocity: particle.PointDirection{
point_variation: vec.Vec2[f64]{0.5,0.5}
}
acceleration: particle.PointDirection{
//point: vec.Vec2[f64]{0.1,5}
point_variation: vec.Vec2[f64]{0.7,0.7}
}
life_time: 4000
life_time_variation: 2000
movement_velocity: 50
//movement_velocity_flip: true
}
a.ps.add(e)
bottom_right := vec.Vec2[f64]{f64(a.width),f64(a.height)}
vwhdiv6 := vec.Vec2[f64]{f64(a.width)/6,f64(a.height)/6}
e1 := particle.Emitter{
enabled: true
position: vwhdiv6
rate: 10
velocity: particle.PointDirection{
point_variation: vec.Vec2[f64]{0.5,0.5}
}
acceleration: particle.PointDirection{
point_variation: vec.Vec2[f64]{0.7,0.7}
}
life_time: 2000
life_time_variation: 4000
}
a.ps.add(e1)
e2 := particle.Emitter{
enabled: true
position: vec.Vec2[f64]{vwhdiv6.x*2,vwhdiv6.y}
rate: 4.5
velocity: particle.AngleDirection{
angle: -90
angle_variation: 25
magnitude: 0.2
magnitude_variation: 0.01
}
acceleration: particle.AngleDirection{
angle: -90
angle_variation: 25
magnitude: 1
magnitude_variation: 0.4
}
life_time: 2000
life_time_variation: 1000
}
a.ps.add(e2)
e3 := particle.Emitter{
enabled: true
position: vec.Vec2[f64]{vwhdiv6.x*3,vwhdiv6.y}
rate: 4.5
velocity: particle.TargetDirection {
target: bottom_right
target_variation: vec.Vec2[f64]{0.5,0.5}
magnitude: 5
magnitude_variation: 2
}
acceleration: particle.TargetDirection {
target: bottom_right
target_variation: vec.Vec2[f64]{bottom_right.x*0.2,bottom_right.y*0.2}
magnitude: 5
magnitude_variation: 0.5
}
life_time: 2000
life_time_variation: 1000
}
a.ps.add(e3)
painter := particle.RectPainter{
groups: [""]
color: particle.Color{255,0,0,255}
}
a.ps.add(painter)
a.ps.init({pool: 20000})
}
fn (mut a App) cleanup() {
a.ps.free()
free(a.ps)
sgl.destroy_pipeline(a.alpha_pip)
}
fn cleanup(user_data voidptr) {
mut app := &App(user_data)
app.cleanup()
gfx.shutdown()
}
fn (a App) run() {
title := 'V Particles'
desc := C.sapp_desc{
width: a.width
height: a.height
user_data: &a
init_userdata_cb: init
frame_userdata_cb: frame
event_userdata_cb: event
window_title: title.str
cleanup_userdata_cb: cleanup
}
sapp.run(&desc)
}
fn (mut a App) draw() {
sgl.load_pipeline(a.alpha_pip)
a.ps.draw()
}
fn init(user_data voidptr) {
mut app := &App(user_data)
desc := C.sg_desc{}
gfx.setup(&desc)
sgl_desc := C.sgl_desc_t {
max_vertices: 4*65536
max_commands: 2*16384
}
sgl.setup(&sgl_desc)
mut pipdesc := C.sg_pipeline_desc{}
unsafe {
C.memset(&pipdesc, 0, sizeof(pipdesc))
}
pipdesc.blend.enabled = true
pipdesc.blend.src_factor_rgb = C.SG_BLENDFACTOR_SRC_ALPHA
pipdesc.blend.dst_factor_rgb = C.SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
app.alpha_pip = sgl.make_pipeline(&pipdesc)
}
fn frame(user_data voidptr) {
mut app := &App(user_data)
app.width = sapp.width()
app.height = sapp.height()
t := time.ticks()
dt := f64(t - app.last) / 1000.0
sgl.default_pipeline()
app.ps.update(dt)
draw(mut app)
gfx.begin_default_pass(&app.pass_action, app.width, app.height)
sgl.draw()
gfx.end_pass()
gfx.commit()
app.last = t
}
fn event(ev &C.sapp_event, user_data voidptr) {
mut app := &App(user_data)
mut emitter := app.ps.get_emitter(0)
mut target_emitter := app.ps.get_emitter(3)
if ev.@type == .mouse_move {
emitter.position.x = ev.mouse_x
emitter.position.y = ev.mouse_y
}
if ev.@type == .mouse_up || ev.@type == .mouse_down {
if ev.mouse_button == .left {
is_pressed := ev.@type == .mouse_down
if is_pressed {
emitter.enabled = !emitter.enabled
mut tea := target_emitter.acceleration
match mut tea {
particle.TargetDirection {
tea.target.x = emitter.position.x
tea.target.y = emitter.position.y
}
else { }
}
}
}
if ev.mouse_button == .right {
is_pressed := ev.@type == .mouse_down
if is_pressed {
emitter.burst(500)
}
}
}
if ev.@type == .key_up || ev.@type == .key_down {
if ev.key_code == .r {
is_pressed := ev.@type == .key_down
if is_pressed {
app.ps.reset()
}
}
if ev.key_code == .escape {
released := ev.@type == .key_up
if released {
sapp.quit()
}
}
}
if ev.@type == .touches_began || ev.@type == .touches_moved {
if ev.num_touches > 0 {
touch_point := ev.touches[0]
emitter.position.x = touch_point.pos_x
emitter.position.y = touch_point.pos_y
}
}
}
fn draw(mut a App) {
sgl.defaults()
sgl.matrix_mode_projection()
sgl.ortho(0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
a.draw()
}