Skip to content

Interview questionnaire ​

How to run this interview ​

Conduct the interview in whatever language the user writes to you in — translate the questions on the fly.

Rules:

  1. Read the SDK documentation first (order: README.md). Half the value of this interview is your ability to say "the engine already does that" instead of letting the user design a feature that cannot exist.
  2. One block at a time. Ask a block, get the answers, confirm your understanding in one sentence, move on. Never dump all 14 blocks at once.
  3. Every question has a "same as tanks" default. State it, and let the user accept it with a single word. Blocks 1, 5, 6, 7, 10 are the ones that really define the game — spend the time there.
  4. Push back immediately on impossible answers. The list of things that do not exist is at the end of pitfalls.md. Offer the nearest workable alternative in the same message.
  5. Skip what is already settled. If the user described the game in the first message, do not re-ask; confirm instead.
  6. After the last block, write the design document and get confirmation before generating anything.

Block 1. Game identity and package ​

  1. What is the game called? A short id (Latin letters, no spaces) is needed — it becomes manifest.id, the URL segment /games/<id>/ and must match the identifier the game is registered under on the platform. In tanks — tanks.
  2. The npm package name? The convention is @vimp-games/<id>; your own scope is also fine. In tanks — @vimp-games/tanks.
  3. The display title (manifest.title) — what the player sees in the lobby. In tanks — VIMP Tanks.
  4. In one paragraph: what kind of game is it, what genre, what does the player do in a match? (Needed to choose the shape of entities and the snapshot.)

Block 2. Room and lobby ​

  1. What is the target room size (roomDefaults.maxPlayers)? Note that the platform clamps it to 8 anyway. In tanks — 8.
  2. Which fields belong in the server creation form? Important: the host accepts only maxPlayers, map, roundTime, mapTime, friendlyFire (plus the map catalog). Any custom form field is accepted by the form and silently dropped — a setting that affects the rules cannot be passed through the room form. If such a setting is needed, we will discuss how to bake it into the game config or the core logic.
  3. The form controls are text, select, checkbox, radio; range, number, toggle and segmented are permanent aliases of them (see Form schema). Numeric bounds are set by the min/max fields and the auto-generated regExp. Is that fine?
  4. Is friendly fire (friendlyFire) on or off by default? In tanks — off (false); the player can switch it when creating a room.
  5. The default round and map duration? In tanks — 120 s and 600 s; custom values are clamped to 10 s … 3600 s.

Block 3. Sign-in screen (auth) ​

  1. What does the player choose before entering a match? (Model/class/colour/ faction — any set of fields.) The nick is not among them: the name comes from the lobby JWT. In tanks — only the tank model.
  2. The screen texts: the title and the hint block (usually the controls layout — "keys → action" pairs). Give the wording.
  3. Which fields must be remembered between sessions (storage) and which must be checked on the host side (validator)? In tanks — the model is remembered and validated against the model list.

