350 likes | 452 Views
2011 年 11 月 14 日. metagun. 1. 打游戏没有? 2. 项目结构: metagun metagun-android 或 游戏名 游戏名 -android 游戏名 -desktop. package com.badlogic.metagun; 入口,准备 package com.mojang.metagun.entity; 实体 package com.mojang.metagun.level; 关卡 package com.mojang.metagun.screen; 显示. 入口:.
E N D
2011年11月14日 metagun
1.打游戏没有? • 2. 项目结构: • metagun • metagun-android • 或 • 游戏名 • 游戏名-android • 游戏名-desktop
package com.badlogic.metagun; • 入口,准备 • package com.mojang.metagun.entity; • 实体 • package com.mojang.metagun.level; • 关卡 • package com.mojang.metagun.screen; • 显示
入口: • publicvoid create () {}; • publicvoid render () {};
准备 • 图片素材Art.java • 声音Sound.java • 交互Input.java • 统计Stats.java
Metagun.java的render () • 行为:隔一会儿进来一次 • 测试:System.out.println("screen.render()"); • 参考解释: • 代码中的注释 • 笔记:应用程序的render()
不要:捡了芝麻丢了西瓜 • TitleScreen会牵连出ExpositionScreen,一个是游戏开始画面、另一个是说明画面;我们先跳过,我们切入核心画面——GameScreen。
GameScreen • 核心Tick() -overrides 说明父类有 • 核心Render() –implements 说明父类有,但抽象了
GameScreen的Tick() 主要做的3件事: 1.若按下ESCAPE,则交给PauseScreen 2.若有player,则player.tick(),否则,看是否要重生player. 3.关卡的tick() 启发:显示屏幕的跳转,在tick()里写 2、3点:一个玩家、一个当前关卡 GameScreen持有Level,Level持有Player
GameScreen的Render() • spriteBatch.begin(); • 1.绘背景 • 2.关卡地图绘制 • 3.如重生,绘制提示"PRESS X TO TRY AGAIN“ • spriteBatch.end(); • 启示:显示信息,用“状态变量”,直接在Render()里显示;若交互,必须tick()处理
Player.java • Screen的核心是GameScreen • Entity的核心是Player • Player有什么
GameScreen、Player、Level的关系 • GameScreen产生Level view • Level知道是谁产生了自己 control • Level产生了Player,及其它实体 model
Level.java • 关卡总共解决4个问题: • 1.构造函数,墙材质、Player和其它实体 • 2.tick() • 3.render() • 4.遮罩
Level的构造函数: • 一个关卡中,屏幕显示出的所有东西,包括三类:1.墙;2实体;3出生点 • 在关卡的地图中用不同的颜色表明,通过颜色,在屏幕上显示相应屏幕的东西。 • 玩家角色,属于实体,但不用颜色来决定生成,而是用出生点决定生成位置 • 墙的种类有9种:用字节数组walls来保存,该数组大小32*24 • 实体的种类有种9种:用ArrayList数组entityMap来保存,该数组大小32*24,同时用entities保存
墙的种类: • //白色:普通墙 • //wall = 1; • //粉红:能被枪子推动的箱子 • //wall = 2; • //黄色:炸药箱 • //wall = 3; • //红色:钉子地 • //wall = 4; • //浅灰色:透明墙,敌人的子弹可以穿透射你,你的子弹却穿不透,打不到敌人! • //wall = 5; • //一种红色:向右滚动地面 • //wall = 6; • //一种红色:向左滚动地面 • //wall = 7; • //深灰色:过关门 • //wall = 8; • //淡蓝绿色:最后一关,绿色方块 • //wall = 9;
实体的总类: • 1个怪头 Boss (其父类为BossPart) • 10个绿球 BossNeck(其父类为BossPart) • 绿怪 Gremlin • 绿怪 Gremlin(与前个不同) • 架子怪 Jabberwocky • 帽子 Hat • 提示牌 Sign,包括一二级枪 • 红色手枪人 Gunner • Player
构造函数做了3件事 • 根据level.png里的颜色来,来设定用不同的“墙”,一共9种材质;同时,来决定生成哪种实体。 • 32*24的每个像素点逐行,逐列“看颜色”,每个像素点对应walls的一个元素,也对应一个entityMap的一个元素(某个像素点对应有哪种墙材质和有几个实体)
墙-walls实体-entities,entityMap • 实体的保存使用了2个东西: • 一个ArrayList类型的entities • 另一个ArrayList数组类型的entityMap • entities保存该关卡所有实体,用来绘制 • entityMap,保存某个像素格有几个实体,用来配合实现“遮罩”
Level的tick() • Removed 是实体的存在与消亡的标志 • 考察Player和其它实体
Level的render() • 给walls的每个元素的值(9种可能),指定某种材质,就是用walls.png上哪个位置的图 • 根据保存该关卡所有实体的entities,让每个实体自绘
Level的“遮罩” • isFree(), isBulletFree(), getEntities() • 判断Player的下一移动位置是否“受限制” • entityMap用来存储某个像素格有几个实体
类的状态和行为 • 现实世界中的对象都具有两个特征:它们都有各自的状态,它们都有各自的行为。比如,人有状态(名字,肤色,国籍,性别等)和行为(走、看)。 • 软件中的对象以现实生活中的对象为原型,它们也有状态和行为。把这些对象抽象成一类,这个类就代表了所有拥有这些属性的人的集合。软件对象就用类的成员变量来维护这些对象的状态,用类的成员函数来实现这些对象的行为。
主角 • hitSpikes撞到钉子上就die
主角 • die挂掉: • 若状态removed为真,则return • 有帽子的话,帽子留给关卡 • 播放死亡声音 • 关卡中增加16个PlayerGore • 统计 • 状态removed置为真
连锁反应 • 看最后一句的:状态removed置为真, • Level和GameScreen的反映
关卡的tick() • 对于关卡 • 若player.removed为真,则20次tick后,screen.mayRespawn置为ture • 20次,是延缓效果
GameScreen的Render • 若GameScreen的mayRespawn为真,则显示PRESS X TO TRY AGAIN
若player.removed为真,则entities.remove(i--); • 则在Level的render时,entities里的元素自绘,此时player已经给删掉了
有帽子的话,帽子留给关卡 • 关卡的entities里多了一个Hat对象 • 并在entityMap的某个元素中多了一个Hat对象 • 在关卡render()时,Hat调用自己的render()
关卡中增加16个PlayerGore • 关卡的entities里多了16个PlayerGore对象 • 并在entityMap的某个元素中多了16个PlayerGore对象 • 在关卡render()时, PlayerGore调用自己的render()
提问 • 帽子怎么飘飘悠悠的下降? • 结合tick() • xa = xxa + Math.sin(time * 0.05) * 0.2; • xxa *= 0.95; • ya *= 0.95; • ya += Level.GRAVITY * 0.1; • Render() • 还得看看
数学 • 碰到左边和碰到右边 • if (xa < 0) { • double xx = x / 10; • xa = -(xx - ((int)xx)) * 10; • } else { • double xx = (x + w) / 10; • xa = 10 - (xx - ((int)xx)) * 10; • } • if (level.isFree(this, x + xa, y, w, h, xa, 0)) { • x += xa; • } • this.xa *= -bounce;