Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag and drop animations #223

Open
wants to merge 75 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
907bed2
Migrate food wheel from old branch
peter-tanner Dec 4, 2021
42e1570
Wheel now focuses correct slice
peter-tanner Dec 4, 2021
b2aa368
Wheel now scales correctly if the window height decreases
peter-tanner Dec 7, 2021
7a5ecb4
Fix #199, add resize hook and css to make vertical resize work
peter-tanner Dec 8, 2021
1ee5fc1
Basic attempt at drag and drop object. Proper window resize still req…
peter-tanner Dec 10, 2021
f37aa2a
Removed window height hook, made pie chart use relative position for …
peter-tanner Dec 15, 2021
6834946
test changes
RupesAUS Dec 17, 2021
caa2c12
character image mapping 5 images working
RupesAUS Dec 17, 2021
cc43197
Start refactoring to angles, mutex test
peter-tanner Dec 18, 2021
1cb3ef7
Use disk to determine slice instead of `<area>` polygon
peter-tanner Dec 21, 2021
8366dd0
Merge remote-tracking branch 'origin/experimental-drag-drop-rupert' i…
peter-tanner Dec 21, 2021
8305d30
Remove old react-draggable files, add events to `Draggable`, basic ga…
peter-tanner Dec 21, 2021
81ca0b5
added foundation for character spawner
RupesAUS Jan 5, 2022
5ca13f5
generate character set function works, not functional with game logic…
RupesAUS Jan 5, 2022
51c8e9c
Added 'highlighting' zoom of food character under mouse.
bryce-oc Jan 8, 2022
a446521
Use `Draggable` position for wheel detection, add round modal, refactor
peter-tanner Jan 15, 2022
997f01a
- Updated tailwind
CodeWithTheDoctor Jan 15, 2022
d8f8b41
Added float() and defloat() functions to make hovered Draggables 'flo…
bryce-oc Jan 15, 2022
7167327
Removed redundant z-0 in second <div> and adjusted width and height v…
bryce-oc Jan 15, 2022
5d26f2b
Removed defloat() call from stopDrag() as characters should only defl…
bryce-oc Jan 17, 2022
1448d34
functional 10 character randomisation
RupesAUS Jan 17, 2022
7c3bec6
Pushed small experimental changes for John
RupesAUS Jan 20, 2022
1df9e71
characters received from the DB
x4wiz Jan 20, 2022
dcad2a1
Notion character db integration with draggables now functional
RupesAUS Jan 21, 2022
edfd18b
Added 'wiggle' and 'vibrate' animation styles, made Draggables wiggle…
bryce-oc Jan 22, 2022
a8faa2b
Refactored wiggle transform and Draggable scale to be more stable for…
bryce-oc Jan 22, 2022
ba9a783
Merge branch 'update-simple-drag-and-drop-foodgroupV2' into drag-and-…
bryce-oc Jan 22, 2022
51a13ae
Fixed positioning bug with NextJS12 : Wrapper span from nextjs image …
RupesAUS Jan 24, 2022
84addc0
Tailwind css
peter-tanner Jan 24, 2022
50f7961
Merge branch 'update-simple-drag-and-drop-foodgroupV2' of github.com:…
peter-tanner Jan 24, 2022
c7cd8a7
Unbreak package-lock
peter-tanner Jan 24, 2022
d0e25fd
Cleanup styles, converted css to tailwindcss
peter-tanner Jan 24, 2022
6a1f8ee
Fixed image loading problem (hacky solution with hidden html element)
RupesAUS Jan 25, 2022
00810a2
Merge branch 'update-simple-drag-and-drop-foodgroupV2' of https://git…
RupesAUS Jan 25, 2022
2b16f6e
Clean up/refactor
peter-tanner Jan 26, 2022
4c6c3e3
Merge branch 'refactor/firebase-authentication' into update-simple-dr…
peter-tanner Jan 26, 2022
47fa445
food groups use enum, fix mouse override on unhover and rehover
peter-tanner Jan 26, 2022
3bebb11
Merge branch 's174-trophy-room' into update-simple-drag-and-drop-food…
peter-tanner Jan 29, 2022
24e8840
Merge branch 'update-simple-drag-and-drop-foodgroupV2' into drag-and-…
bryce-oc Jan 29, 2022
8501d98
Basic achievements for foodgame
peter-tanner Jan 29, 2022
4d4bfee
Merge branch 'update-simple-drag-and-drop-foodgroupV2' into drag-and-…
bryce-oc Jan 29, 2022
55441f0
Fixed errors and redundancies created by merge.
bryce-oc Jan 29, 2022
7b2b01c
Added functionality to make characters' names appear when hovered on …
bryce-oc Jan 29, 2022
e32fdc4
Styled name popup on Draggables to be clearer.
bryce-oc Feb 1, 2022
313a580
Modified Transition parameters to improve name appearance/disappearan…
bryce-oc Feb 1, 2022
ec15380
Modified Transition parameters slightly to improve smoothness.
bryce-oc Feb 1, 2022
3010d1c
Achievement logic works logged out/signing in, refactor notion
peter-tanner Feb 2, 2022
4135040
Styled Foodwheel with appropriate draggable spawner locations and add…
RupesAUS Feb 4, 2022
30f04b9
Merge branch 'update-simple-drag-and-drop-foodgroupV2' of https://git…
RupesAUS Feb 4, 2022
7e626dc
Replaced hoverStyle useState with z-20 hover:z-30 Tailwind classes; c…
bryce-oc Feb 5, 2022
52a1206
WIP - added CSS animation-delay to attempt to cancel starting jolt of…
bryce-oc Feb 5, 2022
8ce5827
Merge branch 'update-simple-drag-and-drop-foodgroupV2' into drag-and-…
bryce-oc Feb 5, 2022
ef019ba
Crap
peter-tanner Feb 5, 2022
61c21ed
Start of dirty refactor
RupesAUS Feb 8, 2022
6126cbf
Refactored code, Added Randomized Features, General Cleanup, Fixed Us…
RupesAUS Feb 8, 2022
e179f43
Merge branch 'update-simple-drag-and-drop-foodgroupV2' into drag-and-…
bryce-oc Feb 9, 2022
4a7f403
Images now scale responsively
RupesAUS Feb 10, 2022
c2c7642
fix reset on 2nd round
peter-tanner Feb 12, 2022
316e6ed
Merge branch 'drag-and-drop-animations' into update-simple-drag-and-d…
peter-tanner Feb 12, 2022
eb936b2
Merge branch 'drag-and-drop-animations' into update-simple-drag-and-d…
peter-tanner Feb 12, 2022
057af90
fix issue with img caching, wrong positions for second draggables set
peter-tanner Feb 12, 2022
8045b91
Added backdrop to drag-and-drop game that scales to fit page.
bryce-oc Feb 12, 2022
b296409
Responsive edits
RupesAUS Feb 14, 2022
7861b46
Merge branch 'update-simple-drag-and-drop-foodgroupV2' of https://git…
RupesAUS Feb 14, 2022
344dbfd
Shared Coding Changes
RupesAUS Feb 15, 2022
4d97bde
Responsive start positions, fix center wheel bug
peter-tanner Feb 17, 2022
18eb897
responsive end positions on wheel
peter-tanner Feb 17, 2022
d568ae9
Basic clean up of old unused code
peter-tanner Feb 17, 2022
38f4133
Made background image fit to parent (which ideally means fitting to s…
bryce-oc Feb 19, 2022
df968bb
Merged main into update-simple-drag-and-drop-foodgroupV2
RupesAUS Feb 19, 2022
bcfe7cb
Merge branch 'update-simple-drag-and-drop-foodgroupV2' into drag-and-…
bryce-oc Feb 19, 2022
3c3c6c7
Fixed merge-related import bug causing error.
bryce-oc Feb 19, 2022
10d389f
Fixed merge-related bug where background would not fill to bottom of …
bryce-oc Feb 19, 2022
c6c034e
Added variable top padding on title for md and lg breakpoints.
bryce-oc Feb 19, 2022
f036ae5
Style heading text, centered instruction text.
bryce-oc Mar 2, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .husky/pre-commit

This file was deleted.

89 changes: 89 additions & 0 deletions components/FoodGroups/API/getData.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Client } from '@notionhq/client'
import { FoodGroupCharacterImage } from '../Draggable/types'

