Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
311 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,19 @@ | ||
# A snake game writted by TypeScript | ||
# Description | ||
|
||
This is a basic snake game writted by TypeScript | ||
|
||
## Install dependencies | ||
|
||
```bash | ||
npm i | ||
``` | ||
|
||
## Run | ||
|
||
```bash | ||
npm start | ||
``` | ||
|
||
## License | ||
|
||
[MIT](https://choosealicense.com/licenses/mit/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export default class Food { | ||
element:HTMLElement; | ||
|
||
constructor() { | ||
// get food element and store | ||
this.element = document.getElementById('food')!; | ||
} | ||
|
||
// get position of the food | ||
get X():number { | ||
return this.element.offsetLeft; | ||
} | ||
|
||
get Y():number { | ||
return this.element.offsetTop; | ||
} | ||
|
||
// change food position | ||
changePosition():void { | ||
const top = Math.round(Math.random() * 29) * 10; | ||
const left = Math.round(Math.random() * 29) * 10; | ||
this.element.style.left = `${top}px`; | ||
this.element.style.top = `${left}px`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,69 @@ | ||
*{ | ||
padding: 0; | ||
margin: 0; | ||
box-sizing: border-box; | ||
} | ||
|
||
body{ | ||
transform: translateX(30px); | ||
display: flex; | ||
} | ||
justify-content: center; | ||
align-items: center; | ||
height: 100vh; | ||
.container{ | ||
width: 360px; | ||
height: 420px; | ||
background-color: #999; | ||
border: 5px black solid; | ||
border-radius:30px; | ||
.screen{ | ||
width: 304px; | ||
height: 304px; | ||
border:2px black solid; | ||
margin: 18px auto; | ||
position: relative; | ||
#snake{ | ||
&>div{ | ||
width: 10px; | ||
height: 10px; | ||
background-color: #000; | ||
padding:1px; | ||
background-clip: content-box; | ||
position: absolute; | ||
} | ||
} | ||
#food{ | ||
width: 10px; | ||
height: 10px; | ||
background-color: #000; | ||
position: absolute; | ||
left:20px; | ||
top:20px; | ||
border-radius:50%; | ||
} | ||
#restart{ | ||
font-size: 2rem; | ||
background-color: transparent; | ||
color: white; | ||
border: none; | ||
position: absolute; | ||
top:50%; | ||
left:50%; | ||
transform: translate(-50%, -50%); | ||
cursor: pointer; | ||
|
||
} | ||
} | ||
.info{ | ||
font: 1rem; | ||
font-weight: bolder; | ||
padding:20px; | ||
div:first-child{ | ||
float: left; | ||
} | ||
div:last-child{ | ||
float: right; | ||
} | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,91 @@ | ||
/* eslint-disable import/extensions */ | ||
/* eslint-disable import/no-unresolved */ | ||
import './index.less'; | ||
import Food from './food'; | ||
import Info from './info'; | ||
import Snake from './snake'; | ||
|
||
const nihd = 'hello'; | ||
console.log('nihao'); | ||
function sum(a:number):number { | ||
return a + 4; | ||
class Game { | ||
snake:Snake; | ||
|
||
food:Food; | ||
|
||
info:Info; | ||
|
||
direction:string='ArrowRight'; | ||
|
||
isLive = true; | ||
|
||
startButton:HTMLElement; | ||
|
||
keydownHandler = (e:KeyboardEvent) => { | ||
if (e.key.startsWith('Arrow')) { | ||
this.direction = e.key; | ||
} | ||
} | ||
|
||
restart = () => { | ||
this.snake = new Snake(); | ||
this.food.changePosition(); | ||
this.info = new Info(); | ||
this.startButton.style.display = 'none'; | ||
this.direction = 'ArrowRight'; | ||
this.start(); | ||
} | ||
|
||
constructor() { | ||
this.snake = new Snake(); | ||
this.food = new Food(); | ||
this.info = new Info(); | ||
this.startButton = document.getElementById('restart')!; | ||
this.startButton.addEventListener('click', this.restart); | ||
document.addEventListener('keydown', this.keydownHandler); | ||
} | ||
|
||
hasEat(x:number, y:number) { | ||
return x === this.food.X && y === this.food.Y; | ||
} | ||
|
||
start() { | ||
let { X, Y } = this.snake; | ||
|
||
switch (this.direction) { | ||
case 'ArrowUp': { | ||
Y -= 10; | ||
break; | ||
} | ||
case 'ArrowDown': { | ||
Y += 10; | ||
break; | ||
} | ||
case 'ArrowLeft': { | ||
X -= 10; | ||
break; | ||
} | ||
case 'ArrowRight': { | ||
X += 10; | ||
break; | ||
} | ||
default: | ||
} | ||
|
||
if (this.hasEat(X, Y)) { // if is ture then it is safe and no error | ||
this.food.changePosition(); | ||
this.info.addScore(); | ||
this.snake.increaseLength(X, Y); | ||
} else { | ||
// may cause error since eat self or cash wall | ||
try { | ||
this.snake.eatSelf(X, Y); | ||
this.snake.move(X, Y); | ||
} catch (e) { | ||
this.startButton.style.display = 'block'; | ||
return; | ||
} | ||
} | ||
// eslint-disable-next-line no-unused-expressions | ||
this.isLive && setTimeout(this.start.bind(this), (12 - this.info.level) * 50); | ||
} | ||
} | ||
|
||
console.log(sum(4)); | ||
console.log(sum(4)); | ||
const game = new Game(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
export default class Info { | ||
score=0; | ||
|
||
level=1; | ||
|
||
scoreEle:HTMLElement; | ||
|
||
levelEle:HTMLElement; | ||
|
||
maxLEVEL:number; | ||
|
||
upScore:number; | ||
|
||
constructor(maxLEVEL:number = 10, upScore:number = 3) { | ||
this.scoreEle = document.getElementById('score')!; | ||
this.levelEle = document.getElementById('level')!; | ||
this.maxLEVEL = maxLEVEL; | ||
this.upScore = upScore; | ||
} | ||
|
||
// add score | ||
addScore():void { | ||
this.score += 1; | ||
this.scoreEle.textContent = String(this.score); | ||
if (this.score % this.upScore === 0) this.levelUp(); | ||
} | ||
|
||
levelUp():void { | ||
if (this.level < 10) { | ||
this.level += 1; | ||
this.levelEle.textContent = String(this.level); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
export default class Snake { | ||
head:HTMLElement; | ||
|
||
bodies:HTMLCollection; | ||
|
||
snake:HTMLElement; | ||
|
||
constructor() { | ||
this.snake = document.getElementById('snake')!; | ||
this.init(); | ||
this.head = document.querySelector('#snake > div')!; | ||
this.bodies = this.snake.getElementsByTagName('div')!; | ||
} | ||
|
||
init() { | ||
this.snake.innerHTML = '<div></div>'; // restart and make sure only one div exists | ||
} | ||
|
||
// get the head of the Snake | ||
get X() { | ||
return this.head.offsetLeft; | ||
} | ||
|
||
get Y() { | ||
return this.head.offsetTop; | ||
} | ||
|
||
// set the head position of the snake | ||
setPosition(x: number, y: number) { | ||
if (x < 0 || x > 290 || y < 0 || y > 290) throw new Error('dead'); | ||
this.head.style.left = `${x}px`; | ||
this.head.style.top = `${y}px`; | ||
} | ||
|
||
// test whether next move will eat self | ||
eatSelf(x:number, y:number) { | ||
if ([...this.bodies].some((body) => body !== this.head | ||
&& x === (<HTMLScriptElement>body).offsetLeft | ||
&& y === (<HTMLScriptElement>body).offsetTop)) { throw new Error('dead'); } | ||
} | ||
|
||
// increase length at the next setp position | ||
increaseLength(x: number, y: number) { | ||
const step = document.createElement('div'); | ||
this.snake.insertBefore(step, this.head); | ||
this.head = step; | ||
this.setPosition(x, y); | ||
} | ||
|
||
// move | ||
// remove the last child add to the front of the child | ||
move(x: number, y: number) { | ||
if (x < 0 || x > 290 || y < 0 || y > 290) throw new Error('dead'); | ||
const lastChild:HTMLElement = this.snake.querySelector('div:last-child')!; | ||
const step = document.createElement('div'); | ||
this.snake.insertBefore(step, this.head); | ||
this.head = step; | ||
this.snake.removeChild(lastChild); | ||
this.setPosition(x, y); // use set position to add new div to right position | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9f50e18
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
snake-game-ts – ./
snake-game-ts-git-main-yanceymails-gmailcom.vercel.app
snake-game-ts-yanceymails-gmailcom.vercel.app
snake-game-ts-ten.vercel.app