暂停时离子框架倒计时
Ionic Framework countdown when Pause
我正在制作一个有时间限制的游戏。
为了实现这一点,我制作了这些 services.js 文件:
var module=angular.module('starter.services', ['ionic', 'ui.router']);
module.factory('Game', function($interval)
{
/**
*Class we need for the game
*@param items {Array} with the items the game consisted of
*@param time {Int} How many seconds tis the duration of game
*@param grid_width How many Items each row will have
*@param grid_height How many items the grid will have vertically
*/
function Game(items,time,grid_width,grid_height,callbacks,scope)
{
var game=this;
//The total Items The game is consisted of
game.items=items;
//The grid of the items that will be swapped
game.grid=[];
game.callbacks=callbacks;
game.scope=scope;
/**
*Function that performs the logic
*and does the comparisons between Items
*/
game.swap=function()
{
};
/**
*Method that Initialises and starts the game
*Why I used this function and not game.start()
*is because this way the code for initializing the grid is saparate from the code that initialises the clock
*/
game.init=function()
{
game.timer=time;
if(typeof game.callbacks === 'object' && typeof game.callbacks['afterInit'] === 'function') game.callbacks['afterInit'](game);
game.play();
}
/*####################### Starting apausing and overing the game #############*/
/**
*The Game has the Foillowing Status
*'uninitialised': When the game has Not Been Started yet
*'play': When gameplay is on progress
*'paused': When the game is paused
*'over': When Game Over
*/
game.status='uninitialised';
game.timer=time;
/**
*Function that starts the timer
*/
var startTimer=function()
{
if(game.timer>0)
{
//Better to Use Angular's Interval
interval=$interval(function()
{
if(game.status==='play')
{
game.timer--;
if(game.timer==0) game.over();
if(typeof game.callbacks === 'object' && typeof game.callbacks['timerUpdate'] === 'function')
{
game.callbacks['timerUpdate'](game.timer,game.scope);
}
}
},1000);
}
}
/**
*Function that stops the timer
*/
var stopTimer=function()
{
if(interval!==null) $interval.cancel(interval);
}
/**
*The Interval of the setInterval();
*/
var interval=null;
/**
*Method that Pauses the game
*Enter here code that tell what will be executed when the game is paused
*/
game.pause=function()
{
game.status='paused';
if(typeof game.callbacks === 'object' && typeof game.callbacks['pause'] === 'function') game.callbacks['pause'](game.timer);
//stopTimer();
}
/**
*Method that starts the game
*Enter code here to be executer when the game is started
*/
game.play=function()
{
console.log("Game Started");
game.status='play';
//Start the counter
startTimer();
}
/**
*Method that ends the game
*Enter code here to be executer when the game is ended
*/
game.over=function()
{
game.status='over';
if(interval!==null) $interval.cancel(interval);
}
game.isOver=function()
{
return game.status==='over';
}
game.isPaused=function()
{
return game.status==='paused';
}
game.isNotPausedOrOver=function()
{
return game.status==='play';
}
/*##############################################################################*/
/*######################### For Scoring system #######################*/
game.points=0;
game.addScore=function(points)
{
game.points+=points;
}
game.removeScore=function(points)
{
game.points-=points;
}
/*#####################################################################*/
/*########### Functions for Game Saving and Loading ###################*/
game.save=function()
{
console.log("Game Saving");
//Code for game saving
}
game.load=function()
{
//Code for game loading
}
/*########### End of Functions ddor Game saving and Loading ###########*/
};//End Of Game Class
/**
*Function we need for the Game Item
*@param icon {String} Normal Icon For the Item (it can be either html or image path)
*@param icon_destroyed {String} Icon when The Game is Destroyed (it can be either html or image path)
*@param icon_marked {String}
*/
function GameItem(icon,icon_destroyed,icon_marked,name)
{
var item=this;
item.icon=icon;//Icon for the normal situations
item.icon_destroyed=icon_destroyed;//Icon if the item is Destroyed
item.icon_marked=icon_marked;//Icon when the item is selected
/*
*A Characteristic name of the itemYourFactory
*It can Be used for comparisons ;)
*/
item.name=name;
/**
*For now takes 2 values:
*start if the Item is not destroyed
*destroyed if the item in destroyed
*whatever dtatus you want
*/
item.status="start";
/**
*The position of the Item
*Check if you need it
*/
item.posistion={x:0,y:0};
/**
*Check if this item is equal with another one
*/
item.equals=function(other)
{
return other.name===item.name;
};
/**
*Gets The icon regarding the status of the Item is
*/
item.getIcon=function()
{
var icon="";
//Add here the status of the
switch(item.status)
{
case 'destroyed':
icon=item.icon_destroyed;
break;
case 'start':
icon=item.icon;
break;
default:
icon=item.icon;
}
return icon;
}
};//End of Item Class
return {
game:Game,
item:GameItem,
current_game:null
};
});
并且我已经将这些控制器存档 controllers.js
angular.module('starter.controllers', ['ionic','ui.router'])
/**
*Controller that does all the Dirty Job for the Game
*/
.controller('Game',function($scope,$timeout,$state,Game,MenuItem)
{
/*################### Controller Initialization ####################*/
var GameItem=Game.item;
var GameClass=Game.game;
/*##################### End Controller Initialization ##############*/
/**
*Function That does all the dirty job for initialization
*/
var init_game=function()
{
console.log(Game.current_game);
if(typeof Game.current_game === 'undefined' || Game.current_game === null)
{
/**
*Items for the Game
*/
var items=[
new GameItem('./img/icon1.png','./img/icon1.png','./img/icon1.png','trolley'),
new GameItem('./img/icon2.png','./img/icon2.png','./img/icon2.png','metro'),
new GameItem('./img/icon3.png','./img/icon3.png','./img/icon3.png','bus'),
new GameItem('./img/icon4.png','./img/icon4.png','./img/icon4.png','tram'),
];
/**
*Callbacks for Game
*/
var callbacks={
'timerUpdate':function(time,scope)
{
$timeout(function()
{
$scope.time=time;
console.log($scope.time);
});
},
'pause':function(time)
{
console.log("Game Paused");
$state.go('menu');
},
'afterInit':function(game)
{
MenuItem.items.play.name_="Continue Game";
MenuItem.items.play.clickFunction=function()
{
console.log("clicked");
$state.go('game');
Game.current_game.play();//Do not comment unlsess game will not resume
};
/*Making An Option For saving*/
var saveItem=new MenuItem.MenuItem("Save Game",'regular-btn',"",false,function()
{
game.save();
});
//Add on the top an Option to save the game
MenuItem.items.others.unshift(saveItem);
console.log(MenuItem.items.others);
}
};
Game.current_game=new GameClass(items,60,5,10,callbacks,$scope);
Game.current_game.init();
}
else // We may need to go to another page and return Therefore we must need a way to resume
{
console.log("Here resuming the game");
Game.current_game.play();
}
};
init_game();
$scope.pause=function()
{
console.log("Pausing Game");
Game.current_game.pause();
}
});
现在的问题是在我的应用程序上有一个暂停按钮,所以当我点击它时它会暂停计时器。问题是当我从主菜单返回时,即使超时继续倒计时,它就像 $scope 从未更新过。
我实际做的是:
- 从主菜单进入游戏页面。 (在这一步显示定时器
正确)
- 点击暂停返回主菜单。
- 从主菜单返回游戏页面。 (即使计时器倒计时,正如我在 console.log 中看到的那样,我在示波器上看不到)。
注意:定时器的值是用angular的$interval()函数更新的。
您可以在此处查看更多详细信息:
Problem Image
这里还有完整的代码:https://github.com/pc-magas/faster
经过一些调试,我找到了解决您的问题的方法。视图未更新,因为 $scope 内的 timerUpdate 回调与游戏控制器中的回调不同。实际上,Angular 应该在间隔内定时器的值发生变化时自动更新作用域。你不应该使用回调来实现这一点。我在下面介绍我的解决方案。
游戏工厂
1) 不要直接将秒值保存在timer中,而是将其保存为对象的属性:
game.timer = {
value: time
}
2) 从 startTimer 函数中删除执行 timerUpdate 回调的代码。你不需要它。
if(typeof game.callbacks === 'object' && typeof game.callbacks['timerUpdate'] === 'function')
{
game.callbacks['timerUpdate'](game.timer);
}
3) 从您的游戏工厂中删除所有控制器作用域引用。服务应该不知道控制器范围的存在。
游戏控制器
1) 从回调中删除 timerUpdate 函数。你将不再需要它了。
2) 在游戏初始化后创建一个范围 属性,而不是将新的计时器值分配给回调内的范围:
init_game();
$scope.timer = Game.current_game.timer;
现在,$scope.timer 包含对您的 timer 对象的引用。一旦计时器的 值 得到更新,范围将注册它并对视图进行适当的更改。
游戏视角
您需要做的最后一个更改是在游戏视图中将 {{timer}}
替换为 {{timer.value}}
。
结尾有两个提示
1) Angular有很多built-in功能,让生活更轻松。其中之一是 angular.isFunction() ,它检查对象是否是一个函数。您不需要这样的代码:
typeof game.callbacks === 'object' && typeof game.callbacks['afterInit'] === 'function'
2) 要检查对象是否为 null 或 undefined,您也不需要像您使用的那样的代码:
if(typeof Game.current_game === 'undefined' || Game.current_game === null)
你可以简单地写:
if(!Game.current_game)
我正在制作一个有时间限制的游戏。
为了实现这一点,我制作了这些 services.js 文件:
var module=angular.module('starter.services', ['ionic', 'ui.router']);
module.factory('Game', function($interval)
{
/**
*Class we need for the game
*@param items {Array} with the items the game consisted of
*@param time {Int} How many seconds tis the duration of game
*@param grid_width How many Items each row will have
*@param grid_height How many items the grid will have vertically
*/
function Game(items,time,grid_width,grid_height,callbacks,scope)
{
var game=this;
//The total Items The game is consisted of
game.items=items;
//The grid of the items that will be swapped
game.grid=[];
game.callbacks=callbacks;
game.scope=scope;
/**
*Function that performs the logic
*and does the comparisons between Items
*/
game.swap=function()
{
};
/**
*Method that Initialises and starts the game
*Why I used this function and not game.start()
*is because this way the code for initializing the grid is saparate from the code that initialises the clock
*/
game.init=function()
{
game.timer=time;
if(typeof game.callbacks === 'object' && typeof game.callbacks['afterInit'] === 'function') game.callbacks['afterInit'](game);
game.play();
}
/*####################### Starting apausing and overing the game #############*/
/**
*The Game has the Foillowing Status
*'uninitialised': When the game has Not Been Started yet
*'play': When gameplay is on progress
*'paused': When the game is paused
*'over': When Game Over
*/
game.status='uninitialised';
game.timer=time;
/**
*Function that starts the timer
*/
var startTimer=function()
{
if(game.timer>0)
{
//Better to Use Angular's Interval
interval=$interval(function()
{
if(game.status==='play')
{
game.timer--;
if(game.timer==0) game.over();
if(typeof game.callbacks === 'object' && typeof game.callbacks['timerUpdate'] === 'function')
{
game.callbacks['timerUpdate'](game.timer,game.scope);
}
}
},1000);
}
}
/**
*Function that stops the timer
*/
var stopTimer=function()
{
if(interval!==null) $interval.cancel(interval);
}
/**
*The Interval of the setInterval();
*/
var interval=null;
/**
*Method that Pauses the game
*Enter here code that tell what will be executed when the game is paused
*/
game.pause=function()
{
game.status='paused';
if(typeof game.callbacks === 'object' && typeof game.callbacks['pause'] === 'function') game.callbacks['pause'](game.timer);
//stopTimer();
}
/**
*Method that starts the game
*Enter code here to be executer when the game is started
*/
game.play=function()
{
console.log("Game Started");
game.status='play';
//Start the counter
startTimer();
}
/**
*Method that ends the game
*Enter code here to be executer when the game is ended
*/
game.over=function()
{
game.status='over';
if(interval!==null) $interval.cancel(interval);
}
game.isOver=function()
{
return game.status==='over';
}
game.isPaused=function()
{
return game.status==='paused';
}
game.isNotPausedOrOver=function()
{
return game.status==='play';
}
/*##############################################################################*/
/*######################### For Scoring system #######################*/
game.points=0;
game.addScore=function(points)
{
game.points+=points;
}
game.removeScore=function(points)
{
game.points-=points;
}
/*#####################################################################*/
/*########### Functions for Game Saving and Loading ###################*/
game.save=function()
{
console.log("Game Saving");
//Code for game saving
}
game.load=function()
{
//Code for game loading
}
/*########### End of Functions ddor Game saving and Loading ###########*/
};//End Of Game Class
/**
*Function we need for the Game Item
*@param icon {String} Normal Icon For the Item (it can be either html or image path)
*@param icon_destroyed {String} Icon when The Game is Destroyed (it can be either html or image path)
*@param icon_marked {String}
*/
function GameItem(icon,icon_destroyed,icon_marked,name)
{
var item=this;
item.icon=icon;//Icon for the normal situations
item.icon_destroyed=icon_destroyed;//Icon if the item is Destroyed
item.icon_marked=icon_marked;//Icon when the item is selected
/*
*A Characteristic name of the itemYourFactory
*It can Be used for comparisons ;)
*/
item.name=name;
/**
*For now takes 2 values:
*start if the Item is not destroyed
*destroyed if the item in destroyed
*whatever dtatus you want
*/
item.status="start";
/**
*The position of the Item
*Check if you need it
*/
item.posistion={x:0,y:0};
/**
*Check if this item is equal with another one
*/
item.equals=function(other)
{
return other.name===item.name;
};
/**
*Gets The icon regarding the status of the Item is
*/
item.getIcon=function()
{
var icon="";
//Add here the status of the
switch(item.status)
{
case 'destroyed':
icon=item.icon_destroyed;
break;
case 'start':
icon=item.icon;
break;
default:
icon=item.icon;
}
return icon;
}
};//End of Item Class
return {
game:Game,
item:GameItem,
current_game:null
};
});
并且我已经将这些控制器存档 controllers.js
angular.module('starter.controllers', ['ionic','ui.router'])
/**
*Controller that does all the Dirty Job for the Game
*/
.controller('Game',function($scope,$timeout,$state,Game,MenuItem)
{
/*################### Controller Initialization ####################*/
var GameItem=Game.item;
var GameClass=Game.game;
/*##################### End Controller Initialization ##############*/
/**
*Function That does all the dirty job for initialization
*/
var init_game=function()
{
console.log(Game.current_game);
if(typeof Game.current_game === 'undefined' || Game.current_game === null)
{
/**
*Items for the Game
*/
var items=[
new GameItem('./img/icon1.png','./img/icon1.png','./img/icon1.png','trolley'),
new GameItem('./img/icon2.png','./img/icon2.png','./img/icon2.png','metro'),
new GameItem('./img/icon3.png','./img/icon3.png','./img/icon3.png','bus'),
new GameItem('./img/icon4.png','./img/icon4.png','./img/icon4.png','tram'),
];
/**
*Callbacks for Game
*/
var callbacks={
'timerUpdate':function(time,scope)
{
$timeout(function()
{
$scope.time=time;
console.log($scope.time);
});
},
'pause':function(time)
{
console.log("Game Paused");
$state.go('menu');
},
'afterInit':function(game)
{
MenuItem.items.play.name_="Continue Game";
MenuItem.items.play.clickFunction=function()
{
console.log("clicked");
$state.go('game');
Game.current_game.play();//Do not comment unlsess game will not resume
};
/*Making An Option For saving*/
var saveItem=new MenuItem.MenuItem("Save Game",'regular-btn',"",false,function()
{
game.save();
});
//Add on the top an Option to save the game
MenuItem.items.others.unshift(saveItem);
console.log(MenuItem.items.others);
}
};
Game.current_game=new GameClass(items,60,5,10,callbacks,$scope);
Game.current_game.init();
}
else // We may need to go to another page and return Therefore we must need a way to resume
{
console.log("Here resuming the game");
Game.current_game.play();
}
};
init_game();
$scope.pause=function()
{
console.log("Pausing Game");
Game.current_game.pause();
}
});
现在的问题是在我的应用程序上有一个暂停按钮,所以当我点击它时它会暂停计时器。问题是当我从主菜单返回时,即使超时继续倒计时,它就像 $scope 从未更新过。
我实际做的是:
- 从主菜单进入游戏页面。 (在这一步显示定时器 正确)
- 点击暂停返回主菜单。
- 从主菜单返回游戏页面。 (即使计时器倒计时,正如我在 console.log 中看到的那样,我在示波器上看不到)。
注意:定时器的值是用angular的$interval()函数更新的。
您可以在此处查看更多详细信息: Problem Image
这里还有完整的代码:https://github.com/pc-magas/faster
经过一些调试,我找到了解决您的问题的方法。视图未更新,因为 $scope 内的 timerUpdate 回调与游戏控制器中的回调不同。实际上,Angular 应该在间隔内定时器的值发生变化时自动更新作用域。你不应该使用回调来实现这一点。我在下面介绍我的解决方案。
游戏工厂
1) 不要直接将秒值保存在timer中,而是将其保存为对象的属性:
game.timer = {
value: time
}
2) 从 startTimer 函数中删除执行 timerUpdate 回调的代码。你不需要它。
if(typeof game.callbacks === 'object' && typeof game.callbacks['timerUpdate'] === 'function')
{
game.callbacks['timerUpdate'](game.timer);
}
3) 从您的游戏工厂中删除所有控制器作用域引用。服务应该不知道控制器范围的存在。
游戏控制器
1) 从回调中删除 timerUpdate 函数。你将不再需要它了。
2) 在游戏初始化后创建一个范围 属性,而不是将新的计时器值分配给回调内的范围:
init_game();
$scope.timer = Game.current_game.timer;
现在,$scope.timer 包含对您的 timer 对象的引用。一旦计时器的 值 得到更新,范围将注册它并对视图进行适当的更改。
游戏视角
您需要做的最后一个更改是在游戏视图中将 {{timer}}
替换为 {{timer.value}}
。
结尾有两个提示
1) Angular有很多built-in功能,让生活更轻松。其中之一是 angular.isFunction() ,它检查对象是否是一个函数。您不需要这样的代码:
typeof game.callbacks === 'object' && typeof game.callbacks['afterInit'] === 'function'
2) 要检查对象是否为 null 或 undefined,您也不需要像您使用的那样的代码:
if(typeof Game.current_game === 'undefined' || Game.current_game === null)
你可以简单地写:
if(!Game.current_game)