import { notion_food_dict } from '../Draggable/characterimages'

import { QueryDatabaseResponse } from '@notionhq/client/build/src/api-endpoints'

if (process.env.NOTION_API_KEY === undefined) {
console.error('[ FATAL ]: NO NOTION_API_KEY IN ENVIRONMENT VARIABLES')
process.exit(1)
}
if (process.env.NOTION_CHARACTERS_DB_ID === undefined) {
console.error(
'[ FATAL ]: NO NOTION_CHARACTERS_DB_ID IN ENVIRONMENT VARIABLES'
)
process.exit(1)
}

const notion = new Client({
auth: process.env.NOTION_API_KEY
})

const getCharacterData = async () => {
let data = await notion.databases.query({
database_id: process.env.NOTION_CHARACTERS_DB_ID ?? 'ERROR'
})

return { data }
}

const getFormatData = (data: QueryDatabaseResponse) => {
const formattedData: FoodGroupCharacterImage[] = []

// iterate through each record in the character database
data.results.forEach(characterRecord => {
const page = characterRecord as Extract<
typeof characterRecord,
{ properties: {} }
>

const properties = page.properties

if (
properties.image.type === 'files' &&
properties.image.files[0] !== undefined &&
properties.image.files[0].type === 'file' &&
properties.foodGroup.type === 'rich_text' &&
properties.name.type === 'title'
) {
if (properties.foodGroup.rich_text[0] === undefined) {
// Melody Melon does not have a food type assigned.
console.error(
`[ ERROR ]: No food type for ${properties.name.title[0].plain_text}`
)
return
}
const characterFoodGroup: string =
properties.foodGroup.rich_text[0].plain_text
const defaultProperties = {
name: properties.name.title[0].plain_text,
img_src: properties.image.files[0].file.url
}

if (characterFoodGroup === 'Water') return // Ignore cool glass

const type = notion_food_dict.get(characterFoodGroup)

if (type === undefined) {
console.error(
`[ ERROR ]: Invalid food type for ${defaultProperties.name}. Got type ${type}`
)
return
}

formattedData.push({
div_id: `${type}-character`,
img_id: `${type}-character-img`,
type: type,
bounding_box_id: 0,
...defaultProperties
})
} else {
console.error('[ ERROR ]: Bad type!')
}
})
return formattedData
}

