From 7608e2967954104771b06612e4e6c21ca7811c9f Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 13 Apr 2024 15:12:17 +0100 Subject: client have multiple chunks and recycle them when they are not visible --- client/main.ha | 77 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 17 deletions(-) (limited to 'client') diff --git a/client/main.ha b/client/main.ha index 4e6fb9f..28d6694 100644 --- a/client/main.ha +++ b/client/main.ha @@ -10,7 +10,10 @@ use unix::poll; use packet_reader; def CHUNKSIZE = 512; -def NCHUNKS = 4; +def NCHUNKS = 16; + +def WIN_H: i32 = 480; +def WIN_W: i32 = 640; export fn main() void = { // sdl init stuff @@ -22,11 +25,9 @@ export fn main() void = { const wsurf = sdl2::SDL_GetWindowSurface(win)!; - // create 4 pictures. later we will have more pictures - // but for now there are just 4, and they are at fixed positions - const offs: [_]pos = [ - (0,0), (0,CHUNKSIZE), (CHUNKSIZE,0), (CHUNKSIZE,CHUNKSIZE), - ]; + let offs: []pos = []; + for (let x = -1; x < 3; x+=1) for (let y = -1; y < 3; y+=1) + append(offs, (x*CHUNKSIZE,y*CHUNKSIZE)); let pictures: []drawing::picture = alloc([],NCHUNKS); let picture_surfaces: []*sdl2::SDL_Surface = alloc([], NCHUNKS); @@ -36,7 +37,10 @@ export fn main() void = { append(picture_surfaces, surf); append(pictures, picture_from_surface(surf, offs[i])); }; - for (const p &.. pictures) drawing::clear_picture(p, 0xffffff); + for (const p &.. pictures) { + drawing::clear_picture(p, 0x00ff00); + drawing::outline_picture(p); + }; // connect to server @@ -64,6 +68,15 @@ export fn main() void = { for (!quit) { do_movement(&camera_pos); + // let nvis = 0; + // for (const pic &.. pictures) { + // if (is_picture_visible(camera_pos, pic)) { + // fmt::printfln(" {} {}",pic.world_pos.0, pic.world_pos.1)!; + // nvis += 1; + // }; + // }; + // fmt::printfln("{} visible",nvis)!; + let ev = sdl2::event { ... }; for (sdl2::SDL_PollEvent(&ev)! == 1) switch (ev.event_type) { case sdl2::SDL_EventType::QUIT => quit = true; @@ -101,26 +114,24 @@ export fn main() void = { drawing::perform(pictures, opc); case let packet: packet_reader::packet_sendchunk => fmt::println(packet.world_pos.0, packet.world_pos.1, len(packet.chunk_data))!; - let did_set = false; - for (let pic &.. pictures) { - if (pic.world_pos.0 == packet.world_pos.0 && pic.world_pos.1 == packet.world_pos.1) { - pic.d[..len(packet.chunk_data)] = packet.chunk_data[..]; - fmt::printfln("setting {},{}",pic.world_pos.0,pic.world_pos.1)!; - did_set = true; - break; - }; - }; - if (!did_set) fmt::println("did not set anything {},{} ....",packet.world_pos.0,packet.world_pos.1)!; + assert(packet.world_pos.0 % CHUNKSIZE == 0 + && packet.world_pos.1 % CHUNKSIZE == 0, "bad chunk world pos"); + const pic = find_picture_for_chunkdata(camera_pos, packet.world_pos, pictures); + pic.world_pos = packet.world_pos; + pic.d[..len(packet.chunk_data)] = packet.chunk_data[..]; }; }; }; + drawing::clear_picture(&picture_from_surface(wsurf,(9,9)), 0xff0000); + for (let i = 0z; i < len(pictures); i += 1) { const psurf = picture_surfaces[i]; const pic = &pictures[i]; render_picture(pic, psurf, wsurf, camera_pos); }; + sdl2::SDL_UpdateWindowSurface(win)!; n += 1; sdl2::SDL_Delay(1000/60); @@ -160,3 +171,35 @@ fn do_movement(pos: *pos) void = { pos.1 += dy * speed; }; +fn is_picture_visible(camera_pos: pos, pic: *drawing::picture) bool = { + const s_min: pos = camera_pos; + const s_max: pos = (camera_pos.0 + WIN_W, camera_pos.1 + WIN_H); + const p_min: pos = pic.world_pos; + const p_max: pos = (pic.world_pos.0 + pic.w: i32, pic.world_pos.1 + pic.h: i32); + return (s_min.0 <= p_max.0 && s_max.0 >= p_min.0) + && (s_min.1 <= p_max.1 && s_max.1 >= p_min.1); +}; + +fn find_picture_for_chunkdata(camera_pos: pos, world_pos: pos, pictures: []drawing::picture) *drawing::picture = { + // if we have one with that exact worldpos, return that + // otherwise find one that isn't visible + + let invisible: nullable *drawing::picture = null; + + for (const pic &.. pictures) { + if (pic.world_pos.0 == world_pos.0 && pic.world_pos.1 == world_pos.1) { + return pic; + }; + if (invisible == null && !is_picture_visible(camera_pos, pic)) invisible = pic; + }; + + match (invisible) { + case null => abort("couldn't find offscreen picture???"); + case let p: *drawing::picture => return p; + }; + +}; + + + + -- cgit v1.2.3