From aec3ea5d321e88fad7bb83309f5356c80c8e290a Mon Sep 17 00:00:00 2001 From: Larpon Date: Wed, 1 Jul 2020 13:29:58 +0200 Subject: [PATCH] examples: add sokol particle example (#5599) --- cmd/tools/modules/testing/common.v | 10 +- examples/sokol/particles/main.v | 138 ++++++++++++++++++ examples/sokol/particles/particle/LICENSE | 21 +++ examples/sokol/particles/particle/color.v | 15 ++ examples/sokol/particles/particle/particle.v | 99 +++++++++++++ examples/sokol/particles/particle/system.v | 109 ++++++++++++++ examples/sokol/particles/particle/v.mod | 0 examples/sokol/particles/particle/vec2/v.mod | 0 examples/sokol/particles/particle/vec2/vec2.v | 99 +++++++++++++ 9 files changed, 490 insertions(+), 1 deletion(-) create mode 100644 examples/sokol/particles/main.v create mode 100644 examples/sokol/particles/particle/LICENSE create mode 100644 examples/sokol/particles/particle/color.v create mode 100644 examples/sokol/particles/particle/particle.v create mode 100644 examples/sokol/particles/particle/system.v create mode 100644 examples/sokol/particles/particle/v.mod create mode 100644 examples/sokol/particles/particle/vec2/v.mod create mode 100644 examples/sokol/particles/particle/vec2/vec2.v diff --git a/cmd/tools/modules/testing/common.v b/cmd/tools/modules/testing/common.v index 68d0c5d276..f350582364 100644 --- a/cmd/tools/modules/testing/common.v +++ b/cmd/tools/modules/testing/common.v @@ -209,7 +209,7 @@ pub fn v_build_failing(zargs string, folder string) bool { return v_build_failing_skipped(zargs, folder, []) } -pub fn v_build_failing_skipped(zargs string, folder string, skipped []string) bool { +pub fn v_build_failing_skipped(zargs string, folder string, oskipped []string) bool { main_label := 'Building $folder ...' finish_label := 'building $folder' vexe := pref.vexe_path() @@ -221,6 +221,7 @@ pub fn v_build_failing_skipped(zargs string, folder string, skipped []string) bo mut session := new_test_session(vargs) files := os.walk_ext(os.join_path(parent_dir, folder), '.v') mut mains := []string{} + mut skipped := oskipped for f in files { if !f.contains('modules') && !f.contains('preludes') { //$if !linux { @@ -240,6 +241,13 @@ pub fn v_build_failing_skipped(zargs string, folder string, skipped []string) bo continue } } + c := os.read_file(f) or { panic(err) } + maxc := if c.len > 300 { 300 } else { c.len } + start := c[0..maxc] + if start.contains('module ') && !start.contains('module main') { + skipped_f := f.replace(os.join_path(parent_dir,''), '') + skipped << skipped_f + } mains << f } } diff --git a/examples/sokol/particles/main.v b/examples/sokol/particles/main.v new file mode 100644 index 0000000000..6a721fca9b --- /dev/null +++ b/examples/sokol/particles/main.v @@ -0,0 +1,138 @@ +// Copyright(C) 2019 Lars Pontoppidan. All rights reserved. +// Use of this source code is governed by an MIT license file distributed with this software package +module main + +import time +import sokol +import sokol.sapp +import sokol.gfx +import sokol.sgl +import particle + +const ( + used_import = sokol.used_import +) + +fn main() { + app := &App{ + width: 800 + height: 400 + pass_action: gfx.create_clear_pass(0.1, 0.1, 0.1, 1.0) + } + app.init() + app.run() +} + +struct App { + pass_action C.sg_pass_action +mut: + width int + height int + frame i64 + last i64 + ps particle.System +} + +fn (mut a App) init() { + a.frame = 0 + a.last = time.ticks() + a.ps = particle.System{a.width, a.height} + a.ps.init(particle.SystemConfig{ + pool: 20000 + }) +} + +fn (mut a App) cleanup() { + a.ps.free() +} + +fn (a App) run() { + title := 'V Particle Example' + 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 + html5_canvas_name: title.str + cleanup_userdata_cb: cleanup + } + sapp.run(&desc) +} + +fn (a App) draw() { + a.ps.draw() +} + +fn init(user_data voidptr) { + desc := C.sg_desc { + mtl_device: sapp.metal_get_device() + mtl_renderpass_descriptor_cb: sapp.metal_get_renderpass_descriptor + mtl_drawable_cb: sapp.metal_get_drawable + d3d11_device: sapp.d3d11_get_device() + d3d11_device_context: sapp.d3d11_get_device_context() + d3d11_render_target_view_cb: sapp.d3d11_get_render_target_view + d3d11_depth_stencil_view_cb: sapp.d3d11_get_depth_stencil_view + } + gfx.setup(&desc) + sgl_desc := C.sgl_desc_t{ + max_vertices: 50 * 65536 + } + sgl.setup(&sgl_desc) +} + +fn cleanup(user_data voidptr) { + mut app := &App(user_data) + app.cleanup() + gfx.shutdown() +} + +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 + app.ps.update(dt) + draw(app) + gfx.begin_default_pass(&app.pass_action, app.width, app.height) + sgl.draw() + gfx.end_pass() + gfx.commit() + app.frame++ + app.last = t +} + +fn event(ev &C.sapp_event, user_data voidptr) { + mut app := &App(user_data) + if ev.@type == .mouse_move { + app.ps.explode(ev.mouse_x, 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 { + app.ps.explode(ev.mouse_x, ev.mouse_y) + } + } + } + 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() + } + } + } +} + +fn draw(a &App) { + sgl.defaults() + sgl.matrix_mode_projection() + sgl.ortho(0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0) + sgl.push_matrix() + a.draw() + sgl.pop_matrix() +} diff --git a/examples/sokol/particles/particle/LICENSE b/examples/sokol/particles/particle/LICENSE new file mode 100644 index 0000000000..1595a57ad2 --- /dev/null +++ b/examples/sokol/particles/particle/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Lars Pontoppidan + +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. diff --git a/examples/sokol/particles/particle/color.v b/examples/sokol/particles/particle/color.v new file mode 100644 index 0000000000..813958a3e3 --- /dev/null +++ b/examples/sokol/particles/particle/color.v @@ -0,0 +1,15 @@ +// Copyright(C) 2019 Lars Pontoppidan. All rights reserved. +// Use of this source code is governed by an MIT license file distributed with this software package + +module particle + +/* +* Color +*/ +pub struct Color { +mut: + r byte + g byte + b byte + a byte +} diff --git a/examples/sokol/particles/particle/particle.v b/examples/sokol/particles/particle/particle.v new file mode 100644 index 0000000000..66564a308a --- /dev/null +++ b/examples/sokol/particles/particle/particle.v @@ -0,0 +1,99 @@ +// Copyright(C) 2019 Lars Pontoppidan. All rights reserved. +// Use of this source code is governed by an MIT license file distributed with this software package + +module particle + +import vec2 +import sokol.sgl + +const ( + default_life_time = 1000 + default_v_color = Color{93, 136, 193, 255 } +) + +/* +* Module public +*/ +pub fn new(location vec2.Vec2) &Particle { + + p := &Particle { + location: location, + velocity: vec2.Vec2{0,0} + acceleration: vec2.Vec2{0,0} + + color: default_v_color + + life_time: default_life_time + life_time_init: default_life_time + } + return p +} + +fn remap(v, min, max, new_min, new_max f64) f64 { + return (((v - min) * (new_max - new_min)) / (max - min)) + new_min +} + +/* +* Particle +*/ +pub struct Particle { + +mut: + location vec2.Vec2 + velocity vec2.Vec2 + acceleration vec2.Vec2 + + color Color + + life_time f64 + life_time_init f64 +} + +pub fn (mut p Particle) update(dt f64) { + mut acc := p.acceleration + acc.multiply_f64(dt) + p.velocity = p.velocity.add(acc) + p.location = p.location.add(p.velocity) + + lt := p.life_time - (1000 * dt) + if lt > 0 { + p.life_time = lt + + p.color.r = p.color.r - 1 //byte(remap(p.life_time,0.0,p.life_time_init,0,p.color.r)) + p.color.g = p.color.g - 1 //byte(remap(p.life_time,0.0,p.life_time_init,0,p.color.g)) + p.color.b = p.color.b - 1 //byte(remap(p.life_time,0.0,p.life_time_init,0,p.color.b)) + + //p.color.a = byte(remap(p.life_time,0.0,p.life_time_init,0,255)) + } else { + p.life_time = 0 + } +} + +pub fn (p Particle) is_dead() bool { + return p.life_time <= 0.0 +} + +pub fn (p Particle) draw() { + l := p.location + + sgl.c4b(p.color.r, p.color.g, p.color.b, p.color.a) + + lx := f32(l.x) + ly := f32(l.y) + sgl.v2f(lx, ly) + sgl.v2f(lx + 2, ly) + sgl.v2f(lx + 2, ly + 2) + sgl.v2f(lx, ly + 2) +} + +pub fn (mut p Particle) reset() { + p.location.zero() + p.acceleration.zero() + p.velocity.zero() + + //p.color = Color{93, 136, 193, 255} + p.color = default_v_color + + p.life_time = default_life_time + p.life_time_init = p.life_time +} diff --git a/examples/sokol/particles/particle/system.v b/examples/sokol/particles/particle/system.v new file mode 100644 index 0000000000..2f419dc285 --- /dev/null +++ b/examples/sokol/particles/particle/system.v @@ -0,0 +1,109 @@ +// Copyright(C) 2019 Lars Pontoppidan. All rights reserved. +// Use of this source code is governed by an MIT license file distributed with this software package + +module particle +import vec2 +import rand +import sokol.sgl + +pub struct SystemConfig { + pool int +} + +pub struct System { + width int + height int +mut: + pool []&Particle + bin []&Particle +} + +pub fn (mut s System) init(sc SystemConfig) { + for i := 0; i < sc.pool; i++ { + p := particle.new( vec2.Vec2{f32(s.width)*0.5, f32(s.height)*0.5} ) + s.pool << p + } +} + +pub fn (mut s System) update(dt f64) { + + mut p := &Particle(0) + for i := 0; i < s.pool.len; i++ { + p = s.pool[i] + + p.update(dt) + + if p.is_dead() { + s.bin << p + s.pool.delete(i) + } + } +} + +pub fn (s System) draw() { + sgl.begin_quads() + for p in s.pool { + p.draw() + } + sgl.end() +} + +pub fn (mut s System) reset() { + for p in s.pool { + p.reset() + p.life_time = 0 + } + for p_ in s.bin { + p_.reset() + p_.life_time = 0 + } +} + +pub fn (mut s System) explode(x f32, y f32) { + + mut reserve := 500 + + center := vec2.Vec2{x,y} + + mut p := &Particle(0) + for i := 0; i < s.bin.len && reserve > 0; i++ { + p = s.bin[i] + + p.reset() + + p.location.from(center) + p.acceleration = vec2.Vec2{rand.f32_in_range(-0.5,0.5),rand.f32_in_range(-0.5,0.5)} + p.velocity = vec2.Vec2{rand.f32_in_range(-0.5,0.5),rand.f32_in_range(-0.5,0.5)} + p.life_time = rand.f64_in_range(500,2000) + + s.pool << p + s.bin.delete(i) + + reserve-- + } +} + +pub fn (mut s System) free() { + for p in s.pool { + if p == 0 { + print(ptr_str(p)+' ouch') + continue + } + unsafe{ + free(p) + } + } + s.pool.clear() + for p in s.bin { + if p == 0 { + print(ptr_str(p)+' ouch') + continue + } + + unsafe{ + //println('Freeing from bin') + free(p) + } + } + s.bin.clear() +} \ No newline at end of file diff --git a/examples/sokol/particles/particle/v.mod b/examples/sokol/particles/particle/v.mod new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/sokol/particles/particle/vec2/v.mod b/examples/sokol/particles/particle/vec2/v.mod new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/sokol/particles/particle/vec2/vec2.v b/examples/sokol/particles/particle/vec2/vec2.v new file mode 100644 index 0000000000..2fdfa7a88d --- /dev/null +++ b/examples/sokol/particles/particle/vec2/vec2.v @@ -0,0 +1,99 @@ +// Copyright(C) 2019 Lars Pontoppidan. All rights reserved. +// Use of this source code is governed by an MIT license file distributed with this software package + +module vec2 + +pub struct Vec2 { +pub mut: + x f64 + y f64 +} + +pub fn (mut v Vec2) zero() { + v.x = 0.0 + v.y = 0.0 +} + +pub fn (mut v Vec2) from(src Vec2) { + v.x = src.x + v.y = src.y +} + +/* + * Addition + */ + +// + operator overload. Adds two vectors +pub fn (v1 Vec2) + (v2 Vec2) Vec2 { + return Vec2{v1.x + v2.x, v1.y + v2.y} +} + +pub fn (v Vec2) add(vector Vec2) Vec2 { + return Vec2{ v.x + vector.x, v.y + vector.y } +} + +pub fn (v Vec2) add_f64(scalar f64) Vec2 { + return Vec2{ v.x + scalar, v.y + scalar } +} + +pub fn (mut v Vec2) plus(vector Vec2) { + v.x += vector.x + v.y += vector.y +} + +pub fn (mut v Vec2) plus_f64(scalar f64) { + v.x += scalar + v.y += scalar +} + + +/* + * Subtraction + */ +pub fn (v1 Vec2) - (v2 Vec2) Vec2 { + return Vec2{v1.x - v2.x, v1.y - v2.y} +} + +pub fn (v Vec2) sub(vector Vec2) Vec2 { + return Vec2{ v.x - vector.x, v.y - vector.y } +} + +pub fn (v Vec2) sub_f64(scalar f64) Vec2 { + return Vec2{ v.x - scalar, v.y - scalar } +} + +pub fn (mut v Vec2) subtract(vector Vec2) { + v.x -= vector.x + v.y -= vector.y +} + +pub fn (mut v Vec2) subtract_f64(scalar f64) { + v.x -= scalar + v.y -= scalar +} + +/* + * Multiplication + */ +pub fn (v1 Vec2) * (v2 Vec2) Vec2 { + return Vec2{v1.x * v2.x, v1.y * v2.y} +} + + +pub fn (v Vec2) mul(vector Vec2) Vec2 { + return Vec2{ v.x * vector.x, v.y * vector.y } +} + +pub fn (v Vec2) mul_f64(scalar f64) Vec2 { + return Vec2{ v.x * scalar, v.y * scalar } +} + +pub fn (mut v Vec2) multiply(vector Vec2) { + v.x *= vector.x + v.y *= vector.y +} + +pub fn (mut v Vec2) multiply_f64(scalar f64) { + v.x *= scalar + v.y *= scalar +} \ No newline at end of file