#Memory Game, delayed? reactivity
33 messages · Page 1 of 1 (latest)
Do you have some example code?
Is it not uploaded,
Sorry, I had failed to press enter
Testcase: Press on first and second card, it woks fine. Then press on the same cards again, only the second will behave correctly.
Code is now uploaded, sorry I failed to press enter after dropping the zip file, so it was just recenly uploaded.
Sorry I won't download a zip file, could you just copy and paste the code from the relevant file here?
Sure!
import { createSignal,createResource, onMount, For, splitProps } from "solid-js";
import global, { Card } from './Global';
enum CardStyle { hidden, normal, greyed };
function GameCard(ACard : Card) {
const { cards, setCards, choosen, setChoosen, attempts,setAttempts, matched,setMatched } = global;
const [card] = splitProps(ACard,["name","image","text","id"])
const [style, setStyle] = createSignal(CardStyle.hidden);
const placeHolder = 'images/placeholder.png';
function ShowCardAs(card:Card, style:string = 'hidden') {
const cardId = card?.id?.toString();
const imgN = document.getElementById(cardId||"X");
if (imgN != null) {
imgN.className = style;
console.log('ShowCardAs(): ',cardId,' ',style);
} else {
console.log('not found image: ',cardId);
}
}
function checkForMatch() {
const firstCard = choosen()[0];
const secondCard = choosen()[1];
setChoosen([]);
console.log(---CheckForMatch() fc1: ${firstCard.name} ${firstCard.id}| fc2: ${secondCard.name} ${secondCard.id});
// Todo: Already matched cards, remove from reactivity
if (firstCard.id == secondCard.id) {
console.log('Same-same card, not allowed!');
setStyle(CardStyle.hidden); // Keeps reactivity
// Hide(firstCard); // Fails on reactivity
}
else if (firstCard.name == secondCard.name) {
console.log('You found a match! grey out cards');
setMatched(matched()+1);
// Keep image visible, but greyed
ShowCardAs(firstCard,'greyed');
ShowCardAs(secondCard,'greyed');
// Overlay with text of Birds name?
} else {
console.log('Wrong guess, turn cards!');
ShowCardAs(firstCard); // *** This does not solve reactivity
setStyle(CardStyle.hidden); // *** This works fine
// ShowCardAs(secondCard);
// ** setCards(crds);
}
setAttempts(attempts()+1);
}
const flipCard = () => {
let choosenArr = choosen();
// Todo: Already matched cards, not touchable
console.log(=== flipCard() OnClick() ${card.id}, ${card.name} Len:${choosenArr.length});
if (choosenArr.length != 2) {
setStyle(CardStyle.normal); // setShowCard
let X = style();
console.log('Card Has Style(): '+X);
choosenArr.push(card);
setChoosen(choosenArr);
if (choosenArr.length == 2) {
setTimeout(checkForMatch,400);
}
}
}
const getClass = () => {
let cl = "";
const stil = style();
switch (stil) {
case CardStyle.hidden: { cl = cl + "hidden "; break; }
case CardStyle.normal: { cl = cl + "normal "; break; };
case CardStyle.greyed: { cl = cl + "greyed "; break; };
}
// if (greyed()) cl = cl + "ungreyed "; else cl = cl + "hidden ";
console.log(getClass() ${stil} class: ${cl});
return cl.trim();
}
return (
<>
<div class="box">
<img id={card.id?.toString()} onClick={flipCard} class={getClass()} src={ card.image } alt={card.text} />
</div>
</>
)
}
export default GameCard;
ShowCardAs() is dirtywork, so wehn correct solution is found it must be removed.
Was it to much code to dig into?
This is the building of the Board
<For each={cards()}>{(card:Card, i) =>
<GameCard name={card.name} image={card.image} text={card.text} id={card.id}></GameCard>
}</For>
</div>
Hi janne, did you figure it out? I think is maybe better next time to upload your code to codesandbox, jsfiddle or something similar. It's a lot easier to debug running code then it is to debug text. The best would be if you could reproduce a simplified version of the problem in https://playground.solidjs.com/ Is also a good exercise, 99% of the time i figure out the bug while making the example-file.
Quickly discover what the solid compiler will generate from your JSX template
Thanks, very good suggestion!
Is it possible to rename tabs of new files Solid Playground? Tried to google it, but no result.
Ye i think u have to DoubleClick it!
Correct!👍
Is it not possible to load a json file via fetch()?
So I must declare the array in code?
🤔 never tried it myself. But yes mocking a payload s a good solution.
Mocked solved, images uploaded on another site, src= changed. But images will not be shown???
This is not working in game.
<img id="1" class="normal" src="http://birds.qip.se/images/knolsvan.jpg" alt="Knölsvan">
I get it working in Firefox with images, but not an any Webkit based browser.
https://playground.solidjs.com/anonymous/1d3de46a-c9b6-4cfe-a022-e0738fdfb318
Code is not cleaned up, but try to click on one card (will be shown) then a second card (shown) and if wrong cards they will be hidden again. Then click on the same first card again, nothing will happen. I have "hidden" it in a dirty non-reactive way. How do I solve this problem (keeping the first selected card reactive after hiding it again)?
Look in GameCard.tsx function checkForMatch() how to hide the firstCard!?
Quickly discover what the solid compiler will generate from your JSX template
hi 👋 sorry forgot this thread
i just looked at it, the reason why the images do not load in chrome is because there is something wrong w the https license of birds.qip.se and chrome is defaulting to https, while firefox still allows for http
that's a tricky bug! had to look in the network-tab for that.
and regarding the reactivity bug: my guess is it has to do with how you update card.state
this is not a valid way how to update a store
you get a linting error about it too: The reactive variable 'card' should not be reassigned or altered directly.
but u do it with the store-setter instead https://www.solidjs.com/tutorial/stores_createstore
there is createMutable https://www.solidjs.com/docs/latest/api#createmutable which allows for what you are trying to do
with createMutable you can just mutate the store as you want
the way how I approach a global store is by passing a readonly store, and then actions to manipulate that store, so card.state = CardStyle.normal would be written as an action in Global.ts: const setCardState = (id: number, state: CardStyle) => { setCards(id, "state", state); }; and then you could do in your code setCardState(card.id, CardStyle.normal)
this way the surface that can actually change your store is minimized, gives you a lot more control in comparison w createMutable
I couldn't get it to work tho, but I think the problem is a bit more in the overall game-logic.
Quickly discover what the solid compiler will generate from your JSX template