This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Doric/doric-web/dist/Snake.js

476 lines
50 KiB
JavaScript
Raw Normal View History

2019-12-26 11:25:41 +08:00
'use strict';
var doric = require('doric');
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
const colors = {
bgColor: doric.Color.parse('#FFB7BFAC'),
snakeColor: doric.Color.BLACK,
foodColor: doric.Color.BLACK,
};
const hignScoreKey = "SnakeHignScore";
const arrowUp = "data:image/png;base64,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
const arrowLeft = "data:image/png;base64,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
const arrowRight = "data:image/png;base64,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
const arrowDown = "data:image/png;base64,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
const startIcon = "data:image/png;base64,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
const pauseIcon = "data:image/png;base64,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";
function scoreFormat(score) {
return `${Math.floor((score % 1000) / 100)}${Math.floor((score % 100) / 10)}${Math.floor(score % 10)}`;
}
var Direction;
(function (Direction) {
Direction[Direction["left"] = 0] = "left";
Direction[Direction["right"] = 1] = "right";
Direction[Direction["up"] = 2] = "up";
Direction[Direction["down"] = 3] = "down";
})(Direction || (Direction = {}));
var State;
(function (State) {
State[State["idel"] = 0] = "idel";
State[State["run"] = 1] = "run";
State[State["fail"] = 2] = "fail";
State[State["paused"] = 3] = "paused";
})(State || (State = {}));
class SnakeModel {
constructor(w, h) {
this.state = State.idel;
this.direction = Direction.right;
this.highScore = 0;
this.food = { x: -1, y: -1 };
this.head = {
x: 0,
y: 0,
};
this.width = w;
this.height = h;
}
refreshFood() {
this.food.x = Math.floor(Math.random() * (this.width - 1));
this.food.y = Math.floor(Math.random() * (this.height - 1));
}
get tail() {
let node = this.head;
while (node.next !== undefined) {
node = node.next;
}
return node;
}
get score() {
let node = this.head;
let n = 0;
while (node.next !== undefined) {
n++;
node = node.next;
}
return n;
}
forward(node) {
switch (this.direction) {
case Direction.left:
node.x -= 1;
break;
case Direction.right:
node.x += 1;
break;
case Direction.up:
node.y -= 1;
break;
case Direction.down:
node.y += 1;
break;
}
}
step() {
if (this.state !== State.run) {
return;
}
let tail = this.tail;
while (tail.prev != undefined) {
tail.x = tail.prev.x;
tail.y = tail.prev.y;
tail = tail.prev;
}
this.forward(this.head);
if (this.head.x < 0 || this.head.x >= this.width
|| this.head.y < 0 || this.head.y >= this.height) {
//If out of bound
this.state = State.fail;
}
else if (this.head.x == this.food.x && this.head.y == this.food.y) {
//If eat food
let head = { x: this.food.x, y: this.food.y };
this.forward(head);
this.head.prev = head;
head.next = this.head;
this.head = head;
this.refreshFood();
this.highScore = Math.max(this.highScore, this.score);
doric.storage(context).setItem(hignScoreKey, `${this.highScore}`);
}
if (this.crashAtSelf()) {
//If crash at self
this.state = State.fail;
}
}
crashAtSelf() {
let cur = this.head.next;
while (cur !== undefined) {
if (cur.x == this.head.x && cur.y == this.head.y) {
return true;
}
cur = cur.next;
}
return false;
}
reset() {
this.direction = Direction.right;
this.state = State.run;
this.head.x = 0;
this.head.y = 0;
this.head.next = undefined;
this.refreshFood();
}
}
class SnakeView extends doric.ViewHolder {
panelZone() {
return doric.vlayout([
doric.stack([
this.panel = doric.stack([]).apply({
layoutConfig: doric.layoutConfig().just(),
}),
]).apply({
padding: {
left: 2,
right: 2,
top: 2,
bottom: 2,
},
border: {
width: 1,
color: doric.Color.BLACK,
},
layoutConfig: doric.layoutConfig().fit().configAlignmnet(doric.Gravity.Center),
}),
doric.hlayout([
doric.text({
text: "SCORE",
textSize: 20,
padding: {
left: 40
},
2019-12-26 11:25:41 +08:00
}),
this.score = doric.text({
text: "000",
textSize: 20,
}),
(new doric.Stack()).apply({
layoutConfig: doric.layoutConfig().just().configWeight(1),
}),
doric.text({
text: "HIGH",
textSize: 20,
}),
this.high = doric.text({
text: "000",
textSize: 20,
padding: {
right: 40
},
2019-12-26 11:25:41 +08:00
}),
]).apply({
layoutConfig: doric.layoutConfig().fit()
.configWidth(doric.LayoutSpec.MOST)
2020-01-03 13:35:40 +08:00
.configAlignment(doric.Gravity.Left),
2019-12-26 11:25:41 +08:00
space: 10,
}),
]).apply({
layoutConfig: doric.layoutConfig().fit().configWidth(doric.LayoutSpec.MOST),
backgroundColor: colors.bgColor,
padding: {
top: 20,
bottom: 20,
}
});
}
controlZone() {
return doric.vlayout([
doric.hlayout([
this.up = doric.image({
layoutConfig: doric.layoutConfig().just(),
width: 50,
height: 50,
imageBase64: arrowUp
})
]),
doric.hlayout([
this.left = doric.image({
layoutConfig: doric.layoutConfig().just(),
width: 50,
height: 50,
imageBase64: arrowLeft,
}),
this.start = doric.image({
layoutConfig: doric.layoutConfig().just(),
width: 50,
height: 50,
imageBase64: startIcon,
}),
this.right = doric.image({
layoutConfig: doric.layoutConfig().just(),
width: 50,
height: 50,
imageBase64: arrowRight,
}),
]).also(it => {
it.space = 10;
}),
doric.hlayout([
this.down = doric.image({
layoutConfig: doric.layoutConfig().just(),
width: 50,
height: 50,
imageBase64: arrowDown,
})
]),
]).also(controlArea => {
controlArea.space = 10;
controlArea.gravity = new doric.Gravity().centerX();
controlArea.layoutConfig = {
alignment: new doric.Gravity().centerX(),
widthSpec: doric.LayoutSpec.FIT,
heightSpec: doric.LayoutSpec.FIT,
};
});
}
build(root) {
root.backgroundColor = doric.Color.WHITE;
doric.vlayout([
this.panelZone(),
this.controlZone(),
]).also(it => {
it.layoutConfig = doric.layoutConfig().most();
it.gravity = new doric.Gravity().centerX();
it.space = 50;
}).in(root);
}
bind(state) {
let node = state.head;
let nodes = [];
while (node != undefined) {
nodes.push(node);
node = node.next;
}
nodes.push(state.food);
nodes.forEach((e, index) => {
let item = this.panel.children[index];
if (item === undefined) {
item = doric.stack([
doric.stack([]).apply({
layoutConfig: doric.layoutConfig().just().configAlignmnet(doric.Gravity.Center),
width: 9,
height: 9,
})
]).apply({
layoutConfig: doric.layoutConfig().just(),
width: 10,
height: 10,
}).in(this.panel);
}
doric.takeNonNull(item.children[0])(v => {
if (index === nodes.length - 1) {
v.backgroundColor = colors.foodColor;
}
else {
v.backgroundColor = colors.snakeColor;
}
});
item.x = e.x * 10;
item.y = e.y * 10;
});
if (nodes.length < this.panel.children.length) {
this.panel.children.length = nodes.length;
}
this.score.text = `${scoreFormat(state.score)}`;
this.high.text = `${scoreFormat(state.highScore)}`;
this.start.imageBase64 = state.state === State.run ? pauseIcon : startIcon;
}
}
class SnakeVM extends doric.ViewModel {
constructor() {
super(...arguments);
this.timeInterval = 500;
this.start = () => {
if (this.timerId !== undefined) {
clearInterval(this.timerId);
}
this.updateState(it => it.reset());
this.timerId = setInterval(() => {
this.updateState(it => it.step());
if (this.getState().state === State.fail) {
this.stop();
}
}, this.timeInterval);
};
this.pause = () => {
if (this.timerId !== undefined) {
clearInterval(this.timerId);
}
this.updateState(it => it.state = State.paused);
};
this.resume = () => {
if (this.timerId !== undefined) {
clearInterval(this.timerId);
}
this.updateState(it => it.state = State.run);
this.timerId = setInterval(() => {
this.updateState(it => it.step());
if (this.getState().state === State.fail) {
this.stop();
}
}, this.timeInterval);
};
this.stop = () => {
if (this.timerId !== undefined) {
clearInterval(this.timerId);
this.timerId = undefined;
}
};
this.left = () => {
this.updateState(it => it.direction = Direction.left);
};
this.right = () => {
this.updateState(it => it.direction = Direction.right);
};
this.up = () => {
this.updateState(it => it.direction = Direction.up);
};
this.down = () => {
this.updateState(it => it.direction = Direction.down);
};
}
onAttached(state, v) {
doric.takeNonNull(v.start)(it => it.onClick = () => {
if (state.state === State.run) {
this.pause();
}
else if (state.state === State.paused) {
this.resume();
}
else {
this.start();
}
});
doric.takeNonNull(v.left)(it => it.onClick = this.left);
doric.takeNonNull(v.right)(it => it.onClick = this.right);
doric.takeNonNull(v.up)(it => it.onClick = this.up);
doric.takeNonNull(v.down)(it => it.onClick = this.down);
v.panel.apply({
width: state.width * 10,
height: state.height * 10,
});
doric.storage(context).getItem(hignScoreKey).then(r => {
this.updateState(s => {
if (r) {
s.highScore = parseInt(r);
}
else {
s.highScore = 0;
}
});
});
}
onBind(state, v) {
v.bind(state);
if (state.state === State.run) {
v.start;
}
if (state.state === State.fail) {
doric.popover(context).show(doric.vlayout([
doric.text({
text: "游戏结束",
textSize: 40,
}),
doric.hlayout([
doric.text({
text: "继续",
textSize: 30,
padding: {
left: 20,
right: 20,
top: 10,
bottom: 10,
},
border: {
width: 1,
color: doric.Color.BLACK,
},
onClick: () => {
doric.popover(context).dismiss();
this.start();
},
}),
doric.text({
text: "退出",
textSize: 30,
padding: {
left: 20,
right: 20,
top: 10,
bottom: 10,
},
border: {
width: 1,
color: doric.Color.BLACK,
},
onClick: () => {
doric.popover(context).dismiss();
doric.navigator(context).pop();
},
}),
]).apply({
space: 100,
layoutConfig: doric.layoutConfig().fit().configMargin({
bottom: 20
}),
}),
]).apply({
layoutConfig: doric.layoutConfig().fit().configWidth(doric.LayoutSpec.MOST).configMargin({
top: 300,
left: 20,
right: 20,
}),
border: {
width: 1,
color: doric.Color.BLACK,
},
backgroundColor: colors.bgColor,
gravity: doric.Gravity.Center,
}));
}
}
}
let SnakePanel = class SnakePanel extends doric.VMPanel {
getViewModelClass() {
return SnakeVM;
}
getState() {
return new SnakeModel(30, 30);
}
getViewHolderClass() {
return SnakeView;
}
onShow() {
doric.navbar(context).setTitle("贪吃蛇");
}
};
SnakePanel = __decorate([
Entry
], SnakePanel);
//# sourceMappingURL=Snake.js.map