Skip to content
Snippets Groups Projects
canvasmodel-example.js 9.21 KiB
Newer Older
  • Learn to ignore specific revisions
  • aimozg's avatar
    aimozg committed
    /**
     * Example model, a 'xray-vaginal' and small part of 'close-vaginal' slots of sex animation.
     * See game/03-JavaScript/canvasmodel.js for API reference
    
    Jimmy's avatar
    Jimmy committed
     * and canvasmodel-example.twee for test passage (accessible in Debug/Main menu).
    
    aimozg's avatar
    aimozg committed
     */
    
    Jimmy's avatar
    Jimmy committed
    Renderer.CanvasModels.sexdemo = {
    
    aimozg's avatar
    aimozg committed
    	name: "sexdemo", // For debugging
    
    	width: 768,
    	height: 256,
    
    	frames: 8, // For CSS animation only. JS animations can have as many frames as needed
    
    	/**
    
    Jimmy's avatar
    Jimmy committed
    	 * List of names of generated options, for debugging & tooling.
    
    aimozg's avatar
    aimozg committed
    	 */
    	generatedOptions() {
    
    Jimmy's avatar
    Jimmy committed
    		return [];
    
    aimozg's avatar
    aimozg committed
    	},
    
    	/**
    	 * Default option values.
    
    klorpa's avatar
    klorpa committed
    	 * All possible options should be initialised to some non-crashing values here.
    
    Jimmy's avatar
    Jimmy committed
    	 * Should also have a `filter:{}` option for model filters.
    
    aimozg's avatar
    aimozg committed
    	 */
    	defaultOptions() {
    		return {
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Global animation speed, "" (no animation) | "slow" | "mid" | "fast" | "vfast".
    
    aimozg's avatar
    aimozg committed
    			 */
    			animation_speed: "",
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Sex position, "doggy" | "missionary".
    
    aimozg's avatar
    aimozg committed
    			 */
    			position: "doggy",
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * PC penis type: "" (none) | "default" | "virgin".
    
    aimozg's avatar
    aimozg committed
    			 */
    			penis: "",
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * PC has vagina.
    
    aimozg's avatar
    aimozg committed
    			 */
    			vagina: false,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * PC has balls.
    
    aimozg's avatar
    aimozg committed
    			 */
    			balls: false,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Show/hide xray-anal slot.
    
    aimozg's avatar
    aimozg committed
    			 */
    			xray_vaginal_show: false,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Animation speed override, "" to use animation_speed.
    
    aimozg's avatar
    aimozg committed
    			 */
    			xray_vaginal_speed: "",
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Show/hide close-vaginal slot.
    
    aimozg's avatar
    aimozg committed
    			 */
    			close_vagina_show: false,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Animation speed override, "" to use animation_speed.
    
    aimozg's avatar
    aimozg committed
    			 */
    			close_vagina_speed: "",
    			/**
    			 * Penetration state, "" (none) | "entrance" | "imminent" | "penetrated"
    			 * NOT the equivalent of $vaginastate, tentacles share entrance/imminent/penetrated
    
    Jimmy's avatar
    Jimmy committed
    			 * and $vaginastate="tentacledeep" should set options.vaginacumming=true.
    
    aimozg's avatar
    aimozg committed
    			 */
    			vagina_state: "",
    			vagina_aroused: false,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Penetrator type, "" (empty) | "penis" (human) | "beast" | "tentacle" | "machine".
    
    aimozg's avatar
    aimozg committed
    			 */
    			vagina_penetrator: "",
    			/**
    			 * Penetrator subtype, options depend on vagina_penetrator:
    			 * - for "human": NPC skin colour
    			 * - for "beast": beast type
    
    Jimmy's avatar
    Jimmy committed
    			 * - for others: "default".
    
    aimozg's avatar
    aimozg committed
    			 */
    			vagina_penetrator_subtype: "default",
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Penetrator size.
    
    aimozg's avatar
    aimozg committed
    			 */
    			vagina_penetrator_size: 0,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Cumming inside vagina.
    
    aimozg's avatar
    aimozg committed
    			 */
    			vagina_cumming: false,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * User-supplied filters go here; typically this is empty in default options.
    
    aimozg's avatar
    aimozg committed
    			 */
    
    Jimmy's avatar
    Jimmy committed
    			filters: {},
    		};
    
    aimozg's avatar
    aimozg committed
    	},
    
    	/**
    	 * This function is called before compiling layers for rendering or animation.
    	 * Generated options and filters implementations go here.
    
    Jimmy's avatar
    Jimmy committed
    	 *
    	 * @param options
    
    aimozg's avatar
    aimozg committed
    	 */
    	preprocess(options) {
    
    Jimmy's avatar
    Jimmy committed
    		if (!options.xray_vaginal_speed) {
    			// "" means use global
    
    aimozg's avatar
    aimozg committed
    			options.xray_vaginal_speed = options.animation_speed;
    		}
    
    Jimmy's avatar
    Jimmy committed
    		if (!options.close_vagina_speed) {
    			// "" means use global
    
    aimozg's avatar
    aimozg committed
    			options.close_vagina_speed = options.animation_speed;
    		}
    
    xao's avatar
    xao committed
    		if (options.worn.under_lower) {
    			const record = setup.colours.clothes_map[options.worn.under_lower.colour];
    
    aimozg's avatar
    aimozg committed
    			if (record) {
    
    Jimmy's avatar
    Jimmy committed
    				options.filters.under_lower = record.canvasfilter;
    
    aimozg's avatar
    aimozg committed
    			} else {
    
    xao's avatar
    xao committed
    				console.error("Unknown under_lower colour " + options.worn.under_lower.colour);
    
    Jimmy's avatar
    Jimmy committed
    				options.filters.under_lower = {};
    
    aimozg's avatar
    aimozg committed
    			}
    		}
    		// Despite the name, filters can have any layer properties, including those affectign composition
    
    Jimmy's avatar
    Jimmy committed
    		options.filters.close_vagina = {
    
    aimozg's avatar
    aimozg committed
    			dx: 386,
    			dy: 0,
    
    Jimmy's avatar
    Jimmy committed
    			width: 64,
    
    aimozg's avatar
    aimozg committed
    		};
    	},
    
    	/**
    	 * The meat.
    	 * Key is layer name, value is layer definition.
    	 * Rendering order is guaranteed only via `z` property.
    	 */
    	layers: {
    
    Jimmy's avatar
    Jimmy committed
    		xray_vaginal: {
    
    aimozg's avatar
    aimozg committed
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * X and Y offsets.
    
    aimozg's avatar
    aimozg committed
    			 */
    			dx: 0,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Shift down for futas.
    			 *
    			 * @param options
    
    aimozg's avatar
    aimozg committed
    			 */
    			dyfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return options.penis && options.vagina ? 64 : 0;
    
    aimozg's avatar
    aimozg committed
    			},
    			/**
    			 * This option is required because layer takes small part of the resulting image.
    			 * Without it, the 2048 pixel wide image would be treated as 3-frame animation (=2048/768).
    			 */
    			width: 256,
    			/**
    			 * As this layer has `showfn`, it will be displayed automatically when needed,
    			 * without <<showlayer "xray_vaginal">>.
    			 * You'll need <<set _modeloptions.xray_vaginal_show = true>> instead.
    			 * Not much difference but it makes more sense when you toggle multiple layers with one option.
    
    Jimmy's avatar
    Jimmy committed
    			 *
    			 * @param options
    
    aimozg's avatar
    aimozg committed
    			 */
    			showfn(options) {
    				return options.xray_vaginal_show && options.vagina_state === "penetrated";
    			},
    			srcfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				const cum = options.vagina_cumming ? "cum" : "";
    
    aimozg's avatar
    aimozg committed
    				switch (options.vagina_penetrator) {
    					case "machine":
    						return "img/sex/machine/vaginal/xray_vaginal.png";
    					case "beast":
    						switch (options.vagina_penetrator_subtype) {
    							case "horse":
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/xrayvaginalhorse" + cum + ".png";
    
    aimozg's avatar
    aimozg committed
    							default:
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/xrayvaginalbeast" + cum + ".png";
    
    aimozg's avatar
    aimozg committed
    						}
    					case "penis":
    						switch (options.vagina_penetrator_subtype) {
    							case "black":
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/black/xrayvaginal" + cum + ".png";
    
    aimozg's avatar
    aimozg committed
    							default:
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/xrayvaginal" + cum + ".png";
    
    aimozg's avatar
    aimozg committed
    						}
    					case "tentacle":
    
    Jimmy's avatar
    Jimmy committed
    						return "img/sex/xrayvaginaltentacle" + cum + ".png";
    
    aimozg's avatar
    aimozg committed
    					default:
    						/**
    
    Jimmy's avatar
    Jimmy committed
    						 * Fallback value, nothing will be renderer.
    
    aimozg's avatar
    aimozg committed
    						 */
    						return "";
    				}
    			},
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Copied from z-index of #xrayvaginal.
    
    aimozg's avatar
    aimozg committed
    			 */
    			z: 3,
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * Returns name of animation, or empty string if none.
    			 *
    			 * @param options
    
    aimozg's avatar
    aimozg committed
    			 */
    			animationfn(options) {
    				/**
    
    Jimmy's avatar
    Jimmy committed
    				 * We use the fact that option values and animation names are same.
    
    aimozg's avatar
    aimozg committed
    				 */
    
    Jimmy's avatar
    Jimmy committed
    				return options.xray_vaginal_speed ? "sex-8f-" + options.xray_vaginal_speed : "";
    			},
    
    aimozg's avatar
    aimozg committed
    		},
    		/***
    		 * CLOSEUPS
    		 */
    
    Jimmy's avatar
    Jimmy committed
    		close_vagina: {
    
    aimozg's avatar
    aimozg committed
    			z: 250,
    			showfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return options.close_vagina_show;
    
    aimozg's avatar
    aimozg committed
    			},
    			srcfn(options) {
    				if (options.vagina_state === "penetrated") {
    
    Jimmy's avatar
    Jimmy committed
    					return options.vagina_penetrator === "beast" && options.vagina_penetrator_size >= 5
    						? "img/sex/close/" + options.position + "/vaginapenetratebig.png"
    						: "img/sex/close/" + options.position + "/vaginapenetrate.png";
    
    aimozg's avatar
    aimozg committed
    				} else {
    
    Jimmy's avatar
    Jimmy committed
    					return options.vagina_aroused
    						? "img/sex/close/" + options.position + "/vaginaaroused.png"
    						: "img/sex/close/" + options.position + "/vagina.png";
    
    aimozg's avatar
    aimozg committed
    				}
    			},
    
    Jimmy's avatar
    Jimmy committed
    			filters: ["close_vagina"],
    
    aimozg's avatar
    aimozg committed
    			animationfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "sex-6f-" + options.close_vagina_speed;
    			},
    
    aimozg's avatar
    aimozg committed
    		},
    
    Jimmy's avatar
    Jimmy committed
    		close_vagina_aroused: {
    
    aimozg's avatar
    aimozg committed
    			z: 251,
    			showfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return options.close_vagina_show && options.vagina_aroused;
    
    aimozg's avatar
    aimozg committed
    			},
    			srcfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "img/sex/close/" + options.position + "/vaginaaroused.png";
    
    aimozg's avatar
    aimozg committed
    			},
    			animationfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "sex-6f-" + options.close_vagina_speed;
    			},
    
    aimozg's avatar
    aimozg committed
    		},
    		/**
    
    Jimmy's avatar
    Jimmy committed
    		 * Futa penis.
    
    aimozg's avatar
    aimozg committed
    		 */
    
    Jimmy's avatar
    Jimmy committed
    		close_vagina_penis: {
    
    aimozg's avatar
    aimozg committed
    			z: 252,
    			showfn(options) {
    				/**
    				 * Only exact 'false' would hide the layer (undefined etc won't),
    				 * so cast non-boolean options to boolean via double negation.
    				 */
    
    Jimmy's avatar
    Jimmy committed
    				return options.close_vagina_show && !!options.penis;
    
    aimozg's avatar
    aimozg committed
    			},
    			srcfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "img/sex/close/" + options.position + "/" + (options.balls ? "futavagina.png" : "futavaginanoballs.png");
    
    aimozg's avatar
    aimozg committed
    			},
    
    Jimmy's avatar
    Jimmy committed
    			filters: ["close_vagina"],
    
    aimozg's avatar
    aimozg committed
    			animationfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "sex-6f-" + options.close_vagina_speed;
    			},
    
    aimozg's avatar
    aimozg committed
    		},
    
    Jimmy's avatar
    Jimmy committed
    		close_vagina_panties: {
    
    aimozg's avatar
    aimozg committed
    			z: 253,
    			showfn(options) {
    
    xao's avatar
    xao committed
    				return options.close_vagina_show && !!options.worn.under_lower.index && options.worn.under_lower.state === "totheside";
    
    aimozg's avatar
    aimozg committed
    			},
    			srcfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "img/sex/close/" + options.position + "/vaginatotheside.png";
    
    aimozg's avatar
    aimozg committed
    			},
    			/**
    
    Jimmy's avatar
    Jimmy committed
    			 * One for dx,dy,width, other for colours.
    
    aimozg's avatar
    aimozg committed
    			 */
    
    Jimmy's avatar
    Jimmy committed
    			filters: ["close_vagina", "under_lower"],
    
    aimozg's avatar
    aimozg committed
    			animationfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "sex-6f-" + options.close_vagina_speed;
    			},
    
    aimozg's avatar
    aimozg committed
    		},
    
    Jimmy's avatar
    Jimmy committed
    		close_vagina_penetrator: {
    
    aimozg's avatar
    aimozg committed
    			z: 254,
    			showfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return options.close_vagina_show && !!options.vagina_state && !!options.vagina_penetrator;
    
    aimozg's avatar
    aimozg committed
    			},
    			srcfn(options) {
    				switch (options.vagina_state) {
    					case "penetrated":
    						switch (options.vagina_penetrator) {
    							case "tentacle":
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/close/" + options.position + "/vaginatentaclepenetrated.png";
    
    aimozg's avatar
    aimozg committed
    							case "machine":
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/close/machine/vaginal/" + options.position + "/penetrated_close.png";
    
    aimozg's avatar
    aimozg committed
    							case "beast":
    								if (options.vagina_penetrator_subtype === "horse" || options.vagina_penetrator_subtype === "centaur") {
    
    Jimmy's avatar
    Jimmy committed
    									return "img/sex/close/horse/vaginapenetratedhorse.png";
    
    aimozg's avatar
    aimozg committed
    								} else {
    
    Jimmy's avatar
    Jimmy committed
    									return "img/sex/close/" + options.position + "/vaginapenetratedbeast.png";
    
    aimozg's avatar
    aimozg committed
    								}
    							default:
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/close/" + options.position + "/vaginapenetrated.png";
    
    aimozg's avatar
    aimozg committed
    						}
    					case "imminent":
    					case "entrance":
    						switch (options.vagina_penetrator) {
    							case "tentacle":
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/close/" + options.position + "/vaginatentacleentrance.png";
    
    aimozg's avatar
    aimozg committed
    							case "machine":
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/machine/vaginal/" + options.position + "/entrance_close.png";
    
    aimozg's avatar
    aimozg committed
    							case "beast":
    								if (options.vagina_penetrator_subtype === "horse" || options.vagina_penetrator_subtype === "centaur") {
    
    Jimmy's avatar
    Jimmy committed
    									return "img/sex/close/horse/vaginaentrancehorse.png";
    
    aimozg's avatar
    aimozg committed
    								} else {
    
    Jimmy's avatar
    Jimmy committed
    									return "img/sex/close/" + options.position + "/vaginaentrancebeast.png";
    
    aimozg's avatar
    aimozg committed
    								}
    							default:
    
    Jimmy's avatar
    Jimmy committed
    								return "img/sex/close/" + options.position + "/vaginaentrance.png";
    
    aimozg's avatar
    aimozg committed
    						}
    				}
    			},
    
    Jimmy's avatar
    Jimmy committed
    			filters: ["close_vagina"],
    
    aimozg's avatar
    aimozg committed
    			animationfn(options) {
    
    Jimmy's avatar
    Jimmy committed
    				return "sex-6f-" + options.close_vagina_speed;
    			},
    		},
    	},
    };