export { getCharacterData, getFormatData }
22 changes: 22 additions & 0 deletions components/FoodGroups/Draggable/boundingbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
interface BoundingBox {
x1: number
y1: number
x2: number
y2: number
}

interface Vector2 {
x: number
y: number
}

export const ORIGIN_VECTOR2 = { x: 0, y: 0 }

const inBoundingBox = (box: BoundingBox, point: Vector2) =>
point.x < box.x2 && point.x > box.x1 && point.y < box.y2 && point.y > box.y1

export const cloneVector2 = (v:Vector2) => {
return {x:v.x, y:v.y}
}
export type { BoundingBox, Vector2 }
export { inBoundingBox }
19 changes: 19 additions & 0 deletions components/FoodGroups/Draggable/characterimages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { GROUPS } from '../groups'

let notion_food_dict = new Map<string, GROUPS>([
// OLD - REMOVE ONCE DATABASE IS MIGRATED (Note that the dash is different from -)
['Vegetables – protective foods', GROUPS.VEGETABLES],
['Breads and Cereals – Energy Foods', GROUPS.GRAINS],
['Dairy foods – body building', GROUPS.DAIRY],
['Meat/Protein – body building', GROUPS.MEAT],
['Fruit – Protective foods', GROUPS.FRUIT],

// TEMP - REMOVE THIS MAP ONCE MIGRATED TO NAMES
[GROUPS.VEGETABLES, GROUPS.VEGETABLES],
[GROUPS.GRAINS, GROUPS.GRAINS],
[GROUPS.DAIRY, GROUPS.DAIRY],
[GROUPS.MEAT, GROUPS.MEAT],
[GROUPS.FRUIT, GROUPS.FRUIT]
])

