游戏中如何定时js点击事件只执行一次个事件

rpg maker vx事件中,如何让一个事件自动执行一次即消失?_百度知道
rpg maker vx事件中,如何让一个事件自动执行一次即消失?
我有更好的答案
常用方法:第一:开关/独立开关:在执行一次后开启某个开关或者独立开关,新建一个空的事件页,条件设置成为开关/独立开关XXXX 开启即可。第二:如果不是永久消失的话,可以使用【暂时消除本事件】
采纳率:58%
1、暂时消失事件2、第一个事件页最后独立开关操作,第二个事件页为空,触发条件是独立开关。3、移动设置-穿透on 透明on
用独立开关吧,这样就可以运行一次了
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。两个小时的游戏事件全部都是自动执行和并行【rpg制作大师吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:56,682贴子:
两个小时的游戏事件全部都是自动执行和并行
对自己的游戏太感叹了
0.0看过有个人也和你一样,还不能存档
这样好啊,有创意,现在RM的游戏最需要的就是创意了
全部都是啊!这个太膜拜了。。。、
贴吧热议榜
使用签名档&&
保存至快速回贴游戏服务器定时任务大家是通过什么方式实现的? - 知乎486被浏览<strong class="NumberBoard-itemValue" title="2分享邀请回答def update_events(milisec = 10):
result = selector.select(milisec)
for fd, event in result:
do something with socket event
current = time.time()
update_timer(current)
WAIT_MILLISEC = 10
update_events(WAIT_MILLISEC)
关键就是这个两次 select 中间 update_timer 的任务:集合中检查需要唤醒的时钟,并且调用它们的回调函数,来驱动整个服务器的时钟运行,以最简单的扫描法为例:def update_timer (current):
for timer in available_timers:
while current &= timer.expires:
timer.callback(current)
timer.expires += timer.period
available_timers 记录着当前可用的所有 timer 的集合,expires 是他们需要被触发的时间,如果当前时间大于等于这个 expires,认为该 timer 需要被触发到。注意 timer.expires 更新的时候是 += 周期,而不是 = current + 周期,后者会导致误差积累,长时间运行后偏差越来越大。同时这里需要 while,因为可能跨越两个以上周期,当然只运行一次的 timer 就不需要了,这里只是简化下。比如 libevent 里面的主循环 event_base_loop 每次 select 完毕后就调用一次 timeout_process。这就是 Timer 调度的基本原理。可能你会发现每次 select 结束都要扫描整个 available_timers 集合,是一个非常费时间的事情,那么首先想到的就是优先队列了:将 Timer 节点按照 expires 的先后顺序,将最快要发生的超时节点放在前面,每次检测队列头就可以判断是否超时了。比如 libevent 里面的 timerout_process 函数,就是用最小堆来存储超时事件,每次检测堆的第一个节点如果超时则删除并继续检测下一个,否则跳出循环(此时没有任何节点到期)。还有一种固定超时队列,就是里面的节点的超时周期都是相同的,那么每次增加都在最后,每次检测都只检测头部。比如所有链接都要检测60秒无事件超时这个事情,就可以用它,因为60秒是固定的,新增时放到队列最后,检测时只检测头部是否超时,如果有事件来到,就删除并重新加入队列末尾,这是固定超时队列。还有上面专门说的系统提供的 timerfd,创建后加入
select, 但是受限于 linux 系统,跨平台就用不了了,不能太依赖。然而这些都不算最完美的解决方案,一旦超时节点多达上万个,每个时间都不同,又考虑通用实现(非特定平台实现)的话,这几种调度方式是要吃亏的,目前最好的算法是 Linux Kernel 的时间轮算法,几乎保证不管有多少个时钟对象要处理,每次 update_timer 的时间都几乎是常数。具体可以看代码 kernel/timer.c ,楼上提到 skynet 里面有个时间轮的应用层实现,看了一眼,和 skynet 依赖太大了,需要自己做剥离工作,同时全局变量做 tvec_base(时钟管理器),这有点要命,你多线程每个线程一个 selector 的时候,就没法用了。更加具备简单性和可拆分性的 Linux 时间轮的应用层实现见我写的:两个文件,拷贝走就得了,没有任何第三个文件的依赖,更没有全局唯一的时钟管理器。一般来讲 “侵入式” 的网络库,都会把这个事情给管理了,因为他们接管你的主循环,比如 libevent, skynet 之类,你进入一个 event_loop 就只有程序结束才能出来了,而非侵入式的网络库不会接管你的主循环,可以让你自己主动去触发。比如某同事想在 libevent 上跑一套自己的时钟系统,而 event_base_dispatch 属于进去就出不来的 “侵入式” 设计。为了能在 select 前后加入自己的时钟调度,不得不把 libevent 改出一个 branch 来,所以 侵入式 是比较恶劣的设计。libevent 应该学习一下 win32,把 GetMessage, DispatchMessage 放出来,比如叫做:int event_base_update(struct event_base *base, int max_wait_time);
让你主动去触发它,然后灵活的在前后做点事情,还可以用 event_base_wakeup 从另外一个现成唤醒它,这样就会灵活很多了,完全取代
event_base_dispatch 这个进去出不来的死循环。每次 select wait 的时间一般用一个固定值,称为一个 TICK,固定值选大了,时钟基准周期就会很长,短时误差就会增大,选小了,又会占用额外 cpu,可以模拟 Linux 使用 100Hz的值,即 10ms来做,这也是通行做法。不嫌麻烦还可以每次从 timer 集合里面选择最先要超时的事件,计算还有多长时间就会超时,作为 select wait 的值,每次都不一样,每次都基本精确,同时不会占用多余 cpu,这叫 tickless,Linux 的 3.x以上版本也支持 tickless 的模式来驱动各种系统级时钟,号称更省电更精确,不过需要你手动打开,FreeBSD 9 以后也引入了 tickless。TICKLESS 模式可以说是一个新的方向,但是目前处于默认关闭的测试状态,那么你的网络库到底是用 TICK 还是 TICKLESS,看你根据具体情况来评估了。14326 条评论分享收藏感谢收起57 条评论分享收藏感谢收起解析Java中的定时器及使用定时器制作弹弹球游戏的示例
转载 &发布时间:日 08:51:54 & 作者:chenssy
这篇文章主要介绍了Java中的定时器及使用定时器制作弹弹球游戏的示例,文中同时也分析了定时器timer的缺点及相关替代方案,需要的朋友可以参考下
& 在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用JDK中的Timer定时任务来实现。下面LZ就其原理、实例以及Timer缺陷三个方面来解析java Timer定时器。
&&&&& 在java中一个完整定时任务需要由Timer、TimerTask两个类来配合完成。 API中是这样定义他们的,Timer:一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。由TimerTask:Timer 安排为一次执行或重复执行的任务。我们可以这样理解Timer是一种定时器工具,用来在一个后台线程计划执行指定任务,而TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务。
&&&&& 在工具类Timer中,提供了四个构造方法,每个构造方法都启动了计时器线程,同时Timer类可以保证多个线程可以共享单个Timer对象而无需进行外部同步,所以Timer类是线程安全的。但是由于每一个Timer对象对应的是单个后台线程,用于顺序执行所有的计时器任务,一般情况下我们的线程任务执行所消耗的时间应该非常短,但是由于特殊情况导致某个定时器任务执行的时间太长,那么他就会“独占”计时器的任务执行线程,其后的所有线程都必须等待它执行完,这就会延迟后续任务的执行,使这些任务堆积在一起,具体情况我们后面分析。
&&&&& 当程序初始化完成Timer后,定时任务就会按照我们设定的时间去执行,Timer提供了schedule方法,该方法有多中重载方式来适应不同的情况,如下:
&&&&& schedule(TimerTask task, Date time):安排在指定的时间执行指定的任务。
&&&&& schedule(TimerTask task, Date firstTime, long period) :安排指定的任务在指定的时间开始进行重复的固定延迟执行。
&&&&& schedule(TimerTask task, long delay) :安排在指定延迟后执行指定的任务。
&&&&& schedule(TimerTask task, long delay, long period) :安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
&&&&& 同时也重载了scheduleAtFixedRate方法,scheduleAtFixedRate方法与schedule相同,只不过他们的侧重点不同,区别后面分析。
&&&&& scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任务在指定的时间开始进行重复的固定速率执行。
&&&&& scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任务在指定的延迟后开始进行重复的固定速率执行。
&&&&& TimerTask类是一个抽象类,由Timer 安排为一次执行或重复执行的任务。它有一个抽象方法run()方法,该方法用于执行相应计时器任务要执行的操作。因此每一个具体的任务类都必须继承TimerTask,然后重写run()方法。
&&&&& 另外它还有两个非抽象的方法:
&&&&& boolean cancel():取消此计时器任务。
&&&&& long scheduledExecutionTime():返回此任务最近实际执行的安排执行时间。
2.1、指定延迟时间执行定时任务
public class TimerTest01 {
public TimerTest01(int time){
timer = new Timer();
timer.schedule(new TimerTaskTest01(), time * 1000);
public static void main(String[] args) {
System.out.println("timer begin....");
new TimerTest01(3);
public class TimerTaskTest01 extends TimerTask{
public void run() {
System.out.println("Time's up!!!!");
运行结果:
首先打印:
timer begin....
3秒后打印:
Time's up!!!!
2.2、在指定时间执行定时任务
public class TimerTest02 {
public TimerTest02(){
Date time = getTime();
System.out.println("指定时间time=" + time);
timer = new Timer();
timer.schedule(new TimerTaskTest02(), time);
public Date getTime(){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 39);
calendar.set(Calendar.SECOND, 00);
Date time = calendar.getTime();
public static void main(String[] args) {
new TimerTest02();
public class TimerTaskTest02 extends TimerTask{
public void run() {
System.out.println("指定时间执行线程任务...");
当时间到达11:39:00时就会执行该线程任务,当然大于该时间也会执行!!执行结果为:
指定时间time=Tue Jun 10 11:39:00 CST 2014
指定时间执行线程任务...
2.3、在延迟指定时间后以指定的间隔时间循环执行定时任务
public class TimerTest03 {
public TimerTest03(){
timer = new Timer();
timer.schedule(new TimerTaskTest03(), );
public static void main(String[] args) {
new TimerTest03();
public class TimerTaskTest03 extends TimerTask{
public void run() {
Date date = new Date(this.scheduledExecutionTime());
System.out.println("本次执行该线程的时间为:" + date);
本次执行该线程的时间为:Tue Jun 10 21:19:47 CST 2014
本次执行该线程的时间为:Tue Jun 10 21:19:49 CST 2014
本次执行该线程的时间为:Tue Jun 10 21:19:51 CST 2014
本次执行该线程的时间为:Tue Jun 10 21:19:53 CST 2014
本次执行该线程的时间为:Tue Jun 10 21:19:55 CST 2014
本次执行该线程的时间为:Tue Jun 10 21:19:57 CST 2014
.................
&&&&& 对于这个线程任务,如果我们不将该任务停止,他会一直运行下去。
&&&&& 对于上面三个实例,LZ只是简单的演示了一下,同时也没有讲解scheduleAtFixedRate方法的例子,其实该方法与schedule方法一样!
2.4、分析schedule和scheduleAtFixedRate
(1)schedule(TimerTask task, Date time)、schedule(TimerTask task, long delay)
&&&&& 对于这两个方法而言,如果指定的计划执行时间scheduledExecutionTime&= systemCurrentTime,则task会被立即执行。scheduledExecutionTime不会因为某一个task的过度执行而改变。
(2)schedule(TimerTask task, Date firstTime, long period)、schedule(TimerTask task, long delay, long period)
&&&&& 这两个方法与上面两个就有点儿不同的,前面提过Timer的计时器任务会因为前一个任务执行时间较长而延时。在这两个方法中,每一次执行的task的计划时间会随着前一个task的实际时间而发生改变,也就是scheduledExecutionTime(n+1)=realExecutionTime(n)+periodTime。也就是说如果第n个task由于某种情况导致这次的执行时间过程,最后导致systemCurrentTime&= scheduledExecutionTime(n+1),这是第n+1个task并不会因为到时了而执行,他会等待第n个task执行完之后再执行,那么这样势必会导致n+2个的执行实现scheduledExecutionTime放生改变即scheduledExecutionTime(n+2) = realExecutionTime(n+1)+periodTime。所以这两个方法更加注重保存间隔时间的稳定。
(3)scheduleAtFixedRate(TimerTask task, Date firstTime, long period)、scheduleAtFixedRate(TimerTask task, long delay, long period)
&&&&& 在前面也提过scheduleAtFixedRate与schedule方法的侧重点不同,schedule方法侧重保存间隔时间的稳定,而scheduleAtFixedRate方法更加侧重于保持执行频率的稳定。为什么这么说,原因如下。在schedule方法中会因为前一个任务的延迟而导致其后面的定时任务延时,而scheduleAtFixedRate方法则不会,如果第n个task执行时间过长导致systemCurrentTime&= scheduledExecutionTime(n+1),则不会做任何等待他会立即执行第n+1个task,所以scheduleAtFixedRate方法执行时间的计算方法不同于schedule,而是scheduledExecutionTime(n)=firstExecuteTime +n*periodTime,该计算方法永远保持不变。所以scheduleAtFixedRate更加侧重于保持执行频率的稳定。
三、Timer的缺陷
3.1、Timer的缺陷
&&&&& Timer计时器可以定时(指定时间执行任务)、延迟(延迟5秒执行任务)、周期性地执行任务(每隔个1秒执行任务),但是,Timer存在一些缺陷。首先Timer对调度的支持是基于绝对时间的,而不是相对时间,所以它对系统时间的改变非常敏感。其次Timer线程是不会捕获异常的,如果TimerTask抛出的了未检查异常则会导致Timer线程终止,同时Timer也不会重新恢复线程的执行,他会错误的认为整个Timer线程都会取消。同时,已经被安排单尚未执行的TimerTask也不会再执行了,新的任务也不能被调度。故如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。
(1)Timer管理时间延迟缺陷
&&&&& 前面Timer在执行定时任务时只会创建一个线程任务,如果存在多个线程,若其中某个线程因为某种原因而导致线程任务执行时间过长,超过了两个任务的间隔时间,会发生一些缺陷:
public class TimerTest04 {
public TimerTest04(){
this.timer = new Timer();
start = System.currentTimeMillis();
public void timerOne(){
timer.schedule(new TimerTask() {
public void run() {
System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start));
Thread.sleep(4000); //线程休眠3000
} catch (InterruptedException e) {
e.printStackTrace();
public void timerTwo(){
timer.schedule(new TimerTask() {
public void run() {
System.out.println("timerOne invoked ,the time:" + (System.currentTimeMillis() - start));
public static void main(String[] args) throws Exception {
TimerTest04 test = new TimerTest04();
test.timerOne();
test.timerTwo();
&&&&& 按照我们正常思路,timerTwo应该是在3s后执行,其结果应该是:
timerOne invoked ,the time:1001
timerOne invoked ,the time:3001
&&&&& 但是事与愿违,timerOne由于sleep(4000),休眠了4S,同时Timer内部是一个线程,导致timeOne所需的时间超过了间隔时间,结果:
timerOne invoked ,the time:1000
timerOne invoked ,the time:5000
(2)Timer抛出异常缺陷
如果TimerTask抛出RuntimeException,Timer会终止所有任务的运行。如下:
public class TimerTest04 {
public TimerTest04(){
this.timer = new Timer();
public void timerOne(){
timer.schedule(new TimerTask() {
public void run() {
throw new RuntimeException();
public void timerTwo(){
timer.schedule(new TimerTask() {
public void run() {
System.out.println("我会不会执行呢??");
public static void main(String[] args) {
TimerTest04 test = new TimerTest04();
test.timerOne();
test.timerTwo();
运行结果:timerOne抛出异常,导致timerTwo任务终止。
Exception in thread "Timer-0" java.lang.RuntimeException
at com.chenssy.timer.TimerTest04$1.run(TimerTest04.java:25)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
对于Timer的缺陷,我们可以考虑 ScheduledThreadPoolExecutor 来替代。Timer是基于绝对时间的,对系统时间比较敏感,而ScheduledThreadPoolExecutor 则是基于相对时间;Timer是内部是单一线程,而ScheduledThreadPoolExecutor内部是个线程池,所以可以支持多个任务并发执行。
3.2、用ScheduledExecutorService替代Timer
(1)解决问题一:
public class ScheduledExecutorTest {
private ScheduledExecutorService scheduE
ScheduledExecutorTest(){
this.scheduExec = Executors.newScheduledThreadPool(2);
this.start = System.currentTimeMillis();
public void timerOne(){
scheduExec.schedule(new Runnable() {
public void run() {
System.out.println("timerOne,the time:" + (System.currentTimeMillis() - start));
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
},1000,TimeUnit.MILLISECONDS);
public void timerTwo(){
scheduExec.schedule(new Runnable() {
public void run() {
System.out.println("timerTwo,the time:" + (System.currentTimeMillis() - start));
},2000,TimeUnit.MILLISECONDS);
public static void main(String[] args) {
ScheduledExecutorTest test = new ScheduledExecutorTest();
test.timerOne();
test.timerTwo();
运行结果:
timerOne,the time:1003
timerTwo,the time:2005
(2)解决问题二
public class ScheduledExecutorTest {
private ScheduledExecutorService scheduE
ScheduledExecutorTest(){
this.scheduExec = Executors.newScheduledThreadPool(2);
this.start = System.currentTimeMillis();
public void timerOne(){
scheduExec.schedule(new Runnable() {
public void run() {
throw new RuntimeException();
},1000,TimeUnit.MILLISECONDS);
public void timerTwo(){
scheduExec.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("timerTwo invoked .....");
},,TimeUnit.MILLISECONDS);
public static void main(String[] args) {
ScheduledExecutorTest test = new ScheduledExecutorTest();
test.timerOne();
test.timerTwo();
运行结果:
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
timerTwo invoked .....
........................
四、使用定时器实现弹弹球
模拟书上的一个例题做了一个弹弹球,是在画布上的指定位置画多个圆,经过一段的延时后,在附近位置重新画。使球看起来是动,通过JSpinner组件调节延时,来控制弹弹球的移动速度.
&&&&&&& BallsCanvas.java
public class BallsCanvas extends Canvas implements ActionListener,
FocusListener {
private Ball balls[]; // 多个球
private static class Ball {
int x, // 坐标
boolean up, // 运动方向
Ball(int x, int y, Color color) {
this.color =
up = left =
public BallsCanvas(Color colors[], int delay) { // 初始化颜色、延时
this.balls = new Ball[colors.length];
for (int i = 0, x = 40; i & colors. i++, x += 40) {
balls[i] = new Ball(x, x, colors[i]);
this.addFocusListener(this);
timer = new Timer(delay, this); // 创建定时器对象,delay指定延时
timer.start();
// 设置延时
public void setDelay(int delay) {
timer.setDelay(delay);
// 在canvas上面作画
public void paint(Graphics g) {
for (int i = 0; i & balls. i++) {
g.setColor(balls[i].color); // 设置颜色
balls[i].x = balls[i].left &#63; balls[i].x - 10 : balls[i].x + 10;
if (balls[i].x & 0 || balls[i].x &= this.getWidth()) { // 到水平方向更改方向
balls[i].left = !balls[i].
balls[i].y = balls[i].up &#63; balls[i].y - 10 : balls[i].y + 10;
if (balls[i].y & 0 || balls[i].y &= this.getHeight()) { // 到垂直方向更改方向
balls[i].up = !balls[i].
g.fillOval(balls[i].x, balls[i].y, 20, 20); // 画指定直径的圆
// 定时器定时执行事件
public void actionPerformed(ActionEvent e) {
repaint(); // 重画
// 获得焦点
public void focusGained(FocusEvent e) {
timer.stop(); // 定时器停止
// 失去焦点
public void focusLost(FocusEvent e) {
timer.restart(); // 定时器重启动
BallsJFrame.java
class BallsJFrame extends JFrame implements ChangeListener {
private BallsC
private JS
public BallsJFrame() {
super("弹弹球");
this.setBounds(300, 200, 480, 360);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
Color colors[] = { Color.red, Color.green, Color.blue,
Color.magenta, Color.cyan };
ball = new BallsCanvas(colors, 100);
this.getContentPane().add(ball);
JPanel panel = new JPanel();
this.getContentPane().add(panel, "South");
panel.add(new JLabel("Delay"));
spinner = new JSpinner();
spinner.setValue(100);
panel.add(spinner);
spinner.addChangeListener(this);
this.setVisible(true);
public void stateChanged(ChangeEvent e) {
// 修改JSpinner值时,单击JSpinner的Up或者down按钮时,或者在JSpinner中按Enter键
ball.setDelay(Integer.parseInt("" + spinner.getValue()));
public static void main(String[] args) {
new BallsJFrame();
效果如下:
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具【图文】让制度自动执行_百度文库
赠送免券下载特权
10W篇文档免费专享
部分付费文档8折起
每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
让制度自动执行
阅读已结束,下载本文到电脑
想免费下载本文?
登录百度文库,专享文档复制特权,积分每天免费拿!
你可能喜欢}

我要回帖

更多关于 js执行点击事件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信