diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets index ad1f62e5..b47ee331 100644 --- a/.vscode/snippets.code-snippets +++ b/.vscode/snippets.code-snippets @@ -7,5 +7,26 @@ "@experimental This feature is in experimental phase, it will be fully released in v3001.1.0", ], "description": "Add @experimental tag in JSDoc" + }, + "Add documentation template": { + "scope": "typescript", + "prefix": "kpd-doc", + "body": [ + "/**", + "* Attach and render a circle to a Game Object.", + "*", + "* @param radius - The radius of the circle.", + "* @param opt - Options for the circle component. See {@link CircleCompOpt `CircleCompOpt`}.", + "*", + "* @example", + "* ```js", + "* ```", + "*", + "* @returns The circle comp.", + "* @since v3000.0", + "* @group Components", + "*/" + ], + "description": "Add the documentation template in a doc entry." } } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index be03d0e8..cb32edb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,11 +41,32 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Changed default behaviour of `kaplay({ tagsAsComponents: false })` to `false`. - Now if you pass a nullish value to `.use()` it throws an error -## [3001.0.10] - TBD +## [3001.0.10] "Happy Colors" - TBD ### Added -- Added new option in `LoadSpriteOpt` for loading sprites in an individual +- Added **CSS Colors!** 🎨 **(experimental)** - @lajbel (based on + @dragoncoder047 idea) + + ```js + color("slateblue"); + color("red"); + color("wheat"); + color("tomato"); // yum! + ``` + +- Added `loadHappy()` font to load a default font, happy :D - @lajbel + + ```js + kaplay({ font: "happy" }); + loadHappy(); + + add([ + text("ohhi"), + ]); + ``` + +- Added a new option in `LoadSpriteOpt` for loading sprites in an individual spritesheet - @chqs-git ```js loadSprite( diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 306b2e60..5dadbd4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,6 +60,7 @@ There is the structure of a JSDoc comment: - `@requires` when the member requires something to work. Usually a component. - `@param` for each parameter. Each parameter should have - at start. - `@example` for 1 (and only one) example. +- `@static` only if the value is an static method - `@returns` for the return value description. - `@since` for the version when the member was added. - `@group` for the group of the member. diff --git a/examples/lifespan.js b/examples/lifespan.js index 891fa63d..a501aa56 100644 --- a/examples/lifespan.js +++ b/examples/lifespan.js @@ -1,6 +1,5 @@ // @ts-check - kaplay(); const sprites = [ @@ -30,7 +29,7 @@ loop(0.1, () => { // lifespan() comp destroys the object after desired seconds lifespan(1, { // it will fade after 0.5 seconds - fade: 0.5 + fade: 0.5, }), opacity(1), move(choose([LEFT, RIGHT]), rand(60, 240)), diff --git a/examples/particle.js b/examples/particle.js index e21a2e1e..104d860c 100644 --- a/examples/particle.js +++ b/examples/particle.js @@ -5,7 +5,7 @@ kaplay(); loadSprite("star", "./examples/sprites/particle_star_filled.png"); onLoad(() => { - go("game") + go("game"); }); function woah() { @@ -46,4 +46,3 @@ scene("game", () => { text("press space for particles"), ]); }); - diff --git a/src/assets/bitmapFont.ts b/src/assets/bitmapFont.ts index f27814db..cb9a10f8 100644 --- a/src/assets/bitmapFont.ts +++ b/src/assets/bitmapFont.ts @@ -1,6 +1,7 @@ import { ASCII_CHARS } from "../constants"; import { Texture } from "../gfx"; import { _k } from "../kaplay"; +import happyFont from "../kassets/happy.png"; import type { Quad } from "../math/math"; import type { TexFilter } from "../types"; import { type Asset, loadImg } from "./asset"; @@ -38,7 +39,7 @@ export function loadBitmapFont( return _k.assets.bitmapFonts.add( name, - loadImg(src) + loadImg(fontSrc) .then((img) => { return makeFont( Texture.fromImage(_k.gfx.ggl, img, opt), @@ -49,3 +50,11 @@ export function loadBitmapFont( }), ); } + +// loading happiness... +export const loadHappy = ( + fontName: string = "happy", + opt?: LoadBitmapFontOpt, +) => { + return loadBitmapFont(fontName, happyFont, 28, 36, opt); +}; diff --git a/src/assets/sprite.ts b/src/assets/sprite.ts index 9092adba..f4bd04a4 100644 --- a/src/assets/sprite.ts +++ b/src/assets/sprite.ts @@ -139,7 +139,9 @@ export class SpriteData { data: ImageSource, opt: LoadSpriteOpt = {}, ): SpriteData { - const [tex, quad, packerId] = opt.singular ? _k.assets.packer.add_single(data) : _k.assets.packer.add(data); + const [tex, quad, packerId] = opt.singular + ? _k.assets.packer.add_single(data) + : _k.assets.packer.add(data); const frames = opt.frames ? opt.frames.map((f) => new Quad( diff --git a/src/kaplay.ts b/src/kaplay.ts index 34db2687..111a0e67 100644 --- a/src/kaplay.ts +++ b/src/kaplay.ts @@ -59,6 +59,7 @@ import { loadBean, loadBitmapFont, loadFont, + loadHappy, loadJSON, loadMusic, loadPedit, @@ -1213,6 +1214,7 @@ const kaplay = < loadAseprite, loadPedit, loadBean, + loadHappy: loadHappy, loadJSON, load, getSound, diff --git a/src/kassets/happy.png b/src/kassets/happy.png new file mode 100644 index 00000000..0f7b2d03 Binary files /dev/null and b/src/kassets/happy.png differ diff --git a/src/math/color.ts b/src/math/color.ts index b65a72a6..c9c1ac82 100644 --- a/src/math/color.ts +++ b/src/math/color.ts @@ -3,6 +3,152 @@ import { clamp, lerp } from "./math"; export type RGBValue = [number, number, number]; export type RGBAValue = [number, number, number, number]; +// For using color("gray"), color("red") +const CSS_COLOR_MAP = { + black: "#000000", + silver: "#c0c0c0", + gray: "#808080", + white: "#ffffff", + maroon: "#800000", + red: "#ff0000", + purple: "#800080", + fuchsia: "#ff00ff", + green: "#008000", + lime: "#00ff00", + olive: "#808000", + yellow: "#ffff00", + navy: "#000080", + blue: "#0000ff", + teal: "#008080", + aqua: "#00ffff", + aliceblue: "#f0f8ff", + antiquewhite: "#faebd7", + aquamarine: "#7fffd4", + azure: "#f0ffff", + beige: "#f5f5dc", + bisque: "#ffe4c4", + blanchedalmond: "#ffebcd", + blueviolet: "#8a2be2", + brown: "#a52a2a", + burlywood: "#deb887", + cadetblue: "#5f9ea0", + chartreuse: "#7fff00", + chocolate: "#d2691e", + coral: "#ff7f50", + cornflowerblue: "#6495ed", + cornsilk: "#fff8dc", + crimson: "#dc143c", + cyan: "#00ffff", + darkblue: "#00008b", + darkcyan: "#008b8b", + darkgoldenrod: "#b8860b", + darkgray: "#a9a9a9", + darkgreen: "#006400", + darkkhaki: "#bdb76b", + darkmagenta: "#8b008b", + darkolivegreen: "#556b2f", + darkorange: "#ff8c00", + darkorchid: "#9932cc", + darkred: "#8b0000", + darksalmon: "#e9967a", + darkseagreen: "#8fbc8f", + darkslateblue: "#483d8b", + darkslategray: "#2f4f4f", + darkturquoise: "#00ced1", + darkviolet: "#9400d3", + deeppink: "#ff1493", + deepskyblue: "#00bfff", + dimgray: "#696969", + dodgerblue: "#1e90ff", + firebrick: "#b22222", + floralwhite: "#fffaf0", + forestgreen: "#228b22", + gainsboro: "#dcdcdc", + ghostwhite: "#f8f8ff", + gold: "#ffd700", + goldenrod: "#daa520", + greenyellow: "#adff2f", + honeydew: "#f0fff0", + hotpink: "#ff69b4", + indianred: "#cd5c5c", + indigo: "#4b0082", + ivory: "#fffff0", + khaki: "#f0e68c", + lavender: "#e6e6fa", + lavenderblush: "#fff0f5", + lawngreen: "#7cfc00", + lemonchiffon: "#fffacd", + lightblue: "#add8e6", + lightcoral: "#f08080", + lightcyan: "#e0ffff", + lightgoldenrodyellow: "#fafad2", + lightgray: "#d3d3d3", + lightgreen: "#90ee90", + lightpink: "#ffb6c1", + lightsalmon: "#ffa07a", + lightseagreen: "#20b2aa", + lightskyblue: "#87cefa", + lightslategray: "#778899", + lightsteelblue: "#b0c4de", + lightyellow: "#ffffe0", + limegreen: "#32cd32", + linen: "#faf0e6", + mediumaquamarine: "#66cdaa", + mediumblue: "#0000cd", + mediumorchid: "#ba55d3", + mediumpurple: "#9370db", + mediumseagreen: "#3cb371", + mediumslateblue: "#7b68ee", + mediumspringgreen: "#00fa9a", + mediumturquoise: "#48d1cc", + mediumvioletred: "#c71585", + midnightblue: "#191970", + mintcream: "#f5fffa", + mistyrose: "#ffe4e1", + moccasin: "#ffe4b5", + navajowhite: "#ffdead", + oldlace: "#fdf5e6", + olivedrab: "#6b8e23", + orange: "#ffa500", + orangered: "#ff4500", + orchid: "#da70d6", + palegoldenrod: "#eee8aa", + palegreen: "#98fb98", + paleturquoise: "#afeeee", + palevioletred: "#db7093", + papayawhip: "#ffefd5", + peachpuff: "#ffdab9", + peru: "#cd853f", + pink: "#ffc0cb", + plum: "#dda0dd", + powderblue: "#b0e0e6", + rebeccapurple: "#663399", + rosybrown: "#bc8f8f", + royalblue: "#4169e1", + saddlebrown: "#8b4513", + salmon: "#fa8072", + sandybrown: "#f4a460", + seagreen: "#2e8b57", + seashell: "#fff5ee", + sienna: "#a0522d", + skyblue: "#87ceeb", + slateblue: "#6a5acd", + slategray: "#708090", + snow: "#fffafa", + springgreen: "#00ff7f", + steelblue: "#4682b4", + tan: "#d2b48c", + thistle: "#d8bfd8", + tomato: "#ff6347", + turquoise: "#40e0d0", + violet: "#ee82ee", + wheat: "#f5deb3", + whitesmoke: "#f5f5f5", + yellowgreen: "#9acd32", +}; + +export type CSSColor = keyof typeof CSS_COLOR_MAP; + /** * 0-255 RGBA color. * @@ -22,8 +168,7 @@ export class Color { this.b = clamp(b, 0, 255); } - // TODO: Type arr as tuple (no in ts-strict branch yet) - static fromArray(arr: number[]) { + static fromArray(arr: [number, number, number]) { return new Color(arr[0], arr[1], arr[2]); } @@ -93,6 +238,41 @@ export class Color { ); } + /** + * Create a color from a CSS color name + * + * @param cssColor - The color name. + * + * @example + * ```js + * loadHappy(); + * + * add([ + * rect(512, 512, { + * radius: [0, 96, 96, 96] + * }), + * color("#663399"), + * pos(40, 40), + * ]); + * + * add([ + * text("css", { size: 192, font: "happy" }), + * pos(90, 310) + * ]); + * ``` + * + * @static + * @returns The color. + * @experimental This feature is in experimental phase, it will be fully released in v3001.1.0 + */ + static fromCSS(cssColor: CSSColor) { + const color = CSS_COLOR_MAP[cssColor]; + // for js users + if (!color) throw new Error("Can't use an invalid CSS color"); + + return Color.fromHex(color); + } + static RED = new Color(255, 0, 0); static GREEN = new Color(0, 255, 0); static BLUE = new Color(0, 0, 255); @@ -229,24 +409,30 @@ export type ColorArgs = // rgb("#ffffff") | [string] | [number[]] - | []; + | [] + | [CSSColor & (string & {})]; export function rgb(...args: ColorArgs): Color { if (args.length === 0) { return new Color(255, 255, 255); } else if (args.length === 1) { - if (args[0] instanceof Color) { + const cl = args[0]; + + if (cl instanceof Color) { // rgb(new Color(255, 255, 255)) - return args[0].clone(); + return cl.clone(); } - else if (typeof args[0] === "string") { - // rgb("#ffffff") + else if (typeof cl === "string") { + if (cl[0] != "#" && CSS_COLOR_MAP[cl as CSSColor]) { + return Color.fromCSS(cl as CSSColor); + } + return Color.fromHex(args[0]); } else if (Array.isArray(args[0]) && args[0].length === 3) { // rgb([255, 255, 255]) - return Color.fromArray(args[0]); + return Color.fromArray(args[0] as [number, number, number]); } } else if (args.length === 2) { diff --git a/src/types.ts b/src/types.ts index fcb23582..5447b1f4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -124,7 +124,7 @@ import type { Texture, } from "./gfx"; import type { GjkCollisionResult } from "./math"; -import type { Color, RGBAValue, RGBValue } from "./math/color"; +import type { Color, CSSColor, RGBAValue, RGBValue } from "./math/color"; import type { Circle, Ellipse, @@ -496,7 +496,7 @@ export interface KAPLAYCtx< color(r: number, g: number, b: number): ColorComp; color(c: Color): ColorComp; color(rgb: [number, number, number]): ColorComp; - color(c: string): ColorComp; + color(c: CSSColor & (string | {})): ColorComp; color(): ColorComp; /** * Sets the opacity of a Game Object (0.0 - 1.0). @@ -2899,7 +2899,7 @@ export interface KAPLAYCtx< /** * Load default sprite "bean". * - * @param name - The optional name for bean. + * @param name - An optional name for bean. * * @example * ```js @@ -2916,6 +2916,20 @@ export interface KAPLAYCtx< * @group Assets */ loadBean(name?: string): Asset; + /** + * Load default font "happy". + * + * @param name - An optional name for happy. + * + * @example + * ```js + * loadHappy(); + * + * add([ + * text("ohhi", { font: "happy" }), + * ]); + */ + loadHappy(name?: string, opt?: LoadBitmapFontOpt): Asset; /** * Load custom JSON data from url. * @@ -4207,16 +4221,29 @@ export interface KAPLAYCtx< * @example * ```js * sky.color = rgb("#ef6360") + * ``` * * @returns The color. * @since v2000.0 - * @group Math */ rgb(hex: string): Color; /** - * Same as rgb(255, 255, 255). + * Create a color from CSS name. * - * @group Math + * @param cssColor - The CSS name. + * + * @example + * ```js + * sea.color = rgb("slateblue"); + * ``` + * + * @returns The color. + * @since v3001.0.10 + * @experimental This feature is in experimental phase, it will be fully released in v3001.1.0 + */ + rgb(cssColor: CSSColor): Color; + /** + * Same as rgb(255, 255, 255). */ rgb(): Color; /** diff --git a/tests/playtests/css_color.js b/tests/playtests/css_color.js new file mode 100644 index 00000000..fa8853c9 --- /dev/null +++ b/tests/playtests/css_color.js @@ -0,0 +1,15 @@ +kaplay(); +loadHappy(); + +add([ + rect(512, 512, { + radius: [0, 96, 96, 96] + }), + color("rebeccapurple"), + pos(40, 40), +]); + +add([ + text("css", { size: 192, font: "happy" }), + pos(90, 310) +]); \ No newline at end of file