diff --git a/client.c3 b/client.c3 index 0be1565..2551ed5 100644 --- a/client.c3 +++ b/client.c3 @@ -272,11 +272,11 @@ fn Vector2 ray_step(Vector2 p1, Vector2 p2) { return p3; } -fn Vector2 cast_ray(bool *scene, int scene_width, int scene_height, Vector2 p1, Vector2 p2) { +fn Vector2 cast_ray(Scene *scene, Vector2 p1, Vector2 p2) { Vector2 start = p1; while (start.distance(p1) < FAR_CLIPPING_PLANE) { Vector2 c = hitting_cell(p1, p2); - if (common::scene_get_tile(scene, scene_width, scene_height, c)) break; + if (common::scene_get_tile(scene, c)) break; Vector2 p3 = ray_step(p1, p2); p1 = p2; p2 = p3; @@ -287,17 +287,17 @@ fn Vector2 cast_ray(bool *scene, int scene_width, int scene_height, Vector2 p1, fn void render_walls(Color *display, int display_width, int display_height, float *zbuffer, Color *wall, int wall_width, int wall_height, float position_x, float position_y, float direction, - bool *scene, int scene_width, int scene_height) @extern("render_walls") @wasm { + Scene *scene) @extern("render_walls") @wasm { Camera camera = { .position = {position_x, position_y}, .direction = direction }; camera.update(); Vector2 d = from_polar(direction, 1.0f); for (int x = 0; x < display_width; ++x) { - Vector2 p = cast_ray(scene, scene_width, scene_height, camera.position, camera.fovLeft.lerp(camera.fovRight, (float)x/display_width)); + Vector2 p = cast_ray(scene, camera.position, camera.fovLeft.lerp(camera.fovRight, (float)x/display_width)); Vector2 c = hitting_cell(camera.position, p); Vector2 v = p - camera.position; zbuffer[x] = v.dot(d); - if (common::scene_get_tile(scene, scene_width, scene_height, c)) { + if (common::scene_get_tile(scene, c)) { render_column_of_wall(display, display_width, display_height, zbuffer, wall, wall_width, wall_height, x, p.x, p.y, c.x, c.y); } } @@ -308,7 +308,7 @@ fn void render_walls(Color *display, int display_width, int display_height, floa fn void render_minimap(Color *display, int display_width, int display_height, float camera_position_x, float camera_position_y, float camera_direction, float player_position_x, float player_position_y, - bool *scene, int scene_width, int scene_height, + Scene *scene, SpritePool *sprite_pool) @extern("render_minimap") @wasm { // ctx.save(); @@ -499,7 +499,7 @@ fn void emit_particle(float source_x, float source_y, float source_z, ParticlePo fn void update_particles(Color *image_pixels, int image_width, int image_height, SpritePool *sprite_pool, float deltaTime, - bool *scene, int scene_width, int scene_height, + Scene *scene, ParticlePool *particle_pool) @extern("update_particles") @wasm { foreach (&particle: particle_pool.items) { if (particle.lifetime > 0) { @@ -507,7 +507,7 @@ fn void update_particles(Color *image_pixels, int image_width, int image_height, particle.velocity_z -= common::BOMB_GRAVITY*deltaTime; Vector2 new_position = particle.position + particle.velocity*deltaTime; - if (common::scene_get_tile(scene, scene_width, scene_height, new_position)) { + if (common::scene_get_tile(scene, new_position)) { float dx = math::abs(math::floor(particle.position.x) - math::floor(new_position.x)); float dy = math::abs(math::floor(particle.position.y) - math::floor(new_position.y)); @@ -640,12 +640,12 @@ fn void explode_bomb(float bomb_position_x, float bomb_position_y, float bomb_po } } -fn void update_bombs_on_client_side(SpritePool *sprite_pool, ParticlePool *particle_pool, Color *bomb_image_pixels, int bomb_image_width, int bomb_image_height, bool *scene, int scene_width, int scene_height, float player_position_x, float player_position_y, float delta_time, Bombs *bombs) @extern("update_bombs_on_client_side") @wasm { +fn void update_bombs_on_client_side(SpritePool *sprite_pool, ParticlePool *particle_pool, Color *bomb_image_pixels, int bomb_image_width, int bomb_image_height, Scene *scene, float player_position_x, float player_position_y, float delta_time, Bombs *bombs) @extern("update_bombs_on_client_side") @wasm { foreach (&bomb: *bombs) { if (bomb.lifetime > 0) { push_sprite(sprite_pool, bomb_image_pixels, bomb_image_width, bomb_image_height, bomb.position.x, bomb.position.y, bomb.position_z, common::BOMB_SCALE, 0, 0, bomb_image_width, bomb_image_height); - if (common::update_bomb(bomb, scene, scene_width, scene_height, delta_time)) { + if (common::update_bomb(bomb, scene, delta_time)) { play_sound(BOMB_RICOCHET, player_position_x, player_position_y, bomb.position.x, bomb.position.y); } diff --git a/client.mjs b/client.mjs index 69d1778..1c8f261 100644 --- a/client.mjs +++ b/client.mjs @@ -393,13 +393,13 @@ function renderGame(display, deltaTime, time, game) { game.wasmClient.reset_sprite_pool(game.spritePoolPtr); game.players.forEach((player) => { if (player !== game.me) - updatePlayer(game.wasmClient, player, game.level.scene, deltaTime); + updatePlayer(game.wasmClient, player, game.level.scenePtr, deltaTime); }); - updatePlayer(game.wasmClient, game.me, game.level.scene, deltaTime); + updatePlayer(game.wasmClient, game.me, game.level.scenePtr, deltaTime); updateCamera(game.me, game.camera); updateItems(game.wasmClient, game.ws, game.spritePoolPtr, time, game.me, game.level.itemsPtr, game.assets); - game.wasmClient.update_bombs_on_client_side(game.spritePoolPtr, game.particlesPtr, game.assets.bombImage.ptr, game.assets.bombImage.width, game.assets.bombImage.height, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height, game.me.position.x, game.me.position.y, deltaTime, game.level.bombsPtr); - game.wasmClient.update_particles(game.assets.particleImage.ptr, game.assets.particleImage.width, game.assets.particleImage.height, game.spritePoolPtr, deltaTime, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height, game.particlesPtr); + game.wasmClient.update_bombs_on_client_side(game.spritePoolPtr, game.particlesPtr, game.assets.bombImage.ptr, game.assets.bombImage.width, game.assets.bombImage.height, game.level.scenePtr, game.me.position.x, game.me.position.y, deltaTime, game.level.bombsPtr); + game.wasmClient.update_particles(game.assets.particleImage.ptr, game.assets.particleImage.width, game.assets.particleImage.height, game.spritePoolPtr, deltaTime, game.level.scenePtr, game.particlesPtr); game.players.forEach((player) => { if (player !== game.me) { const index = spriteAngleIndex(game.camera.position, player); @@ -407,12 +407,12 @@ function renderGame(display, deltaTime, time, game) { } }); game.wasmClient.render_floor_and_ceiling(display.backImage.ptr, display.backImage.width, display.backImage.height, game.camera.position.x, game.camera.position.y, game.camera.direction); - game.wasmClient.render_walls(display.backImage.ptr, display.backImage.width, display.backImage.height, display.zBufferPtr, game.assets.wallImage.ptr, game.assets.wallImage.width, game.assets.wallImage.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height); + game.wasmClient.render_walls(display.backImage.ptr, display.backImage.width, display.backImage.height, display.zBufferPtr, game.assets.wallImage.ptr, game.assets.wallImage.width, game.assets.wallImage.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.level.scenePtr); game.wasmClient.cull_and_sort_sprites(game.camera.position.x, game.camera.position.y, game.camera.direction, game.spritePoolPtr); game.wasmClient.render_sprites(display.backImage.ptr, display.backImage.width, display.backImage.height, display.zBufferPtr, game.spritePoolPtr); displaySwapBackImageData(display, game.wasmClient); if (MINIMAP) - game.wasmClient.render_minimap(display.minimap.ptr, display.minimap.width, display.minimap.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.me.position.x, game.me.position.y, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height, game.spritePoolPtr); + game.wasmClient.render_minimap(display.minimap.ptr, display.minimap.width, display.minimap.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.me.position.x, game.me.position.y, game.level.scenePtr, game.spritePoolPtr); renderDebugInfo(display.ctx, deltaTime, game); } (async () => { diff --git a/client.mts b/client.mts index ea593c4..be46c88 100644 --- a/client.mts +++ b/client.mts @@ -85,14 +85,14 @@ interface WasmClient extends common.WasmCommon { reset_sprite_pool: (sprite_pool: number) => void, render_floor_and_ceiling: (pixels: number, pixels_width: number, pixels_height: number, position_x: number, position_y: number, direction: number) => void, render_column_of_wall: (display: number, display_width: number, display_height: number, zbuffer: number, cell: number, cell_width: number, cell_height: number, x: number, px: number, py: number, cx: number, cy: number) => void, - render_walls: (display: number, display_width: number, display_height: number, zbuffer: number, wall: number, wall_width: number, wall_height: number, position_x: number, position_y: number, direction: number, scene: number, scene_width: number, scene_height: number) => void; - render_minimap: (display: number, display_width: number, display_height: number, camera_position_x: number, camera_position_y: number, camera_direction: number, player_position_x: number, player_position_y: number, scene: number, scene_width: number, scene_height: number, sprite_pool: number) => void; + render_walls: (display: number, display_width: number, display_height: number, zbuffer: number, wall: number, wall_width: number, wall_height: number, position_x: number, position_y: number, direction: number, scene: number) => void; + render_minimap: (display: number, display_width: number, display_height: number, camera_position_x: number, camera_position_y: number, camera_direction: number, player_position_x: number, player_position_y: number, scene: number, sprite_pool: number) => void; cull_and_sort_sprites: (camera_position_x: number, camera_position_y: number, camera_direction: number, sprite_pool: number) => void; push_sprite: (sprite_pool: number, image_pixels: number, image_width: number, image_height: number, x: number, y: number, z: number, scale: number, crop_position_x: number, crop_position_y: number, crop_size_x: number, crop_size_y: number) => void; render_sprites: (display: number, display_width: number, display_height: number, zbuffer: number, sprite_pool: number) => void, allocate_particle_pool: () => number, emit_particle: (source_x: number, source_y: number, source_z: number, particle_pool: number) => void, - update_particles: (image_pixels: number, image_width: number, image_height: number, sprite_pool: number, deltaTime: number, scene: number, scene_width: number, scene_height: number, particle_pool: number) => void + update_particles: (image_pixels: number, image_width: number, image_height: number, sprite_pool: number, deltaTime: number, scene: number, particle_pool: number) => void kill_all_items: (items: number) => void, verify_items_collected_batch_message: (message: number) => boolean, apply_items_collected_batch_message_to_level_items: (message: number, items: number, player_position_x: number, player_position_y: number) => boolean, @@ -104,7 +104,7 @@ interface WasmClient extends common.WasmCommon { apply_bombs_spawned_batch_message_to_level_items: (message: number, bombs: number) => boolean, verify_bombs_exploded_batch_message: (message: number) => boolean, apply_bombs_exploded_batch_message_to_level_items: (message: number, bombs: number, player_position_x: number, player_position_y: number, particle_pool: number) => boolean, - update_bombs_on_client_side: (sprite_pool: number, particle_pool: number, bomb_image_pixels: number, bomb_image_width: number, bomb_image_height: number, scene: number, scene_width: number, scene_height: number, player_position_x: number, player_position_y: number, delta_time: number, bombs: number) => void + update_bombs_on_client_side: (sprite_pool: number, particle_pool: number, bomb_image_pixels: number, bomb_image_width: number, bomb_image_height: number, scene: number, player_position_x: number, player_position_y: number, delta_time: number, bombs: number) => void } function createDisplay(wasmClient: WasmClient, backImageWidth: number, backImageHeight: number): Display { @@ -286,14 +286,14 @@ async function instantiateWasmClient(url: string): Promise { reset_sprite_pool: wasm.instance.exports.reset_sprite_pool as (sprite_pool: number) => void, render_floor_and_ceiling: wasm.instance.exports.render_floor_and_ceiling as (position_x: number, position_y: number, direction: number) => void, render_column_of_wall: wasm.instance.exports.render_column_of_wall as (display: number, display_width: number, display_height: number, zbuffer: number, cell: number, cell_width: number, cell_height: number, x: number, px: number, py: number, cx: number, cy: number) => void, - render_walls: wasm.instance.exports.render_walls as (display: number, display_width: number, display_height: number, zbuffer: number, wall: number, wall_width: number, wall_height: number, position_x: number, position_y: number, direction: number, scene: number, scene_width: number, scene_height: number) => void, - render_minimap: wasm.instance.exports.render_minimap as (display: number, display_width: number, display_height: number, camera_position_x: number, camera_position_y: number, camera_direction: number, player_position_x: number, player_position_y: number, scene: number, scene_width: number, scene_height: number, sprite_pool: number) => void, + render_walls: wasm.instance.exports.render_walls as (display: number, display_width: number, display_height: number, zbuffer: number, wall: number, wall_width: number, wall_height: number, position_x: number, position_y: number, direction: number, scene: number) => void, + render_minimap: wasm.instance.exports.render_minimap as (display: number, display_width: number, display_height: number, camera_position_x: number, camera_position_y: number, camera_direction: number, player_position_x: number, player_position_y: number, scene: number, sprite_pool: number) => void, cull_and_sort_sprites: wasm.instance.exports.cull_and_sort_sprites as (camera_position_x: number, camera_position_y: number, camera_direction: number, sprite_pool: number) => void, push_sprite: wasm.instance.exports.push_sprite as (sprite_pool: number, image_pixels: number, image_width: number, image_height: number, x: number, y: number, z: number, scale: number, crop_position_x: number, crop_position_y: number, crop_size_x: number, crop_size_y: number) => void, render_sprites: wasm.instance.exports.render_sprites as (display: number, display_width: number, display_height: number, zbuffer: number, sprite_pool: number) => void, allocate_particle_pool: wasm.instance.exports.allocate_particle_pool as () => number, emit_particle: wasm.instance.exports.emit_particle as (source_x: number, source_y: number, source_z: number, particle_pool: number) => void, - update_particles: wasm.instance.exports.update_particles as (image_pixels: number, image_width: number, image_height: number, sprite_pool: number, deltaTime: number, scene: number, scene_width: number, scene_height: number, particle_pool: number) => void, + update_particles: wasm.instance.exports.update_particles as (image_pixels: number, image_width: number, image_height: number, sprite_pool: number, deltaTime: number, scene: number, particle_pool: number) => void, kill_all_items: wasm.instance.exports.kill_all_items as (items: number) => void, verify_items_collected_batch_message: wasm.instance.exports.verify_items_collected_batch_message as (message: number) => boolean, apply_items_collected_batch_message_to_level_items: wasm.instance.exports.apply_items_collected_batch_message_to_level_items as (message: number, items: number, player_position_x: number, player_position_y: number) => boolean, @@ -305,7 +305,7 @@ async function instantiateWasmClient(url: string): Promise { apply_bombs_spawned_batch_message_to_level_items: wasm.instance.exports.apply_bombs_spawned_batch_message_to_level_items as (message: number, bombs: number) => boolean, verify_bombs_exploded_batch_message: wasm.instance.exports.verify_bombs_exploded_batch_message as (message: number) => boolean, apply_bombs_exploded_batch_message_to_level_items: wasm.instance.exports.apply_bombs_exploded_batch_message_to_level_items as (message: number, bombs: number, player_position_x: number, player_position_y: number, particle_pool: number) => boolean, - update_bombs_on_client_side: wasm.instance.exports.update_bombs_on_client_side as (sprite_pool: number, particle_pool: number, bomb_image_pixels: number, bomb_image_width: number, bomb_image_height: number, scene: number, scene_width: number, scene_height: number, player_position_x: number, player_position_y: number, delta_time: number, bombs: number) => void, + update_bombs_on_client_side: wasm.instance.exports.update_bombs_on_client_side as (sprite_pool: number, particle_pool: number, bomb_image_pixels: number, bomb_image_width: number, bomb_image_height: number, scene: number, player_position_x: number, player_position_y: number, delta_time: number, bombs: number) => void, }; } @@ -507,13 +507,13 @@ function renderGame(display: Display, deltaTime: number, time: number, game: Gam game.wasmClient.reset_sprite_pool(game.spritePoolPtr); game.players.forEach((player) => { - if (player !== game.me) updatePlayer(game.wasmClient, player, game.level.scene, deltaTime) + if (player !== game.me) updatePlayer(game.wasmClient, player, game.level.scenePtr, deltaTime) }); - updatePlayer(game.wasmClient, game.me, game.level.scene, deltaTime); + updatePlayer(game.wasmClient, game.me, game.level.scenePtr, deltaTime); updateCamera(game.me, game.camera); updateItems(game.wasmClient, game.ws, game.spritePoolPtr, time, game.me, game.level.itemsPtr, game.assets); - game.wasmClient.update_bombs_on_client_side(game.spritePoolPtr, game.particlesPtr, game.assets.bombImage.ptr, game.assets.bombImage.width, game.assets.bombImage.height, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height, game.me.position.x, game.me.position.y, deltaTime, game.level.bombsPtr); - game.wasmClient.update_particles(game.assets.particleImage.ptr, game.assets.particleImage.width, game.assets.particleImage.height, game.spritePoolPtr, deltaTime, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height, game.particlesPtr); + game.wasmClient.update_bombs_on_client_side(game.spritePoolPtr, game.particlesPtr, game.assets.bombImage.ptr, game.assets.bombImage.width, game.assets.bombImage.height, game.level.scenePtr, game.me.position.x, game.me.position.y, deltaTime, game.level.bombsPtr); + game.wasmClient.update_particles(game.assets.particleImage.ptr, game.assets.particleImage.width, game.assets.particleImage.height, game.spritePoolPtr, deltaTime, game.level.scenePtr, game.particlesPtr); game.players.forEach((player) => { if (player !== game.me) { @@ -523,12 +523,12 @@ function renderGame(display: Display, deltaTime: number, time: number, game: Gam }) game.wasmClient.render_floor_and_ceiling(display.backImage.ptr, display.backImage.width, display.backImage.height, game.camera.position.x, game.camera.position.y, game.camera.direction); - game.wasmClient.render_walls(display.backImage.ptr, display.backImage.width, display.backImage.height, display.zBufferPtr, game.assets.wallImage.ptr, game.assets.wallImage.width, game.assets.wallImage.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height); + game.wasmClient.render_walls(display.backImage.ptr, display.backImage.width, display.backImage.height, display.zBufferPtr, game.assets.wallImage.ptr, game.assets.wallImage.width, game.assets.wallImage.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.level.scenePtr); game.wasmClient.cull_and_sort_sprites(game.camera.position.x, game.camera.position.y, game.camera.direction, game.spritePoolPtr) game.wasmClient.render_sprites(display.backImage.ptr, display.backImage.width, display.backImage.height, display.zBufferPtr, game.spritePoolPtr) displaySwapBackImageData(display, game.wasmClient); - if (MINIMAP) game.wasmClient.render_minimap(display.minimap.ptr, display.minimap.width, display.minimap.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.me.position.x, game.me.position.y, game.level.scene.wallsPtr, game.level.scene.width, game.level.scene.height, game.spritePoolPtr); + if (MINIMAP) game.wasmClient.render_minimap(display.minimap.ptr, display.minimap.width, display.minimap.height, game.camera.position.x, game.camera.position.y, game.camera.direction, game.me.position.x, game.me.position.y, game.level.scenePtr, game.spritePoolPtr); renderDebugInfo(display.ctx, deltaTime, game); } diff --git a/client.wasm b/client.wasm index 51106ea..b9acff3 100755 Binary files a/client.wasm and b/client.wasm differ diff --git a/common.c3 b/common.c3 index fb4c2f1..be45b31 100644 --- a/common.c3 +++ b/common.c3 @@ -41,21 +41,56 @@ struct Message @packed { /// Scene ////////////////////////////// -fn bool scene_get_tile(bool *scene, int scene_width, int scene_height, Vector2 p) { +struct Scene { + usz width; + usz height; + bool[*] walls; +} + +fn Scene *allocate_scene(usz width, usz height) { + Scene *scene = mem::calloc(Scene.sizeof + bool.sizeof*width*height); + scene.width = width; + scene.height = height; + for (usz i = 0; i < width*height; ++i) scene.walls[i] = false; + return scene; +} + +fn Scene *allocate_default_scene() @extern("allocate_default_scene") @wasm { + bool[*][*] default_walls = { + { false, false, true, true, true, false, false}, + { false, false, false, false, false, true, false}, + { true, false, false, false, false, true, false}, + { true, false, false, false, false, true, false}, + { true, false, false, false, false, false, false}, + { false, true, true, true, false, false, false}, + { false, false, false, false, false, false, false}, + }; + usz width = default_walls[0].len; + usz height = default_walls.len; + Scene *scene = allocate_scene(width, height); + for (usz y = 0; y < height; ++y) { + for (usz x = 0; x < width; ++x) { + scene.walls[y*width + x] = default_walls[y][x]; + } + } + return scene; +} + +fn bool scene_get_tile(Scene *scene, Vector2 p) { int x = (int)math::floor(p.x); int y = (int)math::floor(p.y); - if (!(0 <= x && x < scene_width && 0 <= y && y < scene_height)) return false; - return scene[y*scene_width + x]; + if (!(0 <= x && x < scene.width && 0 <= y && y < scene.height)) return false; + return scene.walls[y*scene.width + x]; } -fn bool scene_can_rectangle_fit_here(bool *scene, int scene_width, int scene_height, float px, float py, float sx, float sy) @extern("scene_can_rectangle_fit_here") @wasm { +fn bool scene_can_rectangle_fit_here(Scene *scene, float px, float py, float sx, float sy) @extern("scene_can_rectangle_fit_here") @wasm { int x1 = (int)math::floor(px - sx*0.5f); int x2 = (int)math::floor(px + sx*0.5f); int y1 = (int)math::floor(py - sy*0.5f); int y2 = (int)math::floor(py + sy*0.5f); for (int x = x1; x <= x2; ++x) { for (int y = y1; y <= y2; ++y) { - if (scene_get_tile(scene, scene_width, scene_height, {x, y})) { + if (scene_get_tile(scene, {x, y})) { return false; } } @@ -63,12 +98,6 @@ fn bool scene_can_rectangle_fit_here(bool *scene, int scene_width, int scene_hei return true; } -fn bool *allocate_scene(usz width, usz height) @extern("allocate_scene") @wasm { - bool[] scene = mem::new_array(bool, width*height); - foreach (&c: scene) *c = false; - return &scene[0]; -} - /// Items ////////////////////////////// enum ItemKind: char { @@ -205,14 +234,14 @@ fn int throw_bomb(float player_position_x, float player_position_y, float player return -1; } -fn bool update_bomb(Bomb *bomb, bool* scene, int scene_width, int scene_height, float delta_time) { +fn bool update_bomb(Bomb *bomb, Scene* scene, float delta_time) { bool collided = false; bomb.lifetime -= delta_time; bomb.velocity_z -= BOMB_GRAVITY*delta_time; float nx = bomb.position.x + bomb.velocity.x*delta_time; float ny = bomb.position.y + bomb.velocity.y*delta_time; - if (scene_get_tile(scene, scene_width, scene_height, {nx, ny})) { + if (scene_get_tile(scene, {nx, ny})) { float dx = math::abs(math::floor(bomb.position.x) - math::floor(nx)); float dy = math::abs(math::floor(bomb.position.y) - math::floor(ny)); diff --git a/common.mjs b/common.mjs index 9fecc65..0d977af 100644 --- a/common.mjs +++ b/common.mjs @@ -251,48 +251,22 @@ export function makeWasmCommon(wasm) { wasm, memory: wasm.instance.exports.memory, _initialize: wasm.instance.exports._initialize, - allocate_scene: wasm.instance.exports.allocate_scene, allocate_items: wasm.instance.exports.allocate_items, reset_temp_mark: wasm.instance.exports.reset_temp_mark, allocate_temporary_buffer: wasm.instance.exports.allocate_temporary_buffer, allocate_bombs: wasm.instance.exports.allocate_bombs, throw_bomb: wasm.instance.exports.throw_bomb, scene_can_rectangle_fit_here: wasm.instance.exports.scene_can_rectangle_fit_here, + allocate_default_scene: wasm.instance.exports.allocate_default_scene, }; } -export function createScene(walls, wasmCommon) { - const scene = { - height: walls.length, - width: Number.MIN_VALUE, - wallsPtr: 0, - }; - for (let row of walls) { - scene.width = Math.max(scene.width, row.length); - } - scene.wallsPtr = wasmCommon.allocate_scene(scene.width, scene.height); - const wallsData = new Uint8ClampedArray(wasmCommon.memory.buffer, scene.wallsPtr, scene.width * scene.height); - for (let y = 0; y < walls.length; ++y) { - for (let x = 0; x < walls[y].length; ++x) { - wallsData[y * scene.width + x] = Number(walls[y][x]); - } - } - return scene; -} export function createLevel(wasmCommon) { - const scene = createScene([ - [false, false, true, true, true, false, false], - [false, false, false, false, false, true, false], - [true, false, false, false, false, true, false], - [true, false, false, false, false, true, false], - [true], - [false, true, true, true, false, false, false], - [false, false, false, false, false, false, false], - ], wasmCommon); + const scenePtr = wasmCommon.allocate_default_scene(); const itemsPtr = wasmCommon.allocate_items(); const bombsPtr = wasmCommon.allocate_bombs(); - return { scene, itemsPtr, bombsPtr }; + return { scenePtr, itemsPtr, bombsPtr }; } -export function updatePlayer(wasmCommon, player, scene, deltaTime) { +export function updatePlayer(wasmCommon, player, scenePtr, deltaTime) { const controlVelocity = new Vector2(); let angularVelocity = 0.0; if ((player.moving >> Moving.MovingForward) & 1) { @@ -309,11 +283,11 @@ export function updatePlayer(wasmCommon, player, scene, deltaTime) { } player.direction = player.direction + angularVelocity * deltaTime; const nx = player.position.x + controlVelocity.x * deltaTime; - if (wasmCommon.scene_can_rectangle_fit_here(scene.wallsPtr, scene.width, scene.height, nx, player.position.y, PLAYER_SIZE, PLAYER_SIZE)) { + if (wasmCommon.scene_can_rectangle_fit_here(scenePtr, nx, player.position.y, PLAYER_SIZE, PLAYER_SIZE)) { player.position.x = nx; } const ny = player.position.y + controlVelocity.y * deltaTime; - if (wasmCommon.scene_can_rectangle_fit_here(scene.wallsPtr, scene.width, scene.height, player.position.x, ny, PLAYER_SIZE, PLAYER_SIZE)) { + if (wasmCommon.scene_can_rectangle_fit_here(scenePtr, player.position.x, ny, PLAYER_SIZE, PLAYER_SIZE)) { player.position.y = ny; } } diff --git a/common.mts b/common.mts index 27c3e64..4fd6424 100644 --- a/common.mts +++ b/common.mts @@ -284,23 +284,17 @@ export function clamp(value: number, min: number, max: number) { return Math.min(Math.max(value, min), max); } -export interface Scene { - wallsPtr: number; - width: number; - height: number; -} - export interface WasmCommon { wasm: WebAssembly.WebAssemblyInstantiatedSource, memory: WebAssembly.Memory, _initialize: () => void, - allocate_scene: (width: number, height: number) => number, allocate_items: () => number, reset_temp_mark: () => void, allocate_temporary_buffer: (size: number) => number, allocate_bombs: () => number, throw_bomb: (player_position_x: number, player_position_y: number, player_direction: number, bombs: number) => number, - scene_can_rectangle_fit_here: (scene: number, scene_width: number, scene_height: number, px: number, py: number, sx: number, sy: number) => boolean, + scene_can_rectangle_fit_here: (scene: number, px: number, py: number, sx: number, sy: number) => boolean, + allocate_default_scene: () => number, } export function makeWasmCommon(wasm: WebAssembly.WebAssemblyInstantiatedSource): WasmCommon { @@ -308,60 +302,32 @@ export function makeWasmCommon(wasm: WebAssembly.WebAssemblyInstantiatedSource): wasm, memory: wasm.instance.exports.memory as WebAssembly.Memory, _initialize: wasm.instance.exports._initialize as () => void, - allocate_scene: wasm.instance.exports.allocate_scene as (width: number, height: number) => number, allocate_items: wasm.instance.exports.allocate_items as () => number, reset_temp_mark: wasm.instance.exports.reset_temp_mark as () => void, allocate_temporary_buffer: wasm.instance.exports.allocate_temporary_buffer as (size: number) => number, allocate_bombs: wasm.instance.exports.allocate_bombs as () => number, throw_bomb: wasm.instance.exports.throw_bomb as (player_position_x: number, player_position_y: number, player_direction: number, bombs: number) => number, - scene_can_rectangle_fit_here: wasm.instance.exports.scene_can_rectangle_fit_here as (scene: number, scene_width: number, scene_height: number, px: number, py: number, sx: number, sy: number) => boolean, + scene_can_rectangle_fit_here: wasm.instance.exports.scene_can_rectangle_fit_here as (scenePtr: number, px: number, py: number, sx: number, sy: number) => boolean, + allocate_default_scene: wasm.instance.exports.allocate_default_scene as () => number, } } -export function createScene(walls: Array>, wasmCommon: WasmCommon): Scene { - const scene: Scene = { - height: walls.length, - width: Number.MIN_VALUE, - wallsPtr: 0, - }; - for (let row of walls) { - scene.width = Math.max(scene.width, row.length); - } - scene.wallsPtr = wasmCommon.allocate_scene(scene.width, scene.height); - const wallsData = new Uint8ClampedArray(wasmCommon.memory.buffer, scene.wallsPtr, scene.width*scene.height); - for (let y = 0; y < walls.length; ++y) { - for (let x = 0; x < walls[y].length; ++x) { - wallsData[y*scene.width + x] = Number(walls[y][x]); - } - } - return scene; -} - // NOTE: This is basically the part of the state of the Game that is shared // between Client and Server and constantly synced over the network. export interface Level { - scene: Scene, + scenePtr: number, itemsPtr: number, bombsPtr: number, } export function createLevel(wasmCommon: WasmCommon): Level { - const scene = createScene([ - [ false, false, true, true, true, false, false], - [ false, false, false, false, false, true, false], - [ true, false, false, false, false, true, false], - [ true, false, false, false, false, true, false], - [ true], - [ false, true, true, true, false, false, false], - [ false, false, false, false, false, false, false], - ], wasmCommon); - + const scenePtr = wasmCommon.allocate_default_scene(); const itemsPtr = wasmCommon.allocate_items(); const bombsPtr = wasmCommon.allocate_bombs(); - return {scene, itemsPtr, bombsPtr}; + return {scenePtr, itemsPtr, bombsPtr}; } -export function updatePlayer(wasmCommon: WasmCommon, player: Player, scene: Scene, deltaTime: number) { +export function updatePlayer(wasmCommon: WasmCommon, player: Player, scenePtr: number, deltaTime: number) { const controlVelocity = new Vector2(); let angularVelocity = 0.0; if ((player.moving>>Moving.MovingForward)&1) { @@ -379,11 +345,11 @@ export function updatePlayer(wasmCommon: WasmCommon, player: Player, scene: Scen player.direction = player.direction + angularVelocity*deltaTime; const nx = player.position.x + controlVelocity.x*deltaTime; - if (wasmCommon.scene_can_rectangle_fit_here(scene.wallsPtr, scene.width, scene.height, nx, player.position.y, PLAYER_SIZE, PLAYER_SIZE)) { + if (wasmCommon.scene_can_rectangle_fit_here(scenePtr, nx, player.position.y, PLAYER_SIZE, PLAYER_SIZE)) { player.position.x = nx; } const ny = player.position.y + controlVelocity.y*deltaTime; - if (wasmCommon.scene_can_rectangle_fit_here(scene.wallsPtr, scene.width, scene.height, player.position.x, ny, PLAYER_SIZE, PLAYER_SIZE)) { + if (wasmCommon.scene_can_rectangle_fit_here(scenePtr, player.position.x, ny, PLAYER_SIZE, PLAYER_SIZE)) { player.position.y = ny; } } diff --git a/server.c3 b/server.c3 index 3f57bad..2720fc3 100644 --- a/server.c3 +++ b/server.c3 @@ -259,10 +259,10 @@ fn ExplodedBombs *allocate_exploded_bombs() @extern("allocate_exploded_bombs") @ return mem::new(ExplodedBombs); } -fn void update_bombs_on_server_side(bool* scene, int scene_width, int scene_height, float delta_time, ExplodedBombs *exploded_bombs, Bombs *bombs) @extern("update_bombs_on_server_side") @wasm { +fn void update_bombs_on_server_side(Scene *scene, float delta_time, ExplodedBombs *exploded_bombs, Bombs *bombs) @extern("update_bombs_on_server_side") @wasm { foreach (bombIndex, &bomb: *bombs) { if (bomb.lifetime > 0) { - common::update_bomb(bomb, scene, scene_width, scene_height, delta_time); + common::update_bomb(bomb, scene, delta_time); if (bomb.lifetime <= 0) { exploded_bombs.push(bombIndex); } diff --git a/server.mjs b/server.mjs index 9f4dd86..c5a3fb0 100644 --- a/server.mjs +++ b/server.mjs @@ -270,7 +270,7 @@ function tick() { } { players.forEach((player) => { - common.updatePlayer(wasmServer, player, level.scene, deltaTime); + common.updatePlayer(wasmServer, player, level.scenePtr, deltaTime); wasmServer.collect_items_by_player_at(player.position.x, player.position.y, collectedItemsPtr, level.itemsPtr); }); const bufferItemsCollected = (() => { @@ -287,7 +287,7 @@ function tick() { messageSentCounter += 1; }); } - wasmServer.update_bombs_on_server_side(level.scene.wallsPtr, level.scene.width, level.scene.height, deltaTime, explodedBombsPtr, level.bombsPtr); + wasmServer.update_bombs_on_server_side(level.scenePtr, deltaTime, explodedBombsPtr, level.bombsPtr); const bufferBombsExploded = (() => { const message = wasmServer.exploded_bombs_as_batch_message(explodedBombsPtr, level.bombsPtr); if (message === 0) diff --git a/server.mts b/server.mts index 9be2bd7..fb7f78b 100644 --- a/server.mts +++ b/server.mts @@ -317,7 +317,7 @@ function tick() { // Simulating the world for one server tick. { players.forEach((player) => { - common.updatePlayer(wasmServer, player, level.scene, deltaTime); + common.updatePlayer(wasmServer, player, level.scenePtr, deltaTime); wasmServer.collect_items_by_player_at(player.position.x, player.position.y, collectedItemsPtr, level.itemsPtr); }); @@ -336,7 +336,7 @@ function tick() { }); } - wasmServer.update_bombs_on_server_side(level.scene.wallsPtr, level.scene.width, level.scene.height, deltaTime, explodedBombsPtr, level.bombsPtr); + wasmServer.update_bombs_on_server_side(level.scenePtr, deltaTime, explodedBombsPtr, level.bombsPtr); const bufferBombsExploded = (() => { const message = wasmServer.exploded_bombs_as_batch_message(explodedBombsPtr, level.bombsPtr); if (message === 0) return null; @@ -402,7 +402,7 @@ interface WasmServer extends common.WasmCommon { throw_bomb_on_server_side: (player_position_x: number, player_position_y: number, player_direction: number, bombs: number, thrown_bombs: number) => number, thrown_bombs_as_batch_message: (bombs: number, thrown_bombs: number) => number, allocate_exploded_bombs: () => number, - update_bombs_on_server_side: (scene: number, scene_width: number, scene_height: number, delta_time: number, exploded_bombs: number, bombs: number) => void, + update_bombs_on_server_side: (scene: number, delta_time: number, exploded_bombs: number, bombs: number) => void, exploded_bombs_as_batch_message: (exploded_bombs: number, bombs: number) => number, } @@ -437,7 +437,7 @@ async function instantiateWasmServer(path: string): Promise { throw_bomb_on_server_side: wasm.instance.exports.throw_bomb_on_server_side as (player_position_x: number, player_position_y: number, player_direction: number, bombs: number, thrown_bombs: number) => number, thrown_bombs_as_batch_message: wasm.instance.exports.thrown_bombs_as_batch_message as (bombs: number, thrown_bombs: number) => number, allocate_exploded_bombs: wasm.instance.exports.allocate_exploded_bombs as () => number, - update_bombs_on_server_side: wasm.instance.exports.update_bombs_on_server_side as (scene: number, scene_width: number, scene_height: number, delta_time: number, exploded_bombs: number, bombs: number) => void, + update_bombs_on_server_side: wasm.instance.exports.update_bombs_on_server_side as (scene: number, delta_time: number, exploded_bombs: number, bombs: number) => void, exploded_bombs_as_batch_message: wasm.instance.exports.exploded_bombs_as_batch_message as (exploded_bombs: number, bombs: number) => number }; } diff --git a/server.wasm b/server.wasm index 8ef4222..3ca0292 100755 Binary files a/server.wasm and b/server.wasm differ