You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've noticed several discussions in the community where developers, including myself, were unsure about how to properly animate a sprite sheet using React Native Skia. After much experimentation and navigating through a bit of trial and error, I've developed a solution that seems to work effectively.
Given the apparent gap in resources and tutorials on this topic, I was wondering if you might consider creating a dedicated component to simplify this process for others. Alternatively, a tutorial video on your YouTube channel could greatly benefit the community by providing a clear, accessible guide on sprite sheet animation with React Native Skia.
Thank you for considering this suggestion. Your contributions have been incredibly valuable to the community, and I believe this could be another great addition.
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Pressable, View, useWindowDimensions } from "react-native";
import { collisions } from "../data/collision";
import { PlatformConfig } from "@/Store/PlatformStore";
import { is2DColiding, isColiding } from "@/helpers/isColiding";
Uploading 20240410_144737.mp4…
Description
Hello @william-candillon,
I've noticed several discussions in the community where developers, including myself, were unsure about how to properly animate a sprite sheet using React Native Skia. After much experimentation and navigating through a bit of trial and error, I've developed a solution that seems to work effectively.
Given the apparent gap in resources and tutorials on this topic, I was wondering if you might consider creating a dedicated component to simplify this process for others. Alternatively, a tutorial video on your YouTube channel could greatly benefit the community by providing a clear, accessible guide on sprite sheet animation with React Native Skia.
Thank you for considering this suggestion. Your contributions have been incredibly valuable to the community, and I believe this could be another great addition.
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useCallback, useEffect, useMemo, useState } from "react";
import { Pressable, View, useWindowDimensions } from "react-native";
import { collisions } from "../data/collision";
import { PlatformConfig } from "@/Store/PlatformStore";
import { is2DColiding, isColiding } from "@/helpers/isColiding";
import {
Canvas,
Circle,
Group,
Image,
Mask,
Path,
Rect,
useClock,
useImage,
vec,
} from "@shopify/react-native-skia";
import {
SharedValue,
useDerivedValue,
useFrameCallback,
useSharedValue,
} from "react-native-reanimated";
export default function App() {
const [newTileMap, setNewTileMap] = useState<PlatformConfig[]>([]);
const vec2 = (x: SharedValue, y: SharedValue) => {
return { x, y };
};
const tileSize = 32;
const tileRows = 211;
const tileCols = 15;
const SCREEN_WIDTH = useWindowDimensions().width;
const SCREEN_HEIGHT = useWindowDimensions().height;
const mario_spriteSheet = useImage(require("../assets/sprites/mario_spritesheet.png"));
const spriteWidth = 186;
const spriteHeight = 34;
const frameSize = vec(spriteWidth / 6, spriteHeight);
enum PlayerState {
IDLE,
WALKING,
JUMPING,
FALLING,
}
const playerState = useSharedValue(PlayerState.IDLE);
const bg = useImage(require("../assets/sprites/tiles/bg.png"));
const wall = useImage(require("../assets/sprites/tiles/land_14.png"));
const map = useImage(require("../assets/sprites/tiles/map.png"));
const direction = {
left: useSharedValue(false),
right: useSharedValue(false),
up: useSharedValue(false),
down: useSharedValue(false),
};
const groundY = SCREEN_HEIGHT - 240;
const loadMap = useCallback(() => {
const tileMap: PlatformConfig[] = [];
collisions.forEach((row, rowIndex) => {
row.forEach((col, colIndex) => {
if (col !== 0) {
tileMap.push({
x: colIndex * tileSize,
y: rowIndex * tileSize,
w: tileSize,
h: tileSize,
val: col,
});
}
});
});
setNewTileMap(tileMap);
}, []);
useEffect(() => {
loadMap();
}, []);
const player = {
h: frameSize.y,
w: frameSize.x,
velocity: vec2(useSharedValue(0), useSharedValue(0)),
pos: {
x: useSharedValue(250),
y: useSharedValue(groundY + 154),
},
};
const world = {
x: useSharedValue(0),
y: useSharedValue(groundY),
vel: vec2(useSharedValue(0), useSharedValue(0)),
};
const transform = useDerivedValue(() => {
return [
{ translateX: world.x.value },
{ translateY: world.y.value },
{ scaleX: 2 },
{ scaleY: 2 }
];
});
const frame = useSharedValue(1);
const frameDerived = useDerivedValue(() => {
return -frame.value * frameSize.x;
});
const elapsed = useSharedValue(0);
const prevWorldPosX = useSharedValue(0);
const prevWorldPosY = useSharedValue(0);
const getTileX = (x: number) => {
'worklet'
}
const getTileY = (y: number) => {
'worklet'
}
const playerOBJ = {
x: player.pos.x.value,
y: player.pos.y.value,
w: frameSize.x,
h: frameSize.y,
};
function applyGravity(){
'worklet'
world.vel.y.value -= 2;
world.y.value += world.vel.y.value;
};
function checkCollisionv(){
'worklet'
newTileMap.forEach((tile) => {
const adjustedTile = {
x: getTileX(tile.x),
y: getTileY(tile.y - 45),
w: tile.w,
h: tile.h,
};
};
function checkCollisionH(){
'worklet'
newTileMap.forEach((tile) => {
const adjustedTile = {
x: getTileX(tile.x),
y: getTileY(tile.y),
w: tile.w,
h: tile.h,
};
};
useFrameCallback(({ timeSincePreviousFrame: dt }) => {
if (!dt) return;
function checkPlayerStateAndVelocity(){
'worklet'
if (direction.right.value) {
playerState.value = PlayerState.WALKING;
world.vel.x.value = -3;
} else if (direction.left.value) {
playerState.value = PlayerState.WALKING;
world.vel.x.value = 3;
} else if (!direction.up.value && !direction.down.value && !direction.left.value && !direction.right.value) {
playerState.value = PlayerState.IDLE;
}
};
checkPlayerStateAndVelocity();
applyGravity();
checkCollisionv();
checkCollisionH();
});
return (
<View style={{ position: "relative", flex: 1, justifyContent: "center", alignItems: "center" }}>
<Canvas style={{ width: SCREEN_WIDTH, height: SCREEN_HEIGHT, backgroundColor: "#5c94fc" }}>
<Image image={map} x={0} y={50} width={211 * 16} height={15 * 16} />
);
}
function createControlButton(iconName: string|any, positionLeft: number, onPressIn: () => void, onPressOut: () => void): JSX.Element {
return (
<Pressable
style={{
position: "absolute",
bottom: 20,
left: positionLeft,
}}
onPressIn={onPressIn}
onPressOut={onPressOut}
>
);
}
The text was updated successfully, but these errors were encountered: