Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1528533
  • 博文数量: 3500
  • 博客积分: 6000
  • 博客等级: 准将
  • 技术积分: 43870
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-03 20:31
文章分类

全部博文(3500)

文章存档

2008年(3500)

我的朋友

分类:

2008-05-04 19:14:11

一起学习

教 学 纲 要

Java 世界 里 最 激 动 人 心 的 时 刻 终 于 到 来 了 , 在 这 一 章 里 你 将 学到 在 主 页 里 播 放 动 画 的 技 巧 , 以 及 载 入 和 播 放 声 音 的 方法 , 掌 握 了 本 章 所 讲 授 的 这 些 技 巧 , 再 加 上 你 脑 子 里 各种 希 奇 古 怪 的 念 头 , 你 就 有 能 力 创 造 出 你 自 己 的 真 正 活灵 活 现 、 有 声 有 色 的 活 动 Web 主 页 来 。

正 文

先 不忙 看 程 序 运 行 结 果 , 我 敢 打 赌 这 个 程 序 里 一 定 有 好 几 个地 方 你 还 不 太 理 解 , 那 就 让 我 们 先 来 看 看 这 几 条 令 人 不解 的 语 句 :

1. fps = getParameter("speed");
    这 条 语 句 的 意 思 是 从 HTML 文 件 接 受 一个 名 叫 speed 的 参 数 。 很 多 时 候 我 们 希 望 自 己 控 制 程 序 的运 行 情 况 , 在 这 个 程 序 里 我 们 希 望 能 够 用 一 种 比 较 容 易的 方 法 来 改 变 动 画 的 放 映 速 度 , 而 不 是 到 程 序 源 代 码 里直 接 修 改 程 序 里 的 某 条 语 句 , 然 后 重 新 编 译 程 序 。 的 确完 成 这 样 的 修 改 是 工 程 浩 大 的 , 也 不 是 一 般 人 所 能 胜 任的 。 于 是 我 们 就 想 到 了 利 用 参 数 。 只 要 给 定 了 参 数 , 程序 执 行 时 就 会 按 照 给 定 的 参 数 去 执 行 了 。 那 么 Java 是 从那 里 得 到 参 数 的 呢 ? 我 们 都 知 道 , Java 程 序 是 通 过 编 写 HomePage 的 HTML 文 件 加 载 到 WWW 浏 览 器 里 执 行 的 , 自 然 而 然, 我 们 就 想 到 了 让 Java 程 序 到 包 含 了 它 的 那 个 HTML 文 件 里去 读 取 参 数 。 为 了 使 Java 能 够 从 HTML 文 件 里 读 到 参 数 , 必须 满 足 两 个 条 件 :

  • 在 HTML 文 件 里 , 必 须 用 标 签 , 指 定 参数 的 名 称 和 参 数 的 值 。
  • 在 Java 源 程 序 中 , 必 须 用 方 法 getParameter 来 取得 参 数 值 。
这 回 你 该 明 白 为 什 么 HTML 文 件 里 会 多 出 这 样 一句 话 来这 句 话 正 是 用 来 告 诉 Java 程 序 “ 放 映 速 度 为 每 秒 5 帧 ”

2. pause = 1000/integer.parseint(fps);
    根 据 我 们 的 定 义 , 在 这 条 语 句 中 的 pause 应 该 是 每 帧 图 片 显 示 的 时 间 , 在 Java 里 时 间 都 是 以 毫 秒为 单 位 的 , 所 以 这 里 1000 毫 秒 也 就 是 1 秒 , 不 难 理 解

