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

来源:互联网 发布:网络聊天用语指南 编辑:程序博客网 时间:2024/06/05 05:18
<script type="text/javascript">google_ad_client = "pub-8800625213955058";/* 336x280, 创建于 07-11-21 */google_ad_slot = "0989131976";google_ad_width = 336;google_ad_height = 280;//</script><script type="text/javascript"src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

教 学 纲 要

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);
    大 家 对 这 句 话 的 含 义 应 该 再 清 楚 不 过了 , 它 在 这 里 的 作 用 就 是 重 画 背 景 图 。

原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 膨胀螺丝上不紧怎么办 膨胀螺栓不膨胀怎么办 冷墩机断模板螺丝怎么办 楼上管道渗水怎么办 水凝胶贴片不粘怎么办 视频画幅过大怎么办 工厂噪音大怎么办 钢结构螺栓误差怎么办 螺纹滑牙怎么办 膨胀螺栓拧不紧怎么办 螺栓滑丝怎么办 螺栓滑了怎么办 开口螺丝口滑丝怎么办 没有检疫缸怎么办 钻戒变形了怎么办 金戒指变形了怎么办 戒指瘪了怎么办 戒指压扁了怎么办 瓷砖冷结水怎么办 螺丝刀短够不着怎么办 螺丝刀不够长怎么办 水泵吸力不够怎么办 汽车石子砸小坑怎么办 支座灌浆料怎么办 小孩子脚脱皮怎么办 小孩子脚底脱皮怎么办 袜子往下滑怎么办 袜子滑落怎么办 摩托车下坡熄火怎么办 克霉唑栓解小便怎么办 烧焊脸脱皮怎么办 焊盘脱落怎么办 焊锡堵住孔怎么办 氩弧焊百度怎么办 化学锚栓用小了怎么办? tshirt太长怎么办 nike华莱士发黄怎么办 笔记本热键冲突怎么办 瞄准镜越用越模糊怎么办 秃鹰初速上不去怎么办 单元格数字加不上怎么办