diff options
author | ubq323 <ubq323@ubq323.website> | 2024-03-22 23:52:56 +0000 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-03-22 23:52:56 +0000 |
commit | 6d766d6dd9177ececb14ebfe2ac68cc581eeeb44 (patch) | |
tree | 6b0b7fc17b59a0301fc4cbfa0fb2d6d4324aa2a1 | |
parent | d302628e8665572bc515c254a8d52909cc6db2ae (diff) |
movement, multiple surfaces (sort of)
-rw-r--r-- | drawing.ha | 41 | ||||
-rw-r--r-- | main.ha | 66 |
2 files changed, 65 insertions, 42 deletions
@@ -1,14 +1,13 @@ use sdl2; - // 2d position, x and y -type pos = (int, int); +type pos = (i32, i32); type drawing_state = struct { // is the mouse button held down? drawing: bool, pos: pos, - picture: picture, + picture: *picture, }; type picture = struct { @@ -16,6 +15,7 @@ type picture = struct { w: size, h: size, }; + // Returns array index of the pixel at position pos. // Bounds check happens in here instead of using a slice type, so // that it's easier to remove later. @@ -29,22 +29,42 @@ fn pidx(pic: *picture, pos: pos) size = { return xs + pic.w*ys; }; -fn pic_set(pic: *picture, pos: pos, val: u32) void = pic.d[pidx(pic,pos)] = val; + +fn pic_set(pic: *picture, pos: pos, val: u32) void = + pic.d[pidx(pic,pos)] = val; + fn picture_from_surface(surf: *sdl2::SDL_Surface) picture = picture { w = surf.w: size, h = surf.h: size, d = (surf.pixels as *opaque: *[*]u32), }; -fn min(a: int, b: int) int = if (a<b) a else b; -fn max(a: int, b: int) int = if (a<b) b else a; +fn clear_picture(pic: *picture, color: u32) void = { + for (let i = 0z; i < pic.w*pic.h; i+=1) pic.d[i] = color; +}; -fn circle(dstate: *drawing_state, c: pos, r: int, color: u32) void = { +fn outline_picture(pic: *picture) void = { + for (let x = 0; x:size < pic.w; x+=1) { + pic_set(pic, (x, 0), 0); + pic_set(pic, (x, pic.h:int-1), 0); + }; + for (let y = 0; y:size < pic.h; y+=1) { + pic_set(pic, (0, y), 0); + pic_set(pic, (pic.w:int-1, y), 0); + }; +}; + +fn min(a: i32, b: i32) i32 = if (a<b) a else b; +fn max(a: i32, b: i32) i32 = if (a<b) b else a; + +// Draws a circle onto the dstate's picture, at given position radius color +// Clips at the boundaries of the picture to avoid overflow. +fn circle(dstate: *drawing_state, c: pos, r: i32, color: u32) void = { const (cx,cy) = c; const ymin = max(0, cy-r); - const ymax = min(dstate.picture.h:int-1, cy+r); + const ymax = min(dstate.picture.h:i32-1, cy+r); const xmin = max(0, cx-r); - const xmax = min(dstate.picture.w:int-1, cx+r); + const xmax = min(dstate.picture.w:i32-1, cx+r); const r2 = r*r + r; @@ -53,11 +73,10 @@ fn circle(dstate: *drawing_state, c: pos, r: int, color: u32) void = { for (let x = xmin; x<=xmax; x+=1) { const xd = x-cx; if (yd*yd + xd*xd <= r2) { - pic_set(&dstate.picture, (x,y), color); + pic_set(dstate.picture, (x,y), color); }; }; }; - }; fn do_drawing(dstate: *drawing_state) void = { @@ -1,37 +1,32 @@ use fmt; use sdl2; +use math; export fn main() void = { sdl2::SDL_Init(sdl2::SDL_INIT_VIDEO)!; defer sdl2::SDL_Quit(); - fmt::println(size(i32), size(i64), size(int), size(size))!; - - const win = sdl2::SDL_CreateWindow("hi", sdl2::SDL_WINDOWPOS_UNDEFINED, sdl2::SDL_WINDOWPOS_UNDEFINED, 640, 480, sdl2::SDL_WindowFlags::NONE)!; defer sdl2::SDL_DestroyWindow(win); const wsurf = sdl2::SDL_GetWindowSurface(win)!; - const format = wsurf.format; - assert(format.bytesperpixel == 4, "can only work with u32 pixels"); - fmt::printfln("got format {}. bytes per pixel {}. r{:x} g{:x} b{:x} a{:x}", - format.format, format.bytesperpixel, format.rmask, format.gmask, format.bmask, format.amask)!; - fmt::printfln("red: {:x} green {:x} blue {:x}", - sdl2::SDL_MapRGB(format, 255, 0, 0), - sdl2::SDL_MapRGB(format, 0, 255, 0), - sdl2::SDL_MapRGB(format, 0, 0, 255))!; - fmt::println(wsurf.w * wsurf.h)!; - fmt::println(sdl2::SDL_GetPixelFormatName(format.format))!; + + const xsurf = sdl2::SDL_CreateRGBSurface(0, + 512, 512, 32, 0xff0000, 0xff00, 0xff, 0)!; let dstate = drawing_state { drawing = false, pos = (0,0), - picture = picture_from_surface(wsurf) + picture = &picture_from_surface(xsurf) }; + let camera_pos: pos = (25, 50); + + clear_picture(dstate.picture, 0xffffff); + outline_picture(dstate.picture); let quit = false; - let n = 0z; + let n = 0; let lasttime = sdl2::SDL_GetTicks(); for (!quit) { let ev = sdl2::event { ... }; @@ -52,28 +47,37 @@ export fn main() void = { case => void; }; - do_drawing(&dstate); - - - // if (drawing) { - // circle(pic, mousex, mousey, 5, 0x00ffff); - // }; + movement(&camera_pos); - // circle(pic, 100, 100, n:int, 0xff0000); + do_drawing(&dstate); + + sdl2::SDL_BlitSurface(xsurf, null, wsurf, &sdl2::SDL_Rect { + x = camera_pos.0, y = camera_pos.1, ... + })!; sdl2::SDL_UpdateWindowSurface(win)!; n += 1; sdl2::SDL_Delay(1000/60); - - // if (n % 100 == 0) { - // const thistime = sdl2::SDL_GetTicks(); - // const dt = (thistime - lasttime): f64; - // lasttime = thistime; - // const dt = dt / 100.0; - // const fps = 1000.0/dt; - // fmt::printfln("fps: {}",fps)!; - // }; }; }; +def SPEED = 17; +def DIAG_SPEED = 12; // thereabouts + +fn movement(pos: *pos) void = { + const kb = sdl2::SDL_GetKeyboardState(); + let dx = 0; + let dy = 0; + if (kb[sdl2::SDL_Scancode::W]) dy -= 1; + if (kb[sdl2::SDL_Scancode::S]) dy += 1; + if (kb[sdl2::SDL_Scancode::A]) dx -= 1; + if (kb[sdl2::SDL_Scancode::D]) dx += 1; + + let speed = SPEED; + if (dx != 0 && dy != 0) speed = DIAG_SPEED; + + pos.0 += dx * speed; + pos.1 += dy * speed; +}; + |