Tighten camera and pose diversity rules for card prompts
This commit is contained in:
@@ -47,7 +47,7 @@ The game art direction is adult-oriented multi-world pinup:
|
||||
- Medium through defeated stages may show clear combat-pain reactions from abdominal hits: gasping open mouth, hunched posture, labored breathing, tears, and small saliva/drool details. These must read as combat injury reactions, not sexual acts or fetish framing.
|
||||
- High-damage stages should make the combat feel intense through missing or destroyed hand, foot, shoulder, abdomen, hip, and torso armor/clothing. Strong adult damaged-costume presentation should be used wherever possible, and the composition should be built to show it clearly.
|
||||
- Adult pinup body language is strongly encouraged when it remains framed as battle damage, defeat, or damaged-costume card art. Use arched backs, twisted torsos, hip-forward stances, side-back views, exposed-leg kneeling, strained chest/shoulder posture, damaged-costume torso silhouettes, and defeated poses that emphasize mature curves. Do not depict intimate acts, penetration, minors, gore, or explicit closeups.
|
||||
- Do not keep every card as a frontal shot. Use camera variety across stages: side and low/high combinations for baseline, twisted side or side-back for abdomen impacts, and rear/low/high angles for heavy damage and defeated art when it helps show shoulders, back, cloak, and armor destruction.
|
||||
- Do not keep every card as a frontal shot. Use camera variety across stages: side and low/high combinations for baseline, twisted side or side-back for abdomen impacts, and rear/low/high angles for heavy damage and defeated art when it helps show shoulders, back, cloak, and armor destruction. Force at least one low-angle and one high-angle view in every 5-stage damage set, and avoid two consecutive front-facing reads by default.
|
||||
- For each character, force low-angle or high-angle framing somewhere in every consecutive damage-set. Stages should not read as a mirrored front-facing sequence even when same movement language is used.
|
||||
|
||||
All damage-state art must use adult characters only. Intimate acts, penetration, childlike characters, and gore are out of scope; adult-only damaged-costume presentation, adult pinup posing, mature body language, and visible non-sensitive body areas are allowed and encouraged when framed as battle damage, defeat, or damaged-costume card art. Do not make the roster feel like a teen-safe or modest game; high-damage cards should read unmistakably as adult-only card art while remaining non-explicit.
|
||||
|
||||
@@ -193,11 +193,6 @@ const CAMERA_ORIENTATION_PLAN = {
|
||||
|
||||
const CAMERA_VARIANTS = {
|
||||
normal: {
|
||||
front: [
|
||||
"low side-three-quarter composition with a shoulder twist that keeps the body angled",
|
||||
"three-quarter profile composition with one foot forward and hips leading the movement",
|
||||
"slanted side-front composition where the face stays readable through a short turn",
|
||||
],
|
||||
side: [
|
||||
"strong profile side shot with one step forward and hips leading the movement",
|
||||
"45-degree profile turn with the leading shoulder pushed toward camera",
|
||||
@@ -220,11 +215,6 @@ const CAMERA_VARIANTS = {
|
||||
],
|
||||
},
|
||||
"light-damage": {
|
||||
front: [
|
||||
"front-canted three-quarter read with shoulders turned against impact and one side stepping in",
|
||||
"low-front slant with torso dropping into counter step and side-shifted hips",
|
||||
"eye-level angled guard frame that keeps the strike angle visible in the shoulder and waist",
|
||||
],
|
||||
side: [
|
||||
"side pivot camera with shoulder turn and counter-step body shift",
|
||||
"off-center side-frame with one foot forward and hips leading",
|
||||
@@ -247,11 +237,6 @@ const CAMERA_VARIANTS = {
|
||||
],
|
||||
},
|
||||
"medium-damage": {
|
||||
front: [
|
||||
"front-angled three-quarter combat lock with shoulder and hip crossing against a force",
|
||||
"low-front recovery turn with one leg absorbing impact and waist twisted for balance",
|
||||
"angled forward body-lock pose as the torso rotates into a side-facing response",
|
||||
],
|
||||
side: [
|
||||
"strong side profile, body twisted from force so shoulder, torso, and abdomen damage are obvious",
|
||||
"rearward three-quarter side-forward action frame while keeping enough face profile",
|
||||
@@ -274,11 +259,6 @@ const CAMERA_VARIANTS = {
|
||||
],
|
||||
},
|
||||
"heavy-damage": {
|
||||
front: [
|
||||
"low-front collapse angle where one shoulder drops while body rotates around a failing knee",
|
||||
"aggressive forward-lean collapse with side weight shift and heavy gear drag",
|
||||
"frontal-to-side rebound pose with fractured guard and broken upper-body support",
|
||||
],
|
||||
side: [
|
||||
"dramatic side view from near ground, torn shoulder and torso damage clearly visible",
|
||||
"wide extreme-side camera with body falling forward and equipment flying",
|
||||
@@ -301,11 +281,6 @@ const CAMERA_VARIANTS = {
|
||||
],
|
||||
},
|
||||
defeated: {
|
||||
front: [
|
||||
"front-canted defeated collapse with one knee down and torso dropping into recoil",
|
||||
"kneeling recoil frame with hip-heavy fall and waist opening",
|
||||
"collapsed chest-forward posture with profile drift and controlled face read",
|
||||
],
|
||||
side: [
|
||||
"low angle side-back shot with fallen armor pieces and defeated body posture",
|
||||
"rear three-quarter, side-back, or very low side view; show damaged back/shoulder/cloak with readable face profile",
|
||||
@@ -331,7 +306,7 @@ const CAMERA_VARIANTS = {
|
||||
|
||||
const CAMERA_ORIENTATION_RULES = {
|
||||
normal:
|
||||
"Use only side/rear/low/high framing. Never use a pure front-on head-on lock. Across one character's 5 stages, make sure at least one low-angle and one high-angle shot appear.",
|
||||
"Use only side/rear/low/high framing. Frontal-on faces are disallowed unless identity continuity absolutely requires it. Across one character's 5 stages, enforce at least one low-angle and one high-angle shot.",
|
||||
"light-damage":
|
||||
"Prioritize low-angle, rear, side, and high-angle framing. Frontal reads are disallowed unless strict identity continuity would otherwise fail.",
|
||||
"medium-damage":
|
||||
@@ -598,7 +573,7 @@ function nextDifferentIndex(plan, startIndex, bannedOrientation) {
|
||||
for (let i = 1; i <= plan.length; i += 1) {
|
||||
const index = (startIndex + i) % plan.length;
|
||||
const candidate = normalizeOrientation(plan[index]);
|
||||
if (candidate !== bannedOrientation && candidate !== "front") {
|
||||
if (candidate !== bannedOrientation) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
@@ -606,11 +581,29 @@ function nextDifferentIndex(plan, startIndex, bannedOrientation) {
|
||||
}
|
||||
|
||||
function normalizeOrientation(orientation) {
|
||||
return orientation === "front" ? "side" : orientation;
|
||||
return orientation;
|
||||
}
|
||||
|
||||
const cameraHistoryByCharacter = new Map();
|
||||
const poseHistoryByCharacter = new Map();
|
||||
const poseFamilyHistoryByCharacter = new Map();
|
||||
|
||||
function poseFamily(phrase) {
|
||||
const key = phrase.toLowerCase();
|
||||
if (/(drop|kneel|crouch|crawl|collapse|sit|ground|fall)/.test(key)) {
|
||||
return "ground-recovery";
|
||||
}
|
||||
if (/(jump|vault|leap|swing|spin|air|mid-air|rebound)/.test(key)) {
|
||||
return "airborne";
|
||||
}
|
||||
if (/(counter|parry|brace|rebound|recover|drag|pull|guard)/.test(key)) {
|
||||
return "defensive";
|
||||
}
|
||||
if (/(lunge|dash|step|stride|pivot|split|run|dodge|advance)/.test(key)) {
|
||||
return "forward-motion";
|
||||
}
|
||||
return "impact";
|
||||
}
|
||||
|
||||
function pickCameraForStage(spec, character, stage) {
|
||||
const orientationPlan = CAMERA_ORIENTATION_PLAN[spec.label] ?? CAMERA_ORIENTATION_PLAN.normal;
|
||||
@@ -686,23 +679,36 @@ function pickPoseModifier(spec, character, stage, orientation) {
|
||||
POSE_ORIENTATION_VARIANTS.normal?.[normalizedOrientation] ??
|
||||
[];
|
||||
const posePool = orientationBonus.concat(list);
|
||||
const pick = pickDiverseOption(
|
||||
posePool,
|
||||
charSeed(`${character.id}-${character.pose}-${character.weapon}-${orientation}`),
|
||||
stage,
|
||||
19,
|
||||
);
|
||||
const historyKey = character.id;
|
||||
const history = poseHistoryByCharacter.get(historyKey) ?? [];
|
||||
let selected = pick;
|
||||
const familyHistory = poseFamilyHistoryByCharacter.get(character.id) ?? [];
|
||||
const avoidedFamilies = new Set(familyHistory.slice(-2));
|
||||
const familyFilteredPool = posePool.filter((pose) => !avoidedFamilies.has(poseFamily(pose)));
|
||||
const finalPool = familyFilteredPool.length > 0 ? familyFilteredPool : posePool;
|
||||
|
||||
const poolSeed = charSeed(`${character.id}-${character.pose}-${character.weapon}-${normalizedOrientation}`);
|
||||
const index = (poolSeed + stage * 19) % finalPool.length;
|
||||
const selectedCandidate = finalPool[index];
|
||||
|
||||
const history = poseHistoryByCharacter.get(character.id) ?? [];
|
||||
let selected = selectedCandidate;
|
||||
if (history.length > 0 && selected === history[history.length - 1]) {
|
||||
selected = posePool[(posePool.indexOf(pick) + 1) % posePool.length];
|
||||
const fallbackIndex = (finalPool.indexOf(selected) + 1) % finalPool.length;
|
||||
selected = finalPool[fallbackIndex];
|
||||
}
|
||||
|
||||
const family = poseFamily(selected);
|
||||
const familyHistoryKey = character.id;
|
||||
const nextFamilyHistory = poseFamilyHistoryByCharacter.get(familyHistoryKey) ?? [];
|
||||
nextFamilyHistory.push(family);
|
||||
if (nextFamilyHistory.length > 8) {
|
||||
nextFamilyHistory.shift();
|
||||
}
|
||||
poseFamilyHistoryByCharacter.set(familyHistoryKey, nextFamilyHistory);
|
||||
|
||||
history.push(selected);
|
||||
if (history.length > 12) {
|
||||
history.shift();
|
||||
}
|
||||
poseHistoryByCharacter.set(historyKey, history);
|
||||
poseHistoryByCharacter.set(character.id, history);
|
||||
return selected;
|
||||
}
|
||||
|
||||
@@ -726,6 +732,8 @@ function promptFor(character, stage) {
|
||||
"Angle strictness: this render must use side/rear/low/high framing first; direct frontal composition is disallowed unless the model absolutely cannot preserve face identity.";
|
||||
const angleConstraint =
|
||||
"Do not output front-facing framing for default action shots. Use side/rear/low/high angles as primary composition, and rotate the view family between shots so the same character does not repeat the exact same camera axis.";
|
||||
const poseDiversityConstraint =
|
||||
"Pose diversity is mandatory: rotate through guard, movement, recoil, evasive, grounded, and collapse actions across the five stages; do not repeat the same motion family in multiple consecutive shots.";
|
||||
const poseModifier = pickPoseModifier(spec, character, stage, camera.orientation);
|
||||
return [
|
||||
"Use case: stylized-concept",
|
||||
@@ -742,6 +750,7 @@ function promptFor(character, stage) {
|
||||
`Camera/view variation: ${camera.orientation} angle. Composition directive: ${camera.phrase}.`,
|
||||
angleControl,
|
||||
angleConstraint,
|
||||
poseDiversityConstraint,
|
||||
"Across the character's five damage stages, rotate between side, rear, low-angle, and high-angle views as the primary framing, and only use frontal composition when the identity cannot be preserved.",
|
||||
`Camera constraint: ${CAMERA_ORIENTATION_RULES[spec.label] ?? CAMERA_ORIENTATION_RULES.normal}`,
|
||||
`Adult visual appeal: ${character.appealFocus}; ${adultAppeal}.`,
|
||||
|
||||
Reference in New Issue
Block a user