windows 下典型的让游戏稳定在一个固定的帧速率的方法

未分类 Comments(37)

摘自《我的编程感悟》

 

constint time_per_frame = 1秒的时间单位/fps;

int time = 当前时刻;

while(游戏没有退出)

{

    查询是否有新的Windows消息;

    if(有新的消息)

    {

       处理消息;

    }

    else 

    {

     int t =当前时刻-time;

     if(t>time_per_frame){

        time = 当前时刻-(t-time_per_frame);

        更新一帧的游戏逻辑;

        刷新画面;

     }

    else 

     {

      Sleep(0);

      }

}

}

 

这只是一个简单的框架,我们以最高的频率检测和处理Windows消息,这样,即使游戏被限制的帧率不高时,游戏窗口也不会显得迟钝。而没有消息需要处理时,则以time_per_frame中的时间单位为间隔处理游戏的逻辑。我们看到,当CPU可以处理游戏的逻辑能力超过我们时,调用了Sleep(0).

这个Windows API 将使当前的线程放出自己的控制权,这一点对windows平台很重要,可以使游戏程序不至于占用了全部的CPU(如果不这样,就使游戏程序几乎独占了CPU,每次切换进游戏的线程,都把可以用的时间片用完了)。

这个简单的流程还可以在完善一些,比如当检测到游戏的速度总是跟不上设想的帧速率时,可以省略刷新画面这个环节,但是,游戏逻辑正常运作。这样用户感到的只是游戏画面跳跃了一下。

有时候,某帧游戏逻辑的运行时间过长,比如进行了大量的阻塞式操作,应该对time进行复位,以防止接下来的游戏运行为了赶上计时器的进度而看起来过快。

 

算法

未分类 Comments(29)

给定一个最多包含40亿随机排列的32位整数的顺序文件,找出一个不在文件的32位整数(在文件至少缺少一个这样的数)。在具有足够内存的情况下,如何解决该问题?如果有几个外部的“临时文件可用”,但是仅有几百字节的内存,如何解决该问题。

 

解决方法:

我们从表示的每个整数的32位的视角来考虑二分搜索。算法的第一趟(最多)读取40亿个输入整数,并把起始位为0的整数写入另一个顺序文件,将起始位为1的写入另外一个顺序文件。

这两个文件中,有一个文件最多包含20亿个整数,我们接下来将该文件用作当前输入并重复探测过程,但这次探测的是第二个位。如果原始的输入文件包含n个数,第二趟最多读取n/2个数,第三趟最多读取n/4个数,以此类推,所以总的运行时间正比于N,通过排序文件并扫描,我们能够找到缺失的整数,但是这样会导致运行时间正比于nlogn。本习题是伊利诺伊大学的ED Reingold给出的一道检测题。

JSP/Servlet

未分类 Comments(0)

M:Model,模型,对应JavaBean

V:View,视图,对应JSP页面

C:Controller,控制器,对应Servlet

MVC

未分类 Comments(1)

模型-视图-控件(Model-View-Controller,MVC)结构是以一种开发组件的方法,它将数据存储和数据处理从的数据的可视化表示中分离出来。存储和处理数据的组件称为模型(Model)。他包含组件的实际内容。表示数据的组件称为了视图(View),他处理组件所有必要的行为。控件(Controller)通常是一种用来获取数据的组件。

MVC优点:

1.可以使更多的视图显示成为可能。这样,可以通过一个模型共享数据。

2.可以简化复杂应用程序的编写。

模型包含数据,而视图使数据对外界可见。一旦一个视图与一个模型建立联系,它一定要与该模型同步。这样,可以确保模型的所有视图显示的数据都与模型的数据保持一致。要使模型与所属视图保持一致和同步,当视图中与数据相关的属性发生改变的时候,模型应当通知该视图。相应的,视图应当在收到模型的变化的通知后作出响应,重行显示受这些改变影响的视图区域。

Java事件委托模型提供了一种很好的架构以支持MVC组件模型的开发。这个模型可以具体实现为一个带适当的事件和事件监视器注册方法的源。视图可以实现为监视器。这样如果模型中的数据发生改变的时候,模型将会通知在模型已经注册的视图(也可以叫监听器),这样就能够保持模型与视图的数据保持一致。

下面是例子:

 

import java.awt.event.*;
import java.util.*;

public class CircleModel {

    private double radius = 20;
    private boolean filled;
    private java.awt.Color color;
    private ArrayList<ActionListener> actionListenerList;

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;

        processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "radius"));

    }

    public boolean isFilled() {
        return filled;
    }

    public void setFilled(boolean filled) {
        this.filled = filled;
        processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "filled"));
    }

    public java.awt.Color getColor() {
        return color;
    }

    public void setColor(java.awt.Color color) {
        this.color = color;
        processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "color"));
    }

    public synchronized void removeActionListener(ActionListener l) {
        if (actionListenerList != null && actionListenerList.contains(l)) {
            actionListenerList.add(l);
        }
    }

    public synchronized void addActionListener(ActionListener l) {
        if (actionListenerList == null) {
            actionListenerList = new ArrayList<ActionListener>();
        }
        actionListenerList.add(l);
    }

    private void processEvent(ActionEvent e) {
        ArrayList list;
        synchronized (this) {
            if (actionListenerList == null) {
                return;
            }
            list = (ArrayList) actionListenerList.clone();
        }
        for (int i = 0; i < list.size(); i++) {
            ActionListener listener = (ActionListener) list.get(i);
            listener.actionPerformed(e);
        }
    }
}

 

 

import java.awt.*;
import java.awt.event.*;

public class CircleView extends javax.swing.JPanel implements ActionListener {

    private CircleModel model;
    
    public void actionPerformed(ActionEvent actionEvent) {
        repaint();
    }
    
    public void setModel(CircleModel newModel) {
        model = newModel;
        model.addActionListener(this);
        repaint();
    }
    
    public CircleModel getModel() {
        return model;
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (model == null) {
            return;
        }
        g.setColor(model.getColor());
        
        int xCenter = getWidth() / 2;
        int yCenter = getHeight() / 2;
        int radius = (int) model.getRadius();
        
        if (model.isFilled()) {
            g.fillOval(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius);
        } else {
            g.drawOval(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius);
        }       
    }
}

 

package mvx;

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;

public class CircleController extends JPanel {

    private CircleModel model;
    private JTextField jtfRadius = new JTextField();
    private JComboBox jcboFilled = new JComboBox(new Boolean[]{new Boolean(false), new Boolean(true)});

    public CircleController() {
        JPanel panel1 = new JPanel();
        panel1.setLayout(new GridLayout(2, 1));
        panel1.add(new Label("Radius"));
        panel1.add(new JLabel("Filled"));

        JPanel panel2 = new JPanel();
        panel2.setLayout(new GridLayout(2, 1));
        panel2.add(jtfRadius);
        panel2.add(jcboFilled);

        setLayout(new BorderLayout());
        add(panel1, BorderLayout.WEST);
        add(panel2, BorderLayout.CENTER);

        jtfRadius.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (model == null) {
                    return;
                }
                model.setRadius(new Double(jtfRadius.getText()).doubleValue());

            }
        });

        jcboFilled.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (model == null) {
                    return;
                }
                model.setFilled(((Boolean) jcboFilled.getSelectedItem()).booleanValue());
            }
        });



    }

    public void setModel(CircleModel model) {
        this.model = model;
    }

    public CircleModel getModel() {
        return model;
    }
}