export { notion_food_dict }
242 changes: 242 additions & 0 deletions components/FoodGroups/Draggable/characterspawner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import React, { useState, useEffect } from 'react'
import Draggable, { DRAGGING_STATE } from '@components/FoodGroups/Draggable'
import { State_, StateDispatch } from '../types'

import {
FoodGroupCharacterImage,
FoodGroupCharacterImageDynamic
} from './types'
import { FOOD_GROUPS, GROUPS } from '@components/FoodGroups/groups'
import {
ORIGIN_VECTOR2,
Vector2
} from '@components/FoodGroups/Draggable/boundingbox'

const N_DRAGGABLES = 5

const updatedFunction = (f: Function) => {
const [rerender, setRerender] = useState(0)
useEffect(() => {
f()
}, [rerender])
return () => setRerender(rerender + 1)
}

export const CHARACTER_POSITIONS: Vector2[] = [
{ x: 5, y: 25 },
{ x: 25, y: 5 },
{ x: 45, y: 25 },
{ x: 50 / 3, y: 50 },
{ x: 100 / 3, y: 50 }
]

export const CHARACTER_END: Record<string, Vector2[]> = {
// TODO: Add positions for the second set of characters if a game with 10 charcters is used.
[GROUPS.DAIRY]: [
{ x: 45, y: 70 },
{ x: 0, y: 0 }
],
[GROUPS.FRUIT]: [
{ x: 60, y: 55 },
{ x: 0, y: 0 }
],
[GROUPS.GRAINS]: [
{ x: 20, y: 20 },
{ x: 0, y: 0 }
],
[GROUPS.VEGETABLES]: [
{ x: 60, y: 20 },
{ x: 0, y: 0 }
],
[GROUPS.MEAT]: [
{ x: 25, y: 60 },
{ x: 0, y: 0 }
],
[GROUPS.NONE]: [],
[GROUPS.DEFAULT]: [],
[GROUPS.TUCKER]: []
}

function generateCharacterSet(character_data: FoodGroupCharacterImage[]) {
if (character_data === undefined)
throw new Error('Undefined character_data data')

const characterSet: FoodGroupCharacterImageDynamic[] = []

const filterFunction = (type: string) =>
character_data.filter(character => character.type === type)

const characters = FOOD_GROUPS.map(group => filterFunction(group))

let positionsTmp = Array.from(Array(N_DRAGGABLES).keys()) // [0,1,2,...,N_DRAGGABLES-1]
let positions: number[] = []
for (let i = positionsTmp.length - 1; i >= 0; i--) {
const idx = Math.floor(Math.random() * i)
positions.push(positionsTmp[idx])
positionsTmp.splice(idx, 1)
}

const TYPE_COUNT: { [K in GROUPS]: number } = {
[GROUPS.DAIRY]: 0,
[GROUPS.FRUIT]: 0,
[GROUPS.GRAINS]: 0,
[GROUPS.VEGETABLES]: 0,
[GROUPS.MEAT]: 0,
// Others for type safety
[GROUPS.NONE]: 0,
[GROUPS.DEFAULT]: 0,
[GROUPS.TUCKER]: 0
}

characters.forEach((characterTypeSet, i) => {
const character =
characterTypeSet[Math.floor(Math.random() * characterTypeSet.length)]
const test: FoodGroupCharacterImageDynamic = {
start_index: positions[i],
end_index: TYPE_COUNT[character.type],
...character
}
characterSet.push(test)
TYPE_COUNT[character.type]++
})

return characterSet
}