每 张 图 片 在 屏 幕 上 停 留 的 时 间 = 1 秒 / 1 秒内 放 映 的 图 片 张 数

    根 据 这 个 算 式 , 理 解 这 条 语 句 就 很 容易 了 , 可 是 为 什 么 还 有 Integer.parseInt(fps) 呢 ? 要 知 道 HTML 里 的 变 量 都 是 字 符 型 的 , 即 使 是 数 字 5 , 它 也 仅 仅 是 一个 写 成 5 这 个 样 子 的 一 个 字 符 , 所 以 fps 一 开 始 就 被 说 明成 字 符 型 , 为 的 就 是 在 这 里 赋 值 时 不 至 于 类 型 不 匹 配 。那 么 既 然 fps 只 是 一 个 字 符 , 我 们 怎 么 能 把 它 放 到 数 学 算式 里 来 进 行 计 算 呢 ? 当 然 要 进 行 类 型 转 换 , 把 fps 这 个 字符 串 类 型 的 值 转 换 成 能 进 行 数 学 运 算 的 整 数 。 Integer.parseInt(fps) 就 是 完 成 这 一 功 能 的 。

3. try {Thread.sleep(pause);}
  catch(InterruptedException e){}

    这 是 什 么 东 西 ? 这 么 复 杂 。 哦 ! 请 你千 万 不 要 看 它 复 杂 就 轻 易 放 弃 。 try 和 catch 只 不 过 是 一 个防 止 意 外 的 保 险 栓 , 把 你 要 进 行 保 险 的 东 西 放 在 try 后 面的 {} 里 , 然 后 把 一 旦 发 生 意 外 要 进 行 的 处 理 写 在 catch 后面 的 {} 里 。 这 和 填 一 张 保 险 单 一 样 简 单 , 在 try 里 填 你 投保 的 东 西 , 在 catch 里 填 入 发 生 意 外 时 你 希 望 保 险 公 司 为你 做 的 事 。

    好 了 , 关 于 try 和 catch 我 们 在 后 面 的 章节 里 还 要 详 细 地 介 绍 。 在 这 个 程 序 里 我 们 把 Thread.sleep(pause) ; 这 条 语 句 投 了 保 , 不 过 没 有 对 它 进 行 什 么 意 外 处 理 ,因 为 catch 里 什 么 也 没 做 。 Thread.sleep(pause) ; 这 条 语 句 又是 什 么 意 思 呢 ? 再 容 易 理 解 不 过 了 , 它 就 是 “ 让 线 程 睡上 一 会 儿 ” , 睡 多 久 呢 ? 每 帧 图 片 显 示 时 间 多 久 , 它 就睡 多 久 。 pause 不 就 决 定 了 每 帧 图 片 显 示 的 时 间 吗 ?

4. num = ( num 1) % frame.length ;

    这 是 图 片 帧 数 的 计 数 器 , 每 放 完 一 帧图 片 , num 就 加 1 。 % 我 们 在 第 四 章 里 已 经 学 过 , 它 表 示取 模 运 算 , 再 说 简 单 一 些 , 就 是 计 算 余 数 。 在 这 里 我 们用 它 来 干 什 么 呢 ? 哦 ! 对 了 , 还 没 有 说 frame.length 呢 , frame 在 前 面 定 义 过 , 它 是 一 个 Image 数 组 , 包 含 了 动 画 的 一 组图 片 , frame.length 就 是 这 个 数 组 的 长 度 , 也 就 是 frame 所 包含 的 图 片 张 数 。 明 白 了 每 一 个 参 数 的 意 义 以 后 , 再 来 看看 算 式 吧 , 这 个 算 式 的 意 思 就 是 : 显 示 图 片 的 计 数 值 对图 片 的 总 张 数 取 模 。 为 什 么 要 这 样 做 呢 ? 如 果 不 对 图 片的 总 张 数 取 模 又 会 发 生 什 么 呢 ? 设 想 一 下 , 当 图 片 显 示到 了 最 后 一 张 , 再 没 有 图 片 可 供 显 示 了 , 你 想 让 动 画 再从 头 放 一 遍 , 也 就 是 从 第 一 张 开 始 再 重 新 来 一 遍 。 取 模就 是 完 成 这 个 功 能 的 , 它 让 显 示 的 图 片 可 以 再 次 从 头 开始 。 在 这 个 程 序 里 我 们 一 共 有 17 张 图 片 , 所 以 frame.length 等 于 17 , 当 计 数 器 num 计 到 16 时 , 已 经 没 有 图 片 可 以 显 示了 , ( 注 意 数 组 下 标 都 以 0 开 始 ) 应 该 显 示 第 0 张 , 所 以 num = (16 1 ) % 17 = 0 正 好 符 合 要 求 。

    好 啦 ! 现 在 你 对 程 序 的 理 解 应 该 更 清楚 了 。 看 看 程 序 的 运 行 结 果 吧 ! 程 序 运 行 起 来 会 有 一 只顽 皮 的 小 企 鹅 在 窗 口 里 翻 筋 斗 。 当 然 我 们 不 可 能 在 这 里看 到 那 只 会 动 的 小 企 鹅 , 不 过 小 企 鹅 翻 筋 斗 的 每 一 个 动作 都 在 这 里 了 ( 见 图 18.2 ) , 我 们 的 动 画 就 是 快 速 地 切换 这 些 图 片 , 让 它 动 起 来 。

图 18.2 动 画 的 每 一 帧 图 片



不 再 闪 烁 的 动 画

    看 了 上 面 的 程 序 , 你 可 能 会 觉 得 有 些不 尽 如 人 意 , 小 企 鹅 翻 起 筋 斗 来 总 是 一 闪 一 闪 地 。 虽 然动 起 来 了 , 开 始 一 闪 一 闪 的 动 画 实 在 不 能 令 人 满 意 。 为什 么 我 们 的 小 动 画 会 有 这 种 讨 厌 的 闪 烁 呢 ? 有 没 有 办 法让 它 不 闪 烁 呢 ?

    不 知 道 你 还 记 不 记 得 前 一 章 讲 过 的 repaint 方 法 的 执 行 过 程 , 当 调 用 repaint 时 , 系 统 首 先 调 用 的 是 update, 省 缺 的 update 是 用 背 景 色 把 整 个 窗 口 重 刷 一 次 , 然后 再 调 用 paint 方 法 在 窗 口 里 画 出 要 显 示 的 内 容 。 为 什 么会 发 生 画 面 闪 烁 ? 现 在 就 应 该 比 较 清 楚 了 , 原 因 就 在 于我 们 每 次 调 用 repaint 重 画 窗 口 时 , 都 相 当 于 先 调 用 update 清 除 窗 口 里 的 所 有 画 面 , 然 后 再 调 用 paint 方 法 在 一 张 干净 的 纸 上 显 示 下 一 幅 画 面 。 这 样 重 复 的 清 除 画 面 , 又 重绘 画 面 就 造 成 了 动 画 的 闪 烁 。

    其 实 我 们 在 换 图 片 的 时 候 真 的 需 要 清除 所 有 画 面 再 重 画 它 吗 ? 完 全 没 有 必 要 。 我 们 只 需 要 用下 一 张 图 片 去 覆 盖 上 一 张 图 片 就 可 以 了 。 所 以 在 update 里, 我 们 不 再 需 要 清 除 画 面 , 而 是 直 接 调 用 paint 重 绘 画 面就 可 以 了 。 你 也 许 要 奇 怪 了 , 我 们 的 程 序 里 并 没 有 什 么 update 呀 ? 是 的 , 我 们 上 面 的 程 序 里 的 确 没 有 update 这 个方 法 , 可 是 正 如 我 们 前 面 提 过 的 , update 是 在 调 用 repaint 的 时 候 , 由 repaint 去 自 动 调 用 的 。 如 果 我 们 不 在 程 序 里重 写 一 个 新 的 update , 它 就 会 自 己 去 调 用 系 统 省 缺 的 那 个, 用 背 景 色 先 清 除 整 个 窗 口 。 如 果 你 不 想 要 系 统 省 缺 的那 个 笨 笨 的 update , 你 只 需 要 在 程 序 里 写 上 自 己 的 update 就 行 了 。

    在 我 们 这 个 程 序 里 只 需 用 下 一 张 图 片去 覆 盖 上 一 张 图 片 , 而 无 需 先 清 除 窗 口 , 所 以 我 们 的 update 就 可 以 省 去 清 除 窗 口 这 一 步 , 直 接 调 用 paint 重 绘 窗 口 。那 么 这 就 在 程 序 里 加 上 我 们 自 己 的 update 方 法 吧 !
    public void update ( Graphics g ) { paint (g) ; }
    好 啦 ! , 闪 烁 的 问 题 就 解 决 了 。 不 信你 试 试 , 把 上 面 一 句 话 加 到 程 序 的 最 后 一 个 } 之 前 , 重新 编 译 一 次 , 看 看 运 行 结 果 是 不 是 好 多 了 呢 ?

连 续 的 筋 斗

    现 在 我 们 的 小 企 鹅 已 经 能 把 筋 斗 翻 得相 当 漂 亮 了 , 可 是 如 果 你 是 个 完 美 主 义 者 的 话 , 可 能 还是 感 到 有 些 美 中 不 足 。 这 只 小 企 鹅 怎 么 只 会 在 原 地 翻 筋斗 ? 能 让 它 连 续 地 翻 几 个 筋 斗 吗 ? 当 然 可 以 。 这 就 是 动画 常 见 的 另 一 种 效 果 , 在 固 定 的 背 景 上 , 一 边 放 映 主 角的 动 作 , 一 边 同 时 改 变 主 角 的 位 置 。 听 起 来 似 乎 挺 复 杂的 , 不 过 实 现 起 来 并 没 有 想 像 的 那 么 难 。 在 这 种 效 果 的动 画 里 , 除 了 前 面 讲 过 的 技 巧 外 , 我 们 所 要 做 的 就 是 加上 重 画 背 景 和 改 变 主 角 位 置 这 两 个 动 作 的 处 理 。

    制 作 这 样 的 动 画 , 除 了 需 要 一 组 连 续动 作 的 图 片 外 , 还 应 该 准 备 一 张 背 景 图 让 我 们 的 动 画 人物 以 此 为 背 景 来 进 行 表 演 。 我 们 想 让 小 企 鹅 连 续 地 翻 上好 几 个 筋 斗 , 就 需 要 在 显 示 图 片 的 同 时 改 变 显 示 的 位 置, 连 续 不 断 地 在 不 同 位 置 画 小 企 鹅 翻 筋 斗 的 图 片 是 不 是就 可 以 让 它 连 续 地 翻 筋 斗 了 呢 ? 还 不 行 。 每 次 显 示 完 上一 帧 图 片 后 , 我 们 还 必 须 用 背 景 图 去 重 画 一 次 背 景 , 然后 再 按 正 确 的 位 置 显 示 下 一 次 图 片 。 如 果 不 这 样 做 , 可以 想 像 , 背 景 图 上 就 会 留 下 每 个 动 作 的 残 迹 。 根 据 前 面的 分 析 , 我 们 需 要 做 的 修 改 实 际 就 在 run 和 paint 这 两 个 方法 里 。 在 run 里 修 改 图 片 显 示 的 位 置 , 在 paint 里 加 入 重 画背 景 图 的 动 作 。 那 么 就 来 看 看 修 改 过 的 程 序 是 什 么 样 子。 程 序 18.2 // tumble.java
