Commit 4244b24f authored by Chen Jiping's avatar Chen Jiping

完成模板开发

parent 3695f7ce
...@@ -128,5 +128,8 @@ ...@@ -128,5 +128,8 @@
} }
} }
}, },
"defaultProject": "ng-template-generator" "defaultProject": "ng-template-generator",
} "cli": {
"analytics": "882c12b6-e63d-4a1e-8be1-2de06114c519"
}
}
\ No newline at end of file
<div class="model-content"> <div class="model-content">
<div nz-row>
<div nz-col nzOffset='4'>
<div style="position: absolute; left: 200px; top: 100px; width: 800px;"> <h1 nz-title>课程练习内容编辑</h1>
</div>
<input type="text" nz-input [(ngModel)]="item.text" (blur)="save()"> </div>
<div nz-row>
<app-upload-image-with-preview <div nz-col [nzSpan]="15" nzOffset="3">
[picUrl]="item.pic_url" <div nz-form>
(imageUploaded)="onImageUploadSuccess($event, 'pic_url')" <nz-form-item>
></app-upload-image-with-preview> <nz-form-label [nzSpan]="6" nzFor="exercises">练习题内容</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-audio-recorder <button nz-button nzType="dashed" class="add-btn" id="add-btn" (click)="addExercisesItem()">
[audioUrl]="item.audio_url" <i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
(audioUploaded)="onAudioUploadSuccess($event, 'audio_url')" </button>
></app-audio-recorder> </nz-form-control>
<app-custom-hot-zone></app-custom-hot-zone> </nz-form-item>
<app-upload-video></app-upload-video> <div>
<app-lesson-title-config></app-lesson-title-config> <div *ngFor="let it of item.exercisesArr;let i = index" style="padding: 0.5vw;">
<div class="border">
<nz-divider nzText="练习-{{i+1}}" nzOrientation="left"></nz-divider>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="it.audio_url">发音</nz-form-label>
<nz-form-control [nzSpan]="6">
<app-audio-recorder id="it.audio_url"
[audioUrl]="it.audio_url"
(audioUploaded)="onImageUploadSuccess($event, it, 'audio_url')">
</app-audio-recorder>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="6" nzFor="it.answers">答案</nz-form-label>
<nz-form-control [nzSpan]="6">
<button nz-button nzType="dashed" class="add-btn" id="add-btn"
(click)="addAnswerItem(it.answers, it)" [disabled]="it.answers.length == 3 ? true : false">
<i nz-icon nzType="plus-circle" nzTheme="outline"></i>添加
</button>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<div nz-col [nzSpan]="22" nzOffset="1">
<nz-table #answersTable [nzData]="it.answers" [nzHideOnSinglePage]="true" [nzBordered]="true" [nzNoResult]=''>
<thead>
<tr>
<th>序号</th>
<th>答案类型</th>
<th>备选答案</th>
<th>是否正确</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of answersTable.data;let j = index">
<td>{{j+1}}</td>
<td>
<nz-select [(ngModel)]="data.contentType" nzPlaceHolder="请选择" (ngModelChange)="setAnswerType($event, data)">
<nz-option nzValue="T" nzLabel="文字"></nz-option>
<nz-option nzValue="P" nzLabel="图片"></nz-option>
</nz-select>
</td>
<td>
<div *ngIf="data.contentType == 'P'">
<app-upload-image-with-preview
style="width: 100%"
[picUrl]="data.pic_url"
(imageUploaded)="onImageUploadSuccess($event, data, 'pic_url')"
></app-upload-image-with-preview>
</div>
<div *ngIf="data.contentType == 'T'">
<input type="text" nz-input placeholder="请录入备选答案" [(ngModel)]="data.text" (blur)="save()">
</div>
</td>
<td>
<nz-switch [ngModel]="data.right" nzCheckedChildren="是" nzUnCheckedChildren="否" (ngModelChange)="setAnswerRight($event, data)"></nz-switch>
</td>
<td>
<button nz-button nzType="danger" (click)="delAnswerItem(it.answers, j, it)" [disabled]="it.answers.length == 2 ? true : false"><i nz-icon nzType="delete" nzTheme="outline"></i>删除</button>
</td>
</tr>
</tbody>
</nz-table>
</div>
</nz-form-item>
<nz-form-item>
<button style="margin: 10px;" nz-button nzType="danger" (click)="delExercisesItem(i)">
<span>删除</span>
</button>
</nz-form-item>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
...@@ -10,7 +10,7 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap ...@@ -10,7 +10,7 @@ import {Component, EventEmitter, Input, OnDestroy, OnChanges, OnInit, Output, Ap
export class FormComponent implements OnInit, OnChanges, OnDestroy { export class FormComponent implements OnInit, OnChanges, OnDestroy {
// 储存数据用 // 储存数据用
saveKey = "test_0011"; saveKey = "DF-L211";
// 储存对象 // 储存对象
item; item;
...@@ -24,6 +24,8 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -24,6 +24,8 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
this.item = {}; this.item = {};
this.item.exercisesArr = [];
// 获取存储的数据 // 获取存储的数据
(<any> window).courseware.getData((data) => { (<any> window).courseware.getData((data) => {
...@@ -58,19 +60,19 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -58,19 +60,19 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
* 储存图片数据 * 储存图片数据
* @param e * @param e
*/ */
onImageUploadSuccess(e, key) { onImageUploadSuccess(e, item, key) {
this.item[key] = e.url; item[key] = e.url;
this.save(); this.save();
} }
/** /**
* 储存音频数据 * 储存音频数据
* @param e * @param e
*/ */
onAudioUploadSuccess(e, key) { onAudioUploadSuccess(e, item, key) {
this.item[key] = e.url; item[key] = e.url;
this.save(); this.save();
} }
...@@ -93,5 +95,100 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy { ...@@ -93,5 +95,100 @@ export class FormComponent implements OnInit, OnChanges, OnDestroy {
}, 1); }, 1);
} }
/**
* 获取缺省的练习题内容
*/
getDefaultExercisesItem(){
let exercises = {
audio_url:"",
answers:[]
}
for(let i = 0; i < 2; ++ i){
let answer = this.getDefaultAnswer();
exercises.answers.push(answer);
}
return exercises;
}
getDefaultAnswer(){
let answer = {
contentType:"T",
text:"",
pic_url:"",
right:true
};
return answer;
}
/**
* 添加练习
*/
addExercisesItem(){
let exercises = this.getDefaultExercisesItem();
this.item.exercisesArr.push(exercises);
this.save();
}
delExercisesItem(index){
if (index !== -1) {
this.item.exercisesArr.splice(index, 1);
this.save();
}
}
setAnswerType(e, item){
if(e == 'P'){
item.text = "";
}
else if(e == 'T'){
item.pic_url = "";
}
else{
item.text = "";
item.pic_url = "";
}
this.save();
}
setAnswerRight(e, item){
item.right = e;
this.save();
}
/**
* 添加答案
*/
addAnswerItem(answers, exercises){
let answer = this.getDefaultAnswer();
exercises.answers = [...answers, answer];
this.save();
}
/**
* 删除答案
* @param answers
* @param index
*/
delAnswerItem(answers, index, practice){
if (index !== -1) {
answers.splice(index, 1);
practice.answers = [...answers];
this.save();
}
}
} }
import {
MySprite, tweenChange,
ShapeRect
} from './Unit';
export class AudioAnimation {
private x = 0;
private y = 0;
images = new Map();
bg : ShapeRect;
scaleX = 1;
scaleY = 1;
playPic1;
playPic2;
playPic3;
curAudio;
playing = false;
hideFlag = true;
/**
* 设置播放帧图片
* @param images
*/
constructor(images) {
this.images = images;
}
setXY(x, y){
this.x = x;
this.y = y;
}
/**
* 初始化图
* @param parent 图片显示父对象
* @param scaleX
* @param sacleY
* @param show 是否直接显示
*/
initPic(parent, scaleX: number, sacleY: number, show: boolean) {
if (!parent) {
return;
}
const bg = new ShapeRect();
const getAudioPic = (index) => {
const playPic = new MySprite();
playPic.init(this.images.get("icon_laba" + index));
playPic.scaleX = scaleX;
playPic.scaleY = sacleY;
playPic.alpha = 0;
playPic.x = playPic.getBoundingBox().width / 2;
playPic.y = playPic.getBoundingBox().height / 2;
bg.addChild(playPic);
return playPic;
};
const playPic1 = getAudioPic(1);
if (show) {
playPic1.alpha = 1;
this.hideFlag = false;
}
else {
playPic1.alpha = 0;
this.hideFlag = true;
}
this.playPic1 = playPic1;
const playPic2 = getAudioPic(2);
this.playPic2 = playPic2;
const playPic3 = getAudioPic(3);
this.playPic3 = playPic3;
bg.setSize(playPic1.getBoundingBox().width, playPic1.getBoundingBox().height);
bg.alpha = 0;
this.bg = bg;
bg.x = this.x;
bg.y = this.y;
if (parent instanceof Array) {
parent.push(bg);
}
else {
parent.addChild(bg);
}
}
/**
* 显示播放状态
*/
showPlayStauts() {
this.hideFlag = false;
const setPause = () => {
if(this.hideFlag){
this.playPic1.alpha = 0;
}
else{
this.playPic1.alpha = 1;
}
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
}
const show1 = () => {
if (this.playing) {
this.playPic1.alpha = 0;
this.playPic2.alpha = 1;
this.playPic3.alpha = 0;
setTimeout(() => {
show2();
}, 500);
}
else {
setPause();
}
};
const show2 = () => {
if (this.playing) {
this.playPic1.alpha = 0;
this.playPic2.alpha = 0;
this.playPic3.alpha = 1;
setTimeout(() => {
show3();
}, 500);
}
else {
setPause();
}
};
const show3 = () => {
if (this.playing) {
this.playPic1.alpha = 1;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
setTimeout(() => {
show1();
}, 500);
}
else {
setPause();
}
};
show1();
}
/**
*
* @param audio 播放音频
* @param callback
*/
playAudio(audio, callback = null) {
//console.log(audio);
if (!audio) {
return;
}
this.curAudio = audio;
audio.onended = () => {
this.playing = false;
if (callback) {
callback();
}
};
audio.play();
this.playing = true;
this.showPlayStauts();
}
/**
*
* @param reset 是否重置
* @param callback 暂停后执行方法
*/
pauseAudio(reset = false, callback = null) {
const audio = this.curAudio;
if (audio) {
this.playing = false;
if (reset) {
audio.currentTime = 0;
}
audio.pause();
if (callback) {
callback();
}
}
}
/**
* 隐藏音频播放动画
* @param reset 是否重置
*/
hide(reset = false) {
this.hideFlag = true;
this.pauseAudio(reset);
this.playPic1.alpha = 0;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
}
/**
* 显示播放动画
*/
show(){
this.hideFlag = false;
this.playPic1.alpha = 1;
this.playPic2.alpha = 0;
this.playPic3.alpha = 0;
}
}
\ No newline at end of file
/**
*
* @param audio 音频
* @param now true-重新开始播放,flase-继续播放
* @param callback
*/
export function playAudio(audio, now = false, callback = null) {
if (audio) {
if (now) {
audio.pause();
audio.currentTime = 0;
}
if (callback) {
audio.onended = () => {
callback();
};
}
audio.play();
}
}
/**
* 暂停播放音频
* @param audio 音频
* @param reset 暂停是否重置:true-是,false-否
* @param callback
*/
export function pauseAudio(audio, reset = false, callback = null) {
if (audio) {
if (reset) {
audio.currentTime = 0;
}
audio.pause();
if (callback) {
callback();
}
}
}
\ No newline at end of file
import {
ShapeRect,
MySprite,
tweenChange,
shake
} from './Unit';
import {
pauseAudio,
playAudio
} from './AudioUtil'
export class Box {
name: string;
/**图片框 */
picBox: MySprite;
picBoard: ShapeRect;
/**文本框 */
wordBox: MySprite;
wordBoard: ShapeRect;
/**框发光图片 */
boxLightPic: MySprite;
/**背景 */
boxBg: ShapeRect;
curBox;
images = new Map();
scaleX = 1;
scaleY = 1;
answer;
inited = false;
wrongAudio;
rightAudio;
showed = false;
initX = 0;
initY = 0;
moveout = false;
constructor(name, images) {
this.images = images;
this.name = name;
}
setScaleXY(scale) {
this.scaleX = this.scaleY = scale;
}
init() {
if (this.inited) {
return;
}
const picBox = new MySprite();
picBox.init(this.images.get('box_pic'));
picBox.scaleX = this.scaleX;
picBox.scaleY = this.scaleY;
picBox.alpha = 0;
this.picBox = picBox;
const wordBox = new MySprite();
wordBox.init(this.images.get('box_word'));
wordBox.scaleX = this.scaleX;
wordBox.scaleY = this.scaleY;
wordBox.alpha = 0;
this.wordBox = wordBox;
const boxLight = new MySprite();
boxLight.init(this.images.get('box_light'));
boxLight.scaleX = this.scaleX;
boxLight.scaleY = this.scaleY;
boxLight.alpha = 0;
this.boxLightPic = boxLight;
let width = picBox.getBoundingBox().width;
let height = picBox.getBoundingBox().height;
const bg = new ShapeRect();
bg.setSize(width, height);
bg.alpha = 0;
this.boxBg = bg;
const picBoard = new ShapeRect();
picBoard.setSize(width, height);
picBoard.alpha = 0;
picBoard.x = 0;
picBoard.y = 0;
this.picBoard = picBoard;
this.boxBg.addChild(picBoard);
picBox.x = width / 2;
picBox.y = height / 2;
bg.addChild(picBox);
wordBox.x = picBox.x;
wordBox.y = picBox.y;
bg.addChild(wordBox);
const wordBoard = new ShapeRect();
wordBoard.setSize(width, height);
wordBoard.alpha = 0;
wordBoard.x = 0;
wordBoard.y = 0;
this.wordBoard = wordBoard;
this.boxBg.addChild(wordBoard);
boxLight.x = picBox.x;
boxLight.y = picBox.y - 20 * this.scaleY;
bg.addChild(boxLight);
this.inited = true;
}
showBox(answer, callback = null) {
if (!answer) {
return;
}
if (!this.inited) {
this.init();
}
const show = () => {console.log('show answer......');
let lastAnswer = this.answer ? this.answer : null;
this.answer = answer;
this.boxLightPic.alpha = 0;
const showAnswer = () => {
let x = (this.boxBg.width - this.answer.getWidth()) / 2;
let y = 22 * this.scaleY;
let sX = x;
let sY = this.boxBg.height + this.answer.getHeight();
if (this.answer.contentType == 'T') {
this.wordBoard.addChild(this.answer.bg);
}
else {
this.picBoard.addChild(this.answer.bg);
}
this.answer.moveIn(sX, sY, x, y, () => {
if (callback) {
callback();
}
});
this.showed = true;
};
if (answer.contentType == 'T') {
if (!this.curBox) {
this.curBox = this.wordBox;
this.show(() => {
showAnswer();
});
}
else if (this.curBox == this.wordBox) {
lastAnswer.moveOut(lastAnswer.bg.x, lastAnswer.bg.y, () => {
this.wordBoard.removeChild(lastAnswer.bg);
showAnswer();
});
}
else {
this.hide(lastAnswer, () => {
this.curBox = this.wordBox;
this.wordBox.alpha = 1;
showAnswer();
})
}
}
else {
if (!this.curBox) {
this.curBox = this.picBox;
this.show(() => {
showAnswer();
});
}
else if (this.curBox == this.picBox) {
lastAnswer.moveOut(lastAnswer.bg.x, lastAnswer.bg.y, () => {
this.picBoard.removeChild(lastAnswer.bg);
});
showAnswer();
}
else {
this.hide(lastAnswer, () => {
this.curBox = this.picBox;
this.picBox.alpha = 1;
showAnswer();
})
}
}
};
if (this.moveout) {
this.moveIn(() => {
show();
});
}
else {
show();
}
}
hide(answer, callback = null) {
this.boxLightPic.alpha = 0;
if (this.curBox && this.showed) {
this.showed = false;
if (answer) {
answer.moveOut(answer.bg.x, answer.bg.y, () => {
if (answer.contentType == 'T') {
this.wordBoard.removeChild(answer.bg);
}
else {
this.picBoard.removeChild(answer.bg);
}
let tBox = this.curBox;
tBox.alpha = 0;
this.curBox = null;
if (callback) {
callback();
}
});
}
else {
let tBox = this.curBox;
tBox.alpha = 0;
this.curBox = null;
if (callback) {
callback();
}
}
}
else {
if (callback) {
callback();
}
}
}
show(callback = null) {
if (this.curBox) {
this.curBox.alpha = 1;
if (callback) {
callback();
}
}
else {
if (callback) {
callback();
}
}
}
click(callback = null,wrongCallback = null) {
if (!this.showed) {
return;
}
if (!this.answer) {
this.showWrong();
return false;
}
if (this.answer.right) {
this.answer.selected = true;
this.boxLightPic.alpha = 1;
playAudio(this.rightAudio, true, () => {
});
if (callback) {
callback();
}
return true;
}
else {
this.showWrong();
if(wrongCallback){
wrongCallback();
}
return false;
}
}
private showWrong() {
this.boxLightPic.alpha = 1;
playAudio(this.wrongAudio, true, () => {
this.boxLightPic.alpha = 0;
});
shake(this.boxBg);
}
moveOut(callback = null) {
this.initX = this.boxBg.x;
this.initY = this.boxBg.y;
this.moveout = true;
tweenChange(this.boxBg, { y: this.boxBg.y + this.boxBg.height }, 0.3, () => {
if (this.answer) {
if (this.answer.contentType == 'T') {
this.wordBoard.removeChild(this.answer.bg);
}
else {
this.picBoard.removeChild(this.answer.bg);
}
}
if (callback) {
callback();
}
});
}
moveIn(callback = null) {
tweenChange(this.boxBg, { y: this.initY }, 0.3, callback);
}
}
\ No newline at end of file
import {
ShapeRect,
MySprite,
tweenChange
} from './Unit';
import{
playAudio
} from './AudioUtil';
export class Buttion {
bg;
up;
down;
scaleX = 1;
scaleY = 1;
images = new Map();
audio;
curStatus;
constructor(images) {
this.images = images;
}
setScaleXY(scale) {
this.scaleX = this.scaleY = scale;
}
init(upImgKey, downImgKey) {
const bg = new ShapeRect();
bg.alpha = 0;
this.bg = bg;
const up = new MySprite();
up.init(this.images.get(upImgKey));
up.scaleX = this.scaleX;
up.scaleY = this.scaleY;
up.x = up.getBoundingBox().width / 2;
up.y = up.getBoundingBox().height / 2;
this.up = up;
bg.addChild(up);
this.curStatus = up;
const down = new MySprite();
down.init(this.images.get(downImgKey));
down.scaleX = this.scaleX;
down.scaleY = this.scaleY;
down.alpha = 0;
down.x = up.x;
down.y = up.y;
this.down = down;
bg.addChild(down);
bg.setSize(up.getBoundingBox().width, up.getBoundingBox().height);
}
click(callback = null) {
playAudio(this.audio, true, callback);
this.up.alpha = 0;
this.down.alpha = 1;
this.curStatus = this.down;
setTimeout(() => {
this.resetStatus();
}, 100);
}
resetStatus(){
this.up.alpha = 1;
this.down.alpha = 0;
this.curStatus = this.up;
}
hide(time = 0.3, callback = null){
tweenChange(this.curStatus, { alpha: 0 }, time, ()=>{
if(callback){
callback();
}
});
}
}
\ No newline at end of file
import {
ShapeRect,
MySprite,
tweenChange,
Label
} from './Unit';
export class Exercise{
exercise;
_listeningAudio;
answers = [];
constructor(exercise){
this.exercise = exercise;
}
addAnswer(answer : Answer){
this.answers.push(answer);
}
set listeningAudio(audio){
this._listeningAudio = audio;
}
get listeningAudio(){
return this._listeningAudio;
}
}
export class Answer{
bg;
/**内容类型:T-文本,P-图片;默认为文本 */
contentType;
/**内容 */
contentSprite: MySprite;
answerContent;
scaleX = 1;
scaleY = 1;
images = new Map();
inited = false;
right = false;
selected = false;
constructor(images, answerContent){
this.images = images;
this.answerContent = answerContent;
}
setScaleXY(scale) {
this.scaleX = this.scaleY = scale;
}
init() {
if (this.inited) {
return;
}
this.right = this.answerContent.right;
const bg = new ShapeRect();
bg.setSize(this.getWidth(), this.getHeight());
bg.alpha = 0;
this.bg = bg;
this.setContent(bg);
}
/**
* 设置答案卡片内容
* @param parItem
*/
setContent(parItem) {
//图片存在,则渲染图片
if (this.answerContent.pic_url) {
const content_pic = new MySprite();
content_pic.init(this.images.get(this.answerContent.pic_url));
content_pic.alpha = 1;
let w = content_pic.width;
let h = content_pic.height;
let scale = Math.min((parItem.height - 15 * this.scaleX) / h, (parItem.width - 15 * this.scaleY) / w);
//如果小于1,则缩放图片
if(scale < 1){
content_pic.setScaleXY(scale);
}
content_pic.x = this.getWidth() / 2;
content_pic.y = this.getHeight() / 2;
parItem.addChild(content_pic);
this.contentType = 'P';
this.contentSprite = content_pic;
}
else {
let content_val = new Label();
content_val.text = this.answerContent.text;
content_val.textAlign = 'middle';
content_val.fontSize = 66;
content_val.fontName = "arial";
content_val.fontColor = "#FBEB4F";
content_val.setOutline(3, '#315305');
content_val.alpha = 0;
content_val.refreshSize();
content_val.setMaxSize(parItem.width - 60 * this.scaleX);
content_val.x = (this.getWidth() - content_val.getBoundingBox().width) / 2;
content_val.y = this.getHeight() / 2;
parItem.addChild(content_val);
this.contentType = 'T';
this.contentSprite = content_val;
}
}
getWidth(){
return 234 * this.scaleX;
}
getHeight(){
return 178 * this.scaleY;
}
/**
* 从指定位置移动到新位置
* @param sX 左上角x坐标
* @param sY 左上角Y坐标
* @param toX 左上角x坐标
* @param toY 左上角Y坐标
* @param callback
*/
moveIn(sX, sY, toX, toY, callback = null) {
if (this.contentType == 'T') {
this.bg.x = toX;
this.bg.y = toY;
tweenChange(this.contentSprite, { alpha: 1 }, 0.4, callback);
}
else if (this.contentType == 'P') {
this.contentSprite.alpha = 1;
this.bg.x = sX;
this.bg.y = sY;
let newToX = toX;
let newToY = toY;
tweenChange(this.bg, { x: newToX, y: newToY }, 0.2, callback);
}
}
/**
* 从当前位置移到指定位置
* @param toX 左上角x坐标
* @param toY 左上角Y坐标
* @param callback
*/
moveOut(toX, toY, callback = null) {
if (this.contentType == 'T') {
this.bg.x = toX;
this.bg.y = toY;
tweenChange(this.contentSprite, { alpha: 0 }, 0.3, callback);
}
else if (this.contentType == 'P') {
this.bg.x = toX;
this.bg.y = toY;
tweenChange(this.contentSprite, { alpha: 0 }, 0.3, callback);
}
}
reset(){
this.selected = false;
}
}
\ No newline at end of file
import {
MySprite, tweenChange,
ShapeRect
} from './Unit';
import {
pauseAudio,
playAudio
} from './AudioUtil'
export class Handclap {
bg: ShapeRect;
leftHand: MySprite;
rightHand: MySprite;
audio;
playing = false;
init(leftHandImgObj, rightHandImgObj, scaleX: number, sacleY: number) {
const leftHand = new MySprite();
leftHand.init(leftHandImgObj);
leftHand.scaleX = scaleX;
leftHand.scaleY = sacleY;
this.leftHand = leftHand;
const rightHand = new MySprite();
rightHand.init(rightHandImgObj);
rightHand.scaleX = scaleX;
rightHand.scaleY = sacleY;
this.rightHand = rightHand;
let height = Math.max(rightHand.getBoundingBox().height, leftHand.getBoundingBox().height);
let width = leftHand.getBoundingBox().width + rightHand.getBoundingBox().width;
const bg = new ShapeRect();
bg.setSize(width, height);
bg.alpha = 0;
this.bg = bg;
rightHand.x = leftHand.getBoundingBox().width + rightHand.getBoundingBox().width / 2;
rightHand.y = height/2;
bg.addChild(rightHand);
leftHand.x = leftHand.getBoundingBox().width/ 2;
leftHand.y = height/2;
bg.addChild(leftHand);
}
getWidth(){
return this.bg.getBoundingBox().width;
}
getHight(){
return this.bg.getBoundingBox().height;
}
play(callback = null){
//播放音效
playAudio(this.audio, false, ()=>{
this.playing = false;
if(callback){
callback();
}
});
const applaud = () => {
if(this.playing){
let scaleX = this.leftHand.scaleX;
let leftHandX = this.leftHand.x;
tweenChange(this.leftHand, {x: leftHandX + 60 * scaleX}, 0.1, () => {
tweenChange(this.leftHand, {x: leftHandX}, 0.1, ()=>{
setTimeout(() => {
applaud();
}, 50);
});
});
let rightHandX = this.rightHand.x;
tweenChange(this.rightHand, {x: rightHandX - 60 * scaleX}, 0.1, () => {
tweenChange(this.rightHand, {x: rightHandX}, 0.1, ()=>{
});
});
}
}
this.playing = true;
//鼓掌
applaud();
}
/**
* 停止鼓掌
* @param callback
*/
stop(callback = null){
this.playing = false;
pauseAudio(this.audio, true);
if(callback){
callback();
}
}
}
\ No newline at end of file
import {
MySprite,
moveItem,
removeItemFromArr,
rotateItem
} from './Unit';
export class Petal {
renderArr = [];
images;
ctx;
playing = true;
tempRenderArr = [];
constructor(renderArr, images, ctx) {
this.renderArr = renderArr;
this.images = images;
this.ctx = ctx;
this.tempRenderArr = [];
}
stop(callback = null) {
this.playing = false;
const checkFinish = () => {
if (this.tempRenderArr.length == 0) {
if (callback) {
callback();
}
}
else {
setTimeout(() => {
checkFinish();
}, 100);
}
}
checkFinish();
}
/**
* 显示结束花瓣
* @param rect {x,y,width, height} 花瓣显示位置及大小
* @param mapScale
* @param timeout 花瓣显示间隔
* @param kinds 花瓣种类,即花瓣图片样式数组个数
*/
showPetal(rect, mapScale: number, timeout: number, kinds = 9) {
if (!this.playing) {
return;
}
const petal = this.getPetal(rect, mapScale, kinds);
this.renderArr.push(petal);
this.tempRenderArr.push(petal);
let toY = rect.y + rect.height;
moveItem(petal, petal.x, toY + petal.height * petal.scaleY, petal['time'], () => {
removeItemFromArr(this.renderArr, petal);
removeItemFromArr(this.tempRenderArr, petal);
});
rotateItem(petal, petal['tr'], petal['time']);
setTimeout(() => {
this.showPetal(rect, mapScale, timeout);
}, timeout);
}
/**
* 得到花瓣
* @param rect
* @param mapScale
* @param kinds
*/
private getPetal(rect, mapScale, kinds) {
const petal = new MySprite(this.ctx);
const id = Math.ceil(Math.random() * kinds);
petal.init(this.images.get('petal_' + id));
const randomS = (Math.random() * 0.4 + 0.6) * mapScale;
petal.setScaleXY(randomS);
const randomR = Math.random() * 360;
petal.rotation = randomR;
const randomX = rect.x + Math.random() * rect.width;
petal.x = randomX;
petal.y = rect.y - petal.height / 2 * petal.scaleY;
const randomT = 0.5 + Math.random() * 2;
petal['time'] = randomT;
let randomTR = 360 * Math.random(); // - 180;
if (Math.random() < 0.5) { randomTR *= -1; }
petal['tr'] = randomTR;
return petal;
}
}
\ No newline at end of file
import {
MySprite, tweenChange,
ShapeRect,
Label
} from './Unit';
import {
playAudio
} from './AudioUtil';
export class Player {
/**背景 */
bg;
playerPic;
/**汗水 */
sweatPic;
//图片数组
images = new Map();
scaleX = 1;
scaleY = 1;
initX = 0;
initY = 0;
sweatAudio;
pullAudio;
car: ShapeRect;
cargos = [];
constructor(images) {
this.images = images;
}
setScaleXY(scale) {
this.scaleX = this.scaleY = scale;
}
init() {
const playerPic = new MySprite();
playerPic.init(this.images.get('player'));
playerPic.scaleX = this.scaleX;
playerPic.scaleY = this.scaleY;
playerPic.x = playerPic.getBoundingBox().width / 2;
playerPic.y = playerPic.getBoundingBox().height / 2;
this.playerPic = playerPic;
let width = playerPic.getBoundingBox().width;
let height = playerPic.getBoundingBox().height;
const bg = new ShapeRect();
bg.setSize(width, height);
bg.alpha = 0;
this.bg = bg;
const car = new ShapeRect();
car.setSize(160 * this.scaleX, 10 * this.scaleY);
car.x = 20 * this.scaleX;
car.y = 90 * this.scaleY;
car.alpha = 0;
this.car = car;
bg.addChild(car);
bg.addChild(playerPic);
const sweatPic = new MySprite();
sweatPic.init(this.images.get('sweat'));
sweatPic.scaleX = this.scaleX;
sweatPic.scaleY = this.scaleY;
sweatPic.x = 300 * this.scaleX + sweatPic.getBoundingBox().width / 2;
sweatPic.y = 20 * this.scaleY + sweatPic.getBoundingBox().height / 2;
sweatPic.alpha = 0;
this.sweatPic = sweatPic;
bg.addChild(sweatPic);
}
pullCar(toX: number, toY: number, callback = null, time = 0.3, ) {
playAudio(this.pullAudio, true);
tweenChange(this.bg, { x: toX, y: toY }, time, () => {
if (callback) {
callback();
}
})
}
reset() {
this.bg.x = this.initX;
this.bg.y = this.initY;
}
flowSweat(callback = null) {
playAudio(this.sweatAudio, true);
this.sweatPic.alpha = 1;
let y = this.sweatPic.y;
tweenChange(this.sweatPic, { y: y + 30 * this.scaleY }, 0.3, () => {
this.sweatPic.alpha = 0;
this.sweatPic.y = y;
if (callback) {
callback();
}
});
}
getCargoY = (x, b) => {
//斜率
let k = 0.195;
let c = - b * this.scaleY;
let y = k * x + c;
return -y;
}
loading(cargo) {
if (!cargo) {
return;
}
let x = 10 * this.scaleX;
let length = this.cargos.length;
if ( length > 0) {
if(length % 4 != 0){
let lastCargo = this.cargos[length - 1];
x = lastCargo.x;
x += lastCargo.getBoundingBox().width;
}
else{
x = 10 * this.scaleX + Math.floor(length / 4) * 5 * this.scaleX;
}
}
let startY = Math.floor(length / 4) * 15 * this.scaleY;
let c = Math.random() * this.car.height;
let y = this.getCargoY(x, c) - startY;
cargo.x = x - cargo.getBoundingBox().width / 2;
cargo.y = y - cargo.getBoundingBox().height / 2;
this.cargos.push(cargo);
this.car.addChild(cargo, -length);
}
unloading() {
this.car.removeChildren();
this.cargos = [];
}
}
\ No newline at end of file
import {
MySprite, tweenChange,
ShapeRect,
Label
} from './Unit';
export class Stage {
/**背景 */
bg;
/**舞台 */
stage: ShapeRect;
//图片数组
images = new Map();
scaleX = 1;
scaleY = 1;
prompt;
leftDoor;
rightDoor;
constructor(images){
this.images = images;
}
setScaleXY(scale){
this.scaleX = this.scaleY = scale;
}
init(){
const stage_box = new MySprite();
stage_box.init(this.images.get('stage_box'));
stage_box.scaleX = this.scaleX;
stage_box.scaleY = this.scaleY;
let width = stage_box.getBoundingBox().width;
let height = stage_box.getBoundingBox().height;
const bg = new ShapeRect();
bg.setSize(width, height);
bg.alpha = 0;
this.bg = bg;
const stage_bg = new MySprite();
stage_bg.init(this.images.get('stage_bg'));
stage_bg.scaleX = this.scaleX;
stage_bg.scaleY = this.scaleY;
stage_bg.x = width / 2;
stage_bg.y = 52 * this.scaleY + stage_bg.getBoundingBox().height / 2;
bg.addChild(stage_bg);
const stage = new ShapeRect();
stage.setSize(width, height);
stage.alpha = 0;
this.stage = stage;
stage.x = 0;
stage.y = 0;
bg.addChild(stage);
let prompt = new Label();
prompt.text = '0/0';
prompt.textAlign = 'middle';
prompt.fontSize = 66;
prompt.fontName = "BRLNSDB";
prompt.fontColor = "#F2CE29";
prompt.setOutline(3, '#93490B');
prompt.setShadow(0, 4, 3.0, '#A6643F');
prompt.scaleX = this.scaleX;
prompt.scaleY = this.scaleY;
prompt.refreshSize();
prompt.x = 120 * this.scaleX;
prompt.y = 116 * this.scaleY + prompt.getBoundingBox().height / 2;
this.prompt = prompt;
bg.addChild(prompt);
//初始化门
this.initDoor();
stage_box.x = width / 2;
stage_box.y = height /2;
bg.addChild(stage_box);
const left = new MySprite();
left.init(this.images.get('bg_1'));
left.scaleX = this.scaleX;
left.scaleY = this.scaleY;
left.x = - left.getBoundingBox().width / 2;
left.y = height - left.getBoundingBox().height/ 2;
bg.addChild(left);
const right = new MySprite();
right.init(this.images.get('bg_1'));
right.scaleX = this.scaleX;
right.scaleY = this.scaleY;
right.x = bg.width + left.getBoundingBox().width / 2;
right.y = left.y;
bg.addChild(right);
}
private initDoor(){
const leftDoor = new MySprite();
leftDoor.init(this.images.get('doorleft'), 0);
leftDoor.scaleX = this.scaleX;
leftDoor.scaleY = this.scaleY;
leftDoor.x = 75 * this.scaleX;
leftDoor.y = 51 * this.scaleY + leftDoor.getBoundingBox().height / 2;
this.bg.addChild(leftDoor);
this.leftDoor = leftDoor;
const rightDoor = new MySprite();
rightDoor.init(this.images.get('doorright'), 1);
rightDoor.scaleX = this.scaleX;
rightDoor.scaleY = this.scaleY;
rightDoor.x = leftDoor.x + leftDoor.getBoundingBox().width * 2;
rightDoor.y = leftDoor.y;
this.bg.addChild(rightDoor);
this.rightDoor = rightDoor;
leftDoor.scaleX = 0;
rightDoor.scaleX = 0;
}
setPromptText(text){
this.prompt.text = text;
}
closeDoor(callback = null){
tweenChange(this.leftDoor, {scaleX : this.scaleX}, 2, callback);
tweenChange(this.rightDoor, {scaleX : this.scaleX}, 2);
}
openDoor(callback = null){
tweenChange(this.leftDoor, {scaleX : 0}, 2, callback);
tweenChange(this.rightDoor, {scaleX : 0}, 2);
}
}
\ No newline at end of file
...@@ -17,3 +17,8 @@ ...@@ -17,3 +17,8 @@
src: url("../../assets/font/BRLNSDB.TTF") ; src: url("../../assets/font/BRLNSDB.TTF") ;
} }
@font-face
{
font-family: 'arial';
src: url("../../assets/font/arial.ttf") ;
}
\ No newline at end of file
import {Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener} from '@angular/core'; import { Component, ElementRef, ViewChild, OnInit, Input, OnDestroy, HostListener } from '@angular/core';
import { import {
Label, ShapeRect,
MySprite, tweenChange, MySprite, tweenChange,
randomSortByArr,
removeItemFromArr
} from './Unit'; } from './Unit';
import {res, resAudio} from './resources'; import { res, resAudio } from './resources';
import {Subject} from 'rxjs'; import { Subject } from 'rxjs';
import {debounceTime} from 'rxjs/operators'; import { debounceTime } from 'rxjs/operators';
import TWEEN from '@tweenjs/tween.js'; import TWEEN from '@tweenjs/tween.js';
import { Stage } from './Stage';
import { AudioAnimation } from './AudioAnimation';
import {
Player
} from './Player';
import {
Box
} from './Box';
import {
Exercise,
Answer
} from './Exercises';
import { Handclap } from './Handclap';
import { Petal } from './PetalUtil';
import {
Buttion
} from './Button';
@Component({ @Component({
selector: 'app-play', selector: 'app-play',
...@@ -22,8 +44,8 @@ import TWEEN from '@tweenjs/tween.js'; ...@@ -22,8 +44,8 @@ import TWEEN from '@tweenjs/tween.js';
}) })
export class PlayComponent implements OnInit, OnDestroy { export class PlayComponent implements OnInit, OnDestroy {
@ViewChild('canvas', {static: true }) canvas: ElementRef; @ViewChild('canvas', { static: true }) canvas: ElementRef;
@ViewChild('wrap', {static: true }) wrap: ElementRef; @ViewChild('wrap', { static: true }) wrap: ElementRef;
// 数据 // 数据
data; data;
...@@ -52,22 +74,54 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -52,22 +74,54 @@ export class PlayComponent implements OnInit, OnDestroy {
audioObj = {}; audioObj = {};
renderArr; renderArr;
boxRenderArr = [];
endRenderArr = [];
mapScale = 1; mapScale = 1;
mapScaleX = 1;
mapScaleY = 1;
canvasLeft; canvasLeft;
canvasTop; canvasTop;
saveKey = 'test_0011'; saveKey = 'DF-L211';
canTouch = false;
canPlay = false;
btnLeft; gameover = false;
btnRight;
pic1;
pic2;
canTouch = true; /**舞台 */
stage;
curPic; audioTool;
rightBox;
midBox;
leftBox;
exerciseArr = [];
tempExerciseArr = [];
curExercise;
curIndex = 0;
restartBtn;
player;
lemonPosArr = [];
lemonArr = [];
playerPosArr = [];
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])
onResize(event) { onResize(event) {
...@@ -80,13 +134,13 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -80,13 +134,13 @@ export class PlayComponent implements OnInit, OnDestroy {
this.data = {}; this.data = {};
// 获取数据 // 获取数据
const getData = (<any> window).courseware.getData; const getData = (<any>window).courseware.getData;
getData((data) => { getData((data) => {
if (data && typeof data == 'object') { if (data && typeof data == 'object') {
this.data = data; this.data = data;
} }
// console.log('data:' , data); console.log('data:', data);
// 初始化 各事件监听 // 初始化 各事件监听
this.initListener(); this.initListener();
...@@ -431,11 +485,10 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -431,11 +485,10 @@ export class PlayComponent implements OnInit, OnDestroy {
* 添加默认数据 便于无数据时的展示 * 添加默认数据 便于无数据时的展示
*/ */
initDefaultData() { initDefaultData() {
if (!this.data.exercisesArr) {
if (!this.data.pic_url) { this.data.exercisesArr = [];
this.data.pic_url = 'assets/play/default/pic.jpg';
this.data.pic_url_2 = 'assets/play/default/pic.jpg';
} }
} }
...@@ -444,8 +497,23 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -444,8 +497,23 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initImg() { initImg() {
this.addUrlToImages(this.data.pic_url); for (let i = 0; i < this.data.exercisesArr.length; ++i) {
this.addUrlToImages(this.data.pic_url_2); let exercises = this.data.exercisesArr[i];
if (!exercises.answers) {
continue;
}
for (let j = 0; j < exercises.answers.length; ++j) {
let answer = exercises.answers[j];
if (answer.contentType == 'P' && answer.pic_url) {
this.addUrlToImages(answer.pic_url);
}
}
}
} }
...@@ -454,13 +522,34 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -454,13 +522,34 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initAudio() { initAudio() {
// 音频资源
this.addUrlToAudioObj(this.data.audio_url);
this.addUrlToAudioObj(this.data.audio_url_2);
// 音效 // 音效
this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3); this.addUrlToAudioObj('click', this.rawAudios.get('click'), 0.3);
// 音效
this.addUrlToAudioObj('wrong', this.rawAudios.get('wrong'));
// 音效
this.addUrlToAudioObj('right', this.rawAudios.get('right'));
this.addUrlToAudioObj('handclap', this.rawAudios.get('handclap'));
this.addUrlToAudioObj('win', this.rawAudios.get('win'));
this.addUrlToAudioObj('clickBtn', this.rawAudios.get('clickBtn'));
this.addUrlToAudioObj('pull', this.rawAudios.get('pull'));
this.addUrlToAudioObj('lemon', this.rawAudios.get('lemon'));
this.addUrlToAudioObj('sweat', this.rawAudios.get('sweat'));
for (let i = 0; i < this.data.exercisesArr.length; ++i) {
let exercises = this.data.exercisesArr[i];
if (exercises.audio_url) {
this.addUrlToAudioObj(exercises.audio_url);
}
}
} }
...@@ -475,16 +564,82 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -475,16 +564,82 @@ export class PlayComponent implements OnInit, OnDestroy {
const s = Math.min(sx, sy); const s = Math.min(sx, sy);
this.mapScale = s; this.mapScale = s;
// this.mapScale = sx; this.mapScaleX = sx;
// this.mapScale = sy; this.mapScaleY = sy;
this.renderArr = []; this.renderArr = [];
this.boxRenderArr = [];
this.endRenderArr = [];
this.exerciseArr = [];
this.tempExerciseArr = [];
this.canTouch = false;
this.canPlay = false;
this.gameover = false;
this.curExercise = null;
this.curIndex = 0;
this.lemonPosArr = [];
this.playerPosArr = [];
this.lemonArr = [];
const getLemonY = (x) => {
//斜率
let k = 0.195;
let b = - 385 * this.mapScale;
let y = k * x + b;
return -y;
}
let startX = 427 * this.mapScale;
let interval = 134 * this.mapScale;
for (let i = 0; i < 6; ++i) {
let y = getLemonY(startX);
this.lemonPosArr.push({ x: startX, y: y });
startX += interval;
}
startX = 170 * this.mapScale;
for (let i = 0; i < 6; ++i) {
let y = this.getPlayerY(startX);
this.playerPosArr.push({ x: startX, y: y });
startX += interval;
}
} }
getPlayerY = (x) => {
//斜率
let k = 0.195;
let b = - 300 * this.mapScale;
let y = k * x + b;
return -y;
}
/** /**
...@@ -492,131 +647,226 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -492,131 +647,226 @@ export class PlayComponent implements OnInit, OnDestroy {
*/ */
initView() { initView() {
this.initBg();
this.initPic(); this.initPic();
this.initPlayer();
this.initBottomPart(); this.initBottomPart();
this.initExercises();
this.initGame();
} }
initBottomPart() { initBg() {
const btnLeft = new MySprite(); let width = 1280 * this.mapScale;
btnLeft.init(this.images.get('btn_left'));
btnLeft.x = this.canvasWidth - 150 * this.mapScale;
btnLeft.y = this.canvasHeight - 100 * this.mapScale;
btnLeft.setScaleXY(this.mapScale); let height = 720 * this.mapScale;
this.renderArr.push(btnLeft); let col = Math.ceil(this.canvasWidth / width);
this.btnLeft = btnLeft; let row = Math.ceil(this.canvasHeight / height);
const getBg = () => {
const bg = new MySprite();
bg.init(this.images.get('bg_1'));
bg.setScaleXY(this.mapScale);
this.renderArr.push(bg);
return bg;
};
let startY = 0;
const btnRight = new MySprite(); let startX = 0;
btnRight.init(this.images.get('btn_right'));
btnRight.x = this.canvasWidth - 50 * this.mapScale;
btnRight.y = this.canvasHeight - 100 * this.mapScale;
btnRight.setScaleXY(this.mapScale);
this.renderArr.push(btnRight); for (let i = 0; i < row; ++i) {
this.btnRight = btnRight; startY = startY + height * i;
}
initPic() { for (let j = 0; j < col; ++j) {
const maxW = this.canvasWidth * 0.7; startX = startX + width * j;
const pic1 = new MySprite(); let bg = getBg();
pic1.init(this.images.get(this.data.pic_url));
pic1.x = this.canvasWidth / 2;
pic1.y = this.canvasHeight / 2;
pic1.setScaleXY(maxW / pic1.width);
this.renderArr.push(pic1); bg.x = startX + bg.getBoundingBox().width / 2;
this.pic1 = pic1;
bg.y = startY + bg.getBoundingBox().height / 2;
const label1 = new Label(); }
label1.text = this.data.text;
label1.textAlign = 'center';
label1.fontSize = 50;
label1.fontName = 'BRLNSDB';
label1.fontColor = '#ffffff';
pic1.addChild(label1); }
}
initBottomPart() {
const initBox = (name) => {
const box = new Box('right', this.images);
box.setScaleXY(this.mapScale);
box.init();
box.boxBg.y = this.canvasHeight - box.boxBg.height + 20 * this.mapScale;
box.rightAudio = this.audioObj['right'];
box.wrongAudio = this.audioObj['wrong'];
this.boxRenderArr.push(box.boxBg);
return box;
}
const rightBox = initBox('right');
rightBox.boxBg.x = 869 * this.mapScale;
this.rightBox = rightBox;
const midBox = initBox('mid');
midBox.boxBg.x = 506 * this.mapScale;
this.midBox = midBox;
const pic2 = new MySprite(); const leftBox = initBox('left');
pic2.init(this.images.get(this.data.pic_url_2)); leftBox.boxBg.x = 133 * this.mapScale;
pic2.x = this.canvasWidth / 2 + this.canvasWidth; this.leftBox = leftBox;
pic2.y = this.canvasHeight / 2; }
pic2.setScaleXY(maxW / pic2.width);
this.renderArr.push(pic2); initPic() {
this.pic2 = pic2;
this.curPic = pic1; const stage = new Stage(this.images);
stage.setScaleXY(this.mapScale);
stage.init();
this.stage = stage;
stage.bg.x = (this.canvasWidth - stage.bg.width) / 2;
stage.bg.y = this.canvasHeight - stage.bg.height;
this.renderArr.push(stage.bg);
const audio = new AudioAnimation(this.images);
audio.setXY(849 * this.mapScale, 0);
audio.initPic(stage.bg, this.mapScale, this.mapScale, true);
this.audioTool = audio;
const restartBtn = new Buttion(this.images);
restartBtn.setScaleXY(this.mapScale);
restartBtn.init('btn_restart_up', 'btn_restart_down');
restartBtn.audio = this.audioObj['clickBtn'];
this.restartBtn = restartBtn;
} }
initPlayer() {
const player = new Player(this.images);
player.setScaleXY(this.mapScale);
player.sweatAudio = this.audioObj['sweat'];
player.pullAudio = this.audioObj['pull'];
player.init();
player.bg.x = 101 * this.mapScale;
player.bg.y = 280 * this.mapScale;
player.initX = player.bg.x;
player.initY = player.bg.y;
this.player = player;
this.stage.stage.addChild(player.bg);
}
btnLeftClicked() { initLemon() {
this.lastPage(); let lemonNum = 6;
}
btnRightClicked() { if (lemonNum > this.tempExerciseArr.length) {
lemonNum = this.tempExerciseArr.length;
}
this.nextPage(); for (let i = 0; i < lemonNum; ++i) {
const lemon = new MySprite();
lemon.init(this.images.get('lemon'), 0, 0);
lemon.setScaleXY(this.mapScale);
lemon.x = this.lemonPosArr[i].x;
lemon.y = this.lemonPosArr[i].y;
this.stage.stage.addChild(lemon);
this.lemonArr.push(lemon);
}
} }
lastPage() {
if (this.curPic == this.pic1) { initExercises() {
return;
}
this.canTouch = false; for (let i = 0; i < this.data.exercisesArr.length; ++i) {
let exercises = this.data.exercisesArr[i];
const moveLen = this.canvasWidth; let exercise = new Exercise(exercises);
tweenChange(this.pic1, {x: this.pic1.x + moveLen}, 1); exercise.listeningAudio = this.audioObj[exercises.audio_url];
tweenChange(this.pic2, {x: this.pic2.x + moveLen}, 1, () => {
this.canTouch = true;
this.curPic = this.pic1;
});
}
nextPage() { for (let j = 0; j < exercises.answers.length; ++j) {
let answer = new Answer(this.images, exercises.answers[j]);
answer.setScaleXY(this.mapScale);
answer.init();
exercise.addAnswer(answer);
if (this.curPic == this.pic2) { answer.bg.x = 0;
return; answer.bg.y = this.canvasHeight + answer.bg.height;
}
this.canTouch = false; }
const moveLen = this.canvasWidth; this.exerciseArr.push(exercise);
tweenChange(this.pic1, {x: this.pic1.x - moveLen}, 1); }
tweenChange(this.pic2, {x: this.pic2.x - moveLen}, 1, () => {
this.canTouch = true;
this.curPic = this.pic2;
});
} }
pic1Clicked() { initGame() {
this.playAudio(this.data.audio_url);
} this.tempExerciseArr = randomSortByArr(this.exerciseArr);
this.lemonArr = [];
this.initLemon();
this.curIndex = 0;
this.gameover = false;
pic2Clicked() { this.showNextExercise();
this.playAudio(this.data.audio_url_2);
} }
showNextExercise() {
let exercise = this.tempExerciseArr.shift();
//如果存在,则加载;不存在,则表示结束
if (exercise) {
this.curIndex += 1;
this.stage.setPromptText(this.curIndex + "/" + this.exerciseArr.length);
let answers = exercise.answers;
this.curExercise = exercise;
for (let i = 0; i < answers.length; ++i) {
if (i == 0) {
this.leftBox.showBox(answers[i], () => {
this.canTouch = true;
this.canPlay = true;
});
}
else if (i == 1) {
this.midBox.showBox(answers[i]);
}
if (i == 2) {
this.rightBox.showBox(answers[i]);
}
}
if (answers.length < 3) {
let lastAnswer = this.rightBox.answer;
this.rightBox.hide(lastAnswer);
}
}
else {
this.curExercise = null;
this.gameover = true;
this.showGameOver();
}
}
mapDown(event) { mapDown(event) {
...@@ -625,26 +875,61 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -625,26 +875,61 @@ export class PlayComponent implements OnInit, OnDestroy {
return; return;
} }
if ( this.checkClickTarget(this.btnLeft) ) { if (this.checkClickTarget(this.audioTool.bg)) {
this.btnLeftClicked();
if (this.audioTool.playing) {
this.audioTool.pauseAudio(true);
}
else {
if (this.curExercise) {
let audio = this.curExercise.listeningAudio;
this.audioTool.playAudio(audio, true);
}
}
return; return;
} }
if ( this.checkClickTarget(this.btnRight) ) { if (this.checkClickTarget(this.leftBox.boxBg)) {
this.btnRightClicked(); this.clickBox(this.leftBox);
return; return;
} }
if ( this.checkClickTarget(this.pic1) ) { if (this.checkClickTarget(this.midBox.boxBg)) {
this.pic1Clicked(); this.clickBox(this.midBox);
return; return;
} }
if ( this.checkClickTarget(this.pic2) ) { if (this.checkClickTarget(this.rightBox.boxBg)) {
this.pic2Clicked(); this.clickBox(this.rightBox);
return; return;
} }
if (this.checkClickTarget(this.restartBtn.bg)) {
this.restartBtn.click(() => {
this.player.reset();
//卸车
this.player.unloading();
this.restartBtn.hide(0.3, () => {
removeItemFromArr(this.endRenderArr, this.restartBtn.bg);
this.curIndex = 0;
this.stage.setPromptText(this.curIndex + "/" + this.exerciseArr.length);
this.stage.openDoor(() => {
this.initGame();
});
});
});
return;
}
} }
mapMove(event) { mapMove(event) {
...@@ -671,9 +956,168 @@ export class PlayComponent implements OnInit, OnDestroy { ...@@ -671,9 +956,168 @@ export class PlayComponent implements OnInit, OnDestroy {
this.updateArr(this.renderArr); this.updateArr(this.renderArr);
this.updateArr(this.boxRenderArr);
this.updateArr(this.endRenderArr);
} }
clickBox(box) {
this.canTouch = false;
box.click(() => {
let answers = this.curExercise.answers;
let selectAll = true;
for (let i = 0; i < answers.length; ++i) {
let answer = answers[i];
if (answer.right) {
if (!answer.selected) {
selectAll = false;
break;
}
}
};
//全部选中,加载下一道题
if (selectAll) {
//获取小车拉坐坐标
let index = (this.curIndex - 1) % 6;
let pos = this.playerPosArr[index];
this.player.pullCar(pos.x, pos.y, () => {
let lemon = this.lemonArr[this.curIndex - 1];
//从舞台上移除lemon
this.stage.stage.removeChild(lemon);
//装车
this.player.loading(lemon);
//如果到达坡顶,练习题未结束,则小车从坡顶划出,从坡底划入
if(this.curIndex == 6 && this.tempExerciseArr.length > 0){
let toX = this.stage.stage.width + this.player.bg.width;
let toY = this.getPlayerY(toX);
this.player.pullCar(toX, toY, ()=>{
let sX = -this.player.bg.width;
let sY = this.getPlayerY(sX);
this.player.bg.x = sX;
this.player.bg.y = sY;
this.initLemon();
this.player.pullCar(this.player.initX, this.player.initY, ()=>{
//显示下一个练习题
this.showNextExercise();
}, 1);
}, 1.5);
}
else{
//显示下一个练习题
this.showNextExercise();
}
});
}
else {
this.canTouch = true;
}
}, () => {
this.canTouch = true;
this.player.flowSweat();
});
}
showGameOver() {
this.canTouch = false;
this.playAudio('win');
this.audioTool.pauseAudio(true);
this.audioTool.curAudio = null;
const showCelebrate = () => {
const showPetal = () => {
let petal = new Petal(this.endRenderArr, this.images, this.ctx);
//显示花瓣
petal.showPetal({ x: 0, y: 0, width: this.canvasWidth, height: this.canvasHeight }, this.mapScale, 100);
//播放鼓掌
const handClap = new Handclap();
handClap.init(this.images.get('left_hand'), this.images.get('right_hand'), this.mapScale, this.mapScale);
handClap.bg.x = (this.canvasWidth - handClap.getWidth()) / 2;
handClap.bg.y = (this.canvasHeight - handClap.getHight()) / 2;
handClap.audio = this.audioObj['handclap'];
this.endRenderArr.push(handClap.bg);
handClap.play(() => {
removeItemFromArr(this.endRenderArr, handClap.bg);
//隐藏cover
tweenChange(cover, { alpha: 0 }, 0.3, () => {
removeItemFromArr(this.endRenderArr, cover);
this.restartBtn.resetStatus();
this.endRenderArr.push(this.restartBtn.bg);
this.restartBtn.bg.x = (this.canvasWidth - this.restartBtn.bg.width) / 2;
this.restartBtn.bg.y = this.canvasHeight - 185 * this.mapScale - this.restartBtn.bg.height;
this.canTouch = true;
})
});
setTimeout(() => {
//结束花瓣显示
petal.stop(() => {
});
}, 2000);
}
let cover = new ShapeRect();
cover.setSize(this.canvasWidth, this.canvasHeight);
cover.fillColor = "#696969";
cover.alpha = 0.7;
cover.x = 0;
cover.y = 0;
this.endRenderArr.push(cover);
showPetal();
}
//关闭大门
this.stage.closeDoor(() => {
//将答案滑出屏幕
this.leftBox.moveOut(() => {
showCelebrate();
});
this.midBox.moveOut();
this.rightBox.moveOut();
});
}
} }
const res = [ const res = [
// ['bg', "assets/play/bg.jpg"], ['bg_1', "assets/play/bg_1.png"],
['btn_left', "assets/play/btn_left.png"], ['stage_bg', "assets/play/stage_bg.png"],
['btn_right', "assets/play/btn_right.png"], ['stage_box', "assets/play/stage_box.png"],
// ['text_bg', "assets/play/text_bg.png"], ['icon_laba1', 'assets/play/icon_laba1.png'],
['icon_laba2', 'assets/play/icon_laba2.png'],
['icon_laba3', 'assets/play/icon_laba3.png'],
['icon_laba3', 'assets/play/icon_laba3.png'],
['icon_laba3', 'assets/play/icon_laba3.png'],
['btn_restart_down', 'assets/play/btn_restart_down.png'],
['btn_restart_up', 'assets/play/btn_restart_up.png'],
['box_light', 'assets/play/box_light.png'],
['box_pic', 'assets/play/box_pic.png'],
['box_word', 'assets/play/box_word.png'],
['doorleft', 'assets/play/doorleft.png'],
['doorright', 'assets/play/doorright.png'],
['left_hand', 'assets/play/left_hand.png'],
['right_hand', 'assets/play/right_hand.png'],
['lemon', 'assets/play/lemon.png'],
['player', 'assets/play/player.png'],
['sweat', 'assets/play/sweat.png'],
['petal_1', "assets/play/petal_1.png"],
['petal_2', "assets/play/petal_2.png"],
['petal_3', "assets/play/petal_3.png"],
['petal_4', "assets/play/petal_4.png"],
['petal_5', "assets/play/petal_5.png"],
['petal_6', "assets/play/petal_6.png"],
['petal_7', "assets/play/petal_7.png"],
['petal_8', "assets/play/petal_8.png"],
['petal_9', "assets/play/petal_9.png"],
['petal_10', "assets/play/petal_10.png"],
['petal_11', "assets/play/petal_11.png"],
['petal_12', "assets/play/petal_12.png"],
['petal_13', "assets/play/petal_13.png"],
['petal_14', "assets/play/petal_14.png"],
['petal_15', "assets/play/petal_15.png"]
]; ];
...@@ -12,7 +47,14 @@ const res = [ ...@@ -12,7 +47,14 @@ const res = [
const resAudio = [ const resAudio = [
['click', "assets/play/music/click.mp3"], ['click', "assets/play/music/click.mp3"],
['right', "assets/play/music/right.mp3"],
['wrong', "assets/play/music/wrong.mp3"],
['handclap', 'assets/play/music/handclap.mp3'],
['win', 'assets/play/music/win.mp3'],
['pull', "assets/play/music/pull.mp3"],
['lemon', 'assets/play/music/lemon.mp3'],
['sweat', 'assets/play/music/sweat.mp3'],
['clickBtn', 'assets/play/music/clickBtn.mp3']
]; ];
export {res, resAudio}; export {res, resAudio};
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment