devskill 2.0.7 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/meta.ts +4 -0
- package/package.json +1 -1
- package/skills/add-educational-comments/LICENSE.md +21 -0
- package/skills/add-educational-comments/SKILL.md +128 -0
- package/skills/add-educational-comments/SYNC.md +5 -0
- package/skills/agent-governance/LICENSE.md +21 -0
- package/skills/agent-governance/SKILL.md +569 -0
- package/skills/agent-governance/SYNC.md +5 -0
- package/skills/agentic-eval/LICENSE.md +21 -0
- package/skills/agentic-eval/SKILL.md +189 -0
- package/skills/agentic-eval/SYNC.md +5 -0
- package/skills/ai-prompt-engineering-safety-review/LICENSE.md +21 -0
- package/skills/ai-prompt-engineering-safety-review/SKILL.md +230 -0
- package/skills/ai-prompt-engineering-safety-review/SYNC.md +5 -0
- package/skills/appinsights-instrumentation/LICENSE.md +21 -0
- package/skills/appinsights-instrumentation/LICENSE.txt +21 -0
- package/skills/appinsights-instrumentation/SKILL.md +48 -0
- package/skills/appinsights-instrumentation/SYNC.md +5 -0
- package/skills/appinsights-instrumentation/examples/appinsights.bicep +30 -0
- package/skills/appinsights-instrumentation/references/ASPNETCORE.md +29 -0
- package/skills/appinsights-instrumentation/references/AUTO.md +13 -0
- package/skills/appinsights-instrumentation/references/NODEJS.md +28 -0
- package/skills/appinsights-instrumentation/references/PYTHON.md +48 -0
- package/skills/appinsights-instrumentation/scripts/appinsights.ps1 +20 -0
- package/skills/apple-appstore-reviewer/LICENSE.md +21 -0
- package/skills/apple-appstore-reviewer/SKILL.md +305 -0
- package/skills/apple-appstore-reviewer/SYNC.md +5 -0
- package/skills/arch-linux-triage/LICENSE.md +21 -0
- package/skills/arch-linux-triage/SKILL.md +31 -0
- package/skills/arch-linux-triage/SYNC.md +5 -0
- package/skills/architecture-blueprint-generator/LICENSE.md +21 -0
- package/skills/architecture-blueprint-generator/SKILL.md +322 -0
- package/skills/architecture-blueprint-generator/SYNC.md +5 -0
- package/skills/aspire/LICENSE.md +21 -0
- package/skills/aspire/SKILL.md +231 -0
- package/skills/aspire/SYNC.md +5 -0
- package/skills/aspire/references/architecture.md +341 -0
- package/skills/aspire/references/cli-reference.md +307 -0
- package/skills/aspire/references/dashboard.md +226 -0
- package/skills/aspire/references/deployment.md +237 -0
- package/skills/aspire/references/integrations-catalog.md +68 -0
- package/skills/aspire/references/mcp-server.md +195 -0
- package/skills/aspire/references/polyglot-apis.md +296 -0
- package/skills/aspire/references/testing.md +281 -0
- package/skills/aspire/references/troubleshooting.md +194 -0
- package/skills/aspnet-minimal-api-openapi/LICENSE.md +21 -0
- package/skills/aspnet-minimal-api-openapi/SKILL.md +41 -0
- package/skills/aspnet-minimal-api-openapi/SYNC.md +5 -0
- package/skills/automate-this/LICENSE.md +21 -0
- package/skills/automate-this/SKILL.md +244 -0
- package/skills/automate-this/SYNC.md +5 -0
- package/skills/autoresearch/LICENSE.md +21 -0
- package/skills/autoresearch/SKILL.md +275 -0
- package/skills/autoresearch/SYNC.md +5 -0
- package/skills/aws-cdk-python-setup/LICENSE.md +21 -0
- package/skills/aws-cdk-python-setup/SKILL.md +111 -0
- package/skills/aws-cdk-python-setup/SYNC.md +5 -0
- package/skills/az-cost-optimize/LICENSE.md +21 -0
- package/skills/az-cost-optimize/SKILL.md +305 -0
- package/skills/az-cost-optimize/SYNC.md +5 -0
- package/skills/azure-deployment-preflight/LICENSE.md +21 -0
- package/skills/azure-deployment-preflight/SKILL.md +216 -0
- package/skills/azure-deployment-preflight/SYNC.md +5 -0
- package/skills/azure-deployment-preflight/references/ERROR-HANDLING.md +392 -0
- package/skills/azure-deployment-preflight/references/REPORT-TEMPLATE.md +352 -0
- package/skills/azure-deployment-preflight/references/VALIDATION-COMMANDS.md +379 -0
- package/skills/azure-devops-cli/LICENSE.md +21 -0
- package/skills/azure-devops-cli/SKILL.md +94 -0
- package/skills/azure-devops-cli/SYNC.md +5 -0
- package/skills/azure-devops-cli/references/advanced-usage.md +197 -0
- package/skills/azure-devops-cli/references/boards-and-iterations.md +258 -0
- package/skills/azure-devops-cli/references/org-and-security.md +469 -0
- package/skills/azure-devops-cli/references/pipelines-and-builds.md +245 -0
- package/skills/azure-devops-cli/references/repos-and-prs.md +333 -0
- package/skills/azure-devops-cli/references/variables-and-agents.md +212 -0
- package/skills/azure-devops-cli/references/workflows-and-patterns.md +668 -0
- package/skills/azure-pricing/LICENSE.md +21 -0
- package/skills/azure-pricing/SKILL.md +189 -0
- package/skills/azure-pricing/SYNC.md +5 -0
- package/skills/azure-pricing/references/COPILOT-STUDIO-RATES.md +135 -0
- package/skills/azure-pricing/references/COST-ESTIMATOR.md +142 -0
- package/skills/azure-pricing/references/REGIONS.md +84 -0
- package/skills/azure-pricing/references/SERVICE-NAMES.md +106 -0
- package/skills/azure-resource-health-diagnose/LICENSE.md +21 -0
- package/skills/azure-resource-health-diagnose/SKILL.md +290 -0
- package/skills/azure-resource-health-diagnose/SYNC.md +5 -0
- package/skills/azure-resource-visualizer/LICENSE.md +21 -0
- package/skills/azure-resource-visualizer/LICENSE.txt +21 -0
- package/skills/azure-resource-visualizer/SKILL.md +233 -0
- package/skills/azure-resource-visualizer/SYNC.md +5 -0
- package/skills/azure-resource-visualizer/assets/template-architecture.md +41 -0
- package/skills/azure-role-selector/LICENSE.md +21 -0
- package/skills/azure-role-selector/LICENSE.txt +21 -0
- package/skills/azure-role-selector/SKILL.md +6 -0
- package/skills/azure-role-selector/SYNC.md +5 -0
- package/skills/azure-static-web-apps/LICENSE.md +21 -0
- package/skills/azure-static-web-apps/SKILL.md +315 -0
- package/skills/azure-static-web-apps/SYNC.md +5 -0
- package/skills/bigquery-pipeline-audit/LICENSE.md +21 -0
- package/skills/bigquery-pipeline-audit/SKILL.md +129 -0
- package/skills/bigquery-pipeline-audit/SYNC.md +5 -0
- package/skills/boost-prompt/LICENSE.md +21 -0
- package/skills/boost-prompt/SKILL.md +25 -0
- package/skills/boost-prompt/SYNC.md +5 -0
- package/skills/breakdown-epic-arch/LICENSE.md +21 -0
- package/skills/breakdown-epic-arch/SKILL.md +66 -0
- package/skills/breakdown-epic-arch/SYNC.md +5 -0
- package/skills/breakdown-epic-pm/LICENSE.md +21 -0
- package/skills/breakdown-epic-pm/SKILL.md +58 -0
- package/skills/breakdown-epic-pm/SYNC.md +5 -0
- package/skills/breakdown-feature-implementation/LICENSE.md +21 -0
- package/skills/breakdown-feature-implementation/SKILL.md +128 -0
- package/skills/breakdown-feature-implementation/SYNC.md +5 -0
- package/skills/breakdown-feature-prd/LICENSE.md +21 -0
- package/skills/breakdown-feature-prd/SKILL.md +61 -0
- package/skills/breakdown-feature-prd/SYNC.md +5 -0
- package/skills/breakdown-plan/LICENSE.md +21 -0
- package/skills/breakdown-plan/SKILL.md +509 -0
- package/skills/breakdown-plan/SYNC.md +5 -0
- package/skills/breakdown-test/LICENSE.md +21 -0
- package/skills/breakdown-test/SKILL.md +365 -0
- package/skills/breakdown-test/SYNC.md +5 -0
- package/skills/centos-linux-triage/LICENSE.md +21 -0
- package/skills/centos-linux-triage/SKILL.md +31 -0
- package/skills/centos-linux-triage/SYNC.md +5 -0
- package/skills/chrome-devtools/LICENSE.md +21 -0
- package/skills/chrome-devtools/SKILL.md +97 -0
- package/skills/chrome-devtools/SYNC.md +5 -0
- package/skills/cli-mastery/LICENSE.md +21 -0
- package/skills/cli-mastery/SKILL.md +43 -0
- package/skills/cli-mastery/SYNC.md +5 -0
- package/skills/cli-mastery/references/final-exam.md +24 -0
- package/skills/cli-mastery/references/module-1-slash-commands.md +88 -0
- package/skills/cli-mastery/references/module-2-keyboard-shortcuts.md +38 -0
- package/skills/cli-mastery/references/module-3-modes.md +33 -0
- package/skills/cli-mastery/references/module-4-agents.md +42 -0
- package/skills/cli-mastery/references/module-5-skills.md +33 -0
- package/skills/cli-mastery/references/module-6-mcp.md +50 -0
- package/skills/cli-mastery/references/module-7-advanced.md +38 -0
- package/skills/cli-mastery/references/module-8-configuration.md +34 -0
- package/skills/cli-mastery/references/scenarios.md +44 -0
- package/skills/cloud-design-patterns/LICENSE.md +21 -0
- package/skills/cloud-design-patterns/SKILL.md +62 -0
- package/skills/cloud-design-patterns/SYNC.md +5 -0
- package/skills/cloud-design-patterns/references/architecture-design.md +127 -0
- package/skills/cloud-design-patterns/references/azure-service-mappings.md +13 -0
- package/skills/cloud-design-patterns/references/best-practices.md +34 -0
- package/skills/cloud-design-patterns/references/deployment-operational.md +91 -0
- package/skills/cloud-design-patterns/references/event-driven.md +21 -0
- package/skills/cloud-design-patterns/references/messaging-integration.md +127 -0
- package/skills/cloud-design-patterns/references/performance.md +180 -0
- package/skills/cloud-design-patterns/references/reliability-resilience.md +156 -0
- package/skills/cloud-design-patterns/references/security.md +55 -0
- package/skills/code-exemplars-blueprint-generator/LICENSE.md +21 -0
- package/skills/code-exemplars-blueprint-generator/SKILL.md +126 -0
- package/skills/code-exemplars-blueprint-generator/SYNC.md +5 -0
- package/skills/codeql/LICENSE.md +21 -0
- package/skills/codeql/SKILL.md +405 -0
- package/skills/codeql/SYNC.md +5 -0
- package/skills/codeql/references/alert-management.md +170 -0
- package/skills/codeql/references/cli-commands.md +283 -0
- package/skills/codeql/references/compiled-languages.md +284 -0
- package/skills/codeql/references/sarif-output.md +265 -0
- package/skills/codeql/references/troubleshooting.md +259 -0
- package/skills/codeql/references/workflow-configuration.md +398 -0
- package/skills/comment-code-generate-a-tutorial/LICENSE.md +21 -0
- package/skills/comment-code-generate-a-tutorial/SKILL.md +26 -0
- package/skills/comment-code-generate-a-tutorial/SYNC.md +5 -0
- package/skills/containerize-aspnet-framework/LICENSE.md +21 -0
- package/skills/containerize-aspnet-framework/SKILL.md +454 -0
- package/skills/containerize-aspnet-framework/SYNC.md +5 -0
- package/skills/containerize-aspnetcore/LICENSE.md +21 -0
- package/skills/containerize-aspnetcore/SKILL.md +392 -0
- package/skills/containerize-aspnetcore/SYNC.md +5 -0
- package/skills/context-map/LICENSE.md +21 -0
- package/skills/context-map/SKILL.md +52 -0
- package/skills/context-map/SYNC.md +5 -0
- package/skills/conventional-commit/LICENSE.md +21 -0
- package/skills/conventional-commit/SKILL.md +72 -0
- package/skills/conventional-commit/SYNC.md +5 -0
- package/skills/convert-plaintext-to-md/LICENSE.md +21 -0
- package/skills/convert-plaintext-to-md/SKILL.md +362 -0
- package/skills/convert-plaintext-to-md/SYNC.md +5 -0
- package/skills/copilot-cli-quickstart/LICENSE.md +21 -0
- package/skills/copilot-cli-quickstart/SKILL.md +774 -0
- package/skills/copilot-cli-quickstart/SYNC.md +5 -0
- package/skills/copilot-instructions-blueprint-generator/LICENSE.md +21 -0
- package/skills/copilot-instructions-blueprint-generator/SKILL.md +294 -0
- package/skills/copilot-instructions-blueprint-generator/SYNC.md +5 -0
- package/skills/copilot-sdk/LICENSE.md +21 -0
- package/skills/copilot-sdk/SKILL.md +914 -0
- package/skills/copilot-sdk/SYNC.md +5 -0
- package/skills/copilot-spaces/LICENSE.md +21 -0
- package/skills/copilot-spaces/SKILL.md +205 -0
- package/skills/copilot-spaces/SYNC.md +5 -0
- package/skills/copilot-usage-metrics/LICENSE.md +21 -0
- package/skills/copilot-usage-metrics/SKILL.md +52 -0
- package/skills/copilot-usage-metrics/SYNC.md +5 -0
- package/skills/copilot-usage-metrics/get-enterprise-metrics.sh +22 -0
- package/skills/copilot-usage-metrics/get-enterprise-user-metrics.sh +22 -0
- package/skills/copilot-usage-metrics/get-org-metrics.sh +22 -0
- package/skills/copilot-usage-metrics/get-org-user-metrics.sh +22 -0
- package/skills/cosmosdb-datamodeling/LICENSE.md +21 -0
- package/skills/cosmosdb-datamodeling/SKILL.md +1045 -0
- package/skills/cosmosdb-datamodeling/SYNC.md +5 -0
- package/skills/create-agentsmd/LICENSE.md +21 -0
- package/skills/create-agentsmd/SKILL.md +249 -0
- package/skills/create-agentsmd/SYNC.md +5 -0
- package/skills/create-architectural-decision-record/LICENSE.md +21 -0
- package/skills/create-architectural-decision-record/SKILL.md +97 -0
- package/skills/create-architectural-decision-record/SYNC.md +5 -0
- package/skills/create-github-action-workflow-specification/LICENSE.md +21 -0
- package/skills/create-github-action-workflow-specification/SKILL.md +276 -0
- package/skills/create-github-action-workflow-specification/SYNC.md +5 -0
- package/skills/create-github-issue-feature-from-specification/LICENSE.md +21 -0
- package/skills/create-github-issue-feature-from-specification/SKILL.md +28 -0
- package/skills/create-github-issue-feature-from-specification/SYNC.md +5 -0
- package/skills/create-github-issues-feature-from-implementation-plan/LICENSE.md +21 -0
- package/skills/create-github-issues-feature-from-implementation-plan/SKILL.md +28 -0
- package/skills/create-github-issues-feature-from-implementation-plan/SYNC.md +5 -0
- package/skills/create-github-issues-for-unmet-specification-requirements/LICENSE.md +21 -0
- package/skills/create-github-issues-for-unmet-specification-requirements/SKILL.md +35 -0
- package/skills/create-github-issues-for-unmet-specification-requirements/SYNC.md +5 -0
- package/skills/create-github-pull-request-from-specification/LICENSE.md +21 -0
- package/skills/create-github-pull-request-from-specification/SKILL.md +24 -0
- package/skills/create-github-pull-request-from-specification/SYNC.md +5 -0
- package/skills/create-implementation-plan/LICENSE.md +21 -0
- package/skills/create-implementation-plan/SKILL.md +157 -0
- package/skills/create-implementation-plan/SYNC.md +5 -0
- package/skills/create-llms/LICENSE.md +21 -0
- package/skills/create-llms/SKILL.md +210 -0
- package/skills/create-llms/SYNC.md +5 -0
- package/skills/create-readme/LICENSE.md +21 -0
- package/skills/create-readme/SKILL.md +21 -0
- package/skills/create-readme/SYNC.md +5 -0
- package/skills/create-specification/LICENSE.md +21 -0
- package/skills/create-specification/SKILL.md +127 -0
- package/skills/create-specification/SYNC.md +5 -0
- package/skills/create-spring-boot-java-project/LICENSE.md +21 -0
- package/skills/create-spring-boot-java-project/SKILL.md +163 -0
- package/skills/create-spring-boot-java-project/SYNC.md +5 -0
- package/skills/create-spring-boot-kotlin-project/LICENSE.md +21 -0
- package/skills/create-spring-boot-kotlin-project/SKILL.md +147 -0
- package/skills/create-spring-boot-kotlin-project/SYNC.md +5 -0
- package/skills/create-technical-spike/LICENSE.md +21 -0
- package/skills/create-technical-spike/SKILL.md +230 -0
- package/skills/create-technical-spike/SYNC.md +5 -0
- package/skills/create-tldr-page/LICENSE.md +21 -0
- package/skills/create-tldr-page/SKILL.md +210 -0
- package/skills/create-tldr-page/SYNC.md +5 -0
- package/skills/creating-oracle-to-postgres-master-migration-plan/LICENSE.md +21 -0
- package/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md +83 -0
- package/skills/creating-oracle-to-postgres-master-migration-plan/SYNC.md +5 -0
- package/skills/creating-oracle-to-postgres-migration-bug-report/LICENSE.md +21 -0
- package/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md +43 -0
- package/skills/creating-oracle-to-postgres-migration-bug-report/SYNC.md +5 -0
- package/skills/creating-oracle-to-postgres-migration-bug-report/references/BUG-REPORT-TEMPLATE.md +79 -0
- package/skills/creating-oracle-to-postgres-migration-integration-tests/LICENSE.md +21 -0
- package/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md +60 -0
- package/skills/creating-oracle-to-postgres-migration-integration-tests/SYNC.md +5 -0
- package/skills/csharp-async/LICENSE.md +21 -0
- package/skills/csharp-async/SKILL.md +49 -0
- package/skills/csharp-async/SYNC.md +5 -0
- package/skills/csharp-docs/LICENSE.md +21 -0
- package/skills/csharp-docs/SKILL.md +62 -0
- package/skills/csharp-docs/SYNC.md +5 -0
- package/skills/csharp-mcp-server-generator/LICENSE.md +21 -0
- package/skills/csharp-mcp-server-generator/SKILL.md +59 -0
- package/skills/csharp-mcp-server-generator/SYNC.md +5 -0
- package/skills/csharp-mstest/LICENSE.md +21 -0
- package/skills/csharp-mstest/SKILL.md +478 -0
- package/skills/csharp-mstest/SYNC.md +5 -0
- package/skills/csharp-nunit/LICENSE.md +21 -0
- package/skills/csharp-nunit/SKILL.md +71 -0
- package/skills/csharp-nunit/SYNC.md +5 -0
- package/skills/csharp-tunit/LICENSE.md +21 -0
- package/skills/csharp-tunit/SKILL.md +100 -0
- package/skills/csharp-tunit/SYNC.md +5 -0
- package/skills/csharp-xunit/LICENSE.md +21 -0
- package/skills/csharp-xunit/SKILL.md +68 -0
- package/skills/csharp-xunit/SYNC.md +5 -0
- package/skills/datanalysis-credit-risk/LICENSE.md +21 -0
- package/skills/datanalysis-credit-risk/SKILL.md +113 -0
- package/skills/datanalysis-credit-risk/SYNC.md +5 -0
- package/skills/datanalysis-credit-risk/references/analysis.py +1223 -0
- package/skills/datanalysis-credit-risk/references/func.py +228 -0
- package/skills/datanalysis-credit-risk/scripts/example.py +391 -0
- package/skills/dataverse-python-advanced-patterns/LICENSE.md +21 -0
- package/skills/dataverse-python-advanced-patterns/SKILL.md +17 -0
- package/skills/dataverse-python-advanced-patterns/SYNC.md +5 -0
- package/skills/dataverse-python-production-code/LICENSE.md +21 -0
- package/skills/dataverse-python-production-code/SKILL.md +116 -0
- package/skills/dataverse-python-production-code/SYNC.md +5 -0
- package/skills/dataverse-python-quickstart/LICENSE.md +21 -0
- package/skills/dataverse-python-quickstart/SKILL.md +14 -0
- package/skills/dataverse-python-quickstart/SYNC.md +5 -0
- package/skills/dataverse-python-usecase-builder/LICENSE.md +21 -0
- package/skills/dataverse-python-usecase-builder/SKILL.md +246 -0
- package/skills/dataverse-python-usecase-builder/SYNC.md +5 -0
- package/skills/debian-linux-triage/LICENSE.md +21 -0
- package/skills/debian-linux-triage/SKILL.md +31 -0
- package/skills/debian-linux-triage/SYNC.md +5 -0
- package/skills/declarative-agents/LICENSE.md +21 -0
- package/skills/declarative-agents/SKILL.md +94 -0
- package/skills/declarative-agents/SYNC.md +5 -0
- package/skills/dependabot/LICENSE.md +21 -0
- package/skills/dependabot/SKILL.md +422 -0
- package/skills/dependabot/SYNC.md +5 -0
- package/skills/dependabot/references/dependabot-yml-reference.md +374 -0
- package/skills/dependabot/references/example-configs.md +409 -0
- package/skills/dependabot/references/pr-commands.md +91 -0
- package/skills/devops-rollout-plan/LICENSE.md +21 -0
- package/skills/devops-rollout-plan/SKILL.md +117 -0
- package/skills/devops-rollout-plan/SYNC.md +5 -0
- package/skills/documentation-writer/LICENSE.md +21 -0
- package/skills/documentation-writer/SKILL.md +45 -0
- package/skills/documentation-writer/SYNC.md +5 -0
- package/skills/dotnet-best-practices/LICENSE.md +21 -0
- package/skills/dotnet-best-practices/SKILL.md +85 -0
- package/skills/dotnet-best-practices/SYNC.md +5 -0
- package/skills/dotnet-design-pattern-review/LICENSE.md +21 -0
- package/skills/dotnet-design-pattern-review/SKILL.md +42 -0
- package/skills/dotnet-design-pattern-review/SYNC.md +5 -0
- package/skills/dotnet-timezone/LICENSE.md +21 -0
- package/skills/dotnet-timezone/SKILL.md +109 -0
- package/skills/dotnet-timezone/SYNC.md +5 -0
- package/skills/dotnet-timezone/references/code-patterns.md +153 -0
- package/skills/dotnet-timezone/references/timezone-index.md +87 -0
- package/skills/dotnet-upgrade/LICENSE.md +21 -0
- package/skills/dotnet-upgrade/SKILL.md +116 -0
- package/skills/dotnet-upgrade/SYNC.md +5 -0
- package/skills/doublecheck/LICENSE.md +21 -0
- package/skills/doublecheck/SKILL.md +277 -0
- package/skills/doublecheck/SYNC.md +5 -0
- package/skills/doublecheck/assets/verification-report-template.md +92 -0
- package/skills/editorconfig/LICENSE.md +21 -0
- package/skills/editorconfig/SKILL.md +63 -0
- package/skills/editorconfig/SYNC.md +5 -0
- package/skills/ef-core/LICENSE.md +21 -0
- package/skills/ef-core/SKILL.md +75 -0
- package/skills/ef-core/SYNC.md +5 -0
- package/skills/entra-agent-user/LICENSE.md +21 -0
- package/skills/entra-agent-user/SKILL.md +270 -0
- package/skills/entra-agent-user/SYNC.md +5 -0
- package/skills/eval-driven-dev/LICENSE.md +21 -0
- package/skills/eval-driven-dev/SKILL.md +862 -0
- package/skills/eval-driven-dev/SYNC.md +5 -0
- package/skills/eval-driven-dev/references/pixie-api.md +195 -0
- package/skills/excalidraw-diagram-generator/LICENSE.md +21 -0
- package/skills/excalidraw-diagram-generator/SKILL.md +613 -0
- package/skills/excalidraw-diagram-generator/SYNC.md +5 -0
- package/skills/excalidraw-diagram-generator/references/element-types.md +497 -0
- package/skills/excalidraw-diagram-generator/references/excalidraw-schema.md +350 -0
- package/skills/excalidraw-diagram-generator/scripts/README.md +193 -0
- package/skills/excalidraw-diagram-generator/scripts/add-arrow.py +312 -0
- package/skills/excalidraw-diagram-generator/scripts/add-icon-to-diagram.py +404 -0
- package/skills/excalidraw-diagram-generator/scripts/split-excalidraw-library.py +183 -0
- package/skills/excalidraw-diagram-generator/templates/business-flow-swimlane-template.excalidraw +334 -0
- package/skills/excalidraw-diagram-generator/templates/class-diagram-template.excalidraw +558 -0
- package/skills/excalidraw-diagram-generator/templates/data-flow-diagram-template.excalidraw +279 -0
- package/skills/excalidraw-diagram-generator/templates/er-diagram-template.excalidraw +662 -0
- package/skills/excalidraw-diagram-generator/templates/flowchart-template.excalidraw +179 -0
- package/skills/excalidraw-diagram-generator/templates/mindmap-template.excalidraw +244 -0
- package/skills/excalidraw-diagram-generator/templates/relationship-template.excalidraw +145 -0
- package/skills/excalidraw-diagram-generator/templates/sequence-diagram-template.excalidraw +509 -0
- package/skills/fabric-lakehouse/LICENSE.md +21 -0
- package/skills/fabric-lakehouse/SKILL.md +106 -0
- package/skills/fabric-lakehouse/SYNC.md +5 -0
- package/skills/fabric-lakehouse/references/getdata.md +36 -0
- package/skills/fabric-lakehouse/references/pyspark.md +189 -0
- package/skills/fedora-linux-triage/LICENSE.md +21 -0
- package/skills/fedora-linux-triage/SKILL.md +31 -0
- package/skills/fedora-linux-triage/SYNC.md +5 -0
- package/skills/finalize-agent-prompt/LICENSE.md +21 -0
- package/skills/finalize-agent-prompt/SKILL.md +26 -0
- package/skills/finalize-agent-prompt/SYNC.md +5 -0
- package/skills/finnish-humanizer/LICENSE.md +21 -0
- package/skills/finnish-humanizer/SKILL.md +145 -0
- package/skills/finnish-humanizer/SYNC.md +5 -0
- package/skills/finnish-humanizer/references/patterns.md +338 -0
- package/skills/first-ask/LICENSE.md +21 -0
- package/skills/first-ask/SKILL.md +30 -0
- package/skills/first-ask/SYNC.md +5 -0
- package/skills/flowstudio-power-automate-build/LICENSE.md +21 -0
- package/skills/flowstudio-power-automate-build/SKILL.md +460 -0
- package/skills/flowstudio-power-automate-build/SYNC.md +5 -0
- package/skills/flowstudio-power-automate-build/references/action-patterns-connectors.md +542 -0
- package/skills/flowstudio-power-automate-build/references/action-patterns-core.md +542 -0
- package/skills/flowstudio-power-automate-build/references/action-patterns-data.md +735 -0
- package/skills/flowstudio-power-automate-build/references/build-patterns.md +108 -0
- package/skills/flowstudio-power-automate-build/references/flow-schema.md +225 -0
- package/skills/flowstudio-power-automate-build/references/trigger-types.md +211 -0
- package/skills/flowstudio-power-automate-debug/LICENSE.md +21 -0
- package/skills/flowstudio-power-automate-debug/SKILL.md +322 -0
- package/skills/flowstudio-power-automate-debug/SYNC.md +5 -0
- package/skills/flowstudio-power-automate-debug/references/common-errors.md +188 -0
- package/skills/flowstudio-power-automate-debug/references/debug-workflow.md +157 -0
- package/skills/flowstudio-power-automate-mcp/LICENSE.md +21 -0
- package/skills/flowstudio-power-automate-mcp/SKILL.md +450 -0
- package/skills/flowstudio-power-automate-mcp/SYNC.md +5 -0
- package/skills/flowstudio-power-automate-mcp/references/MCP-BOOTSTRAP.md +53 -0
- package/skills/flowstudio-power-automate-mcp/references/action-types.md +79 -0
- package/skills/flowstudio-power-automate-mcp/references/connection-references.md +115 -0
- package/skills/flowstudio-power-automate-mcp/references/tool-reference.md +445 -0
- package/skills/fluentui-blazor/LICENSE.md +21 -0
- package/skills/fluentui-blazor/SKILL.md +231 -0
- package/skills/fluentui-blazor/SYNC.md +5 -0
- package/skills/fluentui-blazor/references/DATAGRID.md +162 -0
- package/skills/fluentui-blazor/references/LAYOUT-AND-NAVIGATION.md +173 -0
- package/skills/fluentui-blazor/references/SETUP.md +129 -0
- package/skills/fluentui-blazor/references/THEMING.md +103 -0
- package/skills/folder-structure-blueprint-generator/LICENSE.md +21 -0
- package/skills/folder-structure-blueprint-generator/SKILL.md +405 -0
- package/skills/folder-structure-blueprint-generator/SYNC.md +5 -0
- package/skills/game-engine/LICENSE.md +21 -0
- package/skills/game-engine/SKILL.md +139 -0
- package/skills/game-engine/SYNC.md +5 -0
- package/skills/game-engine/assets/2d-maze-game.md +528 -0
- package/skills/game-engine/assets/2d-platform-game.md +1855 -0
- package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
- package/skills/game-engine/assets/paddle-game-template.md +1528 -0
- package/skills/game-engine/assets/simple-2d-engine.md +507 -0
- package/skills/game-engine/references/3d-web-games.md +754 -0
- package/skills/game-engine/references/algorithms.md +843 -0
- package/skills/game-engine/references/basics.md +343 -0
- package/skills/game-engine/references/game-control-mechanisms.md +617 -0
- package/skills/game-engine/references/game-engine-core-principles.md +695 -0
- package/skills/game-engine/references/game-publishing.md +352 -0
- package/skills/game-engine/references/techniques.md +894 -0
- package/skills/game-engine/references/terminology.md +354 -0
- package/skills/game-engine/references/web-apis.md +1394 -0
- package/skills/gen-specs-as-issues/LICENSE.md +21 -0
- package/skills/gen-specs-as-issues/SKILL.md +165 -0
- package/skills/gen-specs-as-issues/SYNC.md +5 -0
- package/skills/generate-custom-instructions-from-codebase/LICENSE.md +21 -0
- package/skills/generate-custom-instructions-from-codebase/SKILL.md +240 -0
- package/skills/generate-custom-instructions-from-codebase/SYNC.md +5 -0
- package/skills/geofeed-tuner/LICENSE.md +21 -0
- package/skills/geofeed-tuner/SKILL.md +864 -0
- package/skills/geofeed-tuner/SYNC.md +5 -0
- package/skills/geofeed-tuner/assets/example/01-user-input-rfc8805-feed.csv +5 -0
- package/skills/geofeed-tuner/assets/iso3166-1.json +1249 -0
- package/skills/geofeed-tuner/assets/iso3166-2.json +20188 -0
- package/skills/geofeed-tuner/assets/small-territories.json +106 -0
- package/skills/geofeed-tuner/references/rfc8805.txt +735 -0
- package/skills/geofeed-tuner/references/snippets-python3.md +85 -0
- package/skills/geofeed-tuner/scripts/templates/index.html +2305 -0
- package/skills/gh-cli/LICENSE.md +21 -0
- package/skills/gh-cli/SKILL.md +2187 -0
- package/skills/gh-cli/SYNC.md +5 -0
- package/skills/git-commit/LICENSE.md +21 -0
- package/skills/git-commit/SKILL.md +124 -0
- package/skills/git-commit/SYNC.md +5 -0
- package/skills/git-flow-branch-creator/LICENSE.md +21 -0
- package/skills/git-flow-branch-creator/SKILL.md +292 -0
- package/skills/git-flow-branch-creator/SYNC.md +5 -0
- package/skills/github-copilot-starter/LICENSE.md +21 -0
- package/skills/github-copilot-starter/SKILL.md +402 -0
- package/skills/github-copilot-starter/SYNC.md +5 -0
- package/skills/github-issues/LICENSE.md +21 -0
- package/skills/github-issues/SKILL.md +201 -0
- package/skills/github-issues/SYNC.md +5 -0
- package/skills/github-issues/references/dependencies.md +71 -0
- package/skills/github-issues/references/images.md +116 -0
- package/skills/github-issues/references/issue-fields.md +191 -0
- package/skills/github-issues/references/issue-types.md +72 -0
- package/skills/github-issues/references/projects.md +273 -0
- package/skills/github-issues/references/search.md +231 -0
- package/skills/github-issues/references/sub-issues.md +137 -0
- package/skills/github-issues/references/templates.md +90 -0
- package/skills/go-mcp-server-generator/LICENSE.md +21 -0
- package/skills/go-mcp-server-generator/SKILL.md +334 -0
- package/skills/go-mcp-server-generator/SYNC.md +5 -0
- package/skills/gtm-0-to-1-launch/LICENSE.md +21 -0
- package/skills/gtm-0-to-1-launch/SKILL.md +321 -0
- package/skills/gtm-0-to-1-launch/SYNC.md +5 -0
- package/skills/gtm-ai-gtm/LICENSE.md +21 -0
- package/skills/gtm-ai-gtm/SKILL.md +569 -0
- package/skills/gtm-ai-gtm/SYNC.md +5 -0
- package/skills/gtm-board-and-investor-communication/LICENSE.md +21 -0
- package/skills/gtm-board-and-investor-communication/SKILL.md +456 -0
- package/skills/gtm-board-and-investor-communication/SYNC.md +5 -0
- package/skills/gtm-developer-ecosystem/LICENSE.md +21 -0
- package/skills/gtm-developer-ecosystem/SKILL.md +310 -0
- package/skills/gtm-developer-ecosystem/SYNC.md +5 -0
- package/skills/gtm-enterprise-account-planning/LICENSE.md +21 -0
- package/skills/gtm-enterprise-account-planning/SKILL.md +429 -0
- package/skills/gtm-enterprise-account-planning/SYNC.md +5 -0
- package/skills/gtm-enterprise-onboarding/LICENSE.md +21 -0
- package/skills/gtm-enterprise-onboarding/SKILL.md +457 -0
- package/skills/gtm-enterprise-onboarding/SYNC.md +5 -0
- package/skills/gtm-operating-cadence/LICENSE.md +21 -0
- package/skills/gtm-operating-cadence/SKILL.md +420 -0
- package/skills/gtm-operating-cadence/SYNC.md +5 -0
- package/skills/gtm-partnership-architecture/LICENSE.md +21 -0
- package/skills/gtm-partnership-architecture/SKILL.md +470 -0
- package/skills/gtm-partnership-architecture/SYNC.md +5 -0
- package/skills/gtm-positioning-strategy/LICENSE.md +21 -0
- package/skills/gtm-positioning-strategy/SKILL.md +438 -0
- package/skills/gtm-positioning-strategy/SYNC.md +5 -0
- package/skills/gtm-product-led-growth/LICENSE.md +21 -0
- package/skills/gtm-product-led-growth/SKILL.md +339 -0
- package/skills/gtm-product-led-growth/SYNC.md +5 -0
- package/skills/gtm-technical-product-pricing/LICENSE.md +21 -0
- package/skills/gtm-technical-product-pricing/SKILL.md +353 -0
- package/skills/gtm-technical-product-pricing/SYNC.md +5 -0
- package/skills/image-manipulation-image-magick/LICENSE.md +21 -0
- package/skills/image-manipulation-image-magick/SKILL.md +252 -0
- package/skills/image-manipulation-image-magick/SYNC.md +5 -0
- package/skills/import-infrastructure-as-code/LICENSE.md +21 -0
- package/skills/import-infrastructure-as-code/SKILL.md +367 -0
- package/skills/import-infrastructure-as-code/SYNC.md +5 -0
- package/skills/issue-fields-migration/LICENSE.md +21 -0
- package/skills/issue-fields-migration/SKILL.md +533 -0
- package/skills/issue-fields-migration/SYNC.md +5 -0
- package/skills/issue-fields-migration/references/issue-fields-api.md +129 -0
- package/skills/issue-fields-migration/references/labels-api.md +74 -0
- package/skills/issue-fields-migration/references/projects-api.md +116 -0
- package/skills/java-add-graalvm-native-image-support/LICENSE.md +21 -0
- package/skills/java-add-graalvm-native-image-support/SKILL.md +449 -0
- package/skills/java-add-graalvm-native-image-support/SYNC.md +5 -0
- package/skills/java-docs/LICENSE.md +21 -0
- package/skills/java-docs/SKILL.md +23 -0
- package/skills/java-docs/SYNC.md +5 -0
- package/skills/java-junit/LICENSE.md +21 -0
- package/skills/java-junit/SKILL.md +63 -0
- package/skills/java-junit/SYNC.md +5 -0
- package/skills/java-mcp-server-generator/LICENSE.md +21 -0
- package/skills/java-mcp-server-generator/SKILL.md +756 -0
- package/skills/java-mcp-server-generator/SYNC.md +5 -0
- package/skills/java-refactoring-extract-method/LICENSE.md +21 -0
- package/skills/java-refactoring-extract-method/SKILL.md +104 -0
- package/skills/java-refactoring-extract-method/SYNC.md +5 -0
- package/skills/java-refactoring-remove-parameter/LICENSE.md +21 -0
- package/skills/java-refactoring-remove-parameter/SKILL.md +84 -0
- package/skills/java-refactoring-remove-parameter/SYNC.md +5 -0
- package/skills/java-springboot/LICENSE.md +21 -0
- package/skills/java-springboot/SKILL.md +65 -0
- package/skills/java-springboot/SYNC.md +5 -0
- package/skills/javascript-typescript-jest/LICENSE.md +21 -0
- package/skills/javascript-typescript-jest/SKILL.md +44 -0
- package/skills/javascript-typescript-jest/SYNC.md +5 -0
- package/skills/kotlin-mcp-server-generator/LICENSE.md +21 -0
- package/skills/kotlin-mcp-server-generator/SKILL.md +449 -0
- package/skills/kotlin-mcp-server-generator/SYNC.md +5 -0
- package/skills/kotlin-springboot/LICENSE.md +21 -0
- package/skills/kotlin-springboot/SKILL.md +70 -0
- package/skills/kotlin-springboot/SYNC.md +5 -0
- package/skills/legacy-circuit-mockups/LICENSE.md +21 -0
- package/skills/legacy-circuit-mockups/SKILL.md +276 -0
- package/skills/legacy-circuit-mockups/SYNC.md +5 -0
- package/skills/legacy-circuit-mockups/references/28256-eeprom.md +190 -0
- package/skills/legacy-circuit-mockups/references/555.md +861 -0
- package/skills/legacy-circuit-mockups/references/6502.md +221 -0
- package/skills/legacy-circuit-mockups/references/6522.md +211 -0
- package/skills/legacy-circuit-mockups/references/6C62256.md +177 -0
- package/skills/legacy-circuit-mockups/references/7400-series.md +177 -0
- package/skills/legacy-circuit-mockups/references/assembly-compiler.md +258 -0
- package/skills/legacy-circuit-mockups/references/assembly-language.md +226 -0
- package/skills/legacy-circuit-mockups/references/basic-electronic-components.md +86 -0
- package/skills/legacy-circuit-mockups/references/breadboard.md +214 -0
- package/skills/legacy-circuit-mockups/references/common-breadboard-components.md +281 -0
- package/skills/legacy-circuit-mockups/references/connecting-electronic-components.md +310 -0
- package/skills/legacy-circuit-mockups/references/emulator-28256-eeprom.md +245 -0
- package/skills/legacy-circuit-mockups/references/emulator-6502.md +251 -0
- package/skills/legacy-circuit-mockups/references/emulator-6522.md +288 -0
- package/skills/legacy-circuit-mockups/references/emulator-6C62256.md +233 -0
- package/skills/legacy-circuit-mockups/references/emulator-lcd.md +266 -0
- package/skills/legacy-circuit-mockups/references/lcd.md +208 -0
- package/skills/legacy-circuit-mockups/references/minipro.md +211 -0
- package/skills/legacy-circuit-mockups/references/t48eeprom-programmer.md +174 -0
- package/skills/make-repo-contribution/LICENSE.md +21 -0
- package/skills/make-repo-contribution/SKILL.md +90 -0
- package/skills/make-repo-contribution/SYNC.md +5 -0
- package/skills/make-repo-contribution/assets/issue-template.md +37 -0
- package/skills/make-repo-contribution/assets/pr-template.md +36 -0
- package/skills/make-skill-template/LICENSE.md +21 -0
- package/skills/make-skill-template/SKILL.md +147 -0
- package/skills/make-skill-template/SYNC.md +5 -0
- package/skills/markdown-to-html/LICENSE.md +21 -0
- package/skills/markdown-to-html/SKILL.md +916 -0
- package/skills/markdown-to-html/SYNC.md +5 -0
- package/skills/markdown-to-html/references/basic-markdown-to-html.md +420 -0
- package/skills/markdown-to-html/references/basic-markdown.md +496 -0
- package/skills/markdown-to-html/references/code-blocks-to-html.md +165 -0
- package/skills/markdown-to-html/references/code-blocks.md +70 -0
- package/skills/markdown-to-html/references/collapsed-sections-to-html.md +136 -0
- package/skills/markdown-to-html/references/collapsed-sections.md +48 -0
- package/skills/markdown-to-html/references/gomarkdown.md +253 -0
- package/skills/markdown-to-html/references/hugo.md +394 -0
- package/skills/markdown-to-html/references/jekyll.md +321 -0
- package/skills/markdown-to-html/references/marked.md +121 -0
- package/skills/markdown-to-html/references/pandoc.md +226 -0
- package/skills/markdown-to-html/references/tables-to-html.md +169 -0
- package/skills/markdown-to-html/references/tables.md +72 -0
- package/skills/markdown-to-html/references/writing-mathematical-expressions-to-html.md +350 -0
- package/skills/markdown-to-html/references/writing-mathematical-expressions.md +76 -0
- package/skills/mcp-cli/LICENSE.md +21 -0
- package/skills/mcp-cli/SKILL.md +78 -0
- package/skills/mcp-cli/SYNC.md +5 -0
- package/skills/mcp-copilot-studio-server-generator/LICENSE.md +21 -0
- package/skills/mcp-copilot-studio-server-generator/SKILL.md +118 -0
- package/skills/mcp-copilot-studio-server-generator/SYNC.md +5 -0
- package/skills/mcp-create-adaptive-cards/LICENSE.md +21 -0
- package/skills/mcp-create-adaptive-cards/SKILL.md +532 -0
- package/skills/mcp-create-adaptive-cards/SYNC.md +5 -0
- package/skills/mcp-create-declarative-agent/LICENSE.md +21 -0
- package/skills/mcp-create-declarative-agent/SKILL.md +315 -0
- package/skills/mcp-create-declarative-agent/SYNC.md +5 -0
- package/skills/mcp-deploy-manage-agents/LICENSE.md +21 -0
- package/skills/mcp-deploy-manage-agents/SKILL.md +341 -0
- package/skills/mcp-deploy-manage-agents/SYNC.md +5 -0
- package/skills/meeting-minutes/LICENSE.md +21 -0
- package/skills/meeting-minutes/SKILL.md +235 -0
- package/skills/meeting-minutes/SYNC.md +5 -0
- package/skills/memory-merger/LICENSE.md +21 -0
- package/skills/memory-merger/SKILL.md +108 -0
- package/skills/memory-merger/SYNC.md +5 -0
- package/skills/mentoring-juniors/LICENSE.md +21 -0
- package/skills/mentoring-juniors/SKILL.md +310 -0
- package/skills/mentoring-juniors/SYNC.md +5 -0
- package/skills/microsoft-agent-framework/LICENSE.md +21 -0
- package/skills/microsoft-agent-framework/SKILL.md +65 -0
- package/skills/microsoft-agent-framework/SYNC.md +5 -0
- package/skills/microsoft-agent-framework/references/dotnet.md +24 -0
- package/skills/microsoft-agent-framework/references/python.md +24 -0
- package/skills/microsoft-code-reference/LICENSE.md +21 -0
- package/skills/microsoft-code-reference/SKILL.md +99 -0
- package/skills/microsoft-code-reference/SYNC.md +5 -0
- package/skills/microsoft-docs/LICENSE.md +21 -0
- package/skills/microsoft-docs/SKILL.md +134 -0
- package/skills/microsoft-docs/SYNC.md +5 -0
- package/skills/microsoft-skill-creator/LICENSE.md +21 -0
- package/skills/microsoft-skill-creator/SKILL.md +250 -0
- package/skills/microsoft-skill-creator/SYNC.md +5 -0
- package/skills/microsoft-skill-creator/references/skill-templates.md +345 -0
- package/skills/migrating-oracle-to-postgres-stored-procedures/LICENSE.md +21 -0
- package/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md +42 -0
- package/skills/migrating-oracle-to-postgres-stored-procedures/SYNC.md +5 -0
- package/skills/mkdocs-translations/LICENSE.md +21 -0
- package/skills/mkdocs-translations/SKILL.md +108 -0
- package/skills/mkdocs-translations/SYNC.md +5 -0
- package/skills/model-recommendation/LICENSE.md +21 -0
- package/skills/model-recommendation/SKILL.md +672 -0
- package/skills/model-recommendation/SYNC.md +5 -0
- package/skills/msstore-cli/LICENSE.md +21 -0
- package/skills/msstore-cli/SKILL.md +600 -0
- package/skills/msstore-cli/SYNC.md +5 -0
- package/skills/multi-stage-dockerfile/LICENSE.md +21 -0
- package/skills/multi-stage-dockerfile/SKILL.md +46 -0
- package/skills/multi-stage-dockerfile/SYNC.md +5 -0
- package/skills/my-issues/LICENSE.md +21 -0
- package/skills/my-issues/SKILL.md +8 -0
- package/skills/my-issues/SYNC.md +5 -0
- package/skills/my-pull-requests/LICENSE.md +21 -0
- package/skills/my-pull-requests/SKILL.md +14 -0
- package/skills/my-pull-requests/SYNC.md +5 -0
- package/skills/nano-banana-pro-openrouter/LICENSE.md +21 -0
- package/skills/nano-banana-pro-openrouter/SKILL.md +74 -0
- package/skills/nano-banana-pro-openrouter/SYNC.md +5 -0
- package/skills/nano-banana-pro-openrouter/assets/SYSTEM_TEMPLATE +14 -0
- package/skills/nano-banana-pro-openrouter/scripts/generate_image.py +191 -0
- package/skills/napkin/LICENSE.md +21 -0
- package/skills/napkin/SKILL.md +154 -0
- package/skills/napkin/SYNC.md +5 -0
- package/skills/napkin/assets/napkin.html +2019 -0
- package/skills/napkin/assets/step1-activate.svg +107 -0
- package/skills/napkin/assets/step2-whiteboard.svg +157 -0
- package/skills/napkin/assets/step3-draw.svg +143 -0
- package/skills/napkin/assets/step4-share.svg +98 -0
- package/skills/napkin/assets/step5-response.svg +112 -0
- package/skills/next-intl-add-language/LICENSE.md +21 -0
- package/skills/next-intl-add-language/SKILL.md +19 -0
- package/skills/next-intl-add-language/SYNC.md +5 -0
- package/skills/noob-mode/LICENSE.md +21 -0
- package/skills/noob-mode/SKILL.md +263 -0
- package/skills/noob-mode/SYNC.md +5 -0
- package/skills/noob-mode/references/examples.md +418 -0
- package/skills/noob-mode/references/glossary.md +368 -0
- package/skills/nuget-manager/LICENSE.md +21 -0
- package/skills/nuget-manager/SKILL.md +68 -0
- package/skills/nuget-manager/SYNC.md +5 -0
- package/skills/oo-component-documentation/LICENSE.md +21 -0
- package/skills/oo-component-documentation/SKILL.md +74 -0
- package/skills/oo-component-documentation/SYNC.md +5 -0
- package/skills/oo-component-documentation/assets/documentation-template.md +97 -0
- package/skills/oo-component-documentation/references/create-mode.md +32 -0
- package/skills/oo-component-documentation/references/update-mode.md +32 -0
- package/skills/openapi-to-application-code/LICENSE.md +21 -0
- package/skills/openapi-to-application-code/SKILL.md +112 -0
- package/skills/openapi-to-application-code/SYNC.md +5 -0
- package/skills/pdftk-server/LICENSE.md +21 -0
- package/skills/pdftk-server/SKILL.md +162 -0
- package/skills/pdftk-server/SYNC.md +5 -0
- package/skills/pdftk-server/references/download.md +75 -0
- package/skills/pdftk-server/references/pdftk-cli-examples.md +193 -0
- package/skills/pdftk-server/references/pdftk-man-page.md +232 -0
- package/skills/pdftk-server/references/pdftk-server-license.md +25 -0
- package/skills/pdftk-server/references/third-party-materials.md +103 -0
- package/skills/penpot-uiux-design/LICENSE.md +21 -0
- package/skills/penpot-uiux-design/SKILL.md +342 -0
- package/skills/penpot-uiux-design/SYNC.md +5 -0
- package/skills/penpot-uiux-design/references/accessibility.md +329 -0
- package/skills/penpot-uiux-design/references/component-patterns.md +339 -0
- package/skills/penpot-uiux-design/references/platform-guidelines.md +367 -0
- package/skills/penpot-uiux-design/references/setup-troubleshooting.md +328 -0
- package/skills/php-mcp-server-generator/LICENSE.md +21 -0
- package/skills/php-mcp-server-generator/SKILL.md +522 -0
- package/skills/php-mcp-server-generator/SYNC.md +5 -0
- package/skills/planning-oracle-to-postgres-migration-integration-testing/LICENSE.md +21 -0
- package/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md +44 -0
- package/skills/planning-oracle-to-postgres-migration-integration-testing/SYNC.md +5 -0
- package/skills/plantuml-ascii/LICENSE.md +21 -0
- package/skills/plantuml-ascii/SKILL.md +305 -0
- package/skills/plantuml-ascii/SYNC.md +5 -0
- package/skills/playwright-automation-fill-in-form/LICENSE.md +21 -0
- package/skills/playwright-automation-fill-in-form/SKILL.md +28 -0
- package/skills/playwright-automation-fill-in-form/SYNC.md +5 -0
- package/skills/playwright-explore-website/LICENSE.md +21 -0
- package/skills/playwright-explore-website/SKILL.md +17 -0
- package/skills/playwright-explore-website/SYNC.md +5 -0
- package/skills/playwright-generate-test/LICENSE.md +21 -0
- package/skills/playwright-generate-test/SKILL.md +17 -0
- package/skills/playwright-generate-test/SYNC.md +5 -0
- package/skills/polyglot-test-agent/LICENSE.md +21 -0
- package/skills/polyglot-test-agent/SKILL.md +161 -0
- package/skills/polyglot-test-agent/SYNC.md +5 -0
- package/skills/polyglot-test-agent/unit-test-generation.prompt.md +155 -0
- package/skills/postgresql-code-review/LICENSE.md +21 -0
- package/skills/postgresql-code-review/SKILL.md +212 -0
- package/skills/postgresql-code-review/SYNC.md +5 -0
- package/skills/postgresql-optimization/LICENSE.md +21 -0
- package/skills/postgresql-optimization/SKILL.md +404 -0
- package/skills/postgresql-optimization/SYNC.md +5 -0
- package/skills/power-apps-code-app-scaffold/LICENSE.md +21 -0
- package/skills/power-apps-code-app-scaffold/SKILL.md +146 -0
- package/skills/power-apps-code-app-scaffold/SYNC.md +5 -0
- package/skills/power-bi-dax-optimization/LICENSE.md +21 -0
- package/skills/power-bi-dax-optimization/SKILL.md +173 -0
- package/skills/power-bi-dax-optimization/SYNC.md +5 -0
- package/skills/power-bi-model-design-review/LICENSE.md +21 -0
- package/skills/power-bi-model-design-review/SKILL.md +403 -0
- package/skills/power-bi-model-design-review/SYNC.md +5 -0
- package/skills/power-bi-performance-troubleshooting/LICENSE.md +21 -0
- package/skills/power-bi-performance-troubleshooting/SKILL.md +382 -0
- package/skills/power-bi-performance-troubleshooting/SYNC.md +5 -0
- package/skills/power-bi-report-design-consultation/LICENSE.md +21 -0
- package/skills/power-bi-report-design-consultation/SKILL.md +351 -0
- package/skills/power-bi-report-design-consultation/SYNC.md +5 -0
- package/skills/power-platform-mcp-connector-suite/LICENSE.md +21 -0
- package/skills/power-platform-mcp-connector-suite/SKILL.md +156 -0
- package/skills/power-platform-mcp-connector-suite/SYNC.md +5 -0
- package/skills/powerbi-modeling/LICENSE.md +21 -0
- package/skills/powerbi-modeling/SKILL.md +153 -0
- package/skills/powerbi-modeling/SYNC.md +5 -0
- package/skills/powerbi-modeling/references/MEASURES-DAX.md +195 -0
- package/skills/powerbi-modeling/references/PERFORMANCE.md +215 -0
- package/skills/powerbi-modeling/references/RELATIONSHIPS.md +147 -0
- package/skills/powerbi-modeling/references/RLS.md +226 -0
- package/skills/powerbi-modeling/references/STAR-SCHEMA.md +103 -0
- package/skills/prd/LICENSE.md +21 -0
- package/skills/prd/SKILL.md +143 -0
- package/skills/prd/SYNC.md +5 -0
- package/skills/premium-frontend-ui/LICENSE.md +21 -0
- package/skills/premium-frontend-ui/SKILL.md +110 -0
- package/skills/premium-frontend-ui/SYNC.md +5 -0
- package/skills/project-workflow-analysis-blueprint-generator/LICENSE.md +21 -0
- package/skills/project-workflow-analysis-blueprint-generator/SKILL.md +293 -0
- package/skills/project-workflow-analysis-blueprint-generator/SYNC.md +5 -0
- package/skills/prompt-builder/LICENSE.md +21 -0
- package/skills/prompt-builder/SKILL.md +141 -0
- package/skills/prompt-builder/SYNC.md +5 -0
- package/skills/publish-to-pages/LICENSE.md +21 -0
- package/skills/publish-to-pages/SKILL.md +107 -0
- package/skills/publish-to-pages/SYNC.md +5 -0
- package/skills/publish-to-pages/scripts/convert-pdf.py +176 -0
- package/skills/publish-to-pages/scripts/convert-pptx.py +376 -0
- package/skills/publish-to-pages/scripts/publish.sh +51 -0
- package/skills/pytest-coverage/LICENSE.md +21 -0
- package/skills/pytest-coverage/SKILL.md +28 -0
- package/skills/pytest-coverage/SYNC.md +5 -0
- package/skills/python-mcp-server-generator/LICENSE.md +21 -0
- package/skills/python-mcp-server-generator/SKILL.md +105 -0
- package/skills/python-mcp-server-generator/SYNC.md +5 -0
- package/skills/quasi-coder/LICENSE.md +21 -0
- package/skills/quasi-coder/SKILL.md +369 -0
- package/skills/quasi-coder/SYNC.md +5 -0
- package/skills/readme-blueprint-generator/LICENSE.md +21 -0
- package/skills/readme-blueprint-generator/SKILL.md +78 -0
- package/skills/readme-blueprint-generator/SYNC.md +5 -0
- package/skills/refactor/LICENSE.md +21 -0
- package/skills/refactor/SKILL.md +645 -0
- package/skills/refactor/SYNC.md +5 -0
- package/skills/refactor-method-complexity-reduce/LICENSE.md +21 -0
- package/skills/refactor-method-complexity-reduce/SKILL.md +98 -0
- package/skills/refactor-method-complexity-reduce/SYNC.md +5 -0
- package/skills/refactor-plan/LICENSE.md +21 -0
- package/skills/refactor-plan/SKILL.md +65 -0
- package/skills/refactor-plan/SYNC.md +5 -0
- package/skills/remember/LICENSE.md +21 -0
- package/skills/remember/SKILL.md +126 -0
- package/skills/remember/SYNC.md +5 -0
- package/skills/remember-interactive-programming/LICENSE.md +21 -0
- package/skills/remember-interactive-programming/SKILL.md +13 -0
- package/skills/remember-interactive-programming/SYNC.md +5 -0
- package/skills/repo-story-time/LICENSE.md +21 -0
- package/skills/repo-story-time/SKILL.md +154 -0
- package/skills/repo-story-time/SYNC.md +5 -0
- package/skills/review-and-refactor/LICENSE.md +21 -0
- package/skills/review-and-refactor/SKILL.md +15 -0
- package/skills/review-and-refactor/SYNC.md +5 -0
- package/skills/reviewing-oracle-to-postgres-migration/LICENSE.md +21 -0
- package/skills/reviewing-oracle-to-postgres-migration/SKILL.md +67 -0
- package/skills/reviewing-oracle-to-postgres-migration/SYNC.md +5 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md +13 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/empty-strings-handling.md +69 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/no-data-found-exceptions.md +99 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/oracle-parentheses-from-clause.md +190 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md +51 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-timestamp-timezone.md +187 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-to-char-numeric.md +145 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-type-coercion.md +182 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/postgres-concurrent-transactions.md +259 -0
- package/skills/reviewing-oracle-to-postgres-migration/references/postgres-refcursor-handling.md +148 -0
- package/skills/ruby-mcp-server-generator/LICENSE.md +21 -0
- package/skills/ruby-mcp-server-generator/SKILL.md +660 -0
- package/skills/ruby-mcp-server-generator/SYNC.md +5 -0
- package/skills/rust-mcp-server-generator/LICENSE.md +21 -0
- package/skills/rust-mcp-server-generator/SKILL.md +577 -0
- package/skills/rust-mcp-server-generator/SYNC.md +5 -0
- package/skills/sandbox-npm-install/LICENSE.md +21 -0
- package/skills/sandbox-npm-install/SKILL.md +80 -0
- package/skills/sandbox-npm-install/SYNC.md +5 -0
- package/skills/sandbox-npm-install/scripts/install.sh +193 -0
- package/skills/scaffolding-oracle-to-postgres-migration-test-project/LICENSE.md +21 -0
- package/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md +54 -0
- package/skills/scaffolding-oracle-to-postgres-migration-test-project/SYNC.md +5 -0
- package/skills/scoutqa-test/LICENSE.md +21 -0
- package/skills/scoutqa-test/SKILL.md +375 -0
- package/skills/scoutqa-test/SYNC.md +5 -0
- package/skills/secret-scanning/LICENSE.md +21 -0
- package/skills/secret-scanning/SKILL.md +224 -0
- package/skills/secret-scanning/SYNC.md +5 -0
- package/skills/secret-scanning/references/alerts-and-remediation.md +245 -0
- package/skills/secret-scanning/references/custom-patterns.md +158 -0
- package/skills/secret-scanning/references/push-protection.md +164 -0
- package/skills/semantic-kernel/LICENSE.md +21 -0
- package/skills/semantic-kernel/SKILL.md +56 -0
- package/skills/semantic-kernel/SYNC.md +5 -0
- package/skills/semantic-kernel/references/dotnet.md +15 -0
- package/skills/semantic-kernel/references/python.md +15 -0
- package/skills/shuffle-json-data/LICENSE.md +21 -0
- package/skills/shuffle-json-data/SKILL.md +150 -0
- package/skills/shuffle-json-data/SYNC.md +5 -0
- package/skills/snowflake-semanticview/LICENSE.md +21 -0
- package/skills/snowflake-semanticview/SKILL.md +83 -0
- package/skills/snowflake-semanticview/SYNC.md +5 -0
- package/skills/sponsor-finder/LICENSE.md +21 -0
- package/skills/sponsor-finder/SKILL.md +258 -0
- package/skills/sponsor-finder/SYNC.md +5 -0
- package/skills/spring-boot-testing/LICENSE.md +21 -0
- package/skills/spring-boot-testing/SKILL.md +189 -0
- package/skills/spring-boot-testing/SYNC.md +5 -0
- package/skills/spring-boot-testing/references/assertj-basics.md +207 -0
- package/skills/spring-boot-testing/references/assertj-collections.md +183 -0
- package/skills/spring-boot-testing/references/context-caching.md +115 -0
- package/skills/spring-boot-testing/references/datajpatest.md +197 -0
- package/skills/spring-boot-testing/references/instancio.md +230 -0
- package/skills/spring-boot-testing/references/mockitobean.md +232 -0
- package/skills/spring-boot-testing/references/mockmvc-classic.md +206 -0
- package/skills/spring-boot-testing/references/mockmvc-tester.md +311 -0
- package/skills/spring-boot-testing/references/restclienttest.md +227 -0
- package/skills/spring-boot-testing/references/resttestclient.md +278 -0
- package/skills/spring-boot-testing/references/sb4-migration.md +181 -0
- package/skills/spring-boot-testing/references/test-slices-overview.md +203 -0
- package/skills/spring-boot-testing/references/testcontainers-jdbc.md +234 -0
- package/skills/spring-boot-testing/references/webmvctest.md +177 -0
- package/skills/sql-code-review/LICENSE.md +21 -0
- package/skills/sql-code-review/SKILL.md +301 -0
- package/skills/sql-code-review/SYNC.md +5 -0
- package/skills/sql-optimization/LICENSE.md +21 -0
- package/skills/sql-optimization/SKILL.md +296 -0
- package/skills/sql-optimization/SYNC.md +5 -0
- package/skills/structured-autonomy-generate/LICENSE.md +21 -0
- package/skills/structured-autonomy-generate/SKILL.md +125 -0
- package/skills/structured-autonomy-generate/SYNC.md +5 -0
- package/skills/structured-autonomy-implement/LICENSE.md +21 -0
- package/skills/structured-autonomy-implement/SKILL.md +19 -0
- package/skills/structured-autonomy-implement/SYNC.md +5 -0
- package/skills/structured-autonomy-plan/LICENSE.md +21 -0
- package/skills/structured-autonomy-plan/SKILL.md +81 -0
- package/skills/structured-autonomy-plan/SYNC.md +5 -0
- package/skills/suggest-awesome-github-copilot-agents/LICENSE.md +21 -0
- package/skills/suggest-awesome-github-copilot-agents/SKILL.md +106 -0
- package/skills/suggest-awesome-github-copilot-agents/SYNC.md +5 -0
- package/skills/suggest-awesome-github-copilot-instructions/LICENSE.md +21 -0
- package/skills/suggest-awesome-github-copilot-instructions/SKILL.md +122 -0
- package/skills/suggest-awesome-github-copilot-instructions/SYNC.md +5 -0
- package/skills/suggest-awesome-github-copilot-skills/LICENSE.md +21 -0
- package/skills/suggest-awesome-github-copilot-skills/SKILL.md +130 -0
- package/skills/suggest-awesome-github-copilot-skills/SYNC.md +5 -0
- package/skills/swift-mcp-server-generator/LICENSE.md +21 -0
- package/skills/swift-mcp-server-generator/SKILL.md +669 -0
- package/skills/swift-mcp-server-generator/SYNC.md +5 -0
- package/skills/technology-stack-blueprint-generator/LICENSE.md +21 -0
- package/skills/technology-stack-blueprint-generator/SKILL.md +242 -0
- package/skills/technology-stack-blueprint-generator/SYNC.md +5 -0
- package/skills/terraform-azurerm-set-diff-analyzer/LICENSE.md +21 -0
- package/skills/terraform-azurerm-set-diff-analyzer/SKILL.md +48 -0
- package/skills/terraform-azurerm-set-diff-analyzer/SYNC.md +5 -0
- package/skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.json +154 -0
- package/skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.md +145 -0
- package/skills/terraform-azurerm-set-diff-analyzer/scripts/README.md +205 -0
- package/skills/terraform-azurerm-set-diff-analyzer/scripts/analyze_plan.py +940 -0
- package/skills/tldr-prompt/LICENSE.md +21 -0
- package/skills/tldr-prompt/SKILL.md +304 -0
- package/skills/tldr-prompt/SYNC.md +5 -0
- package/skills/transloadit-media-processing/LICENSE.md +21 -0
- package/skills/transloadit-media-processing/SKILL.md +194 -0
- package/skills/transloadit-media-processing/SYNC.md +5 -0
- package/skills/typescript-mcp-server-generator/LICENSE.md +21 -0
- package/skills/typescript-mcp-server-generator/SKILL.md +90 -0
- package/skills/typescript-mcp-server-generator/SYNC.md +5 -0
- package/skills/typespec-api-operations/LICENSE.md +21 -0
- package/skills/typespec-api-operations/SKILL.md +418 -0
- package/skills/typespec-api-operations/SYNC.md +5 -0
- package/skills/typespec-create-agent/LICENSE.md +21 -0
- package/skills/typespec-create-agent/SKILL.md +91 -0
- package/skills/typespec-create-agent/SYNC.md +5 -0
- package/skills/typespec-create-api-plugin/LICENSE.md +21 -0
- package/skills/typespec-create-api-plugin/SKILL.md +164 -0
- package/skills/typespec-create-api-plugin/SYNC.md +5 -0
- package/skills/unit-test-vue-pinia/LICENSE.md +21 -0
- package/skills/unit-test-vue-pinia/SKILL.md +198 -0
- package/skills/unit-test-vue-pinia/SYNC.md +5 -0
- package/skills/unit-test-vue-pinia/references/pinia-patterns.md +95 -0
- package/skills/update-avm-modules-in-bicep/LICENSE.md +21 -0
- package/skills/update-avm-modules-in-bicep/SKILL.md +60 -0
- package/skills/update-avm-modules-in-bicep/SYNC.md +5 -0
- package/skills/update-implementation-plan/LICENSE.md +21 -0
- package/skills/update-implementation-plan/SKILL.md +157 -0
- package/skills/update-implementation-plan/SYNC.md +5 -0
- package/skills/update-llms/LICENSE.md +21 -0
- package/skills/update-llms/SKILL.md +216 -0
- package/skills/update-llms/SYNC.md +5 -0
- package/skills/update-markdown-file-index/LICENSE.md +21 -0
- package/skills/update-markdown-file-index/SKILL.md +76 -0
- package/skills/update-markdown-file-index/SYNC.md +5 -0
- package/skills/update-specification/LICENSE.md +21 -0
- package/skills/update-specification/SKILL.md +127 -0
- package/skills/update-specification/SYNC.md +5 -0
- package/skills/vscode-ext-commands/LICENSE.md +21 -0
- package/skills/vscode-ext-commands/SKILL.md +21 -0
- package/skills/vscode-ext-commands/SYNC.md +5 -0
- package/skills/vscode-ext-localization/LICENSE.md +21 -0
- package/skills/vscode-ext-localization/SKILL.md +25 -0
- package/skills/vscode-ext-localization/SYNC.md +5 -0
- package/skills/web-coder/LICENSE.md +21 -0
- package/skills/web-coder/SKILL.md +563 -0
- package/skills/web-coder/SYNC.md +5 -0
- package/skills/web-coder/references/accessibility.md +346 -0
- package/skills/web-coder/references/architecture-patterns.md +625 -0
- package/skills/web-coder/references/browsers-engines.md +358 -0
- package/skills/web-coder/references/css-styling.md +696 -0
- package/skills/web-coder/references/data-formats-encoding.md +411 -0
- package/skills/web-coder/references/development-tools.md +502 -0
- package/skills/web-coder/references/glossary.md +649 -0
- package/skills/web-coder/references/html-markup.md +387 -0
- package/skills/web-coder/references/http-networking.md +538 -0
- package/skills/web-coder/references/javascript-programming.md +807 -0
- package/skills/web-coder/references/media-graphics.md +504 -0
- package/skills/web-coder/references/performance-optimization.md +546 -0
- package/skills/web-coder/references/security-authentication.md +603 -0
- package/skills/web-coder/references/servers-infrastructure.md +615 -0
- package/skills/web-coder/references/web-apis-dom.md +654 -0
- package/skills/web-coder/references/web-protocols-standards.md +265 -0
- package/skills/web-design-reviewer/LICENSE.md +21 -0
- package/skills/web-design-reviewer/SKILL.md +368 -0
- package/skills/web-design-reviewer/SYNC.md +5 -0
- package/skills/web-design-reviewer/references/framework-fixes.md +475 -0
- package/skills/web-design-reviewer/references/visual-checklist.md +236 -0
- package/skills/webapp-testing/LICENSE.md +21 -0
- package/skills/webapp-testing/SKILL.md +104 -67
- package/skills/webapp-testing/SYNC.md +2 -2
- package/skills/webapp-testing/assets/test-helper.js +56 -0
- package/skills/what-context-needed/LICENSE.md +21 -0
- package/skills/what-context-needed/SKILL.md +39 -0
- package/skills/what-context-needed/SYNC.md +5 -0
- package/skills/winapp-cli/LICENSE.md +21 -0
- package/skills/winapp-cli/SKILL.md +217 -0
- package/skills/winapp-cli/SYNC.md +5 -0
- package/skills/winmd-api-search/LICENSE.md +21 -0
- package/skills/winmd-api-search/LICENSE.txt +21 -0
- package/skills/winmd-api-search/SKILL.md +192 -0
- package/skills/winmd-api-search/SYNC.md +5 -0
- package/skills/winmd-api-search/scripts/Invoke-WinMdQuery.ps1 +505 -0
- package/skills/winmd-api-search/scripts/Update-WinMdCache.ps1 +208 -0
- package/skills/winmd-api-search/scripts/cache-generator/CacheGenerator.csproj +29 -0
- package/skills/winmd-api-search/scripts/cache-generator/Directory.Build.props +3 -0
- package/skills/winmd-api-search/scripts/cache-generator/Directory.Build.targets +3 -0
- package/skills/winmd-api-search/scripts/cache-generator/Directory.Packages.props +3 -0
- package/skills/winmd-api-search/scripts/cache-generator/Program.cs +1222 -0
- package/skills/winui3-migration-guide/LICENSE.md +21 -0
- package/skills/winui3-migration-guide/SKILL.md +277 -0
- package/skills/winui3-migration-guide/SYNC.md +5 -0
- package/skills/workiq-copilot/LICENSE.md +21 -0
- package/skills/workiq-copilot/SKILL.md +98 -0
- package/skills/workiq-copilot/SYNC.md +5 -0
- package/skills/write-coding-standards-from-file/LICENSE.md +21 -0
- package/skills/write-coding-standards-from-file/SKILL.md +316 -0
- package/skills/write-coding-standards-from-file/SYNC.md +5 -0
- package/skills/webapp-testing/LICENSE.txt +0 -202
- package/skills/webapp-testing/examples/console_logging.py +0 -35
- package/skills/webapp-testing/examples/element_discovery.py +0 -40
- package/skills/webapp-testing/examples/static_html_automation.py +0 -33
- package/skills/webapp-testing/scripts/with_server.py +0 -106
|
@@ -0,0 +1,1528 @@
|
|
|
1
|
+
# Paddle Game Template (2D Breakout)
|
|
2
|
+
|
|
3
|
+
A complete step-by-step guide for building a 2D Breakout game with pure JavaScript and the HTML5 Canvas API. This template walks through every stage of development, from setting up the canvas to implementing a lives system and polished game loop.
|
|
4
|
+
|
|
5
|
+
**What you will build:** A classic breakout/paddle game where the player controls a paddle to bounce a ball and destroy a field of bricks, with score tracking, win/lose conditions, keyboard and mouse controls, and a lives system.
|
|
6
|
+
|
|
7
|
+
**Prerequisites:** Basic to intermediate JavaScript knowledge and familiarity with HTML.
|
|
8
|
+
|
|
9
|
+
**Source:** Based on the [MDN 2D Breakout Game Tutorial](https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Step 1: Create the Canvas and Draw on It
|
|
14
|
+
|
|
15
|
+
The first step is setting up the HTML document with a `<canvas>` element and learning to draw basic shapes using the 2D rendering context.
|
|
16
|
+
|
|
17
|
+
### HTML Structure
|
|
18
|
+
|
|
19
|
+
Create your base HTML file with an embedded canvas element:
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<!doctype html>
|
|
23
|
+
<html lang="en-US">
|
|
24
|
+
<head>
|
|
25
|
+
<meta charset="utf-8" />
|
|
26
|
+
<title>Gamedev Canvas Workshop</title>
|
|
27
|
+
<style>
|
|
28
|
+
* {
|
|
29
|
+
padding: 0;
|
|
30
|
+
margin: 0;
|
|
31
|
+
}
|
|
32
|
+
canvas {
|
|
33
|
+
background: #eeeeee;
|
|
34
|
+
display: block;
|
|
35
|
+
margin: 0 auto;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<canvas id="myCanvas" width="480" height="320"></canvas>
|
|
41
|
+
|
|
42
|
+
<script>
|
|
43
|
+
// JavaScript code goes here
|
|
44
|
+
</script>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Getting the Canvas Reference and 2D Context
|
|
50
|
+
|
|
51
|
+
The canvas element provides a drawing surface. You access it through a 2D rendering context:
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
const canvas = document.getElementById("myCanvas");
|
|
55
|
+
const ctx = canvas.getContext("2d");
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `canvas` is a reference to the HTML `<canvas>` element.
|
|
59
|
+
- `ctx` is the 2D rendering context object, which provides all drawing methods.
|
|
60
|
+
|
|
61
|
+
### Drawing a Filled Rectangle
|
|
62
|
+
|
|
63
|
+
Use `rect()` to define a rectangle and `fill()` to render it:
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
ctx.beginPath();
|
|
67
|
+
ctx.rect(20, 40, 50, 50);
|
|
68
|
+
ctx.fillStyle = "red";
|
|
69
|
+
ctx.fill();
|
|
70
|
+
ctx.closePath();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- The first two parameters (`20, 40`) set the top-left corner coordinates.
|
|
74
|
+
- The second two parameters (`50, 50`) set the width and height.
|
|
75
|
+
- `fillStyle` sets the fill color.
|
|
76
|
+
- `fill()` renders the shape as a solid fill.
|
|
77
|
+
|
|
78
|
+
### Drawing a Circle
|
|
79
|
+
|
|
80
|
+
Use `arc()` to define a circle:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
ctx.beginPath();
|
|
84
|
+
ctx.arc(240, 160, 20, 0, Math.PI * 2, false);
|
|
85
|
+
ctx.fillStyle = "green";
|
|
86
|
+
ctx.fill();
|
|
87
|
+
ctx.closePath();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- `240, 160` -- center x, y coordinates.
|
|
91
|
+
- `20` -- radius.
|
|
92
|
+
- `0` -- start angle (radians).
|
|
93
|
+
- `Math.PI * 2` -- end angle (full circle).
|
|
94
|
+
- `false` -- draw clockwise.
|
|
95
|
+
|
|
96
|
+
### Drawing a Stroked Rectangle (Outline Only)
|
|
97
|
+
|
|
98
|
+
Use `stroke()` instead of `fill()` for outlines, and `strokeStyle` for outline color:
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
ctx.beginPath();
|
|
102
|
+
ctx.rect(160, 10, 100, 40);
|
|
103
|
+
ctx.strokeStyle = "rgb(0 0 255 / 50%)";
|
|
104
|
+
ctx.stroke();
|
|
105
|
+
ctx.closePath();
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- Uses an RGB color with 50% alpha transparency.
|
|
109
|
+
- `stroke()` draws only the outline, not a solid fill.
|
|
110
|
+
|
|
111
|
+
### Key Methods Reference
|
|
112
|
+
|
|
113
|
+
| Method | Purpose |
|
|
114
|
+
|--------|---------|
|
|
115
|
+
| `beginPath()` | Start a new drawing path |
|
|
116
|
+
| `closePath()` | Close the current path |
|
|
117
|
+
| `rect(x, y, width, height)` | Define a rectangle |
|
|
118
|
+
| `arc(x, y, radius, startAngle, endAngle, counterclockwise)` | Define a circle or arc |
|
|
119
|
+
| `fillStyle` | Set the fill color |
|
|
120
|
+
| `fill()` | Fill the shape with the fill color |
|
|
121
|
+
| `strokeStyle` | Set the stroke (outline) color |
|
|
122
|
+
| `stroke()` | Draw an outline of the shape |
|
|
123
|
+
|
|
124
|
+
### Complete Code for Step 1
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<canvas id="myCanvas" width="480" height="320"></canvas>
|
|
128
|
+
|
|
129
|
+
<style>
|
|
130
|
+
* { padding: 0; margin: 0; }
|
|
131
|
+
canvas { background: #eeeeee; display: block; margin: 0 auto; }
|
|
132
|
+
</style>
|
|
133
|
+
|
|
134
|
+
<script>
|
|
135
|
+
const canvas = document.getElementById("myCanvas");
|
|
136
|
+
const ctx = canvas.getContext("2d");
|
|
137
|
+
|
|
138
|
+
// Filled red square
|
|
139
|
+
ctx.beginPath();
|
|
140
|
+
ctx.rect(20, 40, 50, 50);
|
|
141
|
+
ctx.fillStyle = "red";
|
|
142
|
+
ctx.fill();
|
|
143
|
+
ctx.closePath();
|
|
144
|
+
|
|
145
|
+
// Filled green circle
|
|
146
|
+
ctx.beginPath();
|
|
147
|
+
ctx.arc(240, 160, 20, 0, Math.PI * 2, false);
|
|
148
|
+
ctx.fillStyle = "green";
|
|
149
|
+
ctx.fill();
|
|
150
|
+
ctx.closePath();
|
|
151
|
+
|
|
152
|
+
// Stroked blue rectangle (semi-transparent)
|
|
153
|
+
ctx.beginPath();
|
|
154
|
+
ctx.rect(160, 10, 100, 40);
|
|
155
|
+
ctx.strokeStyle = "rgb(0 0 255 / 50%)";
|
|
156
|
+
ctx.stroke();
|
|
157
|
+
ctx.closePath();
|
|
158
|
+
</script>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Step 2: Move the Ball
|
|
164
|
+
|
|
165
|
+
Now we animate the ball by creating a game loop that redraws the canvas on each frame and updates the ball position using velocity variables.
|
|
166
|
+
|
|
167
|
+
### Creating the Draw Loop
|
|
168
|
+
|
|
169
|
+
Define a `draw()` function that executes repeatedly using `setInterval`:
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
function draw() {
|
|
173
|
+
// drawing code
|
|
174
|
+
}
|
|
175
|
+
setInterval(draw, 10);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`setInterval(draw, 10)` calls the `draw` function every 10 milliseconds, creating approximately 100 frames per second.
|
|
179
|
+
|
|
180
|
+
### Drawing the Ball
|
|
181
|
+
|
|
182
|
+
Inside the `draw()` function, draw a ball (circle) at a fixed position:
|
|
183
|
+
|
|
184
|
+
```javascript
|
|
185
|
+
ctx.beginPath();
|
|
186
|
+
ctx.arc(50, 50, 10, 0, Math.PI * 2);
|
|
187
|
+
ctx.fillStyle = "#0095DD";
|
|
188
|
+
ctx.fill();
|
|
189
|
+
ctx.closePath();
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Adding Position Variables
|
|
193
|
+
|
|
194
|
+
Instead of hardcoded positions, use variables so we can update them each frame. Place these above the `draw()` function:
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
let x = canvas.width / 2;
|
|
198
|
+
let y = canvas.height - 30;
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
This starts the ball at the horizontal center, near the bottom of the canvas.
|
|
202
|
+
|
|
203
|
+
### Adding Velocity Variables
|
|
204
|
+
|
|
205
|
+
Define speed and direction for horizontal (`dx`) and vertical (`dy`) movement:
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
let dx = 2;
|
|
209
|
+
let dy = -2;
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- `dx = 2` moves the ball 2 pixels right per frame.
|
|
213
|
+
- `dy = -2` moves the ball 2 pixels up per frame (negative y is upward on canvas).
|
|
214
|
+
|
|
215
|
+
### Updating Position Each Frame
|
|
216
|
+
|
|
217
|
+
Add position updates at the end of the `draw()` function:
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
x += dx;
|
|
221
|
+
y += dy;
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Clearing the Canvas
|
|
225
|
+
|
|
226
|
+
Without clearing, the ball leaves a trail. Add `clearRect()` at the start of each frame:
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Refactoring Into a Separate drawBall() Function
|
|
233
|
+
|
|
234
|
+
For clean, maintainable code, separate the ball-drawing logic:
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
function drawBall() {
|
|
238
|
+
ctx.beginPath();
|
|
239
|
+
ctx.arc(x, y, 10, 0, Math.PI * 2);
|
|
240
|
+
ctx.fillStyle = "#0095DD";
|
|
241
|
+
ctx.fill();
|
|
242
|
+
ctx.closePath();
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Complete Code for Step 2
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
const canvas = document.getElementById("myCanvas");
|
|
250
|
+
const ctx = canvas.getContext("2d");
|
|
251
|
+
|
|
252
|
+
let x = canvas.width / 2;
|
|
253
|
+
let y = canvas.height - 30;
|
|
254
|
+
let dx = 2;
|
|
255
|
+
let dy = -2;
|
|
256
|
+
|
|
257
|
+
function drawBall() {
|
|
258
|
+
ctx.beginPath();
|
|
259
|
+
ctx.arc(x, y, 10, 0, Math.PI * 2);
|
|
260
|
+
ctx.fillStyle = "#0095DD";
|
|
261
|
+
ctx.fill();
|
|
262
|
+
ctx.closePath();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function draw() {
|
|
266
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
267
|
+
drawBall();
|
|
268
|
+
x += dx;
|
|
269
|
+
y += dy;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
setInterval(draw, 10);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Key concepts:**
|
|
276
|
+
- **Animation loop**: `setInterval(draw, 10)` continuously redraws the scene.
|
|
277
|
+
- **Position variables**: `x` and `y` track the ball's current location.
|
|
278
|
+
- **Velocity variables**: `dx` and `dy` determine movement per frame.
|
|
279
|
+
- **Canvas clearing**: `clearRect()` removes the previous frame before drawing the new one.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Step 3: Bounce Off the Walls
|
|
284
|
+
|
|
285
|
+
We add collision detection so the ball bounces off the canvas edges instead of disappearing.
|
|
286
|
+
|
|
287
|
+
### Defining the Ball Radius
|
|
288
|
+
|
|
289
|
+
Extract the ball radius into a named constant for reuse in collision calculations:
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
const ballRadius = 10;
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Update `drawBall()` to use this variable:
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
function drawBall() {
|
|
299
|
+
ctx.beginPath();
|
|
300
|
+
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
|
|
301
|
+
ctx.fillStyle = "#0095DD";
|
|
302
|
+
ctx.fill();
|
|
303
|
+
ctx.closePath();
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Basic Wall Collision (Without Radius Adjustment)
|
|
308
|
+
|
|
309
|
+
The simplest approach checks if the next ball position goes beyond the canvas boundaries:
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
// Left and right walls
|
|
313
|
+
if (x + dx > canvas.width || x + dx < 0) {
|
|
314
|
+
dx = -dx;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Top and bottom walls
|
|
318
|
+
if (y + dy > canvas.height || y + dy < 0) {
|
|
319
|
+
dy = -dy;
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Reversing `dx` or `dy` (multiplying by -1) changes the ball's direction.
|
|
324
|
+
|
|
325
|
+
### Improved Collision (Accounting for Ball Radius)
|
|
326
|
+
|
|
327
|
+
The basic version lets the ball sink halfway into the wall before bouncing. To fix this, account for the ball's radius:
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
// Left and right walls
|
|
331
|
+
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
|
|
332
|
+
dx = -dx;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Top and bottom walls
|
|
336
|
+
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
|
|
337
|
+
dy = -dy;
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Collision Detection Conditions
|
|
342
|
+
|
|
343
|
+
| Wall | Condition | Action |
|
|
344
|
+
|------|-----------|--------|
|
|
345
|
+
| **Left** | `x + dx < ballRadius` | `dx = -dx` |
|
|
346
|
+
| **Right** | `x + dx > canvas.width - ballRadius` | `dx = -dx` |
|
|
347
|
+
| **Top** | `y + dy < ballRadius` | `dy = -dy` |
|
|
348
|
+
| **Bottom** | `y + dy > canvas.height - ballRadius` | `dy = -dy` |
|
|
349
|
+
|
|
350
|
+
### Complete Code for Step 3
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
const canvas = document.getElementById("myCanvas");
|
|
354
|
+
const ctx = canvas.getContext("2d");
|
|
355
|
+
const ballRadius = 10;
|
|
356
|
+
|
|
357
|
+
let x = canvas.width / 2;
|
|
358
|
+
let y = canvas.height - 30;
|
|
359
|
+
let dx = 2;
|
|
360
|
+
let dy = -2;
|
|
361
|
+
|
|
362
|
+
function drawBall() {
|
|
363
|
+
ctx.beginPath();
|
|
364
|
+
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
|
|
365
|
+
ctx.fillStyle = "#0095DD";
|
|
366
|
+
ctx.fill();
|
|
367
|
+
ctx.closePath();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function draw() {
|
|
371
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
372
|
+
drawBall();
|
|
373
|
+
|
|
374
|
+
// Collision detection - left and right walls
|
|
375
|
+
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
|
|
376
|
+
dx = -dx;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Collision detection - top and bottom walls
|
|
380
|
+
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
|
|
381
|
+
dy = -dy;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
x += dx;
|
|
385
|
+
y += dy;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
setInterval(draw, 10);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Step 4: Paddle and Keyboard Controls
|
|
394
|
+
|
|
395
|
+
Now we add a player-controlled paddle at the bottom of the screen and wire up keyboard input (left/right arrow keys).
|
|
396
|
+
|
|
397
|
+
### Defining Paddle Variables
|
|
398
|
+
|
|
399
|
+
```javascript
|
|
400
|
+
const paddleHeight = 10;
|
|
401
|
+
const paddleWidth = 75;
|
|
402
|
+
let paddleX = (canvas.width - paddleWidth) / 2;
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
- `paddleHeight` and `paddleWidth` define the paddle dimensions.
|
|
406
|
+
- `paddleX` starts the paddle centered horizontally. It is a `let` because it will change as the player moves it.
|
|
407
|
+
|
|
408
|
+
### Drawing the Paddle
|
|
409
|
+
|
|
410
|
+
Create a `drawPaddle()` function. The paddle sits at the very bottom of the canvas:
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
function drawPaddle() {
|
|
414
|
+
ctx.beginPath();
|
|
415
|
+
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
|
|
416
|
+
ctx.fillStyle = "#0095DD";
|
|
417
|
+
ctx.fill();
|
|
418
|
+
ctx.closePath();
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
- The y-position is `canvas.height - paddleHeight`, placing it flush with the bottom edge.
|
|
423
|
+
|
|
424
|
+
### Keyboard State Variables
|
|
425
|
+
|
|
426
|
+
Track whether arrow keys are currently pressed:
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
let rightPressed = false;
|
|
430
|
+
let leftPressed = false;
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Event Listeners for Key Presses
|
|
434
|
+
|
|
435
|
+
Register handlers for `keydown` (key pressed) and `keyup` (key released):
|
|
436
|
+
|
|
437
|
+
```javascript
|
|
438
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
439
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Key Handler Functions
|
|
443
|
+
|
|
444
|
+
Set the boolean flags based on which key is pressed or released:
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
function keyDownHandler(e) {
|
|
448
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
449
|
+
rightPressed = true;
|
|
450
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
451
|
+
leftPressed = true;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function keyUpHandler(e) {
|
|
456
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
457
|
+
rightPressed = false;
|
|
458
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
459
|
+
leftPressed = false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Both `"ArrowRight"` (modern browsers) and `"Right"` (legacy IE/Edge) are checked for compatibility.
|
|
465
|
+
|
|
466
|
+
### Paddle Movement Logic (With Boundary Checking)
|
|
467
|
+
|
|
468
|
+
Add this inside the `draw()` function to move the paddle based on key state, while keeping it within canvas bounds:
|
|
469
|
+
|
|
470
|
+
```javascript
|
|
471
|
+
if (rightPressed) {
|
|
472
|
+
paddleX = Math.min(paddleX + 7, canvas.width - paddleWidth);
|
|
473
|
+
} else if (leftPressed) {
|
|
474
|
+
paddleX = Math.max(paddleX - 7, 0);
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
- The paddle moves 7 pixels per frame.
|
|
479
|
+
- `Math.min` prevents the paddle from going past the right edge.
|
|
480
|
+
- `Math.max` prevents it from going past the left edge.
|
|
481
|
+
|
|
482
|
+
### Complete Code for Step 4
|
|
483
|
+
|
|
484
|
+
```javascript
|
|
485
|
+
const canvas = document.getElementById("myCanvas");
|
|
486
|
+
const ctx = canvas.getContext("2d");
|
|
487
|
+
const ballRadius = 10;
|
|
488
|
+
|
|
489
|
+
let x = canvas.width / 2;
|
|
490
|
+
let y = canvas.height - 30;
|
|
491
|
+
let dx = 2;
|
|
492
|
+
let dy = -2;
|
|
493
|
+
|
|
494
|
+
const paddleHeight = 10;
|
|
495
|
+
const paddleWidth = 75;
|
|
496
|
+
let paddleX = (canvas.width - paddleWidth) / 2;
|
|
497
|
+
|
|
498
|
+
let rightPressed = false;
|
|
499
|
+
let leftPressed = false;
|
|
500
|
+
|
|
501
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
502
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
503
|
+
|
|
504
|
+
function keyDownHandler(e) {
|
|
505
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
506
|
+
rightPressed = true;
|
|
507
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
508
|
+
leftPressed = true;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function keyUpHandler(e) {
|
|
513
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
514
|
+
rightPressed = false;
|
|
515
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
516
|
+
leftPressed = false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function drawBall() {
|
|
521
|
+
ctx.beginPath();
|
|
522
|
+
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
|
|
523
|
+
ctx.fillStyle = "#0095DD";
|
|
524
|
+
ctx.fill();
|
|
525
|
+
ctx.closePath();
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function drawPaddle() {
|
|
529
|
+
ctx.beginPath();
|
|
530
|
+
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
|
|
531
|
+
ctx.fillStyle = "#0095DD";
|
|
532
|
+
ctx.fill();
|
|
533
|
+
ctx.closePath();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function draw() {
|
|
537
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
538
|
+
drawBall();
|
|
539
|
+
drawPaddle();
|
|
540
|
+
|
|
541
|
+
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
|
|
542
|
+
dx = -dx;
|
|
543
|
+
}
|
|
544
|
+
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
|
|
545
|
+
dy = -dy;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (rightPressed) {
|
|
549
|
+
paddleX = Math.min(paddleX + 7, canvas.width - paddleWidth);
|
|
550
|
+
} else if (leftPressed) {
|
|
551
|
+
paddleX = Math.max(paddleX - 7, 0);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
x += dx;
|
|
555
|
+
y += dy;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
setInterval(draw, 10);
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Step 5: Game Over
|
|
564
|
+
|
|
565
|
+
We replace the bottom-wall bounce with actual game logic: the ball should bounce off the paddle, but if it misses, it is game over.
|
|
566
|
+
|
|
567
|
+
### Storing the Interval Reference
|
|
568
|
+
|
|
569
|
+
To stop the game loop on game over, store the interval ID:
|
|
570
|
+
|
|
571
|
+
```javascript
|
|
572
|
+
let interval = 0;
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
Then assign the return value of `setInterval`:
|
|
576
|
+
|
|
577
|
+
```javascript
|
|
578
|
+
interval = setInterval(draw, 10);
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Implementing Game Over and Paddle Collision
|
|
582
|
+
|
|
583
|
+
Replace the bottom-wall collision check. Instead of bouncing off the bottom edge, we now check whether the ball hits the paddle or misses it:
|
|
584
|
+
|
|
585
|
+
```javascript
|
|
586
|
+
if (y + dy < ballRadius) {
|
|
587
|
+
// Ball hits top wall -- bounce
|
|
588
|
+
dy = -dy;
|
|
589
|
+
} else if (y + dy > canvas.height - ballRadius) {
|
|
590
|
+
// Ball reaches bottom edge
|
|
591
|
+
if (x > paddleX && x < paddleX + paddleWidth) {
|
|
592
|
+
// Ball hits paddle -- bounce
|
|
593
|
+
dy = -dy;
|
|
594
|
+
} else {
|
|
595
|
+
// Ball missed the paddle -- game over
|
|
596
|
+
alert("GAME OVER");
|
|
597
|
+
document.location.reload();
|
|
598
|
+
clearInterval(interval);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**How paddle collision works:**
|
|
604
|
+
- `x > paddleX` -- the ball is past the paddle's left edge.
|
|
605
|
+
- `x < paddleX + paddleWidth` -- the ball is before the paddle's right edge.
|
|
606
|
+
- If both are true, the ball is above the paddle, so it bounces.
|
|
607
|
+
- If the ball reaches the bottom without hitting the paddle, the game ends.
|
|
608
|
+
|
|
609
|
+
### Complete Code for Step 5
|
|
610
|
+
|
|
611
|
+
```javascript
|
|
612
|
+
const canvas = document.getElementById("myCanvas");
|
|
613
|
+
const ctx = canvas.getContext("2d");
|
|
614
|
+
const ballRadius = 10;
|
|
615
|
+
|
|
616
|
+
let x = canvas.width / 2;
|
|
617
|
+
let y = canvas.height - 30;
|
|
618
|
+
let dx = 2;
|
|
619
|
+
let dy = -2;
|
|
620
|
+
|
|
621
|
+
const paddleHeight = 10;
|
|
622
|
+
const paddleWidth = 75;
|
|
623
|
+
let paddleX = (canvas.width - paddleWidth) / 2;
|
|
624
|
+
|
|
625
|
+
let rightPressed = false;
|
|
626
|
+
let leftPressed = false;
|
|
627
|
+
let interval = 0;
|
|
628
|
+
|
|
629
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
630
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
631
|
+
|
|
632
|
+
function keyDownHandler(e) {
|
|
633
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
634
|
+
rightPressed = true;
|
|
635
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
636
|
+
leftPressed = true;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function keyUpHandler(e) {
|
|
641
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
642
|
+
rightPressed = false;
|
|
643
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
644
|
+
leftPressed = false;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
function drawBall() {
|
|
649
|
+
ctx.beginPath();
|
|
650
|
+
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
|
|
651
|
+
ctx.fillStyle = "#0095DD";
|
|
652
|
+
ctx.fill();
|
|
653
|
+
ctx.closePath();
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function drawPaddle() {
|
|
657
|
+
ctx.beginPath();
|
|
658
|
+
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
|
|
659
|
+
ctx.fillStyle = "#0095DD";
|
|
660
|
+
ctx.fill();
|
|
661
|
+
ctx.closePath();
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function draw() {
|
|
665
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
666
|
+
drawBall();
|
|
667
|
+
drawPaddle();
|
|
668
|
+
|
|
669
|
+
// Left and right wall collision
|
|
670
|
+
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
|
|
671
|
+
dx = -dx;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Top wall collision
|
|
675
|
+
if (y + dy < ballRadius) {
|
|
676
|
+
dy = -dy;
|
|
677
|
+
} else if (y + dy > canvas.height - ballRadius) {
|
|
678
|
+
// Bottom edge: paddle collision or game over
|
|
679
|
+
if (x > paddleX && x < paddleX + paddleWidth) {
|
|
680
|
+
dy = -dy;
|
|
681
|
+
} else {
|
|
682
|
+
alert("GAME OVER");
|
|
683
|
+
document.location.reload();
|
|
684
|
+
clearInterval(interval);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Paddle movement
|
|
689
|
+
if (rightPressed) {
|
|
690
|
+
paddleX = Math.min(paddleX + 7, canvas.width - paddleWidth);
|
|
691
|
+
} else if (leftPressed) {
|
|
692
|
+
paddleX = Math.max(paddleX - 7, 0);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
x += dx;
|
|
696
|
+
y += dy;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
interval = setInterval(draw, 10);
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
## Step 6: Build the Brick Field
|
|
705
|
+
|
|
706
|
+
Now we create the grid of bricks that the ball will destroy. The bricks are stored in a 2D array and drawn in rows and columns.
|
|
707
|
+
|
|
708
|
+
### Brick Configuration Variables
|
|
709
|
+
|
|
710
|
+
Define constants that control the layout of the brick field:
|
|
711
|
+
|
|
712
|
+
```javascript
|
|
713
|
+
const brickRowCount = 3;
|
|
714
|
+
const brickColumnCount = 5;
|
|
715
|
+
const brickWidth = 75;
|
|
716
|
+
const brickHeight = 20;
|
|
717
|
+
const brickPadding = 10;
|
|
718
|
+
const brickOffsetTop = 30;
|
|
719
|
+
const brickOffsetLeft = 30;
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
- `brickRowCount` / `brickColumnCount` -- how many rows and columns of bricks.
|
|
723
|
+
- `brickWidth` / `brickHeight` -- dimensions of each individual brick.
|
|
724
|
+
- `brickPadding` -- space between bricks.
|
|
725
|
+
- `brickOffsetTop` / `brickOffsetLeft` -- distance from the top and left canvas edges to the first brick.
|
|
726
|
+
|
|
727
|
+
### Creating the Bricks 2D Array
|
|
728
|
+
|
|
729
|
+
Use nested loops to create a 2D array. Each brick stores its `x` and `y` position (initially `0`, calculated during drawing):
|
|
730
|
+
|
|
731
|
+
```javascript
|
|
732
|
+
const bricks = [];
|
|
733
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
734
|
+
bricks[c] = [];
|
|
735
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
736
|
+
bricks[c][r] = { x: 0, y: 0 };
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### The drawBricks() Function
|
|
742
|
+
|
|
743
|
+
Loop through every brick, calculate its position, store it, and draw it:
|
|
744
|
+
|
|
745
|
+
```javascript
|
|
746
|
+
function drawBricks() {
|
|
747
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
748
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
749
|
+
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
|
|
750
|
+
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
|
|
751
|
+
bricks[c][r].x = brickX;
|
|
752
|
+
bricks[c][r].y = brickY;
|
|
753
|
+
ctx.beginPath();
|
|
754
|
+
ctx.rect(brickX, brickY, brickWidth, brickHeight);
|
|
755
|
+
ctx.fillStyle = "#0095DD";
|
|
756
|
+
ctx.fill();
|
|
757
|
+
ctx.closePath();
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
**Position calculation formula:**
|
|
764
|
+
- `brickX = column * (brickWidth + brickPadding) + brickOffsetLeft`
|
|
765
|
+
- `brickY = row * (brickHeight + brickPadding) + brickOffsetTop`
|
|
766
|
+
|
|
767
|
+
This creates an evenly-spaced grid with consistent padding and margins.
|
|
768
|
+
|
|
769
|
+
### Calling drawBricks() in the Game Loop
|
|
770
|
+
|
|
771
|
+
Add the call at the beginning of your `draw()` function, after clearing the canvas:
|
|
772
|
+
|
|
773
|
+
```javascript
|
|
774
|
+
function draw() {
|
|
775
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
776
|
+
drawBricks();
|
|
777
|
+
drawBall();
|
|
778
|
+
drawPaddle();
|
|
779
|
+
// ... rest of draw function
|
|
780
|
+
}
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
### Complete Code for Step 6
|
|
784
|
+
|
|
785
|
+
```javascript
|
|
786
|
+
const canvas = document.getElementById("myCanvas");
|
|
787
|
+
const ctx = canvas.getContext("2d");
|
|
788
|
+
const ballRadius = 10;
|
|
789
|
+
|
|
790
|
+
let x = canvas.width / 2;
|
|
791
|
+
let y = canvas.height - 30;
|
|
792
|
+
let dx = 2;
|
|
793
|
+
let dy = -2;
|
|
794
|
+
|
|
795
|
+
const paddleHeight = 10;
|
|
796
|
+
const paddleWidth = 75;
|
|
797
|
+
let paddleX = (canvas.width - paddleWidth) / 2;
|
|
798
|
+
|
|
799
|
+
let rightPressed = false;
|
|
800
|
+
let leftPressed = false;
|
|
801
|
+
let interval = 0;
|
|
802
|
+
|
|
803
|
+
const brickRowCount = 3;
|
|
804
|
+
const brickColumnCount = 5;
|
|
805
|
+
const brickWidth = 75;
|
|
806
|
+
const brickHeight = 20;
|
|
807
|
+
const brickPadding = 10;
|
|
808
|
+
const brickOffsetTop = 30;
|
|
809
|
+
const brickOffsetLeft = 30;
|
|
810
|
+
|
|
811
|
+
const bricks = [];
|
|
812
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
813
|
+
bricks[c] = [];
|
|
814
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
815
|
+
bricks[c][r] = { x: 0, y: 0 };
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
820
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
821
|
+
|
|
822
|
+
function keyDownHandler(e) {
|
|
823
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
824
|
+
rightPressed = true;
|
|
825
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
826
|
+
leftPressed = true;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function keyUpHandler(e) {
|
|
831
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
832
|
+
rightPressed = false;
|
|
833
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
834
|
+
leftPressed = false;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
function drawBall() {
|
|
839
|
+
ctx.beginPath();
|
|
840
|
+
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
|
|
841
|
+
ctx.fillStyle = "#0095DD";
|
|
842
|
+
ctx.fill();
|
|
843
|
+
ctx.closePath();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
function drawPaddle() {
|
|
847
|
+
ctx.beginPath();
|
|
848
|
+
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
|
|
849
|
+
ctx.fillStyle = "#0095DD";
|
|
850
|
+
ctx.fill();
|
|
851
|
+
ctx.closePath();
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
function drawBricks() {
|
|
855
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
856
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
857
|
+
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
|
|
858
|
+
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
|
|
859
|
+
bricks[c][r].x = brickX;
|
|
860
|
+
bricks[c][r].y = brickY;
|
|
861
|
+
ctx.beginPath();
|
|
862
|
+
ctx.rect(brickX, brickY, brickWidth, brickHeight);
|
|
863
|
+
ctx.fillStyle = "#0095DD";
|
|
864
|
+
ctx.fill();
|
|
865
|
+
ctx.closePath();
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
function draw() {
|
|
871
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
872
|
+
drawBricks();
|
|
873
|
+
drawBall();
|
|
874
|
+
drawPaddle();
|
|
875
|
+
|
|
876
|
+
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
|
|
877
|
+
dx = -dx;
|
|
878
|
+
}
|
|
879
|
+
if (y + dy < ballRadius) {
|
|
880
|
+
dy = -dy;
|
|
881
|
+
} else if (y + dy > canvas.height - ballRadius) {
|
|
882
|
+
if (x > paddleX && x < paddleX + paddleWidth) {
|
|
883
|
+
dy = -dy;
|
|
884
|
+
} else {
|
|
885
|
+
alert("GAME OVER");
|
|
886
|
+
document.location.reload();
|
|
887
|
+
clearInterval(interval);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
if (rightPressed) {
|
|
892
|
+
paddleX = Math.min(paddleX + 7, canvas.width - paddleWidth);
|
|
893
|
+
} else if (leftPressed) {
|
|
894
|
+
paddleX = Math.max(paddleX - 7, 0);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
x += dx;
|
|
898
|
+
y += dy;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
interval = setInterval(draw, 10);
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
---
|
|
905
|
+
|
|
906
|
+
## Step 7: Collision Detection
|
|
907
|
+
|
|
908
|
+
With bricks on screen, we need to detect when the ball hits one and make it disappear. Each brick gets a `status` property: `1` means visible, `0` means destroyed.
|
|
909
|
+
|
|
910
|
+
### Adding the Status Property to Bricks
|
|
911
|
+
|
|
912
|
+
Update the brick initialization to include a `status` flag:
|
|
913
|
+
|
|
914
|
+
```javascript
|
|
915
|
+
const bricks = [];
|
|
916
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
917
|
+
bricks[c] = [];
|
|
918
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
919
|
+
bricks[c][r] = { x: 0, y: 0, status: 1 };
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
### The collisionDetection() Function
|
|
925
|
+
|
|
926
|
+
Loop through every brick and check if the ball's center is within the brick's bounding box:
|
|
927
|
+
|
|
928
|
+
```javascript
|
|
929
|
+
function collisionDetection() {
|
|
930
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
931
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
932
|
+
const b = bricks[c][r];
|
|
933
|
+
if (b.status === 1) {
|
|
934
|
+
if (
|
|
935
|
+
x > b.x &&
|
|
936
|
+
x < b.x + brickWidth &&
|
|
937
|
+
y > b.y &&
|
|
938
|
+
y < b.y + brickHeight
|
|
939
|
+
) {
|
|
940
|
+
dy = -dy;
|
|
941
|
+
b.status = 0;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
**Collision conditions (all four must be true simultaneously):**
|
|
950
|
+
- `x > b.x` -- ball center is to the right of the brick's left edge.
|
|
951
|
+
- `x < b.x + brickWidth` -- ball center is to the left of the brick's right edge.
|
|
952
|
+
- `y > b.y` -- ball center is below the brick's top edge.
|
|
953
|
+
- `y < b.y + brickHeight` -- ball center is above the brick's bottom edge.
|
|
954
|
+
|
|
955
|
+
When a collision is detected:
|
|
956
|
+
- `dy = -dy` reverses the ball's vertical direction (bounce).
|
|
957
|
+
- `b.status = 0` marks the brick as destroyed.
|
|
958
|
+
|
|
959
|
+
### Updating drawBricks() to Respect Status
|
|
960
|
+
|
|
961
|
+
Only draw bricks that are still active (`status === 1`):
|
|
962
|
+
|
|
963
|
+
```javascript
|
|
964
|
+
function drawBricks() {
|
|
965
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
966
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
967
|
+
if (bricks[c][r].status === 1) {
|
|
968
|
+
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
|
|
969
|
+
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
|
|
970
|
+
bricks[c][r].x = brickX;
|
|
971
|
+
bricks[c][r].y = brickY;
|
|
972
|
+
ctx.beginPath();
|
|
973
|
+
ctx.rect(brickX, brickY, brickWidth, brickHeight);
|
|
974
|
+
ctx.fillStyle = "#0095DD";
|
|
975
|
+
ctx.fill();
|
|
976
|
+
ctx.closePath();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
### Calling collisionDetection() in the Game Loop
|
|
984
|
+
|
|
985
|
+
Add the call in your `draw()` function, after drawing all elements:
|
|
986
|
+
|
|
987
|
+
```javascript
|
|
988
|
+
function draw() {
|
|
989
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
990
|
+
drawBricks();
|
|
991
|
+
drawBall();
|
|
992
|
+
drawPaddle();
|
|
993
|
+
collisionDetection();
|
|
994
|
+
// ... rest of draw function
|
|
995
|
+
}
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
---
|
|
999
|
+
|
|
1000
|
+
## Step 8: Track the Score and Win
|
|
1001
|
+
|
|
1002
|
+
We add a score counter that increments each time a brick is destroyed, and a win condition that triggers when all bricks are gone.
|
|
1003
|
+
|
|
1004
|
+
### Initializing the Score
|
|
1005
|
+
|
|
1006
|
+
```javascript
|
|
1007
|
+
let score = 0;
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
### The drawScore() Function
|
|
1011
|
+
|
|
1012
|
+
Display the current score on the canvas using text rendering:
|
|
1013
|
+
|
|
1014
|
+
```javascript
|
|
1015
|
+
function drawScore() {
|
|
1016
|
+
ctx.font = "16px Arial";
|
|
1017
|
+
ctx.fillStyle = "#0095DD";
|
|
1018
|
+
ctx.fillText(`Score: ${score}`, 8, 20);
|
|
1019
|
+
}
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
- `ctx.font` sets the font size and family (like CSS).
|
|
1023
|
+
- `ctx.fillText(text, x, y)` renders text at the given coordinates.
|
|
1024
|
+
- Position `(8, 20)` places the score in the top-left corner.
|
|
1025
|
+
|
|
1026
|
+
### Incrementing the Score
|
|
1027
|
+
|
|
1028
|
+
In the `collisionDetection()` function, increment the score when a brick is hit:
|
|
1029
|
+
|
|
1030
|
+
```javascript
|
|
1031
|
+
dy = -dy;
|
|
1032
|
+
b.status = 0;
|
|
1033
|
+
score++;
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
### Adding the Win Condition
|
|
1037
|
+
|
|
1038
|
+
After incrementing the score, check if the player has destroyed all bricks:
|
|
1039
|
+
|
|
1040
|
+
```javascript
|
|
1041
|
+
score++;
|
|
1042
|
+
if (score === brickRowCount * brickColumnCount) {
|
|
1043
|
+
alert("YOU WIN, CONGRATULATIONS!");
|
|
1044
|
+
document.location.reload();
|
|
1045
|
+
clearInterval(interval);
|
|
1046
|
+
}
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
The total number of bricks is `brickRowCount * brickColumnCount`. When the score reaches that number, every brick has been destroyed.
|
|
1050
|
+
|
|
1051
|
+
### Complete collisionDetection() with Score and Win
|
|
1052
|
+
|
|
1053
|
+
```javascript
|
|
1054
|
+
function collisionDetection() {
|
|
1055
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
1056
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
1057
|
+
const b = bricks[c][r];
|
|
1058
|
+
if (b.status === 1) {
|
|
1059
|
+
if (
|
|
1060
|
+
x > b.x &&
|
|
1061
|
+
x < b.x + brickWidth &&
|
|
1062
|
+
y > b.y &&
|
|
1063
|
+
y < b.y + brickHeight
|
|
1064
|
+
) {
|
|
1065
|
+
dy = -dy;
|
|
1066
|
+
b.status = 0;
|
|
1067
|
+
score++;
|
|
1068
|
+
if (score === brickRowCount * brickColumnCount) {
|
|
1069
|
+
alert("YOU WIN, CONGRATULATIONS!");
|
|
1070
|
+
document.location.reload();
|
|
1071
|
+
clearInterval(interval);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
### Calling drawScore() in the Game Loop
|
|
1081
|
+
|
|
1082
|
+
Add the call in your `draw()` function:
|
|
1083
|
+
|
|
1084
|
+
```javascript
|
|
1085
|
+
function draw() {
|
|
1086
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1087
|
+
drawBricks();
|
|
1088
|
+
drawBall();
|
|
1089
|
+
drawPaddle();
|
|
1090
|
+
drawScore();
|
|
1091
|
+
collisionDetection();
|
|
1092
|
+
// ... rest of draw function
|
|
1093
|
+
}
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
### Canvas Text Methods Reference
|
|
1097
|
+
|
|
1098
|
+
| Method/Property | Purpose |
|
|
1099
|
+
|-----------------|---------|
|
|
1100
|
+
| `ctx.font` | Set font size and family |
|
|
1101
|
+
| `ctx.fillStyle` | Set text color |
|
|
1102
|
+
| `ctx.fillText(text, x, y)` | Draw filled text at coordinates |
|
|
1103
|
+
|
|
1104
|
+
---
|
|
1105
|
+
|
|
1106
|
+
## Step 9: Mouse Controls
|
|
1107
|
+
|
|
1108
|
+
In addition to keyboard controls, we add mouse support so the player can move the paddle by moving the mouse.
|
|
1109
|
+
|
|
1110
|
+
### Adding the mousemove Event Listener
|
|
1111
|
+
|
|
1112
|
+
Register the handler alongside the existing keyboard listeners:
|
|
1113
|
+
|
|
1114
|
+
```javascript
|
|
1115
|
+
document.addEventListener("mousemove", mouseMoveHandler);
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
### The mouseMoveHandler Function
|
|
1119
|
+
|
|
1120
|
+
Calculate the mouse's horizontal position relative to the canvas and update the paddle position:
|
|
1121
|
+
|
|
1122
|
+
```javascript
|
|
1123
|
+
function mouseMoveHandler(e) {
|
|
1124
|
+
const relativeX = e.clientX - canvas.offsetLeft;
|
|
1125
|
+
if (relativeX > 0 && relativeX < canvas.width) {
|
|
1126
|
+
paddleX = relativeX - paddleWidth / 2;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
**How it works:**
|
|
1132
|
+
- `e.clientX` -- the mouse's horizontal position in the browser viewport.
|
|
1133
|
+
- `canvas.offsetLeft` -- the distance from the canvas's left edge to the viewport's left edge.
|
|
1134
|
+
- `relativeX` -- the mouse position relative to the canvas (not the viewport).
|
|
1135
|
+
- The boundary check (`relativeX > 0 && relativeX < canvas.width`) ensures the paddle only moves when the mouse is over the canvas.
|
|
1136
|
+
- `paddleX = relativeX - paddleWidth / 2` centers the paddle under the mouse cursor by subtracting half the paddle width.
|
|
1137
|
+
|
|
1138
|
+
### Complete Event Listener Setup (Keyboard + Mouse)
|
|
1139
|
+
|
|
1140
|
+
```javascript
|
|
1141
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
1142
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
1143
|
+
document.addEventListener("mousemove", mouseMoveHandler);
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
Both control methods work simultaneously. The player can use arrow keys or mouse -- or switch between them at any time.
|
|
1147
|
+
|
|
1148
|
+
---
|
|
1149
|
+
|
|
1150
|
+
## Step 10: Finishing Up
|
|
1151
|
+
|
|
1152
|
+
The final step adds a lives system (so the player gets multiple chances) and upgrades the game loop from `setInterval` to `requestAnimationFrame` for smoother rendering.
|
|
1153
|
+
|
|
1154
|
+
### Adding the Lives Variable
|
|
1155
|
+
|
|
1156
|
+
```javascript
|
|
1157
|
+
let lives = 3;
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
### The drawLives() Function
|
|
1161
|
+
|
|
1162
|
+
Display the remaining lives in the top-right corner:
|
|
1163
|
+
|
|
1164
|
+
```javascript
|
|
1165
|
+
function drawLives() {
|
|
1166
|
+
ctx.font = "16px Arial";
|
|
1167
|
+
ctx.fillStyle = "#0095DD";
|
|
1168
|
+
ctx.fillText(`Lives: ${lives}`, canvas.width - 65, 20);
|
|
1169
|
+
}
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
### Implementing the Lives System
|
|
1173
|
+
|
|
1174
|
+
Replace the immediate game-over logic with a lives-based system. When the ball misses the paddle:
|
|
1175
|
+
|
|
1176
|
+
```javascript
|
|
1177
|
+
if (y + dy < ballRadius) {
|
|
1178
|
+
dy = -dy;
|
|
1179
|
+
} else if (y + dy > canvas.height - ballRadius) {
|
|
1180
|
+
if (x > paddleX && x < paddleX + paddleWidth) {
|
|
1181
|
+
dy = -dy;
|
|
1182
|
+
} else {
|
|
1183
|
+
lives--;
|
|
1184
|
+
if (!lives) {
|
|
1185
|
+
alert("GAME OVER");
|
|
1186
|
+
document.location.reload();
|
|
1187
|
+
} else {
|
|
1188
|
+
// Reset ball and paddle positions
|
|
1189
|
+
x = canvas.width / 2;
|
|
1190
|
+
y = canvas.height - 30;
|
|
1191
|
+
dx = 2;
|
|
1192
|
+
dy = -2;
|
|
1193
|
+
paddleX = (canvas.width - paddleWidth) / 2;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
**What happens when a life is lost:**
|
|
1200
|
+
- `lives--` decrements the lives counter.
|
|
1201
|
+
- If `lives` reaches `0`, the game ends with an alert and page reload.
|
|
1202
|
+
- Otherwise, the ball resets to center-bottom, velocity resets, and the paddle resets to center.
|
|
1203
|
+
|
|
1204
|
+
### Upgrading to requestAnimationFrame
|
|
1205
|
+
|
|
1206
|
+
Replace `setInterval` with `requestAnimationFrame` for a smoother, browser-optimized game loop:
|
|
1207
|
+
|
|
1208
|
+
**Old approach (remove):**
|
|
1209
|
+
```javascript
|
|
1210
|
+
interval = setInterval(draw, 10);
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
**New approach:**
|
|
1214
|
+
Add `requestAnimationFrame(draw)` at the end of the `draw()` function:
|
|
1215
|
+
|
|
1216
|
+
```javascript
|
|
1217
|
+
function draw() {
|
|
1218
|
+
// ... all drawing and logic ...
|
|
1219
|
+
requestAnimationFrame(draw);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
// Start the game by calling draw() once:
|
|
1223
|
+
draw();
|
|
1224
|
+
```
|
|
1225
|
+
|
|
1226
|
+
`requestAnimationFrame` lets the browser schedule rendering at the optimal frame rate (typically 60fps), which is more efficient than a fixed 10ms interval.
|
|
1227
|
+
|
|
1228
|
+
### Calling drawLives() in the Game Loop
|
|
1229
|
+
|
|
1230
|
+
```javascript
|
|
1231
|
+
function draw() {
|
|
1232
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1233
|
+
drawBricks();
|
|
1234
|
+
drawBall();
|
|
1235
|
+
drawPaddle();
|
|
1236
|
+
drawScore();
|
|
1237
|
+
drawLives();
|
|
1238
|
+
collisionDetection();
|
|
1239
|
+
// ... rest of logic ...
|
|
1240
|
+
requestAnimationFrame(draw);
|
|
1241
|
+
}
|
|
1242
|
+
```
|
|
1243
|
+
|
|
1244
|
+
---
|
|
1245
|
+
|
|
1246
|
+
## Complete Final Game Code
|
|
1247
|
+
|
|
1248
|
+
Below is the entire game in a single, self-contained HTML file. This is the final product of all 10 steps combined.
|
|
1249
|
+
|
|
1250
|
+
```html
|
|
1251
|
+
<!doctype html>
|
|
1252
|
+
<html lang="en-US">
|
|
1253
|
+
<head>
|
|
1254
|
+
<meta charset="utf-8" />
|
|
1255
|
+
<title>2D Breakout Game</title>
|
|
1256
|
+
<style>
|
|
1257
|
+
* {
|
|
1258
|
+
padding: 0;
|
|
1259
|
+
margin: 0;
|
|
1260
|
+
}
|
|
1261
|
+
canvas {
|
|
1262
|
+
background: #eeeeee;
|
|
1263
|
+
display: block;
|
|
1264
|
+
margin: 0 auto;
|
|
1265
|
+
}
|
|
1266
|
+
</style>
|
|
1267
|
+
</head>
|
|
1268
|
+
<body>
|
|
1269
|
+
<canvas id="myCanvas" width="480" height="320"></canvas>
|
|
1270
|
+
|
|
1271
|
+
<script>
|
|
1272
|
+
const canvas = document.getElementById("myCanvas");
|
|
1273
|
+
const ctx = canvas.getContext("2d");
|
|
1274
|
+
|
|
1275
|
+
// --- Ball ---
|
|
1276
|
+
const ballRadius = 10;
|
|
1277
|
+
let x = canvas.width / 2;
|
|
1278
|
+
let y = canvas.height - 30;
|
|
1279
|
+
let dx = 2;
|
|
1280
|
+
let dy = -2;
|
|
1281
|
+
|
|
1282
|
+
// --- Paddle ---
|
|
1283
|
+
const paddleHeight = 10;
|
|
1284
|
+
const paddleWidth = 75;
|
|
1285
|
+
let paddleX = (canvas.width - paddleWidth) / 2;
|
|
1286
|
+
|
|
1287
|
+
// --- Controls ---
|
|
1288
|
+
let rightPressed = false;
|
|
1289
|
+
let leftPressed = false;
|
|
1290
|
+
|
|
1291
|
+
// --- Bricks ---
|
|
1292
|
+
const brickRowCount = 3;
|
|
1293
|
+
const brickColumnCount = 5;
|
|
1294
|
+
const brickWidth = 75;
|
|
1295
|
+
const brickHeight = 20;
|
|
1296
|
+
const brickPadding = 10;
|
|
1297
|
+
const brickOffsetTop = 30;
|
|
1298
|
+
const brickOffsetLeft = 30;
|
|
1299
|
+
|
|
1300
|
+
const bricks = [];
|
|
1301
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
1302
|
+
bricks[c] = [];
|
|
1303
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
1304
|
+
bricks[c][r] = { x: 0, y: 0, status: 1 };
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// --- Score and Lives ---
|
|
1309
|
+
let score = 0;
|
|
1310
|
+
let lives = 3;
|
|
1311
|
+
|
|
1312
|
+
// =====================
|
|
1313
|
+
// Event Listeners
|
|
1314
|
+
// =====================
|
|
1315
|
+
document.addEventListener("keydown", keyDownHandler);
|
|
1316
|
+
document.addEventListener("keyup", keyUpHandler);
|
|
1317
|
+
document.addEventListener("mousemove", mouseMoveHandler);
|
|
1318
|
+
|
|
1319
|
+
function keyDownHandler(e) {
|
|
1320
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
1321
|
+
rightPressed = true;
|
|
1322
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
1323
|
+
leftPressed = true;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
function keyUpHandler(e) {
|
|
1328
|
+
if (e.key === "Right" || e.key === "ArrowRight") {
|
|
1329
|
+
rightPressed = false;
|
|
1330
|
+
} else if (e.key === "Left" || e.key === "ArrowLeft") {
|
|
1331
|
+
leftPressed = false;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
function mouseMoveHandler(e) {
|
|
1336
|
+
const relativeX = e.clientX - canvas.offsetLeft;
|
|
1337
|
+
if (relativeX > 0 && relativeX < canvas.width) {
|
|
1338
|
+
paddleX = relativeX - paddleWidth / 2;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
// =====================
|
|
1343
|
+
// Collision Detection
|
|
1344
|
+
// =====================
|
|
1345
|
+
function collisionDetection() {
|
|
1346
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
1347
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
1348
|
+
const b = bricks[c][r];
|
|
1349
|
+
if (b.status === 1) {
|
|
1350
|
+
if (
|
|
1351
|
+
x > b.x &&
|
|
1352
|
+
x < b.x + brickWidth &&
|
|
1353
|
+
y > b.y &&
|
|
1354
|
+
y < b.y + brickHeight
|
|
1355
|
+
) {
|
|
1356
|
+
dy = -dy;
|
|
1357
|
+
b.status = 0;
|
|
1358
|
+
score++;
|
|
1359
|
+
if (score === brickRowCount * brickColumnCount) {
|
|
1360
|
+
alert("YOU WIN, CONGRATULATIONS!");
|
|
1361
|
+
document.location.reload();
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
// =====================
|
|
1370
|
+
// Drawing Functions
|
|
1371
|
+
// =====================
|
|
1372
|
+
function drawBall() {
|
|
1373
|
+
ctx.beginPath();
|
|
1374
|
+
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
|
|
1375
|
+
ctx.fillStyle = "#0095DD";
|
|
1376
|
+
ctx.fill();
|
|
1377
|
+
ctx.closePath();
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
function drawPaddle() {
|
|
1381
|
+
ctx.beginPath();
|
|
1382
|
+
ctx.rect(
|
|
1383
|
+
paddleX,
|
|
1384
|
+
canvas.height - paddleHeight,
|
|
1385
|
+
paddleWidth,
|
|
1386
|
+
paddleHeight
|
|
1387
|
+
);
|
|
1388
|
+
ctx.fillStyle = "#0095DD";
|
|
1389
|
+
ctx.fill();
|
|
1390
|
+
ctx.closePath();
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
function drawBricks() {
|
|
1394
|
+
for (let c = 0; c < brickColumnCount; c++) {
|
|
1395
|
+
for (let r = 0; r < brickRowCount; r++) {
|
|
1396
|
+
if (bricks[c][r].status === 1) {
|
|
1397
|
+
const brickX =
|
|
1398
|
+
c * (brickWidth + brickPadding) + brickOffsetLeft;
|
|
1399
|
+
const brickY =
|
|
1400
|
+
r * (brickHeight + brickPadding) + brickOffsetTop;
|
|
1401
|
+
bricks[c][r].x = brickX;
|
|
1402
|
+
bricks[c][r].y = brickY;
|
|
1403
|
+
ctx.beginPath();
|
|
1404
|
+
ctx.rect(brickX, brickY, brickWidth, brickHeight);
|
|
1405
|
+
ctx.fillStyle = "#0095DD";
|
|
1406
|
+
ctx.fill();
|
|
1407
|
+
ctx.closePath();
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
function drawScore() {
|
|
1414
|
+
ctx.font = "16px Arial";
|
|
1415
|
+
ctx.fillStyle = "#0095DD";
|
|
1416
|
+
ctx.fillText(`Score: ${score}`, 8, 20);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
function drawLives() {
|
|
1420
|
+
ctx.font = "16px Arial";
|
|
1421
|
+
ctx.fillStyle = "#0095DD";
|
|
1422
|
+
ctx.fillText(`Lives: ${lives}`, canvas.width - 65, 20);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
// =====================
|
|
1426
|
+
// Main Game Loop
|
|
1427
|
+
// =====================
|
|
1428
|
+
function draw() {
|
|
1429
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1430
|
+
drawBricks();
|
|
1431
|
+
drawBall();
|
|
1432
|
+
drawPaddle();
|
|
1433
|
+
drawScore();
|
|
1434
|
+
drawLives();
|
|
1435
|
+
collisionDetection();
|
|
1436
|
+
|
|
1437
|
+
// Left and right wall collision
|
|
1438
|
+
if (
|
|
1439
|
+
x + dx > canvas.width - ballRadius ||
|
|
1440
|
+
x + dx < ballRadius
|
|
1441
|
+
) {
|
|
1442
|
+
dx = -dx;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
// Top wall collision
|
|
1446
|
+
if (y + dy < ballRadius) {
|
|
1447
|
+
dy = -dy;
|
|
1448
|
+
} else if (y + dy > canvas.height - ballRadius) {
|
|
1449
|
+
// Bottom edge: paddle collision or lose a life
|
|
1450
|
+
if (x > paddleX && x < paddleX + paddleWidth) {
|
|
1451
|
+
dy = -dy;
|
|
1452
|
+
} else {
|
|
1453
|
+
lives--;
|
|
1454
|
+
if (!lives) {
|
|
1455
|
+
alert("GAME OVER");
|
|
1456
|
+
document.location.reload();
|
|
1457
|
+
} else {
|
|
1458
|
+
x = canvas.width / 2;
|
|
1459
|
+
y = canvas.height - 30;
|
|
1460
|
+
dx = 2;
|
|
1461
|
+
dy = -2;
|
|
1462
|
+
paddleX = (canvas.width - paddleWidth) / 2;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// Paddle movement (keyboard)
|
|
1468
|
+
if (rightPressed) {
|
|
1469
|
+
paddleX = Math.min(
|
|
1470
|
+
paddleX + 7,
|
|
1471
|
+
canvas.width - paddleWidth
|
|
1472
|
+
);
|
|
1473
|
+
} else if (leftPressed) {
|
|
1474
|
+
paddleX = Math.max(paddleX - 7, 0);
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
x += dx;
|
|
1478
|
+
y += dy;
|
|
1479
|
+
requestAnimationFrame(draw);
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
draw();
|
|
1483
|
+
</script>
|
|
1484
|
+
</body>
|
|
1485
|
+
</html>
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
---
|
|
1489
|
+
|
|
1490
|
+
## Quick Reference: All Game Variables
|
|
1491
|
+
|
|
1492
|
+
| Variable | Type | Purpose |
|
|
1493
|
+
|----------|------|---------|
|
|
1494
|
+
| `canvas` | const | Reference to the HTML canvas element |
|
|
1495
|
+
| `ctx` | const | 2D rendering context |
|
|
1496
|
+
| `ballRadius` | const | Radius of the ball (10) |
|
|
1497
|
+
| `x`, `y` | let | Current ball position |
|
|
1498
|
+
| `dx`, `dy` | let | Ball velocity (pixels per frame) |
|
|
1499
|
+
| `paddleHeight` | const | Height of the paddle (10) |
|
|
1500
|
+
| `paddleWidth` | const | Width of the paddle (75) |
|
|
1501
|
+
| `paddleX` | let | Current horizontal position of the paddle |
|
|
1502
|
+
| `rightPressed` | let | Whether the right arrow key is held down |
|
|
1503
|
+
| `leftPressed` | let | Whether the left arrow key is held down |
|
|
1504
|
+
| `brickRowCount` | const | Number of brick rows (3) |
|
|
1505
|
+
| `brickColumnCount` | const | Number of brick columns (5) |
|
|
1506
|
+
| `brickWidth` | const | Width of each brick (75) |
|
|
1507
|
+
| `brickHeight` | const | Height of each brick (20) |
|
|
1508
|
+
| `brickPadding` | const | Space between bricks (10) |
|
|
1509
|
+
| `brickOffsetTop` | const | Distance from top of canvas to first brick row (30) |
|
|
1510
|
+
| `brickOffsetLeft` | const | Distance from left of canvas to first brick column (30) |
|
|
1511
|
+
| `bricks` | const | 2D array holding all brick objects |
|
|
1512
|
+
| `score` | let | Current player score |
|
|
1513
|
+
| `lives` | let | Remaining lives (starts at 3) |
|
|
1514
|
+
|
|
1515
|
+
## Quick Reference: All Functions
|
|
1516
|
+
|
|
1517
|
+
| Function | Purpose |
|
|
1518
|
+
|----------|---------|
|
|
1519
|
+
| `keyDownHandler(e)` | Sets `rightPressed` or `leftPressed` to `true` on key press |
|
|
1520
|
+
| `keyUpHandler(e)` | Sets `rightPressed` or `leftPressed` to `false` on key release |
|
|
1521
|
+
| `mouseMoveHandler(e)` | Moves paddle to follow mouse horizontal position |
|
|
1522
|
+
| `collisionDetection()` | Checks ball against all active bricks; destroys hit bricks, increments score, checks win |
|
|
1523
|
+
| `drawBall()` | Renders the ball at current `(x, y)` position |
|
|
1524
|
+
| `drawPaddle()` | Renders the paddle at current `paddleX` position |
|
|
1525
|
+
| `drawBricks()` | Renders all bricks with `status === 1` |
|
|
1526
|
+
| `drawScore()` | Renders the score text in the top-left corner |
|
|
1527
|
+
| `drawLives()` | Renders the lives text in the top-right corner |
|
|
1528
|
+
| `draw()` | Main game loop: clears canvas, draws everything, handles collisions, updates positions |
|