Skip to content

Commit

Permalink
Merge pull request #1605 from Q-Bert-Reynolds/custom-collision-icons
Browse files Browse the repository at this point in the history
engine.json defined collision layers (flags, masks, colors, names, and icons)
  • Loading branch information
chrismaltby authored Oct 24, 2024
2 parents 3e4d63a + eb411cc commit 1d6af1f
Show file tree
Hide file tree
Showing 16 changed files with 762 additions and 697 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add ability to hover over tiles in debugger VRAM preview to see tile memory address information [@pau-tomas](https://github.com/pau-tomas)
- Add animation states to generated `game_globals.h` allowing use from engine code [@Mico27](https://github.com/Mico27)
- Add ability to change collision layer opacity in World view when collision tool is selected [@Q-Bert-Reynolds](https://github.com/Q-Bert-Reynolds)
- Add ability for engine plugins to define new, per scene, collision tile types in `engine.json` file [@Q-Bert-Reynolds]
- Add ability to show the raw collision tile values when editing collisions in world view

### Changed

Expand All @@ -28,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Optimised script editor by throttling the processing that was occuring on every key press
- Update to latest [GBVM](https://github.com/chrismaltby/gbvm)
- Improved collision handling for ladders and one-way platforms in the Platformer scene type. Ladders now use the player's bottom edge for anchoring, and one-way platforms no longer snap the player to the platform when colliding from below [@Steinbeuge](https://github.com/Steinbeuge)
- Ladder collision tile now only visible on Platform scenes by default, edit `engine.json` to add per scene collision tile types

### Fixed

Expand Down
61 changes: 55 additions & 6 deletions appData/src/gb/engine.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,32 +218,81 @@
{
"key": "TOPDOWN",
"label": "GAMETYPE_TOP_DOWN",
"files": ["include/states/topdown.h", "src/states/topdown.c"]
"files": ["include/states/topdown.h", "src/states/topdown.c"],
"collisionTiles": [
{ "key": "solid", "color": "#FA2828FF", "mask": 15, "flag": 15, "name": "FIELD_SOLID", "icon": "FFFFFFFFFFFFFFFF" },
{ "key": "top", "color": "#2828FAFF", "mask": 15, "flag": 1, "name": "FIELD_COLLISION_TOP", "icon": "FFFFFF0000000000", "multi": true },
{ "key": "bottom", "color": "#FFFA28FF", "mask": 15, "flag": 2, "name": "FIELD_COLLISION_BOTTOM", "icon": "0000000000FFFFFF", "multi": true },
{ "key": "left", "color": "#FA28FAFF", "mask": 15, "flag": 4, "name": "FIELD_COLLISION_LEFT", "icon": "E0E0E0E0E0E0E0E0", "multi": true },
{ "key": "right", "color": "#28FAFAFF", "mask": 15, "flag": 8, "name": "FIELD_COLLISION_RIGHT", "icon": "0707070707070707", "multi": true }
]
},
{
"key": "PLATFORM",
"label": "GAMETYPE_PLATFORMER",
"files": ["include/states/platform.h", "src/states/platform.c"]
"files": ["include/states/platform.h", "src/states/platform.c"],
"collisionTiles": [
{ "key" : "solid", "color" : "#FA2828FF", "mask": 15, "flag": 15, "name" : "FIELD_SOLID", "icon" : "FFFFFFFFFFFFFFFF" },
{ "key" : "top", "color" : "#2828FAFF", "mask": 15, "flag": 1, "name" : "FIELD_COLLISION_TOP", "icon" : "FFFFFF0000000000", "multi":true },
{ "key" : "bottom", "color" : "#FFFA28FF", "mask": 15, "flag": 2, "name" : "FIELD_COLLISION_BOTTOM", "icon" : "0000000000FFFFFF", "multi":true },
{ "key" : "left", "color" : "#FA28FAFF", "mask": 15, "flag": 4, "name" : "FIELD_COLLISION_LEFT", "icon" : "E0E0E0E0E0E0E0E0", "multi":true },
{ "key" : "right", "color" : "#28FAFAFF", "mask": 15, "flag": 8, "name" : "FIELD_COLLISION_RIGHT", "icon" : "0707070707070707", "multi":true },
{ "key" : "ladder", "color" : "#008000FF", "mask": 240, "flag": 16, "name" : "FIELD_LADDER", "icon" : "C3FFFFC3C3FFFFC3", "group" : "prop" },
{ "key" : "slope_45_right", "color" : "#0000FFFF", "mask": 240, "flag": 32, "name" : "FIELD_COLLISION_SLOPE_45_RIGHT", "icon" : "0103070F1F3F7FFF", "extra":10, "group" : "slope" },
{ "key" : "slope_45_left", "color" : "#0000FFFF", "mask": 240, "flag": 48, "name" : "FIELD_COLLISION_SLOPE_45_LEFT", "icon" : "80C0E0F0F8FCFEFF", "extra":6, "group" : "slope" },
{ "key" : "slope_22_right_bot", "color" : "#0000FFFF", "mask": 240, "flag": 64, "name" : "FIELD_COLLISION_SLOPE_22_RIGHT_BOT", "icon" : "00000000030F3FFF", "extra":2, "group" : "slope" },
{ "key" : "slope_22_right_top", "color" : "#0000FFFF", "mask": 240, "flag": 96, "name" : "FIELD_COLLISION_SLOPE_22_RIGHT_TOP", "icon" : "030F3FFF00000000", "extra":10, "group" : "slope" },
{ "key" : "slope_22_left_top", "color" : "#0000FFFF", "mask": 240, "flag": 112, "name" : "FIELD_COLLISION_SLOPE_22_LEFT_TOP", "icon" : "C0F0FCFF00000000", "extra":6, "group" : "slope" },
{ "key" : "slope_22_left_bot", "color" : "#0000FFFF", "mask": 240, "flag": 80, "name" : "FIELD_COLLISION_SLOPE_22_LEFT_BOT", "icon" : "00000000C0F0FCFF", "extra":2, "group" : "slope" },
{ "key" : "spare_08", "color" : "#00800080", "mask": 240, "flag": 128, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFFC399C399C3FF", "group" : "spare" },
{ "key" : "spare_09", "color" : "#00800080", "mask": 240, "flag": 144, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFFC399C1F9C3FF", "group" : "spare" },
{ "key" : "spare_10", "color" : "#80000080", "mask": 240, "flag": 160, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFFC399819999FF", "group" : "spare" },
{ "key" : "spare_11", "color" : "#80000080", "mask": 240, "flag": 176, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFF8399839983FF", "group" : "spare" },
{ "key" : "spare_12", "color" : "#00008080", "mask": 240, "flag": 192, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFFC3999F99C3FF", "group" : "spare" },
{ "key" : "spare_13", "color" : "#00008080", "mask": 240, "flag": 208, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFF8399999983FF", "group" : "spare" },
{ "key" : "spare_14", "color" : "#80008080", "mask": 240, "flag": 224, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFF819F879F81FF", "group" : "spare" },
{ "key" : "spare_15", "color" : "#80008080", "mask": 240, "flag": 240, "name" : "FIELD_COLLISION_SPARE", "icon" : "FFFF819F879F9FFF", "group" : "spare" }
]
},
{
"key": "ADVENTURE",
"label": "GAMETYPE_ADVENTURE",
"files": ["include/states/adventure.h", "src/states/adventure.c"]
"files": ["include/states/adventure.h", "src/states/adventure.c"],
"collisionTiles": [
{ "key": "solid", "color": "#FA2828FF", "mask": 15, "flag": 15, "name": "FIELD_SOLID", "icon": "FFFFFFFFFFFFFFFF" },
{ "key": "top", "color": "#2828FAFF", "mask": 15, "flag": 1, "name": "FIELD_COLLISION_TOP", "icon": "FFFFFF0000000000", "multi": true },
{ "key": "bottom", "color": "#FFFA28FF", "mask": 15, "flag": 2, "name": "FIELD_COLLISION_BOTTOM", "icon": "0000000000FFFFFF", "multi": true },
{ "key": "left", "color": "#FA28FAFF", "mask": 15, "flag": 4, "name": "FIELD_COLLISION_LEFT", "icon": "E0E0E0E0E0E0E0E0", "multi": true },
{ "key": "right", "color": "#28FAFAFF", "mask": 15, "flag": 8, "name": "FIELD_COLLISION_RIGHT", "icon": "0707070707070707", "multi": true }
]
},
{
"key": "SHMUP",
"label": "GAMETYPE_SHMUP",
"files": ["include/states/shmup.h", "src/states/shmup.c"]
"files": ["include/states/shmup.h", "src/states/shmup.c"],
"collisionTiles": [
{ "key": "solid", "color": "#FA2828FF", "mask": 15, "flag": 15, "name": "FIELD_SOLID", "icon": "FFFFFFFFFFFFFFFF" },
{ "key": "top", "color": "#2828FAFF", "mask": 15, "flag": 1, "name": "FIELD_COLLISION_TOP", "icon": "FFFFFF0000000000", "multi": true },
{ "key": "bottom", "color": "#FFFA28FF", "mask": 15, "flag": 2, "name": "FIELD_COLLISION_BOTTOM", "icon": "0000000000FFFFFF", "multi": true },
{ "key": "left", "color": "#FA28FAFF", "mask": 15, "flag": 4, "name": "FIELD_COLLISION_LEFT", "icon": "E0E0E0E0E0E0E0E0", "multi": true },
{ "key": "right", "color": "#28FAFAFF", "mask": 15, "flag": 8, "name": "FIELD_COLLISION_RIGHT", "icon": "0707070707070707", "multi": true }
]
},
{
"key": "POINTNCLICK",
"label": "GAMETYPE_POINT_N_CLICK",
"files": ["include/states/pointnclick.h", "src/states/pointnclick.c"]
"files": ["include/states/pointnclick.h", "src/states/pointnclick.c"],
"collisionTiles": [
{ "key": "solid", "color": "#FA2828FF", "mask": 15, "flag": 15, "name": "FIELD_SOLID", "icon": "FFFFFFFFFFFFFFFF" }
]
},
{
"key": "LOGO",
"label": "GAMETYPE_LOGO",
"files": ["include/states/logo.h", "src/states/logo.c"]
"files": ["include/states/logo.h", "src/states/logo.c"],
"collisionTiles": [
{ "key": "solid", "color": "#FA2828FF", "mask": 15, "flag": 15, "name": "FIELD_SOLID", "icon": "FFFFFFFFFFFFFFFF" }
]
}
]
}
52 changes: 52 additions & 0 deletions src/components/collisions/CollisionTileIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { defaultCollisionTileColor, defaultCollisionTileIcon } from "consts";
import React, { useEffect, useRef } from "react";
import { renderCollisionTileIcon } from "shared/lib/collisions/collisionTiles";
import styled from "styled-components";

interface CollisionTileIconProps {
icon?: string;
color?: string;
}

const CollisionTileIconCanvas = styled.canvas`
image-rendering: pixelated;
width: 20px;
height: 20px;
border-radius: 4px;
background: ${(props) => props.theme.colors.input.background};
border: 2px solid ${(props) => props.theme.colors.input.background};
outline: 1px solid ${(props) => props.theme.colors.input.border};
`;

export const CollisionTileIcon = ({ icon, color }: CollisionTileIconProps) => {
const ref = useRef<HTMLCanvasElement>(null);

useEffect(() => {
const canvas = ref.current;
if (!canvas) {
return;
}
const ctx = canvas.getContext("2d");
if (!ctx) {
return;
}

// eslint-disable-next-line no-self-assign
canvas.width = canvas.width;

const tileIcon = renderCollisionTileIcon(
icon ?? defaultCollisionTileIcon,
color ?? defaultCollisionTileColor
);

ctx.drawImage(tileIcon, 0, 0);
}, [icon, color]);

return (
<CollisionTileIconCanvas
ref={ref}
width="8"
height="8"
></CollisionTileIconCanvas>
);
};
10 changes: 10 additions & 0 deletions src/components/ui/icons/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ export const AngleIcon = () => (
</svg>
);

export const TileValueIcon = () => (
<svg width="24" height="24" viewBox="0 0 24 24">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3 7C3 4.79086 4.79086 3 7 3H17C19.2091 3 21 4.79086 21 7V17C21 19.2091 19.2091 21 17 21H7C4.79086 21 3 19.2091 3 17V7ZM12.5 15.5V8.5H19.5V9.5H14.5V11.5H17.5V12.5H14.5V15.5H12.5ZM5.5 14.5V15.5H11.5V14.5H9.5V8.5H5.5V9.5H7.5V14.5H5.5Z"
/>
</svg>
);

export const SquareRootIcon = () => (
<svg width="24" height="24" viewBox="0 0 24 24">
<path
Expand Down
Loading

0 comments on commit 1d6af1f

Please sign in to comment.