interface Props {
endDragFunc: Function
startDragFunc: [StateDispatch<Vector2>, StateDispatch<GROUPS>]
absPositionSetState: StateDispatch<Vector2>
draggablePositions_1: State_<Vector2>[]
draggablePositions_2: State_<Vector2>[]
draggingStates: State_<DRAGGING_STATE[]>
draggableZone: State_<DOMRect | undefined>
currentCharSet: FoodGroupCharacterImageDynamic[]
nextCharSet: FoodGroupCharacterImageDynamic[]
switchSetFlag: boolean
startZoneE: string

notion_character_data: FoodGroupCharacterImage[]
}

const CharacterSpawner: React.FC<Props> = (props: Props) => {
const [resizeCharacterPositions, setResizeCharacterPositions] =
useState(CHARACTER_POSITIONS)
const [resizeEndPositions, setResizeEndPositions] =
useState<Record<string, Vector2[]>>(CHARACTER_END)
const [resizeF, setResizeF] = useState(() => () => {})

if (typeof window !== 'undefined') {
// const startZoneElem = document.getElementById(props.startZoneE)
useEffect(() => {
setResizeF(() => {
const startZone = document
.getElementById(props.startZoneE)
?.getBoundingClientRect()

const endZone = document
.getElementById('bluezone')
?.getBoundingClientRect()

const draggableZone = props.draggableZone[0]

// RESIZE FOR START POSITIONS
if (startZone === undefined || draggableZone === undefined) return
const updatedStartPositions = CHARACTER_POSITIONS.map(e => {
return {
x:
(((e.x / 100) * startZone.width) / draggableZone.width) * 100 +
((startZone.left - draggableZone.left) / draggableZone.width) *
100,
y:
(((e.y / 100) * startZone.height) / draggableZone.height) * 100 +
((startZone.top - draggableZone.top) / draggableZone.height) * 100
}
})

setResizeCharacterPositions(updatedStartPositions)

// RESIZE FOR END POSITIONS
if (endZone === undefined) return
var updatedEndPositions: Record<string, Vector2[]> = {}
// BASICALLY DEEPCOPY AND SCALE OF CHARACTER_END
Object.keys(CHARACTER_END).forEach(
k =>
(updatedEndPositions[k] = [
...CHARACTER_END[k].map(e => {
return {
x:
(((e.x / 100) * endZone.width) / draggableZone.width) *
100 +
((endZone.left - draggableZone.left) /
draggableZone.width) *
100,
y:
(((e.y / 100) * endZone.height) / draggableZone.height) *
100 +
((endZone.top - draggableZone.top) / draggableZone.height) *
100
}
})
])
)

setResizeEndPositions(updatedEndPositions)
})
window.addEventListener('resize', resizeF)

return () => {
window.removeEventListener('resize', resizeF)
}
}, [props.draggableZone[0]])
}

const generateSetElements = (
charSet: FoodGroupCharacterImageDynamic[],
positions: State_<Vector2>[],
viewable: boolean
) =>
charSet.map((character, index) => {
const endDragF = updatedFunction(() =>
props.endDragFunc(index, character.type)
)

return (
<Draggable
key={index}
index={index}
startPosition={resizeCharacterPositions[character.start_index]}
endPosition={resizeEndPositions[character.type][character.end_index]}
draggingStates={props.draggingStates}
onEndDrag={endDragF}
onStartDrag={() => {
props.startDragFunc[0](ORIGIN_VECTOR2)
props.startDragFunc[1](character.type)
}}
screenPosition={positions[index][0]}
setScreenPosition={positions[index][1]}
setAbsPosition={props.absPositionSetState}
hidden={viewable}
draggableZone={props.draggableZone[0]}
{...character}
/>
)
})

return (
<div className='grid grid-cols-1'>
{generateSetElements(
props.currentCharSet,
props.draggablePositions_1,
!props.switchSetFlag
)}
{generateSetElements(
props.nextCharSet,
props.draggablePositions_2,
props.switchSetFlag
)}
</div>
)
}

export { generateCharacterSet, CharacterSpawner }
Loading