import java.awt.*;
public class tumble extends java.applet.Applet implements Runnable
{
    Image frame[ ];    // 说 明 一 个 用 来 存 放动 画 图 片 的 Image 数 组
    Thread thd;    // 说 明 一 个 线 程 对 象
    int num;
    int pause;
    Image backgnd;    // 说 明 背 景 图 片
    int x,x_pos ;    // 说 明 显 示 图 片 的 x 坐标

public void init( )
{
    int i;
    String fps;
    frame = new Image[17];    // 初 始 化 Image 数组
    thd = null;            // 初 始 化 线 程
    num = 0;            // 初 始 化 计 数 器
    for (i = 0; i < frame.length; i )    // 加载 动 画 图 片     frame[i] = getImage(getCodeBase( ), "images/T" i ".gif");
    backgnd = getImage (getCodeBase( ),"images/backgnd.gif");   // 加 载 背 景 图 片
    fps = getParameter("speed");    // 设 置 播 放速 度
    if (fps == null)
        fps = "10";
    pause = 1000 / Integer.parseInt(fps);    // 计算 每 帧 图 片 显 示 的 时 间
}
public void start( )
{
    if (thd == null)
    {
        thd = new Thread(this);    // 产 生 一个 新 线 程
        thd.start( );    // 启 动 这 个 新 线 程
    }
}
public void stop( )
{
    if (thd != null)
    {
        thd.stop( );    // 中 止 线 程
        thd = null;    // 释 放 线 程
    }
}
public void run( )
{
    while (true)
    {
        try { Thread.sleep(pause);    // 使 线程 睡 眠
    }
        catch (InterruptedException e) {};
        repaint( );    // 重 画 窗 口
        num = (num 1) % frame.length;    // 为显 示 的 图 片 计 数
        x = ((x 130 10)%(size( ).width 130 70))-130; // 计 算 下 一 帧 图 片 显 示 的 位 置
        x_pos= size( ).width-x ;    // 调 整 图片 显 示 的 位 置
    }
}
public void paint(Graphics g)
{
    g.drawImage(backgnd,0,0,this);    // 显 示 背景 图
    g.drawImage(frame[num], x_pos, 0, this);    // 显 示 动 画 图 片
    }
    public void update(Graphics g)
    {
        paint(g);
    }
}     这 个 程 序 的 HTML 文 件 如 下 所 示 :
< HTML>
< HEAD>
< TITLE>tumble< /TITLE>
< /HEAD>
< BODY>
< APPLET CODE = "tumble.class" WIDTH = 500 HEIGHT = 80>
< param name = "speed" value = "5">
< /APPLET>
< /BODY>
< /HTML>

    看 看 程 序 运 行 结 果 , 一 只 会 连 续 翻 筋斗 的 小 企 鹅 高 高 兴 兴 地 在 你 的 主 页 上 玩 开 了 。

图 18.3 程 序 18.2 的 运 行 结 果

    让 它 自 由 自 在 地 玩 吧 , 我 们 再 来 看 看程 序 。 程 序 18.2 比 程 序 18.1 增 加 了 几 句 话 :
1. 方 法 run 中 的
    x = ((x 130 10)%(size( ).width 130 70))-130;

    一 看 就 知 道 这 是 用 来 改 变 图 片 显 示 位置 的 , 在 这 个 长 算 式 中 10 是 每 次 小 企 鹅 前 进 的 步 长 , size( ).width 指 的 是 运 行 这 个 Applet 窗 口 的 宽 度 , 此 外 我 们 还 考虑 了 每 一 帧 图 片 的 宽 度 和 窗 口 显 示 预 留 量 , 为 的 是 让 小企 鹅 从 画 面 右 侧 切 入 , 以 免 造 成 突 然 出 现 的 那 种 突 兀 的感 觉 。

2. 方 法 paint 中 的
    g.drawImage(backgnd,0,0,this);
    大 家 对 这 句 话 的 含 义 应 该 再 清 楚 不 过了 , 它 在 这 里 的 作 用 就 是 重 画 背 景 图 。 下载本文示例代码


第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)第十九讲 动画制作及声音载入(二)

阅读(180) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~