From 3c050f1bd6296fcaafe46cdcdc3776b938d8f685 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 11 May 2021 14:42:24 -0500 Subject: [PATCH] added bitmap font and FPS rendering --- site/js/game.js | 4 ++ site/sand_toy.wasm | Bin 25538 -> 291836 bytes src/build.onyx | 1 + src/font/bitmap_font.onyx | 134 ++++++++++++++++++++++++++++++++++++++ src/res/font.data | Bin 0 -> 262144 bytes src/res/font_2.data | Bin 0 -> 262144 bytes src/sand_toy.onyx | 88 ++++++++++++++++++++++++- 7 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 src/font/bitmap_font.onyx create mode 100644 src/res/font.data create mode 100644 src/res/font_2.data diff --git a/site/js/game.js b/site/js/game.js index 122d816..cdbb24b 100644 --- a/site/js/game.js +++ b/site/js/game.js @@ -12,4 +12,8 @@ window.ONYX_MODULES.push({ window.requestAnimationFrame(loop); }, + + time_now: function() { + return Date.now(); + }, }); diff --git a/site/sand_toy.wasm b/site/sand_toy.wasm index 7f687fa774da28392268b1ce6af3df59e022786c..3afcf053b71453d9a2b37bb1a362dbef58f73a59 100644 GIT binary patch literal 291836 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 delta 7545 zcmb_BYm`*QnN@Y~?N{}qW_sQO%c6YA_Xc2Hkhp0VIzrxxI~SD*+e}@bI@eZa!jJ;Y~0LAbj8)pVK*eZ-&ePLX7G5- zpKXSFtG@c`tM6T3)xG@tyw_f*(@8AVO$j0Nmvl@E%VcP##g)-N(qh1yv{3kO?t&kI z@kghZ0}3FSh(lTkV(s2dS}Z*W2Kg#^6tbbdf=*DkuN#kfgKES-+Ewy$ZAZH^}i0Z4dTJeiK~ zkm+=?V^dRaM^73CC=3Ju+7wI1y5j)pAPi@3jwhg(ooxUlw5g+K^E!t@G8x-R3<*$Q zYa$*?F78eACW(pt{#3jv*}DaZ5u6q5@9AjkO?Iz{!J<26Yuer{Y-Weztdtt+QCgL8 zr{d`~9e2cu1+)Aq&Gnkz{$y)h&j~pEj3yo45>IFQ!^~?rd7`7I>k7=iBnX>@EbD3O zUEaGzbC(Y!Zqf{9x|jF1#?l?VJ;V(Rm>oSGX-y1K94%bANO8O;wkZ+MDnzSPI%V0>rmD8QYHYGCNaR&OArXEA;H`Of|>1#e32z3zXE~M=Z0w zH zgZqpkMCN9Q^N__^z;MHVlFzx9`I$Em2zZH?08toYtkhzVG_pT03=_jNX&))KOiBhk zE;nt;Pk5W?$yq9__DUpPirzdY-aKlY&Zk#`JVbj`m zH{Y^;`G$?R-Tr<0GdlH2+U<4J_tREjQ} z$Rc%X{g`j172KClsF2Ha=wFF8PP6>f|^{h zBoQNGMwrcPvyR#DGU`}049g2a^`2c}L2D?ay6p-dv`XsO4DlVRid;{sc;lAB>wyK} zM|9exnw3b}DNfL(>OZXUYFHe6$q$r=Oj(H~1GwOD3 zt0B)u`m%-%c&oCo*S#C*k2S2>H=cH>W?rFQ_paeCZkx6x{hi_!7`;u8+(}=BcD*X_ zucBx5oWJusv{PVijW0UIIT*QGeIqcAzJ}OLex!a8h_FLU{V8x*&1{K=zoAteH9(e1 z0$QNrC+eND4mwudkzdA6Q}wIqQTl@V>-0@DsbVww%geRsOU(wGqS9;=bXLt~vay1l;vT6pB>Y1WLeKLOz;7nC7t!M%~|H@jmX~BH8a@7*b)bAG5()-kNt|H$_ z;6TpklE*^oT~|AOQLV08#s`CPFlc*V>3M3fs*$#;i&eIIcg-~FRT~%Fn+vJc~rG67$7x8O*fRa#$-=oy!L<|{^?paC15_NaQB6^)VTrov`UQtD#Qd`$o zX*GXVGC{q%J`auj&U&d=ZZBJ>wpcsVof~TZwxVy&+d;opn9(FgS&EL>DidC!KCtRX zlgVj>**Tr?Q6j2mqZN=Q&PQ)sFb&hd#c&Pe+6KA5U@{|vawx1{1@dTMDk1WBL_9`0 z7)fmBKekvXV}Kq(=L`(?%7#h#Ptk)1>Y3kxVHD3(0}H#$=S4I~(k|O0=0yTH4x`vn zyrB`eUDJ>NYoBXa4bK9(Q@1Cm=Vi@|R@8e}B?)nuWr-BT3BhO-y`0ayGMzzmyiPHr zshZB4waQ;ougocBchOUov!7z>JLQ#&@|{FO>cC|om)0?pA4VIC?@~xqBd#n5Y$?Q) z2$knU!0dnxY}jc2TIHQt7aR%!Jm(QLs%d6*O@Tuh0!8Y$&kK+;-bjs%ybPWM>)~6# zg78+&i^~hPa3EaJ8KHi{ISv+xGWDk>3CZjI)wWu{`X1f-cHSJww2-xtVbKNT%hVlB zlky&R(*giTspbob{$TBE3|^_5hJu$voshz5rz}X|NY}bwTCf1L8gKsNm}d>@#cX?; z$qP(A;F8bKoOBPW-_~s{a0X7hJM>|!8>bb3U(iKhxuGobh9D&T|_$79{@={2&skd))oDt`_RQJXjpz^Ja zcMQ|gFkg-y=jtb8lXb=D3b4f{Ptv7l+4RSr7YSwE+~pQGT82i*@oC&7X6 zjiQ#~t6hxa%QXtoi1=qJJUShUgH*JLCn#?onb&AGg!pLH zq3qzf)eH=Vl!vF*Fl%>wBv;#-AULX%bA(p2;T3JJn=W^SHIgc=P^qODXqE{XxDI`ZX zGEwR9Qa=Jg9sy`o5-l|Nj{IM@=;1soG!a4m3Zo%(B*zTkBZEP8WZGB;ua~ElSHT8t z0lV{}Uhr=i%Q|?(2e$K#vfcCrGxqC2n}Gk%CB*hhBY`Pt1Wbp)48bZnz52$F!^mT$ z{B1cbjsNx=_;+8e+*1uWQS@tcK9AstlM$6R0de+G$Z5c}sk0$$5P)PuIVBWTYI#4s zUEL}sqNm*>u3B3P;)3is9NbQ9m+cmD?sG;U8u{H>J7MS*M>RnafStAiY-B-|wg+rf z;MnLhuPjzCt{gYYN~Z9tO)F~rxYg>V#2%`ur?rF@I`v`J$)~A?^%G}3PQ~-!zaR!~ zPop>!_fmeCQ4eGjNaxQz#&QbYr+!^to!OUj3J~0f^_Q=P_#<9OWN!H>l@+KzF$WZX zg33s?1)8l2*|I4n9Bmrd8G>h1v!8XB%oiy8f=#^pfE5ve@pd^FQy6gjvZD< z##cZw`SSQbXD(1#EPe!sr6AJw;J$jlZu+r#3|$TY=tF+w{|ZQzPNvn&k6CEZ@nt$M zd=o2CJnVpujXXH-p&_u^fE?kNcR#QROPxYm(-=8<2psa{!FpI|D2yZiQ<|P~)*Ur` zF|2wf6wlR6Wx)|m>nmqO3hjbHyKoTndoA}H9BMK3+Jxve!z_&|&PEvedVbV|s_1+m zpoQZ9!XQXQr~Hu1JP|IFABV+Q)Y|@_9QfW?EaiuzE9Yo0s`GYD=8B+%P;_FFd{tEX zFe(Sm6FKk}5ez$fMtAl?=ZAZlGjiAH4n(rJk3vStQXj>Q4_$T!R$uk%!H$SJ6IlVL zwdpmJ=RHLu+L&bVuR?D&2&x10OKn9vOza(26=)57#oB?%b++%PH`{9u%u8oLY6NP&(WxP!e%GLRsR5c zre@t5Uf&vF{jgt_<~X-(XF#gG%W4{MJr7o2rtRuFu}A==s9Q565SndvNwE#Kt*EDg z$V`?CK!QK@#jdyp@6L7@!2H4IlhX^>*Wo%yU%R&!#6p#!F!^pteE8 zWDN$W1;{N8!08e>L?eS%hBb^pbPm!e@At{E*%bk5%1{6D!hh{*l%H`K%_)AEM3)>e z9hCz?HE``&jw=dC#i+Lx*Oh~3XeK;*#Sxui#fCg|;WlD{6JVVQ{-B*t)5sah8a9-J z0^~GBoF>vhQ8)`kU3xNVz-7C%ILSIzN^ zb&4Jb>2b9jFUy8mLHC3U8QA2?%6MAUjhhLF()MxlJWo5$x=sDtm{|_UM39=dax&cJ zv@LC?Q`GsTH>&ytlNE2eJ>Zm>;u`eXEo$MW#ePs3kWIib`wgld-c+)xP$x9J;qs(` z;#iz@L9W1wG+U`X{!tX9o$^DUo(N}PmBJf^Q61Td-( zefnr7eU0*90c6CjW&@OAoX^2)tqTEtzHyEKBSyLvtC3lF1$rSMR+RCeW&>4+F%DDp z{i*>K1>CO!R6@yv5>8QPH`#QK3N@F2UZAaxT)%+r@t*qi_04pub14B;^(m@vSWnTf zpakj~rli7KO4S=%g6dM+>{Ekn-=yl1wo)~9$|P00p-8RnD6+nfJC}+Tk5d=jrrK3} zucI+w35qB6LH_LdMUDpbl_R7F3ilPLZruDp$IyC&f;5;2B*iR%`6cHctJQy&uAxiR zwPleBd`Q&60gt=;o45BS6Pt;g$f=LWY7TScBt9mV>gZAD5@qzKYC_j+_61Szc215w zNqI=7Qt+wBZi~SehRt&U`#9yM-O&TB6L8?`n=t+7l>1`MeZ8p;{nbTYpuBi(d)(d* z-w%4X+uLI)I~h;G7op7&0wu5d*Pihe`xtk}np^ePCV2?1=+nvmIFW}Lu+rL_LRQ#m zcIwuyjWq9Ji+lT<;mel(1|lD`)QgD-gEN;*ma#W2^_zq}<|B(+ZLvfOX#4@tVbb%U%7=_*sL<*S+ff?rH2ZxXVnI zv-^GO?X3~d(>_iJY_BS?6;8QaJ-Br?Tw@RQji2xy=PuiBOU7Z{4>`|Eb#(V9^v9>E zt+AeMu@r#}tIqXR1(hE#V~Ip>D@f^AXL`o6lYW)xZVY|_BaVKE{2#ws(p|OT2t*>R zc+`0f2KbDyi|AkWMc%Wn?5Dppj`cM+H4YRl!>!Qcg(-7#34{Rwkzk2SA#Q%sd^fbt kg!zoe?@gI@ZGoQVJPI||P&h~7VpwywzaR%VSO8J}e|BQAE&u=k diff --git a/src/build.onyx b/src/build.onyx index 2d09ee6..4227945 100644 --- a/src/build.onyx +++ b/src/build.onyx @@ -13,3 +13,4 @@ #load "src/simulation" #load "src/sand_toy" +#load "src/font/bitmap_font" diff --git a/src/font/bitmap_font.onyx b/src/font/bitmap_font.onyx new file mode 100644 index 0000000..c83548a --- /dev/null +++ b/src/font/bitmap_font.onyx @@ -0,0 +1,134 @@ +/* + +Bitmap Fonts + +Simple bitmap font renderer. Splits an image of all font characters a set of glyphs +that can be used to render individual characters / text. + +When creating a bitmap font, you need to provide the font texture, and the order of the +glyphs in the texture in a string. You can use non-ASCII characters in the string using +'\xAA' as a character. + +The font data provided is an RGBA byte array, with interlaced components. +In other words the data should look like: + + R G B A R G B A R G B A ... + +The top left (0-th) pixel is taken to be the separator color. It is used to determine the +outline of every glyph. Glyphs are read from the top left, left to right, top to bottom. +The separator color must be present on the entire boundaries of the glyph. + +*/ + + + + + +package bitmap_font +use package core + +Bitmap_Font :: struct { + font_texture : Bitmap_Font_Texture; + + em: f32; // Width of 'M' + + glyphs : map.Map(u32, Glyph); + + Glyph :: struct { + x0, y0, x1, y1: f32; + w, h: f32; + } + + get_glyph :: (use bmp: ^Bitmap_Font, char: u8) -> ^Glyph { + return map.get_ptr(^glyphs, ~~char); + } +} + +Bitmap_Font_Texture :: struct { + Components_Per_Pixel :: 4; // NOTE: RGBA only + + data : [] u8; + width, height : u32; + + // NOTE: Assumes pixels are laid out in RGBA format. + get_pixel :: (use texture: ^Bitmap_Font_Texture, x: u32, y: u32) -> u32 { + return (cast(^u32) data.data)[y * width + x]; + + // SPEED: All of these values could be read simultaneously by treating the data + // array as a slice of u32, and then not multiplying by Components_Per_Pixel. + // + // return (cast(u32) data[(y * width + x) * Components_Per_Pixel + 0] << 24) + // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 1] << 16) + // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 2] << 8) + // | (cast(u32) data[(y * width + x) * Components_Per_Pixel + 3] << 0); + } +} + + +// NOTE: Takes the raw RGBA font data. Therefore, font_data.count is expected to +// be a multiple of 4 in length, with interlaced red, green, blue and alpha components. +// The font data can be load from another source using this method, which is why it +// is preferred. +bitmap_font_create :: (bft: Bitmap_Font_Texture, charset: str) -> Bitmap_Font { + assert(bft.data.count <= bft.width * bft.height * Bitmap_Font_Texture.Components_Per_Pixel, "Bad font size."); + + bmp: Bitmap_Font; + bmp.font_texture = bft; + map.init(^bmp.glyphs, .{0,0,0,0,0,0}); + + success := bitmap_font_prepare_glyphs(^bmp, charset); + assert(success, "Failed to load glyphs out of font."); + + return bmp; +} + +bitmap_font_prepare_glyphs :: (use bmp: ^Bitmap_Font, charset: str) -> bool { + separator_color := font_texture->get_pixel(0, 0); + + g_x0, g_y0: u32; + g_x0, g_y0 = 0, 0; + + for char: charset { + if g_y0 >= font_texture.height do return false; + + // These will need to be converted to floating point when they are inserted into the glyph, + // but it is easier to think about them as actual pixel coordinates when parsing the glyphs. + x0, y0, x1, y1: u32; + x0, y0 = g_x0 + 1, g_y0 + 1; + x1, y1 = x0, y0; + + while font_texture->get_pixel(x1, y0) != separator_color do x1 += 1; + while font_texture->get_pixel(x0, y1) != separator_color do y1 += 1; + + map.put(^glyphs, ~~char, .{ + x0 = cast(f32) x0 / ~~font_texture.width, + y0 = cast(f32) y0 / ~~font_texture.height, + x1 = cast(f32) x1 / ~~font_texture.width, + y1 = cast(f32) y1 / ~~font_texture.height, + w = cast(f32) (x1 - x0) / ~~font_texture.width, + h = cast(f32) (y1 - y0) / ~~font_texture.height, + }); + + g_x0 = x1 + 1; + + // CLEANUP: This is gross because Onyx does not support short circuit boolean operators, + // and because g_x0 being greater than font_texture.width would potentially overflow in + // get_pixel, they need to be checked in two different steps instead of with '||'. + reset := g_x0 >= font_texture.width; + if !reset do reset = font_texture->get_pixel(g_x0, g_y0) != separator_color; + if reset { + g_x0 = 0; + g_y0 = y1 + 1; + } + } + + M_glyph := map.get_ptr(^glyphs, #char "M"); + if M_glyph != null { + em = M_glyph.w * ~~font_texture.width; + } else { + // ROBUSTNESS: If there is no 'M' in the character set, then just use 16. It will probably be very wrong. + em = 16; + } + + return true; +} diff --git a/src/res/font.data b/src/res/font.data new file mode 100644 index 0000000000000000000000000000000000000000..615eafbd72191e1cd88f15011f1f4289b42345c3 GIT binary patch literal 262144 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 literal 0 HcmV?d00001 diff --git a/src/res/font_2.data b/src/res/font_2.data new file mode 100644 index 0000000000000000000000000000000000000000..00ac0e0dda6cf92b58f39f31bcbdd7760fe19b45 GIT binary patch literal 262144 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 literal 0 HcmV?d00001 diff --git a/src/sand_toy.onyx b/src/sand_toy.onyx index aebc1c4..8fbeae4 100644 --- a/src/sand_toy.onyx +++ b/src/sand_toy.onyx @@ -3,6 +3,8 @@ use package core #private_file events :: package js_events #private_file gl :: package gl +#private_file bitmap_font :: package bitmap_font + BAR_HEIGHT :: 32.0f particle_board: ParticleBoard; @@ -12,6 +14,9 @@ world_height :: 400 world_texture : gl.GLTexture world_texture_data : [] u8 +font_texture : gl.GLTexture +font : bitmap_font.Bitmap_Font + window_width := 0 window_height := 0 @@ -38,9 +43,35 @@ init :: () { gfx.immediate_renderer_init(); + init_font(); + + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + particle_board = create_board(world_width, world_height); } +init_font :: () { + font_data := #file_contents "src/res/font_2.data"; + + bft := bitmap_font.Bitmap_Font_Texture.{ + data = font_data, + width = 256, + height = 256, + }; + + font = bitmap_font.bitmap_font_create(bft, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \xff:"); + + font_texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, font_texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE, font_data); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.bindTexture(gl.TEXTURE_2D, -1); +} + poll_events :: () { for event: events.consume() do switch event.kind { case .Resize { @@ -121,7 +152,18 @@ remove_particles :: (x: i32, y: i32, radius: i32) { } } -update :: () { +fps := 0; +fps_timer := 1.0f; +frames := 0 +update :: (dt: f32) { + fps_timer -= dt; + frames += 1; + if fps_timer <= 0 { + fps = frames; + frames = 0; + fps_timer = 1.0f; + } + if mouse_down { spawn_particles(~~mouse_x, ~~mouse_y, 20, selected_particle); } @@ -167,6 +209,10 @@ draw :: () { gl.bindTexture(gl.TEXTURE_2D, -1); + fps_buffer : [16] u8; + fps_string := conv.str_format("FPS: %i", ~~fps_buffer, fps); + draw_text(fps_string, 0, BAR_HEIGHT); + draw_selection_bar :: () { gfx.rect(.{ 0, 0 }, .{ ~~window_width, BAR_HEIGHT }, color=.{.2,.2,.2}); @@ -194,10 +240,46 @@ draw :: () { } } +draw_text :: (text: str, x: f32, y: f32, size := 32.0f, color := gfx.Color4.{1,1,1}) { + + gl.bindTexture(gl.TEXTURE_2D, font_texture); + gfx.set_texture(0); + + for char: text { + glyph := font->get_glyph(char); + + if glyph == null { + glyph = font->get_glyph(255); + assert(glyph != null, "NO NULL GLYPH"); + } + + gfx.textured_rect( + .{ x, y }, + .{ glyph.w * size * font.em, glyph.h * size * font.em }, + .{ glyph.x0, glyph.y0 }, + .{ glyph.x1 - glyph.x0, glyph.y1 - glyph.y0 }, + color = color); + + x += glyph.w * size * font.em; + } + + gfx.flush(); + gl.bindTexture(gl.TEXTURE_2D, -1); +} + + +last_time := 0; #export "loop" () { - poll_events(); + time_now :: () -> i32 #foreign "game" "time_now" --- + + if last_time == 0 do last_time = time_now(); - update(); + now := time_now(); + dt := cast(f32) (now - last_time) / 1000.0f; + last_time = now; + + poll_events(); + update(dt); draw(); } -- 2.25.1