| 1 | // Try commenting or changing the drawing functions, that are at the bottom of the file, |
| 2 | // and that are inside functions marked with @[live] ... |
| 3 | import gg |
| 4 | import math |
| 5 | |
| 6 | fn main() { |
| 7 | mut state := init_state() |
| 8 | gg.start( |
| 9 | window_title: 'Tunnel' |
| 10 | bg_color: gg.Color{255, 255, 255, 255} |
| 11 | width: 1024 |
| 12 | height: 768 |
| 13 | frame_fn: unsafe { state.draw } |
| 14 | event_fn: unsafe { state.on_event } |
| 15 | ) |
| 16 | } |
| 17 | |
| 18 | struct BigRect { |
| 19 | mut: |
| 20 | id int |
| 21 | t f32 |
| 22 | x f32 |
| 23 | y f32 |
| 24 | w f32 |
| 25 | bwidth f32 |
| 26 | c gg.Color |
| 27 | } |
| 28 | |
| 29 | struct State { |
| 30 | mut: |
| 31 | t f32 |
| 32 | real_t f32 |
| 33 | drt f32 = 0.1 |
| 34 | tparams gg.DrawTextParams |
| 35 | rects []BigRect |
| 36 | } |
| 37 | |
| 38 | const colors = []gg.Color{len: 1024, init: gg.Color{u8(100 + |
| 39 | 100 * math.sin(f32(index) / 50) * math.cos(f32(index) / 50)), u8(100 + |
| 40 | 100 * math.cos(f32(index) / 50)), 100 + u8(index % 50), 255}} |
| 41 | |
| 42 | fn init_state() State { |
| 43 | mut state := State{ |
| 44 | t: 0 |
| 45 | real_t: 120 |
| 46 | drt: 0.1 |
| 47 | tparams: gg.DrawTextParams{ |
| 48 | x: 40 |
| 49 | size: 20 |
| 50 | color: gg.Color{255, 255, 255, 255} |
| 51 | } |
| 52 | rects: [ |
| 53 | BigRect{ |
| 54 | x: 350 |
| 55 | y: 250 |
| 56 | w: 30 |
| 57 | bwidth: 10 |
| 58 | c: gg.Color{0, 0, 255, 255} |
| 59 | }, |
| 60 | ] |
| 61 | } |
| 62 | for i in 1 .. 50 { |
| 63 | state.rects << BigRect{ |
| 64 | id: i |
| 65 | } |
| 66 | } |
| 67 | return state |
| 68 | } |
| 69 | |
| 70 | fn (mut state State) on_event(e &gg.Event, _ctx voidptr) { |
| 71 | if e.typ == .char { |
| 72 | if e.char_code == `f` { |
| 73 | gg.toggle_fullscreen() |
| 74 | return |
| 75 | } |
| 76 | if e.char_code == `1` { |
| 77 | state.real_t -= 100 |
| 78 | } |
| 79 | if e.char_code == `2` { |
| 80 | state.real_t += 100 |
| 81 | } |
| 82 | if e.char_code == `3` { |
| 83 | state.t -= 100 |
| 84 | } |
| 85 | if e.char_code == `4` { |
| 86 | state.t += 100 |
| 87 | } |
| 88 | if e.char_code == `5` { |
| 89 | state.rects[0].w += 10 |
| 90 | } |
| 91 | if e.char_code == `6` { |
| 92 | state.rects[0].w -= 10 |
| 93 | } |
| 94 | if e.char_code == `r` { |
| 95 | state.real_t = 120 |
| 96 | state.t = 0 |
| 97 | state.rects[0].w = 30 |
| 98 | } |
| 99 | if e.char_code == ` ` { |
| 100 | state.drt = if state.drt > 0.0001 { f32(0.0) } else { 0.1 } |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | fn (mut state State) draw(ctx &gg.Context) { |
| 106 | update(mut state) |
| 107 | ctx.begin() |
| 108 | mut r0 := &state.rects[0] |
| 109 | draw_big_rect(ctx, r0) |
| 110 | for i in 1 .. state.rects.len { |
| 111 | draw_big_rect(ctx, state.rects[i]) |
| 112 | } |
| 113 | ctx.draw_text2(gg.DrawTextParams{ |
| 114 | ...state.tparams |
| 115 | y: 0 |
| 116 | text: 'rt[1,2]: ${state.real_t:08.3f}, t[3,4]: ${state.t:08.3f}, r0.x: ${r0.x:07.3f}, r0.y: ${r0.y:07.3f}, r0.w[5,6]: ${r0.w:4.1f}, [f]-toggle fs, [r]-reset, [ ]-pause' |
| 117 | }) |
| 118 | draw_center_point(ctx, r0, state.t) |
| 119 | ctx.show_fps() |
| 120 | ctx.end() |
| 121 | } |
| 122 | |
| 123 | @[live] |
| 124 | fn update(mut state State) { |
| 125 | if state.drt <= 0.0001 { |
| 126 | return |
| 127 | } |
| 128 | state.real_t += state.drt |
| 129 | state.t += 0.5 * math.sinf(state.real_t / 1000) |
| 130 | mut r0 := &state.rects[0] |
| 131 | r0.t = state.t |
| 132 | r0.x = 550 + 450 * math.sinf(state.t / 10) * math.sinf(state.t / 50) |
| 133 | r0.y = 350 + 350 * math.cosf(state.t / 20) * math.cosf(-state.t / 50) |
| 134 | r0.x += 5 * math.sinf(state.t) |
| 135 | r0.y += 5 * math.cosf(state.t) |
| 136 | r0.c = colors[int((50000 + state.t) / 200 * (1 + math.sin(state.t / 5))) % colors.len] |
| 137 | for i := state.rects.len - 1; i > 0; i-- { |
| 138 | state.rects[i] = state.rects[i - 1] |
| 139 | state.rects[i].w *= 1.11 + f32(i) / 1000 |
| 140 | state.rects[i].bwidth *= 1.09 |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | @[live] |
| 145 | fn draw_center_point(ctx &gg.Context, br BigRect, t f32) { |
| 146 | b := u8(128 + 128 * math.sin(t / 12)) |
| 147 | c := gg.Color{255 - b, b, b, 55} |
| 148 | ctx.draw_circle_filled(br.x, br.y, 8, c) |
| 149 | } |
| 150 | |
| 151 | @[live] |
| 152 | fn draw_big_rect(ctx &gg.Context, br BigRect) { |
| 153 | radius := 20 |
| 154 | x := br.x |
| 155 | y := br.y |
| 156 | w := br.w |
| 157 | c := br.c |
| 158 | bwidth := br.bwidth |
| 159 | base := gg.DrawRectParams{ |
| 160 | radius: radius |
| 161 | is_rounded: true |
| 162 | color: c |
| 163 | } |
| 164 | rleft := gg.DrawRectParams{ |
| 165 | ...base |
| 166 | x: x - (w / 2) |
| 167 | y: y - (w / 2) |
| 168 | w: bwidth |
| 169 | h: w |
| 170 | } |
| 171 | rright := gg.DrawRectParams{ |
| 172 | ...base |
| 173 | x: x + (w / 2) - bwidth |
| 174 | y: y - w + (w / 2) |
| 175 | w: bwidth |
| 176 | h: w |
| 177 | } |
| 178 | rtop := gg.DrawRectParams{ |
| 179 | ...base |
| 180 | x: x - (w / 2) |
| 181 | y: y - (w / 2) |
| 182 | w: w |
| 183 | h: bwidth |
| 184 | } |
| 185 | rbottom := gg.DrawRectParams{ |
| 186 | ...base |
| 187 | x: x + (w / 2) - w |
| 188 | y: y + (w / 2) - bwidth |
| 189 | w: w |
| 190 | h: bwidth |
| 191 | } |
| 192 | border := gg.DrawRectParams{ |
| 193 | x: x - (w / 2) + bwidth + 1 |
| 194 | y: y - (w / 2) + bwidth + 2 |
| 195 | w: w - 2 * bwidth - 2 |
| 196 | h: w - 2 * bwidth - 1 |
| 197 | color: gg.Color{255, 255, 255, 155} |
| 198 | style: .stroke |
| 199 | } |
| 200 | ctx.draw_rect(rtop) |
| 201 | ctx.draw_rect(rleft) |
| 202 | ctx.draw_rect(rright) |
| 203 | ctx.draw_rect(border) |
| 204 | ctx.draw_rect(rbottom) |
| 205 | } |
| 206 | |