Block 4. Match rules, chat, votes ​

  1. A round ends when the whole opposing team is destroyed — that is an engine rule. Does that fit? If the game is not round-based, we will discuss workarounds (one long "session", a single playing team, respawn inside the core).
  2. What happens to a player after death? In the engine they become a spectator of the killer until the end of the round. Whether a respawn within the round is needed is implemented in your Rust core, not in the config.
  3. Is a post-respawn invulnerability window needed? The engine has none — it is implemented in the core (a flag on the actor + a check in the damage calculation).
  4. Votes: which types are needed besides the built-in teamChange and mapChange? Note the 30 s category cooldown, the 10 s voting window, one active vote at a time, and ties resolved randomly. The engine has no kick-player vote, no /ban endpoint and no server rating (/like//unlike).
  5. Which chat commands does the game need? The engine parses none of its own — the game declares the whole set (HostPlugin.chatCommands). The usual minimum: /rank, /nr (dev), plus /timeleft and /mapname if the round and the map are finite. Tanks has all four and its own /bot; snakes has only /nr, /rank and /bot.
  6. Which system chat messages does the game add? The group letters s, v, m, c are taken by the engine — choose your own (in tanks it is b). The texts with {0}, {1} placeholders are needed.
  7. The maximum chat message length? The default is 60 characters.
  8. Does the kick policy need changing? Defaults: inactivity 120 s for a player (off for a spectator), kick on average latency > 1000 ms, kick after 5 missed pings, a ping every 3 s, an inactivity check every 30 s.

Block 5. Controls and prediction ​

  1. The full list of player actions with assigned keys. For each: hold (movement) or one-shot (a shot, a weapon switch)? One-shot actions are consumed once per tick, up is ignored.
  2. What do the spectator keys do? The mandatory minimum is nextPlayer and prevPlayer. In tanks — n/p.
  3. Is client-side movement prediction needed (an instant response of your own actor)? Without it the controls feel delayed by ~100 ms + ping. Limit: the predicted state is exactly 8 × f32. List which values go into it. In tanks — x, y, hull angle, gun angle, vx, vy, engine load, state.
  4. Is shot prediction needed (an instant visual effect before the authoritative event arrives)? If so, de-duplication by the author id in the event block is required.

Block 6. Weapons and combat mechanics ​

  1. The list of weapons/abilities. For each: the hit type (an instant ray, a projectile in flight, a radial explosion, something else), damage, range, spread, impulse, camera shake.
  2. Reload is set by the fireRate field in seconds (0 — no cooldown). Give the values.
  3. Ammunition: the starting ammo values are set by the panel field values (panel.fields[*].value) — the same number goes into the core as the starting resource. How much of what?
  4. Are there actor models/classes with different characteristics? For each: dimensions, acceleration, maximum speed, turning, damping, density/friction/restitution, starting weapon.
  5. Are game events needed that the engine does not understand (picking up an item, capturing a point, scoring outside kills)? Such events go through custom → HostPlugin.onCoreEvent.

Block 7. Snapshot and entities ​

  1. List all the entities the client sees: players, projectiles, effects, dynamic map objects.
  2. For each entity — which fields to send and with what precision (f32, u8, u16, u32)? Which of them to interpolate (lerp), which as an angle (lerpAngle), which discretely?
  3. For each entity — the block shape:
    • indexed8 — up to 255 addressable objects (players);
    • indexed32 — many short-lived objects with an id (projectiles in flight);
    • list16 — anonymous one-off events (tracers, explosions);
    • indexedNoNull8 — fixed slots (map dynamics). Limit: only indexed8 and indexedNoNull8 go into the hot buffer (smooth rendering every frame). Everything else arrives as events.
  4. In every weapon event block the last field is the id of the shot's author (needed to suppress duplicates of the predicted effect). Confirm.

Block 8. HUD, statistics, sounds, inform messages ​

  1. Which resources does the panel show? For each: the cell type — bar (a bar, 30 blocks by default, 100 at most), value (a number), weapon (the active one is highlighted), time (M:SS). The round-time cell is mandatory and hard-bound to the key t.
  2. The statistics table: the engine writes exactly five values — name, status, score, deaths, latency (this is the "ping"). The engine will not fill custom columns. Column headings and a (numeric) sort order are needed. Team aggregates are computed by the methods '=' (replace), '+' (accumulate), '#' (count rows).
  3. Sounds: the full list with priorities (more important — higher; the limit is 30 simultaneous spatial voices) and volumes. Each sound needs a webm + mp3 pair.
  4. The mapping of engine events to your sounds: roundStart, victory, defeat, frag, death. Which of them are needed?
  5. The texts of the three inform messages (the indexes are fixed): a team's victory ({0} — the team), round start, game over. In tanks — {0} WINS!, ROUND START!, GAME OVER!.
  6. Is a vote right after entering the match needed (initialVote)? In tanks — the team choice. If the game has a single team and no spectators as a phenomenon, the answer is "no": instead of initialVote/spectatorTeam declare gameConfig.noSpectators: true (exactly one team, entry straight into it), and modules.vote may be omitted altogether. If the game's round is endless, add gameConfig.endlessRound: true as well.

Block 9. Bots (scripted participants) ​

  1. Are bots needed? If so, how should they behave (look for the nearest opponent, patrol, hold a position)? Describe the desired behaviour, not numeric constants: the AI decision rate and other parameters are Rust core code, not a config setting.
  2. How are bots created: by a chat command, by a vote, automatically when there are too few players? In tanks — the /bot command with a vote.
  3. The bot name prefix and the default model?

Block 10. Maps and environment ​

  1. How many maps are needed in the first version, and of what size (in tiles)?
  2. Tiles: what is the tile size (step) and which indexes make a wall (physicsStatic)? The tile images are shipped by your package — the engine serves no game images at all. Which tile-sheet files do you put in assets/img/ (from there they land in dist/img/ and reach the client as ${assetsBase}img/<file>)?
  3. Render layers: which tile indexes on which layer (layers)?
  4. Are dynamic objects (crates, barrels) needed? For each: position, size, density, image, layer, damping. The image is also a file from your package's assets/img/.
  5. Respawn points: their number per team is the hard capacity of that team on the map. How many points per team? (It must cover maxPlayers.)
  6. The map scale (mapScale, and scale of an individual map if needed)? In tanks — 0.3, some maps have their own.
  7. How many maps to offer in the rotation vote (mapsInVote)? In tanks — 4.

Block 11. Canvases, camera and client UI ​

  1. How many canvases are needed? In tanks — the main one (vimp) and the radar (radar). For each: the initial size, the aspect ratio (aspectRatio) or a fixed size (fixSize), the base scale (baseScale).
  2. Is a dynamic camera needed (a forward offset by speed + zoom-out) and camera shake on hits/explosions?
  3. Which DOM elements to show after authorization (initIdList)? Usually — all canvases plus panel and chat.
  4. Are there custom styles (team colours, panel styling)? The game's CSS is handed to the engine as a string. Note that the engine CSS is designed for five statistics columns and the classes .line1–.line3.
  5. Will there be particles/effects in large numbers (smoke, sparks)? If so, we plan an object pool, otherwise the garbage collector will be noticeable.
  6. Which parts need the renderer and soundManager services? (The service pool is fixed to these two.)

Block 12. Network assumptions ​

  1. Which entities must look smooth (interpolation/prediction), and which are fine to show on an event?
  2. Frame send rate: by default every 4th simulation tick — 30 frames/s at a 120 Hz tick. Keep it?
  3. Does the game have pickups, destructible objects or capturable points? The engine has none — they are modelled with snapshot keys (usually indexedNoNull8 or indexed8) plus core logic. Needed?
  4. What must be delivered reliably (events, shake), and what may be lost (positions)? By default a frame goes over the reliable channel if it contains events, forceReset or shake.
  5. Must the game survive a host change in the middle of a round (the new host continues from the same tick)? Yes — gameConfig.migration.midRound: true, and then the whole core state must be in GameSim::serialize, and stateful host modules need serializeState/restoreState. No — on a host change the round restarts (the soft mode, the default).

Block 13. Progression ​

  1. Is progression between matches needed? The engine stores rank (an integer, a format common to all games) and state (arbitrary JSON of your game).
  2. The engine computes rank itself: +1 per frag, −1 per team kill. There is no hook to change this rule. Is that acceptable?
  3. What to put into state and what a new player starts with (playerState.defaultState)? The data is written from onCoreEvent and synchronised at round end, on map change and when the player leaves.

Block 14. Process ​

  1. Is a cargo movement parity test needed (the predictor against the authoritative simulation)? Strongly recommended — without it a prediction divergence is only detected by eye in the game.
  2. Is a JS↔WASM integration harness needed (tests that run the real core through pkg-node)?
  3. Localisation: the engine does not support switching the language at runtime — all texts (chat, panel, votes, informs, the sign-in screen) are set as one set in the config. In which language do we write the texts?
  4. How do you run the game locally during development? npm run dev (a standalone tab with bots) and npm run sim work without an engine checkout. Is a custom dev harness needed beyond the template dev/main.js?
  5. Do we publish entries.wasmNode (the path to core/pkg-node) in the manifest? Strongly recommended: without it the game cannot be run through the engine's headless runner (npm run sim), and all contract checks would have to be done by eye in the browser. See debugging.md.
  6. Which debug-run scenarios do we write right away (movement, shooting, death/respawn, round end, map change, a vote)? A scenario is plain JSON, the format is in debugging.md.
  7. Do we implement GameClientDef::predicted_state (optional, default None) for a component-wise prediction-divergence report? Without it a coarse comparison by the camera works.

Answer → artifact map ​

BlockProduces
1package.json, scripts/build-game-manifest.js, id/title in both plugins
2gameConfig.roomDefaults, gameConfig.roomForm, parts.friendlyFire, timers.roundTime/mapTime
3src/config/auth.js (elems, texts, params, validators)
4gameConfig.teams/spectatorTeam (or noSpectators, then without initialVote, spectatorTeam and modules.vote), endlessRound, chatMaxLength, idleKickTimeout/rtt, src/host/systemMessages.js, chat commands, client modules.chat.params.messages, modules.vote.params
5gameConfig.playerKeys, client modules.controls.keySetList, spectatorKeys, core apply_input, predictor.rs, PLAYER_STATE_LEN layout
6src/data/weapons.js, src/data/models.js, core weapon modules, onCoreEvent for custom events
7src/config/snapshot.js, Rust build_snapshot_blocks rows, client parts.gameSets
8gameConfig.panel + client modules.panel, gameConfig.stat + client modules.stat, src/config/sounds.js, gameConfig.soundCues, gameInform.list
9gameConfig.scripted, src/host/<Bot>Manager.js, createModules, bot chat command, core/src/bots/
10src/data/maps/*.js, gameConfig.maps/currentMap/mapScale/mapSetId/mapsInVote, map parts
11client modules.canvasManager.canvases, initIdList, styles, parts.bakedAssets, parts.componentDependencies
12snapshot kind/class decisions, timers.networkSendRate, extra snapshot keys for pickups/objectives, gameConfig.migration.midRound + GameSim::serialize coverage + module serializeState/restoreState, a checkpointRestore step in the sim scenario
13gameConfig.playerState.defaultState, onCoreEvent state writes
14vitest.config.js projects, core/src/client/predictor.rs parity tests, tests/, the dev/ harness, entries.wasmNode in the manifest, debug scenarios for npm run sim, optional predicted_state

vimp-engine 0.38.3 · vimp-engine-core 0.23.4 · create-vimp-game 0.5.7