Read in the language that you prefer:
Welcome to the Svelte Snake Workshop!
Install the dependencies …
npm install
… then start the SvelteKit development server:
npm run dev -- --open
You are now ready to start the tasks.
A workshop that teaches Svelte and SvelteKit through making the classic game Snake
Home Page: https://svelte-snake-workshop.vercel.app
License: MIT License
Read in the language that you prefer:
Welcome to the Svelte Snake Workshop!
Install the dependencies …
npm install
… then start the SvelteKit development server:
npm run dev -- --open
You are now ready to start the tasks.
Now that I am to hold the workshop at Javazone 2021, the tasks have to be available in English as well as the currently available Norwegian bokmål.
In order to minimize the work with maintaining the parallel translations, I want to use some automated tool to generate the markdown files. I hit upon a Stack Overflow thread about translating Markdown documentation files, and I found the tool mdpo. The answer was from 2017, but the tool was updated as recently as the day before I created this issue, so I'm guessing I can count upon it being maintained for the next few years. I am still open to other alternatives, but if no better alternative materializes, I'll go for mdpo.
After translation, the English version of the tasks will be the authoritative version. This makes contribution simpler for people who do not speak Norwegian.
8e20ea9 introduced the variable headDirectionQueue
to src/App.svelte
, making it simpler for the user to perform sharp turns. This is a usability improvement, but I'm not sure if it should be part of the regular tasks or some later task.
If it is to be introduced at some pre-existing point, it either has to be introduced at task 2.2 or at task 3.5. Otherwise, we could either make a completely new task for this or leave it out altogether.
My hunch is that introducing it at 2.2 will feel premature to most workshop participants. The task currently instructs the user to disregard the possibility of the snake eating itself, and I think that it's smart to introduce as little as possible to the user at once. Task 3.5 is in my opinion a good stepping stone to understanding the need for queuing itself. This makes me think that adding a new task, for example 3.6, is the best solution.
Reading through the current version of the norwegian translation of the tasks, I discovered the text «Åpne filen src/routes/game/App.svelte
.». This refers to the file structure before #12.
Use references that point to the current version.
To the best of my knowledge, the files utils.js and api.js stay the same throughout all tasks.
We could easily place them in src/lib
and show off the $lib
alias at the same time.
I have changed my opinion about leaving file extensions out in imports.
import * as api from "$lib/api";
should be import * as api from "$lib/api.js";
EcmaScript Modules also require using file extensions, so why not just go with the times, eh? 🤷
There is probably some eslint rule that enforces this
The tasks currently make some assumptions that I'm not satisfied with.
Other than that, the entire document could do with some more polish, with almost two years in existence.
It would be cool to show off some of svelte-kit's capabilities in the workshop. Perhaps we could make the pause and high score screens separate routes
This is a long term goal and not something that I'm going to attempt before issues 4 through 6 are resolved.
Currently, we get the following warnings:
svelte-snake-workshop/src/routes/task-3.3/problem/+page.svelte
3:3 error 'DIRECTION' is defined but never used no-unused-vars
svelte-snake-workshop/src/routes/task-3.6/problem/+page.svelte
27:6 error 'headDirectionQueue' is assigned a value but never used no-unused-vars
I am not sure if these are to be considered spoilers, but they seem to give away the solution (at least partially).
Possible solution: Delete the imports and rewrite the tasks with hints.
Perhaps this fixes #9, but it should lead to a more pleasant developer experience anyway
A lot of CSS goes into creating the board in every task. For instance, this long, identical of CSS is found in the +page.svelte
in every task:
.board {
--border-width: var(--cell-size);
width: calc(var(--board-size-x) * var(--cell-size));
height: calc(var(--board-size-y) * var(--cell-size));
position: relative;
margin: var(--border-width);
outline: var(--border-width) solid black;
background-image: linear-gradient(
45deg,
var(--checker-color) 25%,
transparent 25%
),
linear-gradient(-45deg, var(--checker-color) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, var(--checker-color) 75%),
linear-gradient(-45deg, transparent 75%, var(--checker-color) 75%);
background-size: calc(var(--cell-size) * 2) calc(var(--cell-size) * 2);
background-position: 0 0, 0 var(--cell-size),
var(--cell-size) calc(-1 * var(--cell-size)),
calc(-1 * var(--cell-size)) 0;
}
A lot of this could possibly be helped by extracting the board as a separate component.
Perhaps the task of rendering the snake should be delegated this component as well.
It's important that whatever changes we introduce will be a natural extension of the the tasks' flow.
For instance, many of the early tasks are about placing the different components on the board using CSS.
Currently, components are introduced in part 5.
Perhaps we could introduce them earlier.
I read an interesting article earlier this year, Write HTML Right (also see the related discussion on Hacker News).
While I disagree with a lot of the author's points, I found this point to be insightful.
Starting each sentence in a paragraph on its own line (like back in the troff days) makes it easier to rearrange the sentences in a paragraph — something I do more often than I would have expected.
If you hard-wrap your text, starting each sentence on its own line also limits the area affected by edits within a sentence.
– http://lofi.limo/blog/write-html-right
I would not have cared too much for this, had it not been for the effect on the translation files.
Because we currently do not wrap lines within a paragraph, we have to translate each paragraph as one large chunk. See for example
svelte-snake-workshop/locale/nob/TASKS.md.po
Lines 819 to 839 in f1a23b6
I am not sure how md2po behaves if you start each sentence on a new line. I hope it extracts each new line as a separate chunk. If not, I hope it can be configured to do so.
Because svelte can react to assignments within an object as well as to an object itself, perhaps it's best to replace this monstrosity with an object:
// Letting the state variables go uninitialized is safe,
// because they are initialized by resetGame before they are ever read
let apple;
let gameState;
let headDirection;
let headDirectionQueue;
let score;
let snake;
let willGrow;
function resetGame() {
const initialSnake = [
{ x: 4, y: 4 },
{ x: 4, y: 3 },
{ x: 4, y: 2 },
];
apple = drawRandomOpenSpace(BOARD_DIMENSIONS, initialSnake);
gameState = GAME_STATES.START_SCREEN;
headDirection = DIRECTION.SOUTH;
headDirectionQueue = [];
score = 0;
snake = initialSnake;
willGrow = false;
}
Working with #12, I grew dissatisfied with my task naming convention: begin
and end
.
The expressions require too much explanation.
And they simply sound bad.
I settled for working-area
and solution
. These expressions are the best-fitting I have yet thought of. Solution is self-explanatory. working-area
conveys that this is where you should work.
There are two weaknesses with these names:
solution
is where he/she is to program his/her solution in the solution (not so important)working-area
comes later than solution
in the alphabet. Because the tasks themselves are sorted chronologically in the downward direction, the sub-parts of the task should be sorted chronologically in the same direction.To avoid problem two, I have prefixed the folders with 0 and 1, so that their chronology flows in the same direction as the tasks themselves.
That brings us to the title of this issue: Find self-explanatory names for finished and "unfinished" tasks where the finished variant is later in the alphabet. Any suggestions?
It is repeatedly reported as unused, tarnishing the impression of an otherwise well-made workshop.
Utils is a catch-all name that could imply anything. I think game-helpers
would be better.
Subtask 4.4 refers to a rendering bug which I'm not sure if is still needed
Changing branches while the development server (npm run dev
) is running often results in the page going completely blank. Not even a total refresh or opening the tab in a private browser window fixes things.
To reproduce
git checkout task-1.3-begin && npm run dev
git checkout task-1.3-end
New development servers seem to work completely when you start them – even in parallell with the running server. But nothing is able to get the server started before the branch change running again.
There is still a mention of "Start with the state of the repository". This should refer to the state of the game or the folder state or something.
Having each task in a separate folder (instead of a separate branch) should make the workshop easier for participants. I would probably have an easier time maintaining the workshop, too. If participants find a problem with the code in a task, it's easier for them to suggest changes.
The workshop currently requires the participants to know some git
. This has especially been a problem when performing the workshop with students, some of whom are in their first year. Most of the actual help required has been related to performing
Currently, the project is structured so that each task is a separate branch. The finished game is found in the main
branch. When I first made the workshop, I started with the solution to the last task working my way back to the first task. As a consequence, the branches build backwards, like this: task-5.3-end
, task-5.3-begin
and so on through task-1.1-begin
. While simple to start with, introducing changes is cumbersome, as you can see from the long command I use for introducing changes.
Just look at this branch structure. The git GUI in Webstorm can't even.
I have never had to git-revert any mistakes, but I imagine that doing so would be a nightmare compared to working with a single branch.
Because of the advanced git structure, it's hard for outsiders to suggest changes to branches other than the main branch.
Most changes need to be applied to one or more tasks. While the current approach has its limitations, it's actually quite quick, as long as no merge conflicts appear.
I currently do not know I would apply changes that apply to several tasks as quickly. My guess is that I would have to create some script to create and apply patches semi-automatically to predecing/succeeding tasks, stopping to solve merge-conflicts.
This blog post changed my mind in the age-old tabs vs. spaces debate: https://adamtuttle.codes/blog/2021/tabs-vs-spaces-its-an-accessibility-issue/
People with less than perfect eyesight can have trouble differentiating indentation when the tab-width is low. For accessibility reasons, we need to be able to see more space. And the more code we're looking at, the more it's needed. Having to scroll down 14 lines of code and keep 6 levels of indentation aligned by eye is so much easier with a wider tab-width.
– https://adamtuttle.codes/blog/2021/tabs-vs-spaces-its-an-accessibility-issue/
Also:
The main reason I would like to see this change is for refreshable braille displays that are used by blind programmers a lot. Each space wastes one braille cell and takes away valuable braille realestate. So if the default indentation of a project is 4 spaces per level, a 3rd level indentation wastes 12 braaille cells before code starts. On a 40 cell display, which is the most commonly used with notebooks, this is more than a quarter of the available cells wasted with no information. If each indentation level was represented by only one tab character, there would be three cells occupied by a tab character each, and on the 4th cell, the code would start. That's less than 10 percent occupied on the same length display, but all cells contain valuable information that is easily discoverable and immediately comprehensible.
– prettier/prettier#7475 (comment)
Let's just do it.
After #21, the GameOverModal component sticks out like a sore thumb before its first use in task-5.1
. Get rid of it before that.
The expression
style="--cell-size: {CELL_SIZE}px; --tick-time: {TICK_TIME}ms; --board-size-x: {BOARD_DIMENSIONS.x}; --board-size-y: {BOARD_DIMENSIONS.y}"
found in almost every file can be rewritten using --style-props
https://svelte.dev/docs#template-syntax-component-directives---style-props
TASKS.md refers to the main branch as the gold standard for the finished game.
This has been invalid since 9debff0
Refer to the finished-game folder instead.
Right now, the only thing +page.svelte does is import App.svelte and mount it. I don't think this makes a lot of sense.
I think we could simply overwrite +page.svelte with the previous contents of App.svelte and be better off
Using the game sub-folder made a lot of sense when we had to hide it from svelte-kit. We changed to the new routing system in da42931, and now it's just a bit confusing.
We could easily place the files on the same level as the +page.svelte file. Will have to rename the references, though.
The skull animation suddenly stopped working in da42931
I have no clue as to why. The apple scale animations still work.
Introducing mdsvex was not necessary for such a simple page. Use a regular svelte component instead.
Svelte Kit recently implemented a new routing system. The changes are described here: sveltejs/kit#5774 (comment)
Implement this by renaming every index.svelte
file to a +page.svelte
file. I think all other files can be